Professional Documents
Culture Documents
Marco Delaurenti
Politecnico di Torino
Design and optimization techniques of
high–speed VLSI circuits
Marco Delaurenti
PhD Dissertation
December 1999
Politecnico di Torino
Advisor Coordinator
Prof. Maurizio Zamboni Prof. Ivo Montrosset
c
Copyright 1999 Marco Delaurenti
Writing comes more eas-
ily if you have something
to say.
(Sholem Asch)
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix
1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2. A simple model . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.2 Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3. A complex model . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.4 Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3.5 Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4. Mathematic Optimization . . . . . . . . . . . . . . . . . . . . . 47
4.1.2.1 Unconstrained . . . . . . . . . . . . . . . . . 56
4.1.2.2 Constrained . . . . . . . . . . . . . . . . . . 57
Compromise solution . . . . . . . . . . . . . . 57
Dicotomic search . . . . . . . . . . . . . . . . . 59
Fibonacci Search . . . . . . . . . . . . . . . . . 60
Contents ix
Convergence considerations . . . . . . . . . . . 61
Convergence considerations . . . . . . . . . . . 66
4.3 Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
5. Circuit Optimization . . . . . . . . . . . . . . . . . . . . . . . . 77
Critical Paths . . . . . . . . . . . . . . . . . . . 80
5.1.3 Area . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
5.2.2.1 Area . . . . . . . . . . . . . . . . . . . . . . . 95
5.2.2.2 Power . . . . . . . . . . . . . . . . . . . . . . 96
5.2.2.3 Delay . . . . . . . . . . . . . . . . . . . . . . 97
Appendix 143
2.2 RC chain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
The design of high speed integrated circuit is a long and complex op-
eration; nonetheless the total time–to–market required from the idea to the
silicon masks is reducing along the way.
To help the designer during this long and winding road several CAD tools
are available. In the first step the only thing existing is the description of
the circuit behaviour (the “idea”); in the central step of the design flow the
designer knows only the logic functioning of each block composing the cir-
cuit, but he ignores the technology realization of these blocks; in the last
steps, finally, the designer knows exactly the technology implementation
of every single gate of the circuit, and can “compose” the final layout with
every gate. Ca va sans dire that the CAD tool are nowadays of vital import-
ance in the design flow, and moreover the goodness or the badness of such
tools influence a lot the quality of the final design.
Among all the possible instruments, the optimization tools have a pri-
mary role in all the phases of a project, starting from the optimization at
higher level and descending to the optimization made at the electrical level.
This thesis focuses its efforts in developing new strategies and new
techniques for the optimization made at the transistor dimension level, that
is the one done by the cell library engineer, and developing also a CAD in-
strument to make this work as more as harmless as possible.
xx Preface
Part I
CMOS LOGIC
Chapter 1
1.1 Introduction
We might ask: why to optimize a single cell in VLSI circuit, when the
design nowadays is shifting toward higher and higher level?
• Need of re-usable library cells. This makes easier to reuse the same
library for different projects. It is a must nowadays, in order to reduce
the total time to target/market.
The first basic distinction inside the CMOS logic families is among the
static logics and the dynamic logics ([1]).
Static logic: The static logic is a logic in which the functioning of the cir-
cuit is not synchronized by a global signal, namely the clock of the
circuit. The output is solely function of the input of the circuit, and
it is asynchronous with respect to them. The timing of the circuit is
defined exclusively by its internal delay.
Dynamic logic: The dynamic logic is a logic in which the output is syn-
chronized by a global signal, viz. the clock. The output is, then, func-
tion both of the inputs of the circuit and of the clock signal; and the
1.2. CMOS logic families 5
timing of the circuit is defined both by its internal delay and by the
timing of the clock.
Both the static and dynamic logics comprehend several logic families.
A
OUT = A and B
“and” gate. It has two NMOS transistor connected in series and two
PMOS connected in parallel.
The static logic is quite fast, does not dissipate power in steady state
and has a very good noise margin.
PMOS is always conducting and leads the output node to the high
state. When the NMOS branch conducts also, then the output dis-
charges, if the ratio among the NMOS and PMOS transistor is well de-
signed.
This logic is cited here only for historical reason, since it is not so fast,
it dissipates static power in a steady state (when the output is in the
low state) and it is sensible to noise.
Pass-logic The pass-logic is relatively new logic, and, for many digital de-
signs, implementation in pass-transistor logic (PTL) has been shown
to be superior in terms of area, timing, and power characteristics to
static CMOS.
As an example see figure 1.2,
A
A
OUT = A xor B
The principal dynamic logics are divided yet in two sub-families, pipe-
lined and not-pipelined. The first two these are non-pipelined, while the oth-
ers are pipelined:
Domino logic and N–P Domino logic The typical domino gate is depicted
in figure 1.3
OUT
CLOCK
INPUTs
NMOS Block
During the pre-charge phase the clock is at its low state, so that the
pre-charged node before the static inverter is high, and the output is
low. During the evaluation phase the clock is high, so that the inputs
of the n–block (that can perform any logical function) can discharge
the pre-charged node and lead the output to the high state.
We can cascade several of these gates, given that each gate has its
own output inverter, and we can drive every gate with the same clock
signal, given that the evaluation phase lasts the time necessary to all
the gates to finish their inputs evaluation. This last fact explains why
this is a non-pipelined logic: the output of every cell is available when
the cell has finished its evaluation phase.
Moreover this logic has a limited area occupancy, since it has a low
number of PMOS transistors. On the other hand it is not possible to
implement inverting-structure and, as all the other dynamic logics,
this logic is subject to the charge-sharing problem2 .
2
The charge-sharing problem, or charge-redistribution, is a problem that affects the dy-
8 Chapter 1. Introduction to CMOS logic
Cascode voltage switch logic (CVSL) The CVSL is part of the large family
of differential logics. It needs both the inputs and the inputs negated,
and two complementary n-block that perform the logic function, as it
is possible to see in figure 1.4.
OUT OUT
INPUTs
INPUTs
namic logics. Basically the charge stored in an precharged node node during the memory
phase does not remain fully stored in it. Let’s think to a domino gate during the pre-charge
phase, when the clock is low. If there is one input in the n-block that is high, then its cor-
responding transistor is conducting. The n-branch is still not conducting, since the clocked
NMOS transistor is not conducting, but some charge from the precharged node can flow to
others node via the conducting transistors in the n-block. This redistribution of charge is
simply a charge of a cap8citor partition and lead to a state of the precharged node lesser
than the high state.
This problem can produce logic errors, and surely diminishes the noise margins of
1.2. CMOS logic families 9
C 2 MOS logic The typical C2 MOS gate is shown in figure 1.5. It is basically
a three-state gate, since when the clock is at the low state, the output
is floating at the high impedance state.
INPUTs
PMOS Block
CLOCK
OUT
CLOCK
INPUTs
NMOS Block
Since the output stage of every cell is also dynamic (a C2 MOS in-
verter), then this logic is more subject to the charge-sharing problem
that the domino logic is.
10 Chapter 1. Introduction to CMOS logic
True Single Phase Clock logic (TSPC) The final evolution of the NORA is
the TSPC logic, or true single phase clock logic ([2]).
The TSPC logic is a n-p logic, since of each gate exists the n-version
and the p-version. For example the n-latch and the p-latch are shown
in figure 1.6.
CLK
OUT
A
(a) Type n
CLK
OUT
(b) Type p
The TSPC logic is among the faster dynamic families, and surely it has
a great appealing for its very low number of transistor employed.
1.3. Conclusion 11
1.3 Conclusion
For these reasons we have chosen to include in our library a few static
gates (an “and” gate, an “or” gate, and a few more) and a few dynamic
gates, and in particular gates from the TSPC family. This family has shown
good characteristics in term of speed, area occupancy and power dissipa-
tion; it has also the very important feature to need only a single clock.
The complete list of the gates comprising the library can be found in the
table 7.1 (page 122), with their relative schematic diagram of CMOS imple-
mentation.
Part II
CIRCUIT MODELING
Chapter 2
A SIMPLE MODEL
CL
RL
D CD
ON D
Rg
G
= G
Rd
CG S
S
CS
R0
If this simple MOS model is valid, then the Elmore’s delay formula can
be used in every structure containing some MOS. The Elmore’s formula is
16 Chapter 2. A simple model
appealing for its simplicity and its easy of use; however the accuracy of the
formula can worsen in the deep sub–micron domain, since the modeling of
a MOS through its resistance it is no more valid.
The Elmore’s model or the Elmore’s delay formula can predict the delay
of a RC chain as shown in figure 2.2.
Ci-1 Ci C i+1
In order to obtain the formula, let’s start with a single RC cell, as shown
in figure 2.3. We can express the voltage V1 (t) by means of a differential
equation such as:
h i
− t
V1 = V0 (t) 1 − e R0 C0 .
R0
V0 V1
C0
V1 = 0.63V0 (t).
So the time t D = τ represents the 63% delay from V0 (t) to V1 (t). Extend-
ing the formula of the time constant to the chain of figure 2.2, we obtain:
N i
tD = ∑ ∑ Rj Ci .
i=0 j=0
This delay is the input–output delay. When there is the need to know
the delay between the input and one of the inner nodes, a more complex
formula (a semi-empirical one) can be used; for example, with N = 2:
where q is:
r
R0
if R1 ≤ 2R0 ,
q= R 0 + R1
R0 C0
if R1 > 2R0 .
R0 C0 + R1 C1
18 Chapter 2. A simple model
The first case (with R1 ≤ 2R0 ) is named strong coupling, while the second
one is named weak coupling.
Given the unit impulse response h(t) (figure 2.4) of the output node of
the RC tree, Elmore proposed to approximate the delay τ by the mean of
h(t), considering h(t) as a distribution. The 50% delay is given by:
h(t)
m
t
Z τ
h(t)dt = 0.5
0
Z ∞
tD = m = t · h(t)dt
0
with
Z ∞
h(t)dt = 1.
0
2.2. Conclusions 19
2.2 Conclusions
The model shown in this chapter is quite appealing for the calculus of
the delay in CMOS structure, but it is inaccurate as far as we go into the
submicron domain, so its use should be limited to a first validation of an
optimization algorithm, but not for real production.
About this, it is important to note that the delay functions obtained by the
Elmore’s formula satisfy some properties useful in the optimization realm
(for example equation (4.1), page 50): then the Elmore model is very useful
for optimization algorithms testing.
Chapter 3
A COMPLEX MODEL
Most of the proposed power models use estimation algorithms not com-
patible with the delay analysis. The purpose of the FAST model is to com-
bine delay and power evaluations in the same estimation procedure, allow-
ing the simultaneous optimization of delay and power.
22 Chapter 3. A complex model
The section 3.1 reports the theory behind the FAST model, and in par-
ticular: §3.1.1 shows the MOS equations used in the model, §3.1.2 shows
the internal nodes voltage approximation made by the model and §3.1.3
explains how the threshold voltage variation are taken into account in the
model. Section 3.2 shows how the FAST model estimates the delay, and in
particular §3.2.1 shows how the equation are solved; while section 3.3 re-
ports the method used for the calculation of the power consumption, and
in particular §3.3.1 accounts for the switching power, §3.3.2 accounts for the
short-circuit power, and §3.3.3 accounts for the subthreshold power.
Finally the section 3.4 presents some results by the comparison of the model
with HSPICE and the section 3.5 draws some conclusions.
The low complexity and the accuracy that can be obtained by taking
care of the phenomenon of carriers velocity saturation, which is domin-
ant in sub–micron technologies, suggested the use of the classical charge–
control analysis and the gradual–channel approximation (Hodges model),
described in §3.1.1.
5
Vout
Vin
Model
4
3
V
0
1.2 1.25 1.3 1.35 1.4 1.45 1.5
Time (ns)
The well known equations for the MOS transistors are (for the n–type
and p–type transistors)[1]:
below saturation
" #
V2
IDSn, p = βn, p (VGS − VTn, p )VDS − DS (3.1)
2
above saturation
βn, p h i2
IDSn, p = VDSsatn, p (3.2)
2
µn, p Cox W
where βn, p = L , with µn, p modified by the carrier velocity saturation
effect:
µn0 µ p0
µn = µp =
1 + VLEDSc 1 − VLEDSc
24 Chapter 3. A complex model
s
2(VGSn, p − VTn, p )
VDSn, p = ±Vc 1 ± − 1 (3.3)
Vc
where the plus signs are for n–MOSFETs and the minus signs are for the
p–MOSFETs, and Vc = |Ec L|
from 1 to N or from 1 to P (figure 3.2). Let’s assume that the label 1 comes
with the driving transistor (i.e. the n–MOSFET with source connected to VSS
as the p–MOSFET with source connected to VDD ), as in figure 3.2. This hy-
pothesis is only for the develop of the discussion; in our model any (but
only one) transistor can be a driving transistor, that is a transistor with a
changing gate voltage.
Notation 3.1. In the following equations the superscript index refers to the
node number (with the variable i always for the n–MOSFETs and j always
for the p–MOSFETs), and the small–letter subscript indexes n and p refer, re-
spectively, to n–MOSFETs and p–MOSFETs, both for the voltage variables or
for the time variables; for the voltage variables the capital subscript indexes
G and D refer to the drain node and the gate node, while the small–letter
index d refers to the initial conditions of the drain nodes.
So, for example, VGi n (t) is the gate voltage at the node i for the n–MOSFETs
j
(function of time), and Vd p is the initial condition of the drain voltage at
node j for the p–MOSFETs.
The wave forms of the voltage are shown in figure 3.4 and figure 3.5,
with the hypothesis t01n = t20n = · · · = t0Nn and t01 p = t02 p = · · · = t0Pp ; that is
because we suppose the start of conduction of all the MOSFETs in a chain
contemporary1 .
0 t<0
VDD
VG1 n (t) = t 0 ≤ t < τi1n (3.4a)
τi1n
V τi1n ≤ t
DD
VDD t<0
VDD
VG1 p (t) = VDD − τ 1 t 0 ≤ t < τi1p (3.4b)
ip
0 τi1p ≤ t
VGi n (t) = VDD ∀t (3.4c)
i=2,3,..., N
1
This hypothesis is well supported by simulations
26 Chapter 3. A complex model
j
VGp (t) = VSS ∀t (3.4d)
j=2,3,..., P
V i
t < t0i n
dn
i i − Vi
t − t0i n
VD (t) = Vdn dn i i
t0i n ≤ t < τoin (3.4e)
n
i=1,2,..., N
τ o − t 0
n n
VSS τoin ≤ t
j j
Vd p t < t0 p
VDD − V j j j j
τo p Vd p − t0 p VDD
j dp j j
VD p (t) = j j
t+ j j
t0 p ≤ t < τo p (3.4f)
j=1,2,..., P
τ o p − t0 p
τ o p − t0 p
j
V τo p ≤ t
DD
Fig. 3.3: The i–th and i + 1–th MOSFETs with node voltages
It is also possible to define τiin, p = τoi− 1 and the source voltage V i = V i+1 ,
n, p s d
as shown in figure 3.3 for the i–th n–MOS. The same is valid for the p–
MOSFETs.
The starting level Vdn, p are determined with a static analysis, described
in §3.1.3.
τi τo τo τo τo
∗
Vs = VDD − VTn ,
Tn0 + ∆VTn
∗ =V
and, if VTn0 is the threshold voltage with Vsb = 0, then VTn
and we can solve for Vsb :
r q
γ 4γ 2|Φ p | + 8|Φ p | + 4VDD − 4VTn0 + γ 2
Vsb = ±
2
q γ2
+ γ 2|Φ p | + VDD − VTn0 + (> 0)
2
τo τo
τi
q q
∆VTp = −γ ( 2|Φ p | + Vsb − 2|Φ p |)
Again, solving:
q q
Vsb = ∗
−VDD − VTp = −VDD − VTp0 + γ ( 2|Φ p | + Vsb − 2|Φ p |)
where VTp0 is the threshold voltage with Vsb = VDD ; thus we find:
r q
γ 4γ 2|Φ p | + 8|Φ p | + 4VDD + 4VTp0 + γ 2
Vsb = ±
2
q γ2
− γ 2|Φ p | − VDD − VTp0 − (< 0)
2
VDD
VDD
VDD pmos 1
VDD nmos N
VSS - VTP
VDD - VTN
VSS pmos 2
VDD nmos 2
VSS - VTP
VDD - VTN
VSS pmos P
VSS nmos 1
VSS
(a) n–MOSFET chain (b) p–MOSFET chain
VTn = αn Vsb + βn
VTp = α p Vsb + β p
∗ −V
VTn Tn0
αn = βn = VTn0
VDD − VTn
∗
∗ ∗
VTp − VTp 0 VTp VDD + VTp0
αp = βp =
VDD + VTp
∗ VDD + VTp
∗
3.2. Delay estimation 31
1.5 -1
VTn(Vsb) VTp(Vsb)
VTn approx VTp approx
1.4 -1.1
1.3 -1.2
1.2 -1.3
-1.5
VTn
VTp
1.1 -1.4
0.9 -1.6
0.8 -1.7
0 1 2 3 4 5 0 1 2 3 4 5
Vsb Vsb
Fig. 3.8: Threshold variation with Vsb (solid line) and its linear approxima-
tion (dashed line)
In figure 3.8(a) and 3.8(b) the actual threshold variation (of a n–MOS
transistor and a p–MOS transistor) when a Vsb voltage is applied is com-
pared with the linear approximation used in our model, for a 0.7 µm tech-
nology.
The delay estimation of the structures reported in figure 3.2 implies the
evaluation of τoin, p and t0i n, p , for each transistor in the chains.
j
Qin = 0 Qp = 0 i = 1, 2, . . . N and j = 1, 2, . . . , P (3.5)
The generic term Qin is the sum of three elements, Qin = QiI+1 − QiI − QiC ,
define below:
32 Chapter 3. A complex model
• QiI+1 is the charge due to the (i + 1)–th MOSFET placed above the i–th
node:
Z ti+1 Z τ i+1
sn on
QiI+1 = i+1
Isat (t)dt + i+1
Ilin (t)dt (3.6a)
t0i+n 1 tis+
n
1
which includes the contributions due to the currents above and be-
low saturation; ts is the time at which the MOSFET switches from the
saturation to the linear region;
• QiI is the charge due to the (i)–th mos below the i–th node:
Z ti Z τi
sn on
QiI = i
Isat (t)dt + i
Ilin (t)dt (3.6b)
t0i n tisn
• QiC is the charge due to the discharging of the capacitor at the i–th
node, Ci :
Referring to the n–MOS chain in figure 3.3, we can write at the output
node N:
because, neglecting the contribution of the p–MOS chain above (if it exists),
QN
I = 0.
N −1
QnN−1 = Q N
I − QI − QCN−1 ,
QnN−1 = −C N VdNn − Q N
I
−1
− QCN−1 ,
and so on:
More generally:
N
Qin = − ∑ Ck Vdkn − QiI − QiC
k=i+1
N
= − ∑ Ck Vdkn − QiI = 0
k =i
N
Q1n = − ∑ Ck Vdkn − Q1I = 0 , (3.8)
k=1
In order to solve non–linear equation (3.8) one must substitute the defin-
ition of the current to calculate the charge Q, as in equations (3.6a), (3.6b)
(page 32), moreover one must substitute both the current calculated in the
saturation region and the one calculated in the linear region, extending the
integrals of the aforementioned equations to the proper extremes.
between the two regions when the rising of the input has already finished,
or on the contrary can switches when the input is still rising.
All the possible cases are:
Evaluating all the possible cases, the equation (3.8) becomes a non–
linear equation of the variables t1s , t10 , τo1 , τi1 , with t1s , t10 , τo1 as unknowns.
A further step must be done, with the purpose of eliminating all the vari-
ables but one. The real unknown is the time τo1 , while all the other un-
knowns can be expressed in function of τo1 : in particular, the times t1s and
t10 can be calculated together, with the equation VDS = VGS − VT † and with
the equation that states the charge conservation at node 1 between the time
0 and the time t10 , similar to the equation (3.5) (page 31), including the boot-
strap effect due to capacitive coupling between the gate and the drain of
the first transistor.
Both these equations are functions of t1s , t10 , τo1 , τi1 . By this way one has
three equations with three unknowns, and by means of some approxim-
ated methods2 it is possible to evaluate the three unknowns.
This solution scheme ought to be repeated for all the seven cases shown
in equation (3.9). Each case gives as a solution a triple t1s , t01 , τo1 that is com-
patible with one and only one of the conditions expressed by these cases.
Thus, only one working condition is really selected, as it can be expected.
Indeed all the previous solving scheme is true only if the equation (3.6c)
(page 32) apply, i.e. only if the capacitance at the node i is not a function of
the voltage at the same node. But the capacitance actually is function of the
voltage in this manner:
†
Or, taking into account the carrier velocity saturation effect, the equation (3.3) (page 24).
2
The problem is always strictly non–linear.
3.2. Delay estimation 35
−m j −m p
i Vi Vi
C = Cij 1+ i
+ Cp 1 + (3.10)
Φb Φb
If the capacitance at each node are functions of the voltage at the node it-
self, then one equation is no more sufficient: one must write equations like
the equation (3.8) (page 33), one for each node, and the solve them with
standard solving algorithm for non–linear equations. The only difference
among the equations applied at the nodes above the first and the first node
equation is that not all of the cases of equation (3.9) are possible: in par-
ticular these conditions apply only when the transistor can pass from the
saturation region to the linear region, and moreover, only when the input
rising time τi1 can assume whichever value. The passage from saturation to
linearity can be made only by the first and the last transistors of the chain,
as they are the only that can saturate3 . But in the last transistor, the time τiN
is governed by τiN = τoN−1 , giving thus only two possible cases:
These conditions can never verify in a real circuit, since they imply that
the voltages at the source node and at the drain node of the last transistor
3
This is because they are the only that have a full voltage swing at some node, e.g. the
gate node the first, and the drain the last. All the transistor in the middle of the chain
are prevented to saturate by the body-effect, that makes the saturation condition VDS =
VGS − VT , (or, better, the equation (3.3), page 24) impossible.
36 Chapter 3. A complex model
All the other transistors, that can not saturate during the switching from
off to on, have only one possible working condition, again that the voltages
at source and drain nodes do not cross:
j j
τi 6 τ o j = 2, . . . N − 1
j
Solving all the equations, one for each node, the unknowns τo can be
evaluated, giving thus an estimate of the voltage waveform at each node
of the chain. The rising/falling time of the last node of the chain gives also
the delay of the chain itself.
The contribution to the power dissipation due to the charge and dis-
charge of internal nodes for each MOSFET can be defined as the integral of
the voltage across the MOSFET times the current flowing through.
Theorem 3.2. The switching energy in generic n–networks and p–networks can
be written as:
1 N i 02
2 i∑
00 2
Eswn = C V i − Vi (3.11)
=1
1 P
2 2
Esw p = ∑ C j VDD − V j − VDD − V j
0 00
(3.12)
2 j=1
where Ci is the generic total capacitance of node i-th and Vi0 , Vi00 are, re-
spectively, the initial and final value of the voltage swing at the same node.
3.3. Power estimation 37
Corollary 3.2.1. If the voltage swing of each node of the network is the full swing
∆V = VDD − 0, then equations (3.11), (3.12) can be written as:
1 N i 2
2 i∑
Eswn = C ∆V (3.13)
=1
1 P i 2
2 i∑
Esw p = C ∆V (3.14)
=1
Proof of theorem 3.2. Since the internal voltages and currents are known from
the delay analysis, the energy for the n–MOS network can be written by
summing all the contributions of internal nodes (see figure 3.3)
N Z h i
Eswn = ∑ i+1
VD n
(t) − VD
i
n
(t) i
ID n
(t)dt
i=1
Z N −1 h i
Eswn = VDNn (t)ID
N
n
(t) + ∑ i
VD n
(t) i
ID n
i+1
(t) − ID n
(t) dt (3.15)
i =1
i
dVD
i+1 i
ID − ID = Ci n
n n
dt
and, in particular, if we neglect the current of the p–MOS chain above the
node N,
dVDNn
− IDNn = C N .
dt
Thus, for the n network it is possible to define the Eswn energy in the
following way:
38 Chapter 3. A complex model
N Z t00 i
dVD
Eswn = − ∑ C
0
i i
VD n
dt
i=1 t00
n
dt
N Z V 00
=−∑C
i
i i i
VD n
dVD n
i=1 Vi0
1 N
2 i∑
i 02 00 2
= C Vi − Vi
=1
If we integrate the equation (3.11) (page 36) only when the argument of
the integrals are non zero, then the first integral in this equation goes from
i (ti ) to
t00 = t0i n to t000 = τoin , so that the second integral goes from Vi0 = VD n 0n
1
i (τ i ). Since V i (τ i ) = 0, we have E
Vi00 = VD n on Dn o n swn = 2 ∑iN=1 Ci Vi0 2 , where Vi0
is the actual voltage swing at the node i.
P Z t00 dV i
∑C
0 j Dn
j
Esw p = VDD − VD p dt
j=1 t00 dt
P Z V 00
∑C
j j j
j
= VDD − VD p dVD p
j=1 V j0
2 2
1
2∑
0 00
= C j VDD − V j − VDD − V j
j
j j j
Again, V j0 = VD p (t0i n ) and V j00 = VD p (τo p ), and in the same way V j00 =
VDD , so that Esw p = 12 ∑ Pj=1 C j (VDD − V j0 2 ), where (VDD − V j0 2 ) is the voltage
swing at the node j.
In the equations (3.11) and (3.12) (page 36) the voltage variation of ca-
pacitance must be included, obtaining expression for Eswn, p slightly more
complicated, but still in closed form.
3.3. Power estimation 39
Z τo
Esc = VD ID dt
t0
Since voltage swings, internal currents and capacitances are known from
the delay analysis, the power supply dissipation does not require addi-
tional computations.
W kT qVDS
− ξ kT
IDSsub–th = µ0 Q(VS ) 1 − e
L q
where
s
kT qs Na q(VGξ kT
−VT )
Q(VS ) ≈ − e
q |Φ p |
and
s
1 s Na
ξ =1+ .
2Cox |Φ p |
ligible. However, with the scaling down of the dimensions and hence of the
threshold voltage this current may become no more negligible, and with
low VG and higher VD , the current becomes independent from VG .
Moreover, while the short–circuit current is limited by the switching times
of the circuit, the sub–threshold current is not limited in time, so its dissip-
ation can be comparable to the short–circuit dissipation.
3.4 Results
The circuit in figure 3.2 with 2 n–MOS and 2 p–MOS transistors (in a
0.7 µm technology) has been simulated using HSPICE (level 6) and the pro-
posed model, for each combination of MOSFET widths from 1 µm to 100 µm.
Figure 3.9 shows the comparison between delay (defined as the delay at
50% between an input rise ramp of 200 ps and an output falling ramp)
calculated by the model and the delay simulated by HSPICE for each com-
bination of widths among 5 µm and 30 µm; similarly figure 3.10 shows the
comparison between the energy dissipated (during the output discharging)
by the circuit calculated by the model and by HSPICE.
The errors between the proposed model and the HSPICE simulation is
reported in table 3.1 while table 3.2 shows corresponding execution time.
These results are taken from the analysis of the circuit varying the dimen-
sions of the MOSFETs continuously from 1 µm to 100 µm.
3.5. Conclusions 41
3.5 Conclusions
Delay Model
Delay [ps]
180
160
140
120
100
80
60
40
20
30
25
5 20
10 15 W2 [micron]
15
20 10
W1 [micron] 25
30 5
Hspice Simulation
(b) HSPICE
Fig. 3.9: Delay of the circuit 3.2 with several combination of W1 and W2 .
3.5. Conclusions 43
Energy Model
Energy [fJ]
1000
900
800
700
600
500
400
300
200
30
25
5 20
10 15 W2 [micron]
15
20 10
W1 [micron] 25
30 5
Hspice Simulation
(b) HSPICE
Fig. 3.10: Energy dissipated by the circuit of figure 3.2 with several combin-
ation of W1 and W2
Part III
OPTIMIZATION
Chapter 4
MATHEMATIC OPTIMIZATION
min f (x)
x∈ X
this is also known as an unconstrained optimization, since there are not any
constraints on the values the function f may assumes.
where the n equations gi (x) ≤ hi constitute the set of constraints of the op-
timization.
The function f is also called the objective of the optimization, or the cost
function of the problem.
min f i (x), i = 1, 2, . . . , n
x∈ X
4.1. Optimization theory 49
n
f tot (x) = ∑ αi fi (x), αi ∈ R
i=1
The existence of the minimum (at least one) is granted by the Weierstrass
Theorem1 , but these minimums can be local or global:
Definition 4.7 (Local Minimum). The point x? ∈ X is a local (or relative)
minimum of the function f iff
∃ > 0 : f (x) ≥ f (x? ) ∧ ∀x ∈ X |x − x? | < .
1
iff X is a compact set, as is in this context
50 Chapter 4. Mathematic Optimization
i) dT · ∇ f (x? ) ≥ 0;
i) dT · ∇ f (x? ) = 0
ii) dT · ∇2 f (x? ) · d ≥ 0
The conditions of the corollary 4.1.1 are necessary and sufficient con-
ditions for the existence of the minimum (local). In order to have some
information about the existence of a global minimum, the theory of convex
functions must be very briefly reported.
If in the equation (4.1) the sign < applies, then the function is said to be
strictly convex.
∇2 f (x) ≥ 0, ∀x ∈ X
The convex functions are a very useful mathematical tool in the class of
optimization problem, mainly for the next two results:
Theorem 4.15. If f : X → Y is convex over a convex set X, the set A of the min-
imum of the function is convex, and every local minimum is also a global min-
imum.
The theorem 4.16 also implies that the conditions of the lemma 4.10 and
corollary 4.10.1 (first order conditions) are both necessary and sufficient
conditions for the existence of a global minimum.
All the previous results are, almost in theory, sufficient to solve the
problem 4.2. The theory of the convex function ensures the existence of
a global minimum, while lemma 4.10, corollary 4.10.1, and theorem 4.16
suggest a method to find this minimum. We will see in §5.1 how these
methods apply to real circuits, in which, for example, the functions deriv-
ative are not available.
52 Chapter 4. Mathematic Optimization
m
L(x, λ) = f (x) + ∑ λi gi (x) (4.2)
i=1
then we can write the necessary Kuhn–Tucker conditions for the existence
of the minimum:
∇x L(x? , λ? ) = 0 (4.3)
? ?
∇λ L(x , λ ) ≤ 0 (4.4)
? T ?
(λ ) g(x ) = 0 (4.5)
λ? ≥ 0 (4.6)
ii) gi (x? ) ≤ 0, i = 1, 2, . . . , m
It can be proved that if the functions f , g are even not differentiable but
are convex, then the saddle-point conditions are necessary and sufficient
conditions. Although these conditions must hold at the minimum, they are
not very useful in determining the optimum point. The determination of
the optimum by direct solution of these equations is rarely practicable.
m
P(x, K) = f (x) + ∑ Ki [gi (x)]2 (4.7)
i=1
The sum added to the objective function is called penalty function, since it
penalizes the objective function adding a positive quantities (recall that we
want to minimize the cost function). The constants K = [K1 , K2 , . . . , Km ]T
are weighting factors (positive) that define how strongly must be satisfied
the i–th constraint, and can also made it commensurable.
m
P(x, K) = f (x) + ∑ Ki [gi (x)]2 ui (gi ) (4.8)
i=1
The introduction of the step function makes possible to relate the pen-
54 Chapter 4. Mathematic Optimization
alty function defined in (4.8) with the Lagrangian function of (4.2) (page 52):
P(x, K) = L(λ, K)
if we let λi = Ki gi (x)ui (gi ), so that all previous results valid for the Lag-
rangian function are valid for the penalty function.
Note that the solution x? found optimizing the penalty function P(x, K)
converges to (x? , λ? ), defined by the Kuhn–Tucker conditions, only in the
limit K → ∞.
x=y iff x k = y k ∀k = 1, 2, . . . , n
x5y iff x k ≤ y k ∀k = 1, 2, . . . , n
x≤y iff x 5 y and x 6= y (so ∃k : xk < yk )
x<y iff x k < y k ∀k = 1, 2, . . . , n
y1 ≺ y2 iff y1 ≤ y2 .
N({≺}, Y) = {y0 ∈ Y | @y ∈ Y : y ≺ y0 }
D({≺}, Y) = {y0 ∈ Y | ∃y ∈ Y : y ≺ y0 }
We will give now two theorems that are fundamental for the solution of
the multi-objective optimization problem; first we introduce the definition
of convex cone in Rn :
Notation 4.23 (convex cone).
This very important theorem (and its corollary) states that if y0 minim-
izes a linear weighted function λ · y (for some λ), then y0 is a Pareto optimum.
This reduces the problem from a multi-objective one to a mono-objective
one, i.e. is sufficient minimizes a linear weighted function of the cost func-
tions.
Note that:
∂ yi λj
=−
∂yj λi
λj
so the ratio λi is the trade-off exchanging an unit-gain in the variable y j with
an unit-gain for the variable yi . Finally, note that the theorem is valid for
any shape of Y.
4.1.2.1 Unconstrained
4.1.2.2 Constrained
Again, the solution is to reduce the complexity of the problem from the
multi-objectivity to a mono-objective one. It is possible to combine the two
previous methods, that is to minimize a linear weighted function plus a
sum of penalty function; the only critical point is to ensure the same order
of magnitude of each term of the sum, such that there is not a dictatorship
of one term of the sum. The third chance to solve an unconstrained problem
(or a constrained, but with some care) is to use the method of the compromise
solution:
r(y) = ky − y? k;
typically, the L p –norm (the distance between the actual solution and the
ideal point) ) it is used:
" # 1p
n
r(y) = r(y; p) = ∑ | yi − yi? | p .
i=1
" # 1p
n
∑
p
r(y; p, w) = wi | yi − yi? | p .
i=1
When the ideal point is not known, one can use an approximation, or,
even, a constraint; in the latter case the more appropriate term is satisfying
level. To point out the differences between constraints and satisfying level,
one must observe:
3 ∂f f (x + ∆x) − f (x)
Essentially with (x) ≈
∂ xi ∆x
4.2. Optimization Algorithms 59
We show some algorithms, that are the most efficient in this field. First
we introduce the family of sectioning algorithm, from which the the golden
section search is probably the most suitable for our uses. Then we introduce
the Brent’s rule, a quadratic interpolation algorithm.
The algorithms of sectioning apply always the same policy: divide and
conquer. The initial interval [a, c] is reduced at each iteration to a smaller
interval, already bracketing the minimum x? . We have so a series of encap-
sulated intervals (see figure 4.1)
lim Ik = I0 ,
k→∞
where I0 = (c − a).
So the relative uncertainty on the minimum x? is .
60 Chapter 4. Mathematic Optimization
I0
I1
I2
a0 b0=a 1 b1 =c 2 c0 =c1
I1 + f k−2
Ik =
fk
The golden section search Given a triplet (a, b, c) that brackets the min-
imum, we choose a new point x that defines a new bracketing triplet (a, x, b)
or (b, x, c) according to the rule:
x−b b−a
=1−2
c−a c−a
4.2. Optimization Algorithms 61
This implies that |b − a| = |x − c|, and that at each iteration the interval is
scaled of the same ratio λ.
Then we repeat the process with the new triplet. So the interval (a, c) is di-
vided in two parts, a smaller and a larger, and the ratio between the whole
interval and the larger is the same between the larger and the smaller, or in
other words:
1 λ
= ,
λ 1−λ
Ik+1
0≤ ≤ 1.
Ik
Ik+1
lim .
k→∞ Ik
Ik+1 1
lim = .
k→∞ Ik 2
For the Fibonacci search, first we must write the generic number of the
Fibonacci sequence in a closed form:
62 Chapter 4. Mathematic Optimization
√ ! k +1 √ !k+1
1 1+ 5 1− 5
fk = √ − .
5 2 2
Ik+1
For the golden section search, as previously said Ik = λ, so
√
I 5−1
lim k+1 = λ = .
k→∞ Ik 2
Thus the convergence rate of the Fibonacci and the golden-section search are
identical.
This method is useful only when the function is quite smooth in the in-
terval, but it has the advantage that the convergence is almost quadratic,
and it is perfectly quadratic when the function to be optimized is a quad-
ratic form.
The Brent’s rule The Brent’s rule is a mix of the last two techniques: it
uses the golden section when the function is not regular and switches to a
parabolic interpolation when the function is sufficiently regular. In particu-
lar, it tries always a parabolic step. When the parabolic step is useless then
4.2. Optimization Algorithms 63
The method of the steepest descent chooses at each iteration a new point
in the decision space x + dx from the old point x, obviously such that:
This new point must also be chosen such that the variation of the function
f is as more as possible. In other words, if dl is the length of the direction:
s
n
dl = ∑ (dxi )2 ,
i=1
n n
df ∂ f dxi
max ∑ = max ∑ ,
i=1
dl dx i i=1 ∂ xi dl
dl
such that
s
n
dl = ∑ (dxi )2 .
i=1
64 Chapter 4. Mathematic Optimization
This problem can be solved with the Lagrangian multipliers; from equa-
tions (4.3) and (4.4) (page 52) we can write:
dxi 1 ∂f
= ,
dl 2λ ∂ xi
with
n 2 12
1 ∂f
λ=−
2 ∑ ∂ xi
.
i=1
This means:
∂f
(x)
dxi ∂ xi
(x) = − (4.9)
dl n 2 12
∂f
∑ ∂ xi (x)
i=1
∆x = dl k ∇ f (xk ).
Thus:
h iT
f (xk + dl k ∇ f (xk )) = f (xk ) + dl k ∇ f (xk ) ∇ f (xk ) +
1 h iT
+ (dl k )2 ∇ f (xk ) H(xk )∇ f (xk )
2
df h iT h iT
k k k k
= ∇ f (x ) ∇ f (x ) + dl ∇ f (x ) H(xk )∇ f (xk ) = 0 (4.10)
dl k
4
The Hessian matrix of a function f (x1 , x2 , . . . , xn ) is defined as:
2
∂ f ∂f
∂ x21 ∂ x1 ∂ x2 · · · ∂ x∂1 ∂f xn
∂f ∂2 f
∂ x2 ∂ x1 ∂ x 2 · · · ∂ x∂2 ∂f xn
H( f ) =
. .
2
.
. . . . . .
. . .
∂f ∂f ∂2 f
∂ xn ∂ x ∂ xn ∂ x
1 2
· · · ∂x 2
n
66 Chapter 4. Mathematic Optimization
and
" #
− ∇ f (x k ) T ∇ f (xk )
dl k = T . (4.11)
∇ f (xk ) H(xk )∇ f (xk )
df
From dl k
(xk+1 ) = 0, we can see that:
∇ f (xk + dl k ∇ f (xk )), ∇ f (xk )) = 0,
that is ∇ f (xk )) and ∇ f (xk+1 )) are orthogonal, or, the same, xk and xk+1
are orthogonal. This means that successive steps of the optimal gradient
algorithm are orthogonal.
lim ∇ f (xk ) = 0.
k→∞
∂f ∂f
n 1
df n
∂ f dxi ∂ xi ∂ xi ∂f 2 2
=∑ = − 1 = − ∑ ∂x (4.12)
dl ∂ xi dl n
i=1 ∂f 2 2 i=1 i
∑ ∂ xi
i=1
df
Thus ≤ 0, or the function f decreases along the path dl.
dl
Lemma 4.31. The convergence of a descend method along the gradient path can
not be obtained in a finite number of steps.
4.2. Optimization Algorithms 67
n 1
df ∂f 2 2
=− ∑
dl i=1
∂ xi
∂f
lim? (x) = 0
x→ x ∂ xi
so that
df
lim (x) = 0
x→x? dl
meaning that the optimum is reached with a rate convergence that de-
creases.
For the optimal gradient method the convergence is only linear5 in f (xk )
and a halting criterion for the algorithm could be:
f (xk ) − f (xk+1 ) ≤ ;
n 2
∂f k ∂f k
max |
i ∂ xi
(x )| ≤ or ∑ ∂ xi
(x ) ≤
i=1
Finally note that these methods, since they use a local gradient inform-
ation, they find only a local minimum, and that the gradient algorithms are
rather inefficient in the proximity of the optimum, due to the small step
size.
The figure 4.2 shows 20 iterations of the Powell algorithm to find the
minimum (located at x = 30) of a mono-dimensional function ∼ x4 . As it
can be see, the algorithm finds the minimum at x = 31.7 and it is not fooled
by the presence of a local minimum at x = 10. The figure 4.3 shows 24
iterations to find the minimum (located at x = 15) of a more complicated
70 Chapter 4. Mathematic Optimization
80
f(x}
Powell
70
60
50
40
30
20
10
Sol
0
0 5 10 15 20 25 30 35 40 45
The slop algorithm ([16]) is a simple algorithm, suitable for the minim-
ization of a particular function of a digital circuit, the delay. It is feasible
for smaller circuit, since it has no heuristics in reaching the minimum, and
also it stops at the first minimum it finds.
The idea behind the algorithm is simple: start from a given point x0 <
x? , the increment at each iteration a single component of x0 by a defined
step. For each increment track the diminution of the objective function,
then conserve memory only of the increment that give the best diminution.
Finally, use this increment as a new starting point.
Clearly, this algorithm works only if the starting point is x0 < x? (see nota-
tion 4.18), so that an increment in one component moves the function f
near the minimum. Also at the first minimum encountered the algorithm
4.2. Optimization Algorithms 71
h(x}
140 Powell
120
100
80
60
40
20
Sol
0
0 20 40 60 80 100 120
stops.
80
f(x}
Slop
70
60
50
40
30
20
Sol
10
0
0 5 10 15 20 25 30 35 40 45
80
f(x}
Anneal
70
60
50
40
30
20
10
Sol
0
0 5 10 15 20 25 30 35 40 45
The same function of figures 4.2, 4.3 are shown in figures 4.5, 4.6, min-
imized by the simulated annealing algorithm. As in the case of Powell
algorithm, the simulated annealing it is not fooled by the presence of local
minima, but the number of iterations is greater for both the functions: 130
in the first case, 200 in the second one.
74 Chapter 4. Mathematic Optimization
h(x}
140 Anneal
120
100
80
60
40
20
Sol
0
0 20 40 60 80 100 120
4.3 Conclusions
After all this mathematic theory, some words must be spend about the
choice of which algorithm it is feasible to use.
CIRCUIT OPTIMIZATION
There are, mainly, three target policies in optimizing real circuits: min-
imize the delay, minimize the power consumption and minimize the area
occupancy. In some cases these policies can be conflicting among them, as,
for example, minimizing the delay surely increases the circuit area, while
ins some cases these policies can go together, as, for example, minimizing
the power consumption may lead to a reduction of the area occupancy.
Till now the generic word “delay” has been used, but now it is mandat-
ory to better define the meaning of delay in a real circuit.
VIN
50% VIN
time
OUT Delay = t o - ti
VOUT
50%VOUT
time
ti to
generally a circuit has more than one input and more than one output;
not always there is a direct path from the input to the output (let’s
think about dynamic logic), i.e. not always a change in an input cause
directly a change in the output.
Critical Paths The idea of critical paths in a CMOS circuit can be derived,
intuitively, from the idea of path between the the output and the input: a
critical path is a conducting path between a node (the “output” node, i.e.
the final node of the path) and the ground, or between this node and the
power supply, such that a change in the state of an input gate of a MOSFET
comprised in the path causes directly a change in that node. Naturally each
MOSFET included in the path must be on, or switch to, conduction, in order
to create a conducting path.
This concept must be extended, however, since a change of the so called
output node can cause itself a change of another critical path (i.e. the output
node is itself connected to a gate of another critical path), so that a change
in a gate node in the very beginning of the circuit may propagate through
a lot of conducting paths.
Definition 5.1 (Critical path). A critical path is a set of conducting paths such
that:
iii) a change in the state of any MOSFET gates in the first conducting path
propagates till the last conducting path, causing a change in the critical
path output node.
Definition 5.2 (Critical path delay). The delay of a critical path is the delay
between the output node of the critical path and the gate node causing the
state change of the output node.
5.1. Optimization targets 81
From the definition 5.1 it is clear that even a simple circuit has more
than one critical path in it 1 .
G = {set of all the MOSFET gate nodes in the circuit} = g1 , g2 , . . . , g j , . . .
N = {set of all the nodes in the circuit} = n1 , n2 , . . . , n j , . . .
O = {set of all the output nodes of the circuit} = o1 , o2 , . . . , o j , . . .
I = {set of all the input nodes of the circuit} = i1 , i2 , . . . , i j , . . .
M = {set of all MOSFETs in the circuit} = m1 , m2 , . . . , m j , . . .
V = {gnd=ground node, vdd=power supply node} ;
let’s define also the set Nm j as the set of all the nodes pertaining to the
MOSFET m j , and the gate of the j–th MOSFET with gm j .
All these sets are in such relations: I ⊆ G ⊂ N , V ⊂ N , O ⊆ N \ G.
1-2-4-5-11
11
6 1-3-4-5-11
C
5 1-7-8-5-11
A B
4 9-10
8 10
B C C
2 3 6
7 9
11
1
CLK
(and the others are all at the high state), then the gate of p-MOSFET 11 is dis-
charged, and this p-MOSFET conducts, charging the output node. Another
critical path for example is the one composed only by the p-MOSFET 6: if
its gate switch from high to low, then the gate of n-MOSFET 9 switch form
low to high, but this can not produce the discharging of the output node,
since the gate of n-MOSFET 6 is driven by the same signal of the original
p-MOSFET.
Note. The definition of critical path can be viewed as a tree rooted at the
transistor that is driving the change in the critical path. One leaf of the tree
is the transistor which drain (or source) is the critical path output node. So
it is possible to traverse the tree between the root (the input) and a leaf (the
output): if one is able to model all the lateral subtree encountered during
the traversing of the tree as static load, then the tree becomes a transistor
chain (figure 5.4). This is the base of the use of several delay models that
are able to evaluate a chain delay.
TREE CHAIN
OUTPUT OUTPUT
INPUT INPUT
td = max {d(Cn )}
n
where d(Cn ) is the delay of the n–th critical path comprising in the cir-
cuit.
So, finally, in order to known the delay of a circuit, one must search
all the critical paths in the circuit, calculate (or measure) the delay of each
critical path, and calculate the max of these delays.
The delay function obtainable by the Elmore’s model (§2.1, page 16) is a
continuous function. Referring to figure 2.1 (page 15), the delay of a single
MOS is:
The drain and source capacitance, and the dynamic resistance of a MOS
are function of the MOS width W:
4
The reason why we want to define a single value for the optimization of delay and, for
example, we do not apply the multi-objective methods of the following sections, is that all
the critical path delay are commensurable and they have the same global behaviour (cfr.
§5.2.3, page 102)
5.1. Optimization targets 85
CDi = C j Wi
CSi = C j Wi
Rj
R di =
Wi
where C j and R j , are, respectively, the capacitance for unit length and the
resistance for unit length. The delay function of the MOS width become:
Rj Rj
tdi = R0 C j Wi + R0 + C j Wi + R0 + + R L CL .
Wi Wi
Separating the terms containing the width W j from the terms that are
independent from W j we obtain:
Rj
tdi = 2R0 C j Wi + CL + R j C j + (R0 + R L )CL .
Wi
Summing the delay of all the MOS in a conducting path we obtain the
total delay of this path:
B
t d = ∑ t di = ∑ AWi + +C
i i
Wi
The delay of a critical path is the sum5 of the delays of all the conducting
path.
Note that the term A is zero, practically, only if the the resistance R0 is
5
This definition introduces further errors in the delay model, since the conduction of the
conducting path successive to the first one does not start when the output of the first one is
at its 50%, but long before.
86 Chapter 5. Circuit Optimization
td
t min
Wmin Wj
The figures 5.7, 5.8 represent the delay of CMOS inverter, increasing in
an uniform manner the dimension of both the n-MOSFET and the p-MOSFET.
The first figure shows the delay of the inverter driven by another inverter
(with fixed dimensions) simulated by HSPICE; the second figure shows the
delay of the same inverter driven, instead, by an ideal voltage source and
simulated by FAST.
These are an experimental proof of the statement given in the previous sec-
tion: if the voltage source is not ideal, that is dependent from the MOSFET
widths of the circuit, the delay curve is strictly convex (figure 5.7), while if
the voltage source is ideal, i.e. independent from the MOSFET widths, then
6
It is possible, however, after measuring a set of delay varying with widths, to fit the
results with an approximated formula, now in a closed form.
5.1. Optimization targets 87
td
Wj
So, definitively, the delay curve is a convex function, strictly or not, de-
pending of the operating condition of the circuit, of all the MOSFET widths8 .
7
The interconnection delay can be seen, in second approximation, as proportional to the
MOS widths, since greater widths means greater circuits, and in a layout this means that the
average length of interconnections increases also. This proportionality (empirically found
linear to quadratic) does not modify the delay function, since it adds a term that is both an
increasing and a convex function.
8
The two dimensions representation of figures 5.5, 5.6, 5.7 and 5.8 is only for the sake of
simplicity of the drawing. The convexity is still valid in multi-dimensional representations.
88 Chapter 5. Circuit Optimization
260
Delay
240
220
200
td [ps]
180
160
140
120
100
0 10 20 30 40 50 60
Wj [um]
Pd = max { p(Cn )}
n
where p(Cn ) is the power consumption of the entire circuit when the
9
In first approximation the power consumption could be the sum of the power dissip-
ated by each critical path in a fully static CMOS circuit.
10
The same reasoning of note 4 (page 84) applies here.
5.1. Optimization targets 89
80
Delay
75
70
65
td [ps]
60
55
50
45
0 10 20 30 40 50 60
Wj [um]
this means that the calculation of the mean energy dissipated by a circuit is
the integral average of the power and it depends from the simulation time
(or the window of time that we are considering), but it does not depends
from the frequency of the signals at which the circuit itself operates.
The power consumption of a CMOS circuit is the sum of three term (§3.3,
page 36):
70
Energy
60
50
40
Energy [pJ]
30
20
10
0
0 10 20 30 40 50 60 70
Wj [µm]
The three terms of equation (5.2) do not weight equally in the sum giv-
ing the energy consumption: in order of influence the first term (§3.3.1,
page 36) is the greater, then comes the second term (§3.3.2, page 39) , and
finally the third term (§3.3.3, page 39) . For a sub-micron technology the
second term (the short-circuit dissipation) is about 10% of the first, with
the third term (sub-threshold conduction dissipation) about 1% of the first.
It could be expected than with the scaling of the technology (in the deep
sub micron field) the first and the second term become comparable, with
5.2. Optimization examples 91
the third term still a fraction of the other two, giving a power figure not
increasing (or even decreasing) with the MOS widths, but also it could be
expected that with the scaling down the interconnect capacitances become
predominant, making the first term (the power dissipation due to capacit-
ance charging and discharging) still the greatest.
5.1.3 Area
A = ∑ α j W j + β. (5.3)
j
paths in a gate, and the third column showing the total number of MOSFET
in a gate. The last two gates are dynamic full-adder, the former composed
by complex gate in order to perform the computation in one stage, while
the latter is composed only by basic gates (and, or and inverter): this ex-
plain why the last full-adder has much more transistor than the first one.
The table 5.2 shows the delays and the energy consumption of the gates
of table 5.1: for each gate it is shown the maximum delay, the average delay,
the maximum energy and the average energy of all critical paths. All the
simulation are made at the minimum width for that technology (viz. 1 µm
14
For a schematic of the static “and” and the static “or” see figure 5.14: the “and” is the
first gate of the schematic (on the left side of the picture), while the “or” is the last but one
gate, before the final inverter (on the right side); for a static and see also the figure 5.12,
page 96.
Tab. 5.2: Basic gates: pre-optimization delay, power consumption and area
Static and 760.9 727.7 0.7224 0.7160 4. 8 277.2 240.1 0.0907 0.0891 2.4
Static or 1430 776.3 0.75 0.7114 4.8 233.7 89.3 0.0713 0.0434 2.4
Static parity
2650.0 1839.55 0.7442 0.676 57.6 922.2 582.5 0.0944 0.0863 28.8
gate
Static full-
1781 1080.6 6.475 1.219 48.0 571.3 311.3 3.155 0.324 24
adder
TSPC full-
adder 930.6 681.9 2.168 0.9425 15.6 276.7 204.2 0.641 0.188 7.8
(one-stage)
93
TSPC full-
adder 2691 .0 556.4 8.893 3.82 151.2 482.3 79.9 5.27 1.999 75.6
(basic cells)
94 Chapter 5. Circuit Optimization
A
OUT=A
for the 0.7 µm technology and 0.5 µm for the 0.25 µm technology).
Given the results of section 4.2 (page 58), and the results of the above
sections regarding the property of delay, power and area functions in real
circuits, the most suitable algorithm to be applied is the Powell’s scheme.
Briefly, it is fast, reliable, even in presence of multiple minima, and (per-
haps first of all) it does not require the knowledge of the first derivative of
the function to be minimized.
While some other algorithms could give the same quality of accuracy in
finding the minimum (namely the simulation annealing algorithm is prac-
tically the only one), the Powell’s one outperform all the others in the terms
of number of iteration, and hence in execution time, reaching the best solu-
tion.
The Powell’s algorithm is the first choice in all the optimization ex-
amples found in this chapter. As an example, performing the same optim-
ization of table 5.3 with the simulated annealing will require an execution
time by the optimizer15 of about ten times of that required by the Powell’s
algorithm.
15
For a complete description of the optimizer cad tool see chapter 6, page 107.
5.2. Optimization examples 95
CLK
OUT
A
(a) Type n
CLK
OUT
(b) Type p
5.2.2.1 Area
CLK
A OUT=A B
(a) Type n
CLK
B
A
OUT=A B
(b) Type p
5.2.2.2 Power
The power optimization worths some more words: all the attempts to
optimize exclusively the power of the gates of table 5.1 in spite of the delay
have led to the same result, for both technologies: all the transistors in the
circuit had the minimum width after the optimization. This outcome will
arise whatever would be the starting point of the optimization session, i.e.
the initial transistor widths of the circuit.
This is an experimental proof that, out of the three terms of equation (5.2)
(page 89), the term of the switching power Pswitch , due to charging and dis-
5.2. Optimization examples 97
CLK
OUT=A + B
A B
(a) Type n
CLK
B OUT=A + B
(b) Type n
5.2.2.3 Delay
Given the results of the power optimization (and the simple results of
area optimization), the only “mono”-optimization feasible is the delay op-
8
Chapter 5. Circuit Optimization
9
12 7
13
11 10 C
A OUT
B
6 0
4 3
1 2
5
Fig. 5.14: Static and-or gatea .
a
This gate performs the action A · B + C, but there are two inverters between the and and the or. These leave intact the logic function, but introduce
some complexity in the critical paths formulation: it is only for this purpose that these inverters have been introduced.
98
5.2. Optimization examples 99
4 4 4
5 5 5
D D
0 0 2 2 2
1 1 3 3 3
C C C C
B B B B
. . .
/ / /
A A
A A
* * * ( ( (
+ + + ) ) )
B B B B
& &
' '
$ $ $
% % %
C C C C
"# !
, , ,
- - -
D D
timization.
That it is the maximum delay of critical paths is minimized, disregarding
the power consumption and the area occupation, which both increase as
the delay diminishes.
A
B A
C
B A
C
CARRY
B A
B A
SUM
C C
A A A A
B C
C
B B B B
100
CARRY
CLK
B A
SUM
C C CLK
B C
A A A A
C
B B B B
5.2. Optimization examples
CLK
the delay: it is possible to see how the power increases after the delay is
minimized.
The criterion that judges when the optimization is over is based on two
considerations (see chapter 6, page 107 for more details on the algorithms
implementation, and chapter 4, page 47 for mathematical foundations):
ii) if the delay figure is not strictly convex (i.e. is monotone decrescent),
then the optimization algorithm goes on minimizing till the rate of de-
creasing of the delay is below the accuracy.
The former case is more stable from the point of view of the accur-
acy: given an accuracy, the same optimum solution is found independ-
ently from the starting point (i.e. the initial transistor widths) — the start-
ing point influences only the time it takes to reach the solution, which is
unique.
The latter case is somewhat more problematic, since the solution is depend-
ent from the starting point: the decreasing rate of the delay is dependent
from the starting point in the multi-dimensional space delay vs. widths.
This means that several optimization sessions can give different results,
depending on the initial transistor widths in each optimization.
the power, or the power and the area, and so on. From §5.2.2.1, §5.2.2.2
and §5.2.2.3 we have seen that some of these goals clash. These clashes are
briefly summarized in table 5.4.
So, for example, optimizing together delay and power, i.e. minimizing
both, it is not possible: the power is minimized when all the transistors
are at minimum width, while minimizing the delay involves to have some
transistors (maybe all) at a width greater than the minimum.
This disagreement among some optimization targets leads to new possible
definition(s) of “multi-objective” optimization:
ii) there are only primary targets, and each target account into the total
objective function with a relative weight, which indicates how much
the final solution should depend on the corresponding target; or
The most suitable policy is the second, because it gives to each target
the same priority with different importance. The first alternatives leads
to a sub-optimal optimization since: first, the designer must know which
are the order of magnitude of the targets, in order to impose a limit on
them; second, not the whole space of solutions may be explored with such
constraints.
In the case of primary target with relative weights, we have chosen the
sum of relative weights to represents the entire normalized objective func-
tion, that is the sum of relative weights must be equal to one.
104 Chapter 5. Circuit Optimization
Given the results of §4.1.2 (page 54) then the total objective function to be
minimized is a linear combination of the delay (D ), power (P ) and area (A ):
O = αD + β P + γ A , (5.4)
α ≥ 0, β ≥ 0, γ ≥ 0, α+β+γ =1
From the point of view of the user of the optimizer, specifying this kind
of weights means to have the possibility to see this weights as a measure
of how much the corresponding target matters in the final solution: for
example specifying α = 0.5, β = 0.5 and γ = 0 means that we want to op-
timize the delay at the 50% and the power at the 50%.
The subtle point in the eq. (5.4) is that the quantities D , P and A are
not commensurable, that is order of magnitude of the quantities may not be
same. Let’s think only to the unit of measure: if, for example, the delay
is measured in picosecond (e.g. 1000 ps), the power is measured in Joule
(e.g. 10−13 J). When one quantity is very greater than the others, then all
the changes in the latter quantities disappear in the total sum.
Thus the normalization applied here is the division of each quantity for
5.2. Optimization examples 105
its corresponding maximum: a maximum of the delay occurs when all the
transistors are at minimum width, while the maximum of the power and of
the area is measured when all the transistors are at the maximum allowed
width in the optimization session (being careful that choosing a too large
maximum allowed width will result in a power and area term too little).
D P A
O=α +β +γ . (5.5)
D |min widths P |max widths A |max widths
If for, for example the same full-adder of table 5.3 (page 99) are optim-
106 Chapter 5. Circuit Optimization
ized both for delay and for power in the same measure, i.e. in equation (5.5)
α = 0.5, β = 0.5 and γ = 0, we obtain the results of table 5.5.
The comparison of the full delay optimization (mono-objective) and delay–
power optimization (multi-objective) is sketched in table 5.6: as we can
see between the full-delay optimization and the power–delay optimization
(50%–50%) there is a slightly worsening in the delay of the final circuit
(from 5.2% to 46.9%); at the same time there is an effective improvement
in the power consumption: the power dissipation decreases from 5.8% to
76.5%.
5.3 Conclusion
This chapter first defines which are the targets of optimization, and then
it applies the mathematical theory of chapter 4 (page 47) to the optimiza-
tion of real circuits.
It has been shown how the only mono-objective optimization feasible by
means of transistor dimensions trimming is the delay minimization, since
both the minimization of area and power consumption lead the quasi-obvious
solution of all transistor at the minimum width allowed by the technology
or by the designer.
For every other detail refer to appendix A and B (page 145, 149).
The core of the tool, the optimization engine, receives the input from
two modules: the optimization algorithm module (OAM), where different
optimization strategies can be selected, and the function evaluation module
(FEM), including the models for delay, power, and area estimation.
Grad.
SLOP Powell
descent
Constraints
Parser Optimization
constraints
Circuit
Description
(human readable)
each step the size of a single gate, chosen according to the best pos-
sible reduction of the delay along the critical path.
For all the chosen methods, the analytical knowledge of the objective
functions and their derivatives is not required, but just numerical approx-
imations are exploited.
However methods requiring the gradient evaluation (e.g. the Fletcher–
Reeves–Polak–Ribiere version of conjugate directions algorithm [17]) can
be also supported.
The core engine is the main module of the program. It handles the com-
munications among the others module and make the optimization feasible.
First of all, the engine parses the netlist of the circuit to be optimized,
written in a SPICE-like format. It then invokes the module that automatic-
ally searches all the critical paths in the circuit, and finally it invokes the
optimization algorithm.
110 Chapter 6. A CAD tool for optimization
The whole tool has been written in C++. All the classes of the program
are showed in appendix A and all the code details can be found in ap-
pendix B.
• CircuitNetlist
• OptimizationAlgorithm
• EvaluationAlgorithm
The first class, CircuitNetlist, and its derived Circuit, contain the
graph of the circuit, in which every node is a transistor and every edge is a
connection between two transistor.
1 class CircuitNetList
2 {
3 private:
4 ...
5
6 protected:
7 char *FileNetOut;
6.2. Code implementation 111
8 TransistorList TranList;
9 CapacitorList CapList;
10 char *FileIn;
11 double Val;
12 unsigned int ValNode;
13 public:
14 CircuitNetList( const char* FileNetList,
15 const Options& options );
16 virtual ~CircuitNetList();
17 unsigned int GetNTran() const
18 {return TranList.GetNTran(); }
19 unsigned int GetNCap() const
20 {return CapList.NumCap; }
21 double Valim() const
22 {return Val; }
23 unsigned int ValimNode() const {return ValNode; }
24 const TransistorNode& operator[]( unsigned int index ) const;
25 const TransistorNode& operator[]( const char* name ) const;
26 int TranPos( const char* name ) const;
27 };
This class provides some method to return the i–th transistor by means of
operator[], either by calling it with the relative number of transistor or
with its name. Also the class provides the methods to return the effective
power supply node (the ground node is assumed to be always the node 0).
Internally the class contains the list of all the transistors and all the capacit-
ors present in the original netlist.
The public and protected methods of class Circuit are:
60 class EvaluationAlgorithm
61 {
62 private:
63 protected:
64 const CritPathList& pathlist;
65 const Options& options;
66 unsigned int NumPath;
67 unsigned long int Calls;
68 double *CPDelay; // delay
69 double *CPPower; // power
6.2. Code implementation 113
90 class OptimizationAlgorithm
91 {
92 private:
93 ...
94 protected:
95 unsigned int InternalSteps;
114 Chapter 6. A CAD tool for optimization
This class provides the method Run() that invokes the real algorithm,
and the method SimulateCircuit(...) that performs the function evalu-
ations by means of the instance EvaluationAlgorithm& Simulation:
simply every time that the algorithm needs to perform a function evalu-
ation with new dimensions, it invokes the public method
Simulation.Run(...), passing to it the new dimensions. It provides also
the methods to return the optimization steps and the final optimized widths.
6.2. Code implementation 115
The module that performs the retrieving of all the critical paths (see
§5.1.1, page 80, for the mathematical definitions) in the circuit is subdivided
into three parts:
• the first part identifies all the input of the circuit (gate nodes connec-
ted to nothing), and all the internal gate nodes (connected to a source
or a drain of another transistor);
• the first part search all the charging paths between a node and the
power supply and all the discharging paths between the ground, for
every node in the circuit;
• the third part combines all the previous charging and discharging
paths to obtain a true critical path. The combinations is performed
controlling that the inputs permit the real activation of the path; at
the same time the module sets all the inputs at the value necessary to
obtain the excitation of the path, i.e. such that a change in the input
causes a change in the output.
In order to ensure a good flexibility of the tool, there is always the pos-
sibility for the designer to specify the critical paths to be used in the optim-
ization by hand. The standard format for them is a text file that for each
116 Chapter 6. A CAD tool for optimization
critical path lists the input node, the output node, and transition both on
the input and output node (fall or delay). It is possible in this way to list
only a part of all the critical paths present in a circuit and to take into ac-
count during the optimization only those paths.
Moreover it is possible to use the optimizer for topologies that normally
could confuse the algorithm for critical paths search, such as the pass-
transistors logic circuits.
and the class for the Powell optimization algorithm (§4.2.3.2, page 69)
is derived as:
Basically, both the classes should provide only the method Run(...)
(with different parameters, of course), that performs the real simulation or
the real optimization algorithm.
The logical flow of the function that retrieve all the critical paths is di-
vided in a few functions:
1: for all The transistors that have the source or drain connected to Node
do
2: if Source = Node then
3: Node = Drain.
4: else
5: Node = Source.
6: end if
7: Memorize the current transistor in the current list.
8: Copy the current list in a new list, in order to create a new list every
time there are more than one transistors connected at the same node.
9: if At Node are connected both n–type and p–type transistor OR Node
is already visited then
10: Return.
11: else
12: Invoke myself with Node
13: end if
14: end for
15: return all the lists of node starting from Node
Require: A List of all the charging and discharging paths and a path as a
starting point.
1: for all The charging paths do
2: Choose a discharging path that has as an input node the output node
of the first path
3: Check if the input condition are correct and eventually set them.
4: Invoke myself whit the new path as a first path.
5: end for
6: for all The discharging paths do
7: Choose a charging path that has as an input node the output node of
the first path
8: Check if the input condition are correct and eventually set them.
9: Invoke myself whit the new path as a first path.
10: end for
6.4. Conclusions 119
6.4 Conclusions
This chapter describes the implementation of the tool that is behind all
the optimizations through this thesis. It has been written in a very modular
way, in order to permit efficiently the insertion of new algorithms and new
simulators. It consists of about ten thousand lines of C++, and it exploits
deeply the object-oriented features, in order to hide to new developers the
implementing details.
Chapter 7
7.1 Optimization
The library comprehends, thus, the inverter gate, the TSPC gates “and”
(both the n and the p versions), “or” and “latch” gates (again with the n
and the p versions), and a full-adder (the version included here is a n–p
construction, faster than the almost equivalent p–n construction). As above
said, for comparison are included: a complete static full-adder, a full static
“and–or” gate2 , a full static “and”, a full static “or”, a full static “parity”
1
For a description of the TSPC see chapter 1 (page 3), and [1].
2
See note a, (page 98).
122 Chapter 7. Results and conclusions
Gate
Inverter (fig. 5.10, page 94)
TSPC type n latch (fig. 5.11(a), page 95)
TSPC type p latch (fig. 5.11(b), page 95)
TSPC type n and (fig. 5.12(a), page 96)
TSPC type p and (fig. 5.12(b), page 96)
TSPC type n or (fig. 5.13(a), page 97)
TSPC type p or (fig. 5.13(b), page 97)
Static and-or (fig. 5.14, page 98)
Static and (fig. 5.14, page 98) (See note 14, page 92.)
Static or (fig. 5.14, page 98) (See note 14, page 92.)
Static parity gate (fig. 5.15, page 99)
Static full-adder (figs. 5.16(a), 5.16(b), page 100)
TSPC full-adder (one-stage) (figs. 5.17(a), 5.17(b), page 101)
TSPC full-adder (basic cells)
gate (which performs the parity calculation among three inputs), and, fi-
nally, a TSPC full-adder, composed only by the TSPC basic gates above men-
tioned.
The very first result reported here is the comparison of the improve-
ment in the delay and power consumption between the 0.7 µm and the
0.25 µm technology, at minimum width: this comparison is reported in
table 7.2 and graphically pitted in figure 7.1(a) for delay and figure 7.1(b)
for the power consumption.
From that table it is possible to see that the average improvement (di-
minution) of the delay is 69.3% and of the power is 76.2%, passing from the
0.7 µm to the 0.25 µm technology.
Thus with scaling the dimension of quite 13 , the average delay and power
consumption are also scaled down of about the same factor.
The very first optimization policy applied to CMOS circuits was the
Tab. 7.2: Delay and energy dissipation @ minimum width (HSPICE)
Static and 760.9 0.722 4.8 277.2 (-63.6%) 0.0907 (-87.4%) 2.4
Static or 1430 0.75 4.8 233.7 (-83.7%) 0.0713 (-90.5%) 2.4
Static parity gate 2650.0 0.744 57.6 922.2 (-65.2%) 0.0945 (-87.3%) 28.8
Static full-adder 1781 6.475 48 571.3 (-67.9%) 3.155 (-51.3%) 24
TSPC full-adder (one-stage) 930.6 2.168 15.6 276.7 (-70.3%) 0.641 (-70.4%) 7.8
TSPC full-adder (basic cells) 2691.0 8.893 151.2 482.3 (-82.1%) 5.27 (-40.7%) 75.6
Average improvement -69.3% -76.2% -50%
123
124 Chapter 7. Results and conclusions
2500
2000
Delay [ps]
1500
-65.2%
1000
-67.9%
500 -65.9% -65.9% -65.9% -82.1%
-69.3% -66.9% -68.2% -71.7%
-63.8% -63.6% -83.7% -70.3%
0
andn
andp
orn
orp
latchn
latchp
inv
and--or
and--static
or--static
parity
static--fa
tspc--fa1
tspc--fa2
Gate type
(a) Delay
7 -30.6%
6
Energy [pJ]
4
-51.3%
3
-81.5%
-45.1%
2 -81.1% -70.4%
-81.4%
1 -86.1%
-86.2%
-86.5%
-87.5% -87.4% -90.5% -87.4%
0
andn
andp
orn
orp
latchn
latchp
inv
and--or
and--static
or--static
parity
static--fa
tspc--fa1
tspc--fa2
Gate type
(b) Energy-dissipation
Fig. 7.1: Comparison of 0.7 µm and 0.25 µm. gates @ minimum technology
width
delay optimization. The figures 7.2 and 7.3 sketch the delay optimization of
the gates of table 7.1, respectively in 0.7 µm and 0.25 µm technology imple-
mentation, with arrows representing the delay and energy variation. The
7.1. Optimization 125
2500
2000
-56.7%
Delay [ps]
-61.2%
-77.3%
1000 -81.0% -76.5% -60.1%
-88.1% -86.3%
500
0
andn
andp
orn
orp
latchn
latchp
inv
and--or
and--static
or--static
parity
static--fa
tspc--fa1
tspc--fa2
Gate type
+2254.7%
200
+2605.8%
+4261.4%
100 +2680.0%
+2079.7%
50 +2275.7%
+430.7%
+1616.4%
+178.7% +620.9%
+70.1% +1331.5%
0
andn
andp
orn
orp
latchn
latchp
inv
and--or
and--static
or--static
parity
static--fa
tspc--fa1
tspc--fa2
Gate type
arrows start from the initial values (i.e. either the delay or the energy meas-
ured at the minimum technology width), and end to the values after the
optimization.
126 Chapter 7. Results and conclusions
800
700
600 -27.3%
Delay [ps]
400
-59.3% -39.7%
300 -67.7% -74.4%
-87.1% -55.3% -42.8%
-68.1%
200
100
0
andn
andp
orn
orp
latchn
latchp
inv
and--or
and--static
or--static
parity
static--fa
tspc--fa1
tspc--fa2
Gate type
100
+3424.6%
80
Energy [pJ]
60 +847.7%
+2233.8%
40
20
+1818.9%
+1787.7%
+381.9%
+1305.4% +1855.0% +212.7% +465.1%
+279.3% +654.0% +133.7% +171.4%
0
andn
andp
orn
orp
latchn
latchp
inv
and--or
and--static
or--static
parity
static--fa
tspc--fa1
tspc--fa2
Gate type
2500
2000
Delay [ps]
1500
1000
500
0
andn
andp
orn
orp
latchn
latchp
inv
and--or
and--static
or--static
parity
static--fa
tspc--fa1
tspc--fa2
Gate type
200
150
Energy [pJ]
100
50
0
andn
andp
orn
orp
latchn
latchp
inv
and--or
and--static
or--static
parity
static--fa
tspc--fa1
tspc--fa2
Gate type
ments the transistor widths, thus augmenting the overall power dissip-
ation. Table 7.3 and figure 7.4 report the relative variation of delay and
power (as minimum, maximum and mean value), for both technology: so,
128 Chapter 7. Results and conclusions
for the 0.7 µm technology the delay is, in average, decreased by 3.43 times,
while for the 0.25 µm technology it is decreased by 2.75 times (figure 7.4(a)).
On the contrary, the energy dissipation is increased by 20.42 times in 0.7 µm
and by 13.41 in 0.25 µm (figure 7.4(b)).
The table 7.4 shows the total time taken by the optimization of each
gate, together with the total number of function evaluations, that is the
number of times the simulator (in this case HSPICE) of the circuit has been
invoked. These numbers are quite reasonable per se, and moreover the op-
timization of a cell library ought to be performed only once, before the
reuse of it. Furthermore, in the case of very large circuits, the modular ar-
chitecture of the optimizer makes possible to switch from one simulator
to another on the fly; thus we can use a very fast simulator (as FAST) in
the earlier steps of optimization, and switch to a more precise but slower
simulator (as HSPICE) in the later stages of the optimization process.
Tab. 7.3: Delay decreasing and energy increasing (both relative) in a delay
optimization.
Tab. 7.4: Elapsed time and total number of function evaluations for a full-
delay optimization with HSPICE — on a ULTRA-sparc 5
dynamic logic (where there are n-gate and p-gate alternated, working with
different clock phases), the delay of the entire circuit is bounded by the
delay of the worst library cell in circuit. It has no sense, thus, to optimize
the basic library cells (that are present in every circuit) to their limits, when
the delay of a generic circuit is bounded by the worst of them. It is, instead,
more useful to try to optimize the worst cell in the library, while trying to
reduce the delay of the other cells to the value obtained by the previous
optimization. In this way a reduction of the dimensions of these cell is
achieved, obtaining thus a reduction of the overall energy dissipation.
ii) choose the worst cell (with regard to delay) among the previous;
iv) optimize all the other cell to have a delay not superior to the value
obtained in the previous point.
4
§4.1.1.2, page 52
130 Chapter 7. Results and conclusions
It is possible to see, from table 7.5 that the delays after the optimization
have a standard deviation5 (3.83) far smaller than the standard deviation
before the optimization (36.65). This means that all the cells have quite the
same delay after the optimization, and that this value is an “optimal” one,
since minimizes the delay of block constituted by these cells, and in the
same time reduces the power dissipation and area occupancy with respect
to a solution with all the cells optimized independently.
A much more useful policy to take into account specifically more than
5 ∑iN=1 (xi −m)2
The standard deviation of a number N of samples xi is defined as σ 2 = N
, where
∑iN=1 xi
m, m = N
,
is the arithmetic mean of the samples.
It is a measure of the spreading of the samples around the mean.
7.1. Optimization 131
The figures 7.5 and 7.7 show four different multi-objective optimization,
respectively, for the 0.7 µm and 0.25 µm technology (with figures 7.6, 7.8
that are, respectively, a zoom of the figures 7.5(b), 7.7(b). The four different
optimizations performed are:
ii) a delay optimization, taking slightly into account the power consump-
tion, indicated with “Delay=80% Power=20%”;
iv) a delay optimization, taking strongly into account the power consump-
tion, indicated with “Delay=20% Power=80%”;
The percent numbers6 reported after delay and power, are, also, the
coefficients α and β of the equation 5.5 (page 105) used as a cost function
in the optimization algorithm.
From these figures we see the delay that reduces more and more with
the increasing of its relative weight, while the increasing of the power dis-
sipation is somewhat limited by the increase of its relative weight.
From all the optimization policies, the one that gives the most useful
results is the optimization of delay and power with the same weights, that
is the one indicated with “Delay=50% Power=50%” in the previous figures.
These results are reported also in figure 7.9, as a particular case.
This is, probably, the most useful optimization since it still reduces a lot
the delay, but it contains the increasing of the power dissipation to a more
acceptable value.
The figures 7.10, 7.11, 7.12 and 7.13, show the same four optimizations
by means of the trajectory in the space delay–power during the optimiza-
tion process. In these figures each marked point is a step in the optimization
process. It is so possible to see how augmenting the relative weight of the
6
The case “Delay=0% Power=100%” has not been included, since this kind of optim-
ization leads to the trivial result of all the transistor at the minimum width (cfr. §5.2.2.2,
page 96)
132 Chapter 7. Results and conclusions
2000
Delay [ps]
1500
1000
500
0
andn
andp
orn
orp
latchn
latchp
inv
and--or
and--static
or--static
parity
static--fa
tspc--fa1
Gate type
120
Energy [pJ]
100
80
60
40
20
0
andn
andp
orn
orp
latchn
latchp
inv
and--or
and--static
or--static
parity
static--fa
tspc--fa1
Gate type
delay in the cost function (and thus reducing the energy relative weight),
leads the optimizer to go further in the trajectory reducing the delay and
augmenting the energy dissipation.
7.1. Optimization 133
35
30
Energy [pJ]
25
20
15
10
0
andn
andp
orn
orp
latchn
latchp
inv
and--or
and--static
or--static
parity
static--fa
tspc--fa1
Gate type
From these figures it can be clearly seen again that the multi-objective
optimization “Delay=50% Power=50%” has the best results with respect to
delay optimization and, at the same time, to containing the energy dissipa-
tion within reasonable value. These results are summarized in table 7.6: in
134 Chapter 7. Results and conclusions
700
600
Delay [ps]
500
400
300
200
100
0
andn
andp
orn
orp
latchn
latchp
inv
and--or
and--static
or--static
parity
static--fa
tspc--fa1
Gate type
80
Energy [pJ]
60
40
20
0
andn
andp
orn
orp
latchn
latchp
inv
and--or
and--static
or--static
parity
static--fa
tspc--fa1
Gate type
this table are showed the percent variation of delay and energy dissipation
between the values obtained after a full delay optimization and the values
obtained after a delay–power optimization. The average worsening in the
7.2. Conclusions 135
3
Energy [pJ]
0
andn
andp
orn
orp
latchn
latchp
inv
and--or
and--static
or--static
parity
static--fa
tspc--fa1
Gate type
delay (i.e. the difference between the delay value after a full delay optimiz-
ation and the same value after a delay–power optimization) is +27.5% for
the 0.7 µm technology and just +13.6% for the 0.25 µm technology. Despite
these low rate of worsening, the average energy-dissipation reduction is
−67.2% for the 0.7 µm technology and −44.1% for the 0.25 µm technology,
while the area occupancy reductions are, respectively, −69.9% and −49.3%
This means that accepting a slight degradation in the delay figure, leads to
a great reduction of the overall energy-dissipation and area occupancy.
7.2 Conclusions
2500
2000
Delay [ps]
1500
1000
500
0
andn
andp
orn
orp
latchn
latchp
inv
and--or
and--static
or--static
parity
static--fa
tspc--fa1
tspc--fa2
Gate type
50
40
Energy [pJ]
30
20
10
0
andn
andp
orn
orp
latchn
latchp
inv
and--or
and--static
or--static
parity
static--fa
tspc--fa1
tspc--fa2
Gate type
300
280
Delay [ps]
260
240
220
200
0 5 10 15 20 25 30 35 40 45 50
Energy [pJ]
(a) 0.25 µm
1000
900
Delay [ps]
800
700
600
500
400
0 20 40 60 80 100 120 140
Energy [pJ]
(b) 0.7 µm
Fig. 7.10: Delay and power trajectory during 4 different multi-objective op-
timizations for the and–or gate of figure 5.14 (page 98)
almost the same delay is safer from the operating point of view: it develops
less heat, hence it is more reliable.
138 Chapter 7. Results and conclusions
800
700
Delay [ps]
600
500
400
300
0 0.5 1 1.5 2 2.5
Energy [pJ]
(a) 0.25 µm
2200
2000
Delay [ps]
1800
1600
1400
1200
1000
800
600
0 1 2 3 4 5 6 7 8 9 10 11
Energy [pJ]
(b) 0.7 µm
Fig. 7.11: Delay and power trajectory during 4 different multi-objective op-
timizations for the parity gate of figure 5.15 (page 99)
1400
Delay [ps]
1200
1000
800
600
0 20 40 60 80 100 120 140 160 180
Energy [pJ]
(a) 0.25 µm
540
520
Delay [ps]
500
480
460
440
420
400
0 50 100 150 200 250
Energy [pJ]
(b) 0.25 µm
Fig. 7.12: Delay and power trajectory during 4 different multi-objective op-
timizations for the static full-adder of figure 5.16 (page 100)
240
220
Delay [ps]
200
180
160
140
0.5 1 1.5 2 2.5 3 3.5 4 4.5
Energy [pJ]
(a) 0.25 µm
800
700
Delay [ps]
600
500
400
300
2 4 6 8 10 12 14 16 18
Energy [pJ]
(b) 0.7 µm
Fig. 7.13: Delay and power trajectory during 4 different multi-objective op-
timizations for the dynamic full-adder of figure 5.17 (page 101)
Let’s think for example to an “and” gate that performs always the same
function, but with different delays or maybe different power dissipations.
Simply swapping one library version (for example one optimized only for
7.3. Future works 141
the delay) with another (for example one optimized taking into account
the power consumption), the designer can develop several versions of the
same project with different performances.
Some future works that will be faced in the future could be:
CLASS GRAPH
146 Appendix A. Class graph
Class Graph
CircuitNetList
> Circuit
OptimizationAlgorithm
> TestEval
> Slop2
> Slop
> Powell
> Anneal
147
EvaluationAlgorithm
> TestOpt
> Hspice
> Fast
Options
CPNode
CritPathList
TransistorNode
TransistorList
148 Appendix A. Class graph
CapacitorList
Node
NodeList
Appendix B
SOURCE CODE
CPNode.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11
12 ///
13 CPNode::CPNode() :
14 VALID( 0 ), NodeIn( 0 ), NodeOut( 0 ), NumTranList( 0 ),
15 ActiveInputs( 0 ), NoActiveInputs( 0 ), InitialConditions( 0 ),
16 ActiveInputsIter( 0 ), NoActiveInputsIter( 0 ), InitialConditionsIter( 0 ),
17 next( 0 )
18 {
19 for ( unsigned int i = 0; i < MAXCHAIN; i++ )
20 {
21 TransistorNameList[ i ] = 0;
22 TransistorNameListIter[ i ] = 0;
23 NumTranN[ i ] = 0;
24 NumTranP[ i ] = 0;
25 }
26 }
27
28 ///
29 CPNode::~CPNode()
30 {
31 NodeValueList* tmp;
32 while ( ActiveInputs )
33 {
34 tmp = ActiveInputs->next;
35 delete ActiveInputs;
36 ActiveInputs = tmp;
37 }
38 while ( NoActiveInputs )
39 {
40 tmp = NoActiveInputs->next;
41 delete NoActiveInputs;
42 NoActiveInputs = tmp;
43 }
44 while ( InitialConditions )
45 {
46 tmp = InitialConditions->next;
47 delete InitialConditions;
48 InitialConditions = tmp;
49 }
50 TrList* tmp2;
51 for ( unsigned int i = 0; i < MAXCHAIN; i++ )
52 while ( TransistorNameList[ i ] )
53 {
54 tmp2 = ( TransistorNameList[ i ] ) ->next;
55 delete TransistorNameList[ i ];
56 TransistorNameList[ i ] = tmp2;
57 }
58 }
59
60 ///
61 int CPNode::InsNodeIn( unsigned int Node, TransitionType T, double Time )
62 {
63 if ( NodeIn )
64 return NOT_FOUND; /// ERROR, yet inserted
B.1. Main functions 151
65 NodeIn = Node;
66 TransitionIn = T;
67 InTime = Time;
68 return OK;
69 }
70
71 ///
72 int CPNode::InsNodeOut( unsigned int Node, TransitionType T )
73 {
74 if ( NodeOut )
75 return NOT_FOUND; /// ERROR, yet inserted
76 NodeOut = Node;
77 TransitionOut = T;
78 return OK;
79 }
80
81 ///
82 int CPNode::InsActIn( unsigned int Node, double Val )
83 {
84 NodeValueList * tmp;
85 if ( !ActiveInputs )
86 {
87 ActiveInputs = new NodeValueList;
88 if ( !ActiveInputs )
89 return NO_MEM;
90 ActiveInputs->next = 0;
91 }
92 else
93 {
94 tmp = new NodeValueList;
95 if ( !tmp )
96 return NO_MEM;
97 tmp->next = ActiveInputs;
98 ActiveInputs = tmp;
99 }
100 ActiveInputs->node = Node;
101 ActiveInputs->value = Val;
102 ActiveInputsIter = ActiveInputs;
103 return OK;
104 }
105
106 ///
107 int CPNode::InsNoActIn( unsigned int Node, double Val )
108 {
109 NodeValueList * tmp;
110 if ( !NoActiveInputs )
111 {
112 NoActiveInputs = new NodeValueList;
113 if ( !NoActiveInputs )
114 return NO_MEM;
115 NoActiveInputs->next = 0;
116 }
117 else
118 {
119 tmp = new NodeValueList;
120 if ( !tmp )
121 return NO_MEM;
122 tmp->next = NoActiveInputs;
123 NoActiveInputs = tmp;
124 }
125 NoActiveInputs->node = Node;
126 NoActiveInputs->value = Val;
127 NoActiveInputsIter = NoActiveInputs;
128 return OK;
129 }
130
131 ///
132 int CPNode::InsIniCond( unsigned int Node, double Val )
133 {
152 Appendix B. Source code
CapInsert.cc
3 #include "mystdinclude.h"
4 #include "print.h"
5 #include "myenum.h"
6 #include "class_devices.h"
7
8 ///
9 int CapacitorList::Insert( unsigned int node1, unsigned int node2, double val )
10 {
11 Capacitance * tmp;
12 if ( !head )
13 {
14 head = new Capacitance;
15 if ( !head )
16 return NO_MEM;
17 head->next = 0;
18 }
19 else
20 {
21 tmp = new Capacitance;
22 if ( !tmp )
23 return NO_MEM;
24 tmp->next = head;
25 head = tmp;
26 }
27 head->node1 = node1;
28 head->node2 = node2;
29 head->val = val;
30 NumCap++;
31 return OK;
32 }
CapacitorList.cc
3 #include "mystdinclude.h"
4 #include "print.h"
5 #include "myenum.h"
6 #include "class_devices.h"
7
8 ///
9 CapacitorList::CapacitorList() : NumCap( 0 ), head( 0 )
10 {}
11
12 ///
13
14 CapacitorList::~CapacitorList()
15 {
16 Capacitance* tmp;
17 while ( head )
18 {
19 tmp = head->next;
20 delete head;
21 head = tmp;
22 }
23 }
24
25 ///
26 const Capacitance& CapacitorList::operator[]( unsigned int index ) const
27 {
28 if ( index > NumCap )
29 error( NOT_FOUND, 0, "Index out of bounbd in [CapacitorList]..." );
30 unsigned int i = index;
31 Capacitance* tmp = head;
32 while ( i-- )
33 tmp = tmp->next;
B.1. Main functions 155
34 return *tmp;
35 }
36
37 ///
38 Capacitance& CapacitorList::operator[]( unsigned int index )
39 {
40 if ( index > NumCap )
41 error( NOT_FOUND, 0, "Index out of bounbd in [CapacitorList]..." );
42 unsigned int i = index;
43 Capacitance* tmp = head;
44 while ( i-- )
45 tmp = tmp->next;
46 return *tmp;
47 }
Circuit.cc
3 #include "mystdinclude.h"
4 #include "print.h"
5 #include "myenum.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11
12 ///
13 Circuit::Circuit( const char* FileNetList, const Options& options ) :
14 CircuitNetList( FileNetList, options )
15 {
16 print_log( "Creating circuit graph..." );
17 }
18
19 ///
20 Circuit::~Circuit()
21 {}
22
CircuitNetList.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11
12 ///
13 CircuitNetList::CircuitNetList( const char *FileNetList, const Options& options ) :
14 Val( 0.0 ), ValNode( 0 )
15 {
16 print_log( "Creating transistors list..." );
17 char *FileIn = new char[ strlen( FileNetList ) + 1 ];
18 if ( !FileIn )
19 {
20 print_log( "FATAL ERROR:" );
21 print_log( ReturnMessage[ NO_MEM ] );
22 error( NO_MEM, errno, "HEY! " );
23 }
24 strcpy( FileIn, FileNetList );
25 FileNetOut = new char[ strlen( FileNetList ) + strlen( NetListSuffix ) + 1 ];
26 if ( !FileNetOut )
27 {
28 print_log( "FATAL ERROR:" );
29 print_log( ReturnMessage[ NO_MEM ] );
156 Appendix B. Source code
CircuitNetlistParse.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11
12 ///
13 int CircuitNetList::ParseMosLine( char *line, char *line2, const char* mosn, const char* mosp )
14 {
15 char tmpstr[ 128 ];
16 char parsestr[ 128 ];
17 char endpar[ 128 ];
18 char mos[ 8 ];
19 char type[ 16 ];
20 char par[ 16 ];
21 char lstr[ 16 ];
B.1. Main functions 157
CircuitNetlistPreprocess.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11
12 ///
13 int CircuitNetList::PreProcess( const char* FileNetList, const char* NameMosN, const char* NameMosP )
14 {
15 char line[ 1024 ];
16 char line2[ 1024 ];
17 char command[ 32 ];
18 ifstream i_file( FileNetList );
19 ofstream o_file( FileNetOut );
20 int ToBeCopied;
21
22 if ( !i_file )
23 return NOT_FOUND;
24 if ( !o_file )
25 return NOT_FOUND;
26 while ( i_file.getline( line, 1023 ) )
27 {
28 int c = 0;
29 ToBeCopied = 1;
30 while ( isspace( line[ c++ ] ) );
31 switch ( line[ --c ] )
32 {
33 case ’.’:
34 sscanf( &line[ c + 1 ], "%s", command );
35 ToBeCopied = strcasecmp( command, "tran" ) && \
36 strcasecmp( command, "dc" ) && \
37 strcasecmp( command, "ac" );
38 if ( !ToBeCopied )
39 {
40 strcpy( line2, "***** " );
41 strcat( line2, &line[ c ] );
42 }
43 break;
44 case ’v’:
45 case ’V’:
46 sscanf( &line[ c + 1 ], "%s", command );
47 ToBeCopied = !( strcasecmp( command, "dd" ) && \
48 strcasecmp( command, "cc" ) && \
49 strcasecmp( command, "al" ) );
50 if ( ToBeCopied )
51 {
52 int node2;
53 ToBeCopied = 0;
54 sscanf( &line[ c ], "%*s %d %d %*s %lf", &ValNode, &node2, &Val );
55 sprintf( line2, "vdd %d %d dc %g ", ValNode, node2, Val );
56 }
57 else
58 {
59 strcpy( line2, "* " );
60 strcat( line2, &line[ c ] );
B.1. Main functions 159
61 }
62 break;
63 case ’m’:
64 case ’M’:
65 case ’x’:
66 case ’X’:
67 ToBeCopied = ParseMosLine( &line[ c ], line2, NameMosN, NameMosP );
68 break;
69 case ’c’:
70 case ’C’:
71 unsigned int node1, node2;
72 double val;
73 sscanf( &line[ c ], "%*s %u %u %lg", &node1, &node2, &val );
74 if ( CapList.Insert( node1, node2, val ) != OK )
75 {
76 i_file.close();
77 o_file.close();
78 return NO_MEM;
79 }
80 break;
81 default:
82 break;
83 }
84 if ( ToBeCopied == 0 )
85 o_file << line2 << endl;
86 else
87 o_file << &line[ c ] << endl;
88 }
89 o_file.close();
90 i_file.close();
91 if ( Val <= 0.0 )
92 {
93 print_log( "Error: no|wrong VDD defined" );
94 return NOT_FOUND;
95 }
96 return OK;
97 }
CircuitPrint.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11
12
13 ///
14 void Circuit::PrintResult( unsigned long int Step,
15 unsigned int NT,
16 unsigned int NP,
17 const double* NewWidth,
18 const double* CPDelay,
19 const double* CPPower,
20 const double *CPNoise,
21 double Area,
22 double maxT,
23 double maxP,
24 double maxN,
25 double f,
26 double fLast ) const
27 {
28 char log[ 1024 ], tmp[ 1024 ];
29 if ( Step == 1 )
30 {
160 Appendix B. Source code
CircuitTranListNode.cc
3 #include "mystdinclude.h"
4 #include "print.h"
5 #include "myenum.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11
12 ///
13 int Circuit::TransistorListNode(unsigned int node, TransistorList& TList, unsigned int& n, unsigned int& p) const
14 {
15 // find all the nmos transistors with source or drain
162 Appendix B. Source code
CircuitWidth.cc
3 #include "mystdinclude.h"
4 #include "print.h"
5 #include "myenum.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11
12 ///
13 double Circuit::JunctionNWidth( unsigned int node, int& number, const double* NewWidth = 0 ) const
14 {
15 // find all the nmos transistors with source or drain
16 // connected to node an return the sum of widths
17 unsigned int NT = GetNTran();
18 number = 0;
19 double W = 0.0;
20 if ( node == 0 )
21 return 0.0;
22 for ( unsigned int i = 0; i < NT; i++ )
23 {
24 if ( TranList[ i ].TrType() == NMOS )
25 if ( ( TranList[ i ].Source() == node ) ||
26 ( TranList[ i ].Drain() == node ) )
27 {
28 if ( !NewWidth )
29 W += TranList[ i ].Width();
30 else
31 W += NewWidth[ TranPos( TranList[ i ].DevName() ) ];
32 number++;
33 }
34 }
35 return W;
36 }
37
38 ///
39 double Circuit::GateNWidth( unsigned int node, int& number, const double* NewWidth = 0 ) const
40 {
41 // find all the nmos transistors with gate
42 // connected to node an return the sum of widths
43 unsigned int NT = GetNTran();
44 double W = 0.0;
45 number = 0;
46 if ( node == 0 )
47 return 0.0;
B.1. Main functions 163
Critic.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11 #include "main.h"
12
13
14 ///
B.1. Main functions 165
CriticRecurse.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11 #include "main.h"
12
13
14
15 ///
16 int CriticRecurse(const Circuit& circuit,
17 unsigned int node,
18 NodeList& node_list)
19 {
20 TransistorList TList;
21 static int level = 0;
22 unsigned int n = 0;
23 unsigned int p = 0;
24 int RetCode;
25 if ((RetCode = circuit.TransistorListNode(node, TList, n , p)) != OK)
26 return RetCode;
27 unsigned int Nt = TList.GetNTran();
28 if ((RetCode = node_list.InsertNode(node)) != OK)
29 return RetCode;
30 if ( (n > 0) && (p > 0))
31 {
32 return OK;
33 }
34 level++;
35 #ifdef DEBUG
36 cerr << "node " << node << ": ";
37 for (unsigned int i = 0; i < Nt; i++)
168 Appendix B. Source code
CriticalPath.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11
12
13
14 ///
15 CritPathList::CritPathList() : NumPath( 0 ), head( 0 ), tail( 0 )
16 {
17 print_log( "Creating critical path list..." );
18 }
19
20
21 ///
22 CritPathList::~CritPathList()
23 {
24 CPNode* tmp;
25 ///
26 while ( head != 0 )
27 {
28 tmp = head->next;
29 delete head;
30 head = tmp;
31 }
32 }
33
34
35 ///
36 const CPNode& CritPathList::operator[]( unsigned int index ) const
37 {
38 CPNode * tmp = head;
39 unsigned int i = index;
40 if ( index > NumPath )
41 error( NOT_FOUND, 0, "Index out of bound in [CritPathList]..." );
42 while ( i-- )
43 tmp = tmp->next;
44 return *tmp;
45 }
CriticalPathCreate.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
170 Appendix B. Source code
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11 #include "class_simulator.h"
12
13 ///
14 int CritPathList::Create()
15 {
16 if ( !head )
17 {
18 head = new CPNode;
19 if ( !head )
20 return NO_MEM;
21 tail = head;
22 }
23 else
24 {
25 tail->next = new CPNode;
26 if ( !( tail->next ) )
27 return NO_MEM;
28 tail = tail->next;
29 }
30 tail->next = 0;
31 return OK;
32 }
33
34 ///
35 int CritPathList::Stamp( unsigned int NumTranList )
36 {
37 tail->VALID = 1;
38 tail->NumTranList = NumTranList;
39 NumPath++;
40 return OK;
41 }
CriticalPathInsert.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11
12
13 ///
14 int CritPathList::InsertNodeIn( unsigned int NIn, TransitionType Type, double Time )
15 {
16 if ( tail )
17 return tail->InsNodeIn( NIn, Type, Time );
18 else
19 return NOT_FOUND;
20 }
21
22 ///
23 int CritPathList::InsertNodeOut( unsigned int NOut, TransitionType Type )
24 {
25 if ( tail )
26 return tail->InsNodeOut( NOut, Type );
27 else
28 return NOT_FOUND;
29 }
30
31 ///
32 int CritPathList::InsertActiveInputs( unsigned int Node, double Val )
B.1. Main functions 171
33 {
34 if ( tail )
35 return tail->InsActIn( Node, Val );
36 else
37 return NOT_FOUND;
38 }
39
40 ///
41 int CritPathList::InsertNoActiveInputs( unsigned int Node, double Val )
42 {
43 if ( tail )
44 return tail->InsNoActIn( Node, Val );
45 else
46 return NOT_FOUND;
47 }
48
49 ///
50 int CritPathList::InsertInitialCondition( unsigned int Node, double Val )
51 {
52 if ( tail )
53 return tail->InsIniCond( Node, Val );
54 else
55 return NOT_FOUND;
56 }
57
58 ///
59 int CritPathList::InsertPathTransistor( const char* name, TransistorType TR, unsigned int index )
60 {
61 if ( tail )
62 return tail->InsTran( name, TR, index );
63 else
64 return NOT_FOUND;
65 }
CriticalPathParse.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11
12
13 ///
14 int CritPathList::ParseLineCPNode( const char* str, CPCOMMANDOPT NodeType )
15 {
16 char tmpType[ 5 ];
17 unsigned int node;
18 double time;
19 sscanf( str, "%*s%u%s", &node, tmpType );
20 switch ( NodeType )
21 {
22 case NODEIN:
23 sscanf( str, "%*s%*u%*s%lg", &time );
24 for ( unsigned int i = 0; ( TransitionString[ i ] != 0 ); i++ )
25 {
26 if ( !strcasecmp( tmpType, TransitionString[ i ] ) )
27 return InsertNodeIn( node, ( TransitionType ) i, time );
28 }
29 return NOT_FOUND;
30 break;
31 case NODEOUT:
32 for ( unsigned int i = 0; ( TransitionString[ i ] != 0 ); i++ )
33 {
34 if ( !strcasecmp( tmpType, TransitionString[ i ] ) )
172 Appendix B. Source code
CriticalPathRead.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "global.h"
7 #include "class_options.h"
8 #include "class_devices.h"
9 #include "class_nodes.h"
10 #include "class_critical.h"
11 #include "class_circuit.h"
12
13
14 ///
15 int CritPathList::Read( const char* FileOptions, const Circuit& circuit )
16 {
17 ifstream i_file( FileOptions );
18 char line[ 1024 ];
19 char command[ 256 ];
20 if ( !i_file )
21 return NOT_FOUND;
22 unsigned int LineNum = 0;
23 unsigned int NumTranList = 0;
24 while ( i_file.getline( line, 1023 ) )
25 {
26 LineNum++;
27 if ( sscanf( line, "%s ", command ) == 1 )
28 if ( command[ 0 ] != ’#’ )
29 {
30 int RetCode;
31 switch ( CPCOMMANDOPT Cc = WhichCommand( command ) )
32 {
33 case CPATH:
34 RetCode = Create();
35 NumTranList = 0;
36 break;
37 case NODEIN:
38 case NODEOUT:
39 RetCode = ParseLineCPNode( line, Cc );
40 break;
41 case ACTIVEI:
42 case NOACTIVEI:
43 case IC:
44 RetCode = ParseLineCPInputs( line, Cc );
45 break;
46 case TRANLIST:
47 RetCode = ParseLineCPTran( line, circuit, NumTranList );
48 NumTranList++;
49 if ( NumTranList >= MAXCHAIN )
50 RetCode = NO_MEM;
51 break;
52 case ENDCPATH:
53 RetCode = Stamp( NumTranList );
54 break;
174 Appendix B. Source code
55 case NONECP:
56 RetCode = OK;
57 default:
58 break;
59 }
60 if ( RetCode != OK )
61 {
62 sprintf( line, "ERROR reading file %s line %d ", FileOptions, LineNum );
63 print_log( line );
64 i_file.close();
65 return RetCode;
66 }
67 }
68 }
69 i_file.close();
70 return OK;
71 }
EvaluationAlgorithm.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11 #include "class_simulator.h"
12
13
14 ///
15 EvaluationAlgorithm::EvaluationAlgorithm( const CritPathList& pathlist, const Options& options )
16 :
17 pathlist( pathlist ), options( options ),
18 NumPath( 0 ), Calls( 0 ),
19 CPDelay( 0 ), CPPower( 0 ),
20 CPNoise( 0 ), Area( 0.0 )
21 {
22 print_log( "Creating simulation algorithm..." );
23 NumPath = pathlist.GetNumPath();
24 CPDelay = new double[ NumPath ];
25 CPPower = new double[ NumPath ];
26 CPNoise = new double[ NumPath ];
27 if ( !CPDelay || !CPPower || !CPNoise )
28 {
29 print_log( "FATAL ERROR:" );
30 print_log( ReturnMessage[ NO_MEM ] );
31 error( NO_MEM, errno, "HEY! " );
32 }
33
34 }
35
36 ///
37 EvaluationAlgorithm::~EvaluationAlgorithm()
38 {
39 delete[] CPDelay;
40 delete[] CPPower;
41 delete[] CPNoise;
42 }
Global.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "global.h"
B.1. Main functions 175
7
8 ///
9 GLOBCOMMANDOPT WhichGBOption( const char* option )
10 {
11 for ( unsigned int i = 0; (GlobCommandOptions[ i ] != 0 ); i++ )
12 {
13 if ( !strcasecmp( option, GlobCommandOptions[ i ] ) )
14 return ( ( GLOBCOMMANDOPT ) i );
15 }
16 return NONEGLOB;
17 }
18
19 ///
20 SIMCOMMANDOPT WhichSimOption( const char* option )
21 {
22 for ( unsigned int i = 0; (SimCommandOptions[ i ] != 0 ); i++ )
23 {
24 if ( !strcasecmp( option, SimCommandOptions[ i ] ) )
25 return ( ( SIMCOMMANDOPT ) i );
26 }
27 return NONESIM;
28 }
29
30
31 ///
32 OPTCOMMANDOPT WhichOptOption( const char* option )
33 {
34 for ( unsigned int i = 0; (OptCommandOptions[ i ] != 0 ); i++ )
35 {
36 if ( !strcasecmp( option, OptCommandOptions[ i ] ) )
37 return ( ( OPTCOMMANDOPT ) i );
38 }
39 return NONEOPT;
40 }
41
42 ///
43 CPCOMMANDOPT WhichCommand( const char* option )
44 {
45 for ( unsigned int i = 0; (CPCommandOptions[ i ] != 0 ); i++ )
46 {
47 if ( !strcasecmp( option, CPCommandOptions[ i ] ) )
48 return ( ( CPCOMMANDOPT ) i );
49 }
50 return NONECP;
51 }
52
53 #ifndef LINUX
54
55 ///
56 void error( int exitCode, int ErrorType, const char* message )
57 {
58 cerr << message << "Error " << ErrorType << endl;
59 if ( exitCode != 0 )
60 exit( exitCode );
61 }
62
63 #endif
IsIn.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
176 Appendix B. Source code
11 #include "main.h"
12
13
14
15
16 ///
17 int IsIn(unsigned int node, Node& NList, unsigned int& pos)
18 {
19 pos = 0;
20 for (unsigned int i = 0; i < NList.GetNumNode(); i++)
21 if ((NList[i]).node == node)
22 {
23 pos = i;
24 return OK;
25 }
26 return NOT_FOUND;
27 }
28
Node.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9
10 ///
11 Node::Node() : NumNode(0), next( 0 ), Head(0), Tail(0)
12 {}
13
14 ///
15
16 Node::~Node()
17 {
18 _NodeList* tmp;
19 while ( Head )
20 {
21 tmp = Head->next;
22 delete Head;
23 Head = tmp;
24 }
25 }
26
27 ///
28 int Node::Insert( unsigned int node, int flag = -1)
29 {
30 _NodeList * tmp;
31 if ( !Head )
32 {
33 Head = new _NodeList;
34 if ( !Head )
35 return NO_MEM;
36 Head->next = 0;
37 Tail = Head;
38 }
39 else
40 {
41 tmp = new _NodeList;
42 if ( !tmp )
43 return NO_MEM;
44 tmp->next = 0;
45 Tail->next = tmp;
46 Tail = tmp;
47 }
48 Tail->node = node;
49 Tail->flag = flag;
B.1. Main functions 177
50 NumNode++;
51 return OK;
52 }
53
54 ///
55 int Node::DeleteLevelNode(unsigned int level)
56 {
57 // NodeList* tmp = Head;
58 //unsigned int i = level;
59 if (level >= NumNode)
60 return NOT_FOUND;
61 //while(i–)
62 // tmp = tmp-¿next;
63 //tmp-¿next = 0;
64 //Tail = tmp;
65 Tail = &(operator[](level));
66 (operator[](level)).next = 0;
67 NumNode = level + 1;
68 return OK;
69 }
70
71 ///
72 const _NodeList& Node::operator[]( unsigned int index ) const
73 {
74 _NodeList* tmp = Head;
75 unsigned int i = index;
76 if ( index > NumNode )
77 error( NOT_FOUND, 0, "Index out of bound in [_NodeList]..." );
78 while ( i-- )
79 tmp = tmp->next;
80 return *tmp;
81 }
82
83 ///
84 _NodeList& Node::operator[]( unsigned int index )
85 {
86 _NodeList* tmp = Head;
87 unsigned int i = index;
88 if ( index > NumNode )
89 error( NOT_FOUND, 0, "Index out of bound in [_NodeList]..." );
90 while ( i-- )
91 tmp = tmp->next;
92 return *tmp;
93 }
NodeCreate.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_nodes.h"
7
8 ///
9 int NodeList::Create()
10 {
11 if ( !head )
12 {
13 head = new Node;
14 if ( !head )
15 return NO_MEM;
16 tail = head;
17 }
18 else
19 {
20 tail->next = new Node;
21 if ( !( tail->next ) )
22 return NO_MEM;
23 tail = tail->next;
178 Appendix B. Source code
24 }
25 tail->next = 0;
26 NumList++;
27 return OK;
28 }
NodeList.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_nodes.h"
7
8
9 ///
10 NodeList::NodeList() : NumList( 0 ), head( 0 ), tail( 0 )
11 {
12 print_log( "Creating node list..." );
13 }
14
15
16 ///
17 NodeList::~NodeList()
18 {
19 Node* tmp;
20 while ( head != 0 )
21 {
22 tmp = head->next;
23 delete head;
24 head = tmp;
25 }
26 }
27
28
29 ///
30 const Node& NodeList::operator[]( unsigned int index ) const
31 {
32 Node *tmp = head;
33 unsigned int i = index;
34 if ( index > NumList )
35 error( NOT_FOUND, 0, "Index out of bound in [NodeList]..." );
36 while ( i-- )
37 tmp = tmp->next;
38 return *tmp;
39 }
40
41 ///
42 Node& NodeList::operator[]( unsigned int index )
43 {
44 Node *tmp = head;
45 unsigned int i = index;
46 if ( index > NumList )
47 error( NOT_FOUND, 0, "Index out of bound in [NodeList]..." );
48 while ( i-- )
49 tmp = tmp->next;
50 return *tmp;
51 }
NodeListDelete.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_nodes.h"
7
8 ///
9 int NodeList::DeleteList( unsigned int list)
B.1. Main functions 179
10 {
11 if (list >= NumList)
12 return NOT_FOUND;
13 //unsigned int i = list - 1;
14 //Node* tmp = head;
15 //while(i–)
16 // tmp = tmp-¿next;
17 //tmp-¿next = tmp-¿next-¿next;
18 if ((operator[](list)).next)
19 {
20 (operator[](list - 1)).next = (operator[](list)).next;
21 Node* tmp = &(operator[](list - 1));
22 while (tmp->next)
23 tmp = tmp->next;
24 tail = tmp;
25 }
26 else
27 {
28 (operator[](list - 1)).next = 0;
29 tail = &(operator[](list - 1));
30 }
31 NumList--;
32 return OK;
33 }
NodeListInsert.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_nodes.h"
7
8 ///
9 int NodeList::InsertNode( unsigned int node)
10 {
11 if ( tail )
12 return tail->Insert( node );
13 else
14 return NOT_FOUND;
15 }
OptSimulate.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11 #include "class_simulator.h"
12 #include "class_optimizator.h"
13
14 ///
15 int OptimizationAlgorithm::SimulateCircuit( const double *NewWidth )
16 {
17 int RetCode = Simulation.Run( circuit, NewWidth, ValidPath );
18 if ( RetCode != OK )
19 return RetCode;
20 for ( unsigned int i = 0; i < NumPath; i++ )
21 {
22 CPDelay[ i ] = Simulation.GetDelay( i );
23 CPPower[ i ] = Simulation.GetPower( i );
24 CPNoise[ i ] = Simulation.GetNoise( i );
25 }
26 Area = Simulation.GetArea();
180 Appendix B. Source code
27 return OK;
28 }
OptimizationAlFirstSim.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11 #include "class_simulator.h"
12 #include "class_optimizator.h"
13
14 ///
15 int OptimizationAlgorithm::SimulateFirstCircuit()
16 {
17 double* MinimumWidth = new double[ NumTran ];
18 double* MaximumWidth = new double[ NumTran ];
19 if (!MinimumWidth || !MaximumWidth)
20 return NO_MEM;
21 for ( unsigned int i = 0; i < NumTran; i++ )
22 {
23 MinimumWidth[ i ] = options.GetOptOption( WMIN );
24 if (options.GetOptOption( WMAX ) <= 0)
25 MaximumWidth[ i ] = options.GetOptOption( WMIN ) * 100;
26 else
27 MaximumWidth[ i ] = options.GetOptOption( WMAX );
28 }
29 int RetCode = Simulation.Run( circuit, MaximumWidth, ValidPath );
30 if ( RetCode != OK )
31 return RetCode;
32 for ( unsigned int i = 0; i < NumPath; i++ )
33 {
34 CPDelay[ i ] = Simulation.GetDelay( i );
35 CPPower[ i ] = Simulation.GetPower( i );
36 CPNoise[ i ] = Simulation.GetNoise( i );
37 }
38 Area = Simulation.GetArea();
39 MaxDelayInitMax = 0.0;
40 for ( unsigned int i = 0; i < NumPath; i++ )
41 {
42 if ( Simulation.GetDelay( i ) > 0.0 )
43 {
44 if ( Simulation.GetDelay( i ) > MaxDelayInitMax )
45 MaxDelayInitMax = CPDelay[i];
46 if ( Simulation.GetPower( i ) > MaxPowerInitMax )
47 MaxPowerInitMax = CPPower[i];
48 if ( Simulation.GetNoise( i ) > MaxNoiseInitMax )
49 MaxNoiseInitMax = CPNoise[i];
50 }
51 }
52 AreaInitMax = Area;
53 MaxNoiseInitMax = 1.0; /// FIX ME !!!!!!!!!
54 RetCode = Simulation.Run( circuit, MinimumWidth, ValidPath );
55 if ( RetCode != OK )
56 return RetCode;
57 unsigned int tmpP = 0;
58 for ( unsigned int i = 0; i < NumPath; i++ )
59 {
60 CPDelay[ i ] = Simulation.GetDelay( i );
61 if (CPDelay[ i ] > 0.0)
62 {
63 ValidPath[i] = 1;
64 tmpP++;
65 }
B.1. Main functions 181
66 else
67 ValidPath[i] = 0;
68 CPPower[ i ] = Simulation.GetPower( i );
69 CPNoise[ i ] = Simulation.GetNoise( i );
70 }
71 Area = Simulation.GetArea();
72 MaxDelayInitMin = 0.0;
73 for ( unsigned int i = 0; i < NumPath; i++ )
74 {
75 if (ValidPath[i])
76 {
77 if ( Simulation.GetDelay( i ) > MaxDelayInitMin )
78 MaxDelayInitMin = CPDelay[i];
79 if ( Simulation.GetPower( i ) > MaxPowerInitMin )
80 MaxPowerInitMin = CPPower[i];
81 if ( Simulation.GetNoise( i ) > MaxNoiseInitMin )
82 MaxNoiseInitMin = CPNoise[i];
83 }
84 }
85 AreaInitMin = Area;
86 MaxNoiseInitMin = 1.0; /// FIX ME !!!!!!!!!
87 if (MaxDelayInitMin < MaxDelayInitMax)
88 MaxDelayInitMax = MaxDelayInitMin;
89 if (MaxPowerInitMin > MaxPowerInitMax)
90 MaxPowerInitMax = MaxPowerInitMin;
91 if (MaxNoiseInitMin > MaxNoiseInitMax)
92 MaxNoiseInitMax = MaxNoiseInitMin;
93 if (AreaInitMin > AreaInitMax)
94 AreaInitMax = AreaInitMin;
95 char log[512];
96 sprintf( log, "Found %u valid critical paths of %u", tmpP, NumPath );
97 print_log( log );
98 return OK;
99 }
OptimizationAlNormSim.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11 #include "class_optimizator.h"
12
13 ///
14 double OptimizationAlgorithm::NormSim( const double* x, int& RetCode)
15 {
16 double f;
17 double* X = new double[ NumTran ];
18 double DelW = options.GetOptOption( DELTA );
19 unsigned int count_min = 0;
20 unsigned int count_max = 0;
21 static unsigned int elapsed = 0;
22 static double fLast;
23 static unsigned int count_conv = 0;
24 for ( unsigned int i = 0; i < NumTran; i++ )
25 {
26 if ( x[ i ] <= options.GetOptOption( WMIN ) )
27 {
28 X[ i ] = options.GetOptOption( WMIN );
29 count_min++;
30 }
31 else if ( (x[ i ] > options.GetOptOption( WMAX )) &&
32 (options.GetOptOption( WMAX ) > 0) )
33 {
182 Appendix B. Source code
34 X[ i ] = options.GetOptOption( WMAX );
35 count_max++;
36 }
37 else
38 X[ i ] = double( rint( x[ i ] / DelW ) * DelW );
39 }
40 if ((count_min != NumTran) && (count_max != NumTran))
41 RetCode = SimulateCircuit( X );
42 else
43 {
44 RetCode = OK;
45 }
46 if ( RetCode != OK )
47 {
48 delete[] X;
49 return 0.0;
50 }
51 double maxT = 0.0;
52 double maxP = 0.0;
53 double maxN = 0.0;
54 double RatioT = 1.0; // MaxDelayInit / MaxDelayInit
55 //double RatioP = MaxDelayInitMin / MaxPowerInitMax;
56 double RatioP = 1.0;
57 //double RatioN = MaxDelayInitMin / MaxNoiseInitMax;
58 double RatioN = 0.0; // FIX ME !!!!!!!!!!!
59 //double RatioA = MaxDelayInitMin / AreaInitMax;
60 double RatioA = 1.0;
61 f = 0.0;
62 double fMin = COST_FACTOR;
63 if ( options.GetOptOption( WEIGHTS ) )
64 {
65 RatioT *= options.GetOptOption(WDELAY);
66 RatioP *= options.GetOptOption(WPOWER);
67 RatioN *= options.GetOptOption(WNOISE);
68 RatioA *= options.GetOptOption(WAREA);
69 }
70 double fMin_norm;
71 double fMax;
72 unsigned int Constraints = 0;
73 double MAXDelay = options.GetOptOption( MAXDELAY );
74 double MAXPower = options.GetOptOption( MAXPOWER );
75 double MAXNoise = options.GetOptOption( MAXNOISE );
76 double MAXArea = options.GetOptOption( MAXAREA );
77 if ( (MAXDelay > 0) || (MAXPower > 0) || (MAXNoise > 0) || (MAXArea > 0))
78 Constraints = 1;
79 fMin_norm = ( RatioT * MaxDelayInitMin / MaxDelayInitMin + \
80 RatioP * MaxPowerInitMin / MaxPowerInitMax + \
81 RatioN * MaxNoiseInitMin / MaxNoiseInitMax + \
82 RatioA * AreaInitMin / AreaInitMax);
83 fMax = (RatioT * MaxDelayInitMax / MaxDelayInitMin + \
84 RatioP * MaxPowerInitMax / MaxPowerInitMax + \
85 RatioN * MaxNoiseInitMax / MaxNoiseInitMax + \
86 RatioA * AreaInitMax / AreaInitMax) * \
87 COST_FACTOR / fMin_norm;
88 if (elapsed == 0)
89 fLast = fMin;
90 if ((count_min != NumTran) && (count_max != NumTran))
91 {
92 for ( unsigned int i = 0; i < NumPath; i++ )
93 {
94 if ( CPDelay[ i ] > maxT )
95 maxT = CPDelay[ i ];
96 if (CPDelay[ i ] > 0)
97 {
98 if ( CPPower[ i ] > maxP )
99 maxP = CPPower[ i ];
100 if ( CPNoise[ i ] > maxN )
101 maxN = CPNoise[ i ];
102 }
B.1. Main functions 183
103 }
104 f = (RatioT * maxT / MaxDelayInitMin + \
105 RatioP * maxP / MaxPowerInitMax + \
106 RatioN * maxN / MaxNoiseInitMax + \
107 RatioA * Area / AreaInitMax) * \
108 COST_FACTOR / fMin_norm;
109 if ( Constraints )
110 {
111 if (MAXDelay > 0)
112 {
113 if (maxT > MAXDelay)
114 {
115 f += (maxT - MAXDelay ) / MaxDelayInitMin *\
116 (maxT - MAXDelay ) / MaxDelayInitMin *\
117 COST_FACTOR / fMin_norm;
118 RetCode = CONT;
119 }
120 else
121 RetCode = END_ACC;
122 }
123 if (MAXPower > 0)
124 {
125 if (maxP > MAXPower)
126 {
127 f += (maxP - MAXPower ) / MaxPowerInitMax *\
128 (maxP - MAXPower ) / MaxPowerInitMax *\
129 COST_FACTOR / fMin_norm;
130 RetCode = CONT;
131 }
132 else
133 RetCode = END_ACC;
134 }
135 if (MAXNoise > 0)
136 {
137 if (maxN > MAXNoise)
138 {
139 f += (maxN - MAXNoise ) / MaxNoiseInitMax *\
140 (maxN - MAXNoise ) / MaxNoiseInitMax *\
141 COST_FACTOR / fMin_norm;
142 RetCode = CONT;
143 }
144 else
145 RetCode = END_ACC;
146 }
147 if (MAXArea > 0)
148 {
149 if (Area > MAXArea)
150 {
151 f += (Area - MAXArea ) / AreaInitMax *\
152 (Area - MAXArea ) / AreaInitMax *\
153 COST_FACTOR / fMin_norm;
154 RetCode = CONT;
155 }
156 else
157 RetCode = END_ACC;
158 }
159 }
160 }
161 else if (count_min == NumTran)
162 {
163 f = fMin;
164 maxT = MaxDelayInitMin;
165 maxP = MaxPowerInitMin;
166 maxN = MaxNoiseInitMin;
167 }
168 else if (count_max == NumTran)
169 {
170 f = fMax * COST_FACTOR / fMin_norm;
171 maxT = MaxDelayInitMax;
184 Appendix B. Source code
OptimizationAlgorithm.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11 #include "class_simulator.h"
12 #include "class_optimizator.h"
13
14
15 ///
16 OptimizationAlgorithm::OptimizationAlgorithm( const Circuit& circuit, const Options& options, EvaluationAlgorithm& simulation )
17 :
18 InternalSteps( 0 ), circuit( circuit ), options( options ),
19 Steps( 0 ), NumTran( 0 ), NumPath( 0 ),
20 Width( 0 ), CPDelay( 0 ), CPPower( 0 ),
21 CPNoise( 0 ), Area( 0.0 ), ValidPath(0),
22 MaxDelayInitMin( 0.0 ), MaxPowerInitMin( 0.0 ),
23 MaxNoiseInitMin( 0.0 ), AreaInitMin( 0.0 ),
24 MaxDelayInitMax( 0.0 ), MaxPowerInitMax( 0.0 ),
25 MaxNoiseInitMax( 0.0 ), AreaInitMax( 0.0 ),
26 Simulation( simulation )
27 {
28 // default inizialization
29 print_log( "Creating optimization algorithm..." );
30 NumTran = circuit.GetNTran();
31 Width = new double[ NumTran ];
32 NumPath = simulation.GetNPath();
33 CPDelay = new double[ NumPath ];
B.1. Main functions 185
Optimize.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11 #include "class_optimizator.h"
12 #include "class_simulator.h"
13 #include "slop.h"
14 #include "slop2.h"
15 #include "powell.h"
16 #include "anneal.h"
17 #include "test.h"
18
19 ///
20 int Optimize( const Circuit& circuit, const Options& options, EvaluationAlgorithm& simulation, double* LastWidth )
21 {
22 struct timeb start_t, stop_t;
23 ftime( &start_t );
24 char log[ 1024 ];
25 OptimizationAlgorithm* Opt;
26 switch ( options.WhichOptAlgorithm() )
27 {
28 case SLOP:
29 Opt = new Slop( circuit, options, simulation );
30 break;
31 case SLOP2:
32 Opt = new Slop2( circuit, options, simulation );
33 break;
34 case POWELL:
35 Opt = new Powell( circuit, options, simulation );
36 break;
37 case ANNEAL:
38 Opt = new Anneal( circuit, options, simulation );
39 break;
40 case TESTEVAL:
41 Opt = new TestEval( circuit, options, simulation );
42 default:
43 break;
44 }
186 Appendix B. Source code
Options.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7
8
9 ///
10 Options::Options() :
11 SimOptions( 0 ), OptOptions( 0 ),
12 SimulationChosed( HSPICE ), OptimizationChosed( SLOP ),
13 verbose( 0 ), manual(0), NameMosN( 0 ), NameMosP( 0 ), WorkPath( 0 )
14 {
15 print_log( "Parsing Options..." );
16 }
17
18 ///
19 Options::~Options()
B.1. Main functions 187
20 {
21 delete[] SimOptions;
22 delete[] OptOptions;
23 }
OptionsRead.cc
4 #include "mystdinclude.h"
5 #include "myenum.h"
6 #include "print.h"
7 #include "class_options.h"
8 #include "global.h"
9
10 ///
11 int Options::Read( const char* FileOptionsName )
12 {
13 char line[ 1024 ];
14 char opt[ 256 ];
15 char log[1024];
16 int RetCode = OK;
17 ifstream i_file( FileOptionsName );
18 if ( !i_file )
19 return NOT_FOUND;
20 unsigned int NumSimOptions = 0;
21 unsigned int NumOptOptions = 0;
22 while ( OptCommandOptions[ NumOptOptions++ ] );
23 while ( SimCommandOptions[ NumSimOptions++ ] );
24 OptOptions = new double[ NumOptOptions ];
25 SimOptions = new double[ NumSimOptions ];
26 for ( unsigned int i = 0; i < NumOptOptions; i++ )
27 OptOptions[ i ] = 0;
28 for ( unsigned int i = 0; i < NumSimOptions; i++ )
29 SimOptions[ i ] = 0;
30 unsigned int Line = 0;
31 while ( i_file.getline( line, 1023 ) )
32 {
33 Line++;
34 if ( sscanf( line, "%s ", opt ) == 1 )
35 if ( opt[ 0 ] != ’#’ )
36 {
37 GLOBCOMMANDOPT GlobalOption = WhichGBOption( opt );
38 SIMCOMMANDOPT SimOption = WhichSimOption( opt );
39 OPTCOMMANDOPT OptOption = WhichOptOption( opt );
40 switch ( GlobalOption )
41 {
42 case VERBOSE:
43 verbose = 1;
44 print_log("Well, let’s go verbose...");
45 break;
46 case MANUAL:
47 manual = 1;
48 print_log("So you think you’re better than me,");
49 print_log("in calculating critical paths?...");
50 break;
51 case SIMALG:
52 RetCode = NOT_FOUND;
53 sscanf( line, "%*s %s", opt );
54 for ( unsigned int S = 0 ; ( SimAlgorithms[ S ] != 0 ); S++ )
55 if ( !strcasecmp( opt, SimAlgorithms[ S ] ) )
56 {
57 SimulationChosed = ( SimMethod ) S;
58 RetCode = OK;
59 sprintf(log, "Simulator......%s", SimAlgorithms[ S ]);
60 print_log(log);
61 }
62 break;
63 case OPTALG:
64 RetCode = NOT_FOUND;
188 Appendix B. Source code
203 }
ReadTEch.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "tech.h"
7 #include "readt.h"
8
9 ///
10 struct _TECH_STR TECH;
11
12 int ReadTech()
13 {
nmos
ReadTEch.cc
15 TECH.Lmin = 0.25;
16 TECH.u0_n = 37.2; /** micron2̂ / (Volt * ns) */
16
17 TECH.Kp_n = 256.7916; /** uA / V2̂ */
17
18 TECH.vmax_n = 130.7952; /** micron / ns */
18
19 TECH.Vtn0 = 0.5885; /** Volt */
19
20 TECH.epss = 0.10359; /** fF / micron */
20
21 TECH.q = 1.602E-4; /** fF * Volt */
21
22 TECH.Na = 2.679E11; /** micron -̂3 */
22
23 TECH.gamma_n = 0.3356;
24 TECH.phi_n = 0.79424;
25 TECH.Cox_n = 6.903; /** fF / micron 2̂ */
25
26 TECH.C_nj = 689E-3; /** fF / micron2̂ */
26
27 TECH.C_np = 138E-3; /** fF / micron */
27
28 TECH.Ec_n = 3.516; /** Volt / micron = vmax/uo */
28
29 TECH.VT = 25.98E-3; /** Volt */
29
30 TECH.ni = 1.45E-2; /** micron -̂3 */
30
31 TECH.Df = 0.625; /** micron */
31
32 TECH.Cgd0_n = 0.32; /** fF / micron */
32
33 TECH.Cgs0_n = 0.32;
34 TECH.PB_n = 0.79424; /** Volt */
34
35 TECH.mj_n = 0.45495;
36 TECH.mjsw_n = 0.1;
37 TECH.XW_n = -0.79698; /** micron */
37
38 TECH.XL_n = 0; /** micron */
38
39 TECH.WD_n = 0.039849; /** micron */
39
40 TECH.LD_n = 0.0332; /** micron */
40
41 TECH.theta_n = 0.4314; /* V-̂1 */
B.1. Main functions 191
pmos
ReadTEch.cc
43 TECH.u0_p = 6.341; /** micron2̂ / (Volt * ns) */
43
44 TECH.Kp_p = 30.16; /** uA / V2̂ */
44
45 TECH.Cox_p = 6.903; /** fF / micron2̂ */
45
46 TECH.gamma_p = 0.69468;
47 TECH.phi_p = 0.79547;
48 TECH.Vtp0 = -0.434;
49 TECH.vmax_p = 57.6714; /** micron /ns */
49
50 TECH.C_pj = 596E-3; /** fF / micron2̂ */
50
51 TECH.C_pp = 122.1E-3; /** fF / micron */
51
52 TECH.Ec_p = 9.095; /** Volt / micron */
52
53 TECH.Cgd0_p = 0.5; /** fF / micron */
53
54 TECH.Cgs0_p = 0.5;
55 TECH.Nd = 2.8E11; /** micron -̂3 */
55
56 TECH.PB_p = 0.79547; /** Volt */
56
57 TECH.mj_p = 0.36085;
58 TECH.mjsw_p = 0.1;
59 TECH.XW_p = -0.89852; /** micron */
59
60 TECH.XL_p = 0; /** micron */
60
61 TECH.WD_p = 0; /** micron */
61
62 TECH.LD_p = 0.054697; /** micron */
62
63 TECH.theta_p = 0.4071; /** V-̂1 */
63
64 return OK;
65 }
SearchCritic.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11 #include "main.h"
12
13
14 ///
15 int SearchCriticalPath(const Circuit& circuit,
16 CritPathList& pathList,
17 const NodeList& nodeListGnd,
18 const NodeList& nodeListVdd,
19 Node& nodeInputList,
20 Node& gateInternalList,
21 const Options& options)
22 {
23
24 ListNodeList* gndCPath;
25 ListNodeList* vddCPath;
26 int RetCode;
192 Appendix B. Source code
27 char log[1024];
28 unsigned int nlg = nodeListGnd.GetNumList();
29 unsigned int nlv = nodeListVdd.GetNumList();
30 print_log("Searching Critical Path...");
31 #ifdef DEBUG
32 cerr << "Searching Critical Path..." << endl;
33 #endif
34 gndCPath = 0;
35 vddCPath = 0;
36 for (unsigned int i = 0; i < nlg; i++)
37 {
38 ListNodeList* tmp = new ListNodeList;
39 if (!tmp)
40 return NO_MEM;
41 tmp->next = gndCPath;
42 gndCPath = tmp;
43 for (unsigned int j = 0; j < nodeInputList.GetNumNode(); j++)
44 nodeInputList[j].flag = -1;
45 for (unsigned int j = 0; j < gateInternalList.GetNumNode(); j++)
46 gateInternalList[j].flag = -1;
47 RetCode = SearchCPRecurse(gndCPath, circuit.ValimNode(), i, nodeListGnd, nodeListVdd, nodeInputList, gateInternalList, 0);
48 if ((RetCode != OK) && (RetCode != CONT))
49 return RetCode;
50 }
51 sprintf(log, "found first critical paths (gnd)...");
52 print_log(log);
53 for (unsigned int i = 0; i < nlv; i++)
54 {
55 ListNodeList* tmp = new ListNodeList;
56 if (!tmp)
57 return NO_MEM;
58 tmp->next = vddCPath;
59 vddCPath = tmp;
60 for (unsigned int j = 0; j < nodeInputList.GetNumNode(); j++)
61 nodeInputList[j].flag = -1;
62 for (unsigned int j = 0; j < gateInternalList.GetNumNode(); j++)
63 gateInternalList[j].flag = -1;
64 RetCode = SearchCPRecurse(vddCPath, circuit.ValimNode(), i, nodeListVdd, nodeListGnd, nodeInputList, gateInternalList, 0);
65 if ((RetCode != OK) && (RetCode != CONT))
66 return RetCode;
67 }
68 sprintf(log, "found the other critical paths (vdd)...");
69 print_log(log);
70 ListNodeList* tmp = gndCPath;
71 unsigned int count = 0;
72 for (unsigned int gcount = 0; gcount < 2; gcount ++)
73 {
74 while (tmp)
75 {
76 #ifdef DEBUG
77 cerr << endl << "-------------> CP " << count << endl;
78 #endif
79 count++;
80 unsigned int nl = (tmp->NL).GetNumList();
81 if (nl)
82 {
83 if ((RetCode = pathList.Create()) != OK)
84 return RetCode;
85 unsigned int first_node = (((tmp->NL)[0])[0]).node;
86 unsigned int nn = ((tmp->NL)[nl - 1]).GetNumNode();
87 unsigned int output = (((tmp->NL)[nl - 1])[nn - 1]).node;
88 TransitionType Tr_in;
89 TransitionType Tr_out;
90 if (first_node == 0)
91 Tr_in = RISE;
92 else
93 Tr_in = FALL;
94 if (nl % 2)
95 Tr_out = (Tr_in == RISE ? FALL : RISE);
B.1. Main functions 193
96 else
97 Tr_out = (Tr_in == RISE ? RISE : FALL);
98 OPTCOMMANDOPT TRin = (Tr_in == RISE ? RISETIME : FALLTIME);
99 RetCode = pathList.InsertNodeOut(output, Tr_out);
100 if (RetCode != OK)
101 return RetCode;
102 unsigned int pos;
103 unsigned int first_input = 0;
104 double val;
105 double val_n;
106 for (unsigned int i = 0; i < nodeInputList.GetNumNode(); i++)
107 {
108 (nodeInputList[i]).flag = -1;
109 }
110 for (unsigned int i = 0; i < nl; i++)
111 {
112 first_node = (((tmp->NL)[i])[0]).node;
113 if (first_node == 0)
114 {
115 val = circuit.Valim();
116 val_n = 0;
117 }
118 else
119 {
120 val = 0;
121 val_n = circuit.Valim();
122 }
123 nn = ((tmp->NL)[i]).GetNumNode();
124 // set initial condition
125 unsigned int last_l_node = (((tmp->NL)[i])[nn - 1]).node;
126 if (i < nl - 1)
127 {
128 RetCode = pathList.InsertInitialCondition(last_l_node, val);
129 if (RetCode != OK)
130 return RetCode;
131 }
132 for (unsigned int j = 1; j < nn; j = j + 2)
133 {
134 unsigned int input = (((tmp->NL)[i])[j]).node;
135 #ifdef DEBUG
136 cerr << endl << "input " << input;
137 #endif
138 if (IsIn(input, nodeInputList, pos) == OK)
139 {
140 #ifdef DEBUG
141 cerr << " primary input (" << pos << ")";
142 #endif
143 if (first_input == 0)
144 {
145 first_input = input;
146 RetCode = pathList.InsertNodeIn(first_input, Tr_in, options.GetOptOption(TRin));
147 if (RetCode != OK)
148 return RetCode;
149 #ifdef DEBUG
150 cerr << " INPUT";
151 #endif
152 }
153 else
154 {
155 if ((nodeInputList[pos]).flag == -1)
156 {
157 RetCode = pathList.InsertActiveInputs(input, val);
158 if (RetCode != OK)
159 return RetCode;
160 #ifdef DEBUG
161 cerr << " ACTIVE IN " << val;
162 #endif
163 }
164 else
194 Appendix B. Source code
165 {
166 if (first_node == 0)
167 {
168 if ((nodeInputList[pos]).flag != int(circuit.ValimNode()))
169 return NOT_FOUND;
170 }
171 else
172 {
173 if ((nodeInputList[pos]).flag != 0)
174 return NOT_FOUND;
175 }
176 }
177 }
178 (nodeInputList[pos]).flag = (first_node == 0 ? circuit.ValimNode() : 0);
179 }
180 if (i > 0)
181 {
182 unsigned int nn2 = ((tmp->NL)[i - 1]).GetNumNode();
183 last_l_node = (((tmp->NL)[i - 1])[nn2 - 1]).node;
184 }
185 else
186 last_l_node = 0;
187 if (IsIn(input, gateInternalList, pos) == OK)
188 {
189 #ifdef DEBUG
190 cerr << " internal gate (" << pos << " last " << last_l_node << ")";
191 #endif
192 if (last_l_node != input)
193 {
194 if (first_input == 0)
195 {
196 first_input = input;
197 RetCode = pathList.InsertNodeIn(first_input, Tr_in, options.GetOptOption(TRin));
198 if (RetCode != OK)
199 return RetCode;
200 #ifdef DEBUG
201 cerr << " INPUT INTERNAL";
202 #endif
203 }
204 else
205 {
206 RetCode = pathList.InsertActiveInputs(input, val);
207 if (RetCode != OK)
208 return RetCode;
209 #ifdef DEBUG
210 cerr << " ACTIVE IN INTERNAL " << val;
211 #endif
212
213 }
214 }
215 }
216 unsigned int drain = (((tmp->NL)[i])[j - 1]).node;
217 unsigned int source = (((tmp->NL)[i])[j + 1]).node;
218 unsigned int nt = circuit.GetNTran();
219 for (unsigned int k = 0; k < nt; k++)
220 {
221 if ( (circuit[k]).Gate() == input)
222 {
223 if ( (((circuit[k]).Drain() == drain) &&
224 ((circuit[k]).Source() == source)) ||
225 (((circuit[k]).Drain() == source) &&
226 ((circuit[k]).Source() == drain)))
227 {
228 RetCode = pathList.InsertPathTransistor((circuit[k]).DevName(), (circuit[k]).TrType(), i);
229 if (RetCode != OK)
230 return RetCode;
231 }
232 }
233 }
B.1. Main functions 195
234 }
235 }
236 for (unsigned int i = 0; i < nodeInputList.GetNumNode(); i++)
237 {
238 if ((nodeInputList[i]).flag == -1)
239 {
240 unsigned int noActiveNode = (nodeInputList[i]).node;
241 double noActiveSupply;
242 if (gcount == 0) // CP starting with GND
243 noActiveSupply = 0;
244 else // CP starting with VDD
245 noActiveSupply = circuit.Valim();
246 #ifdef DEBUG
247 cerr << endl << "no active input "
248 << noActiveNode << " = " << noActiveSupply ;
249 #endif
250 RetCode = pathList.InsertNoActiveInputs(noActiveNode, noActiveSupply);
251 if (RetCode != OK)
252 return RetCode;
253 }
254 }
255 if ((RetCode = pathList.Stamp(nl)) != OK)
256 return RetCode;
257 }
258 tmp = tmp->next;
259 }
260 tmp = vddCPath;
261 }
262 sprintf(log, "found total %u critical paths...", pathList.GetNumPath());
263 print_log(log);
264 return OK;
265 }
SearchCriticRecurse.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11 #include "main.h"
12
13
14 ///
15 int SearchCPRecurse(ListNodeList* CPath,
16 unsigned int valnode,
17 unsigned int index,
18 const NodeList& nodeListFirst,
19 const NodeList& nodeListSecond,
20 Node& nodeInputList,
21 Node& gateInternalList,
22 unsigned int ilevel)
23 {
24
25 int RetCode;
26 unsigned int level = ilevel;
27 unsigned int i, j;
28 unsigned int nn = (nodeListFirst[index]).GetNumNode();
29 level++;
30 #ifdef DEBUG
31 cerr << endl;
32 for (i = 0; i < level; i++)
33 cerr << " ";
34 cerr << "(" << level << ") " << index << " - ";
35 #endif
196 Appendix B. Source code
SearchOkCond.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11 #include "main.h"
12
13 ///
14 int SearchOKCond(unsigned int node,
15 unsigned int valnode,
198 Appendix B. Source code
TransistorList.cc
3 #include "mystdinclude.h"
4 #include "print.h"
5 #include "myenum.h"
6 #include "class_devices.h"
7
8 ///
9 TransistorList::TransistorList() : NumTran( 0 ), head( 0 ), tail( 0 )
10 {}
11
B.1. Main functions 199
12 ///
13
14 TransistorList::~TransistorList()
15 {
16 TransistorNode* tmp;
17 while ( head )
18 {
19 tmp = head->next;
20 delete head;
21 head = tmp;
22 }
23 }
24
25 ///
26 const TransistorNode& TransistorList::operator[]( unsigned int index ) const
27 {
28 if ( index > NumTran )
29 error( NOT_FOUND, 0, "Index out of bound in [TransistorList]..." );
30 TransistorNode* tmp = head;
31 while ( tmp )
32 {
33 if ( tmp->Index() == index )
34 return * tmp;
35 tmp = tmp->next;
36 }
37 return *tmp;
38 }
39
40 ///
41 const TransistorNode& TransistorList::operator[]( const char* name ) const
42 {
43 TransistorNode * tmp = head;
44 while ( tmp )
45 {
46 if ( !strcasecmp( name, tmp->Name ) )
47 return * tmp;
48 tmp = tmp->next;
49 }
50 return *tmp;
51 }
52
53 ///
54 TransistorNode& TransistorList::operator[]( unsigned int index )
55 {
56 if ( index > NumTran )
57 error( NOT_FOUND, 0, "Index out of bound in [TransistorList]..." );
58 TransistorNode* tmp = head;
59 while ( tmp )
60 {
61 if ( tmp->Index() == index )
62 return * tmp;
63 tmp = tmp->next;
64 }
65 return *tmp;
66 }
67
TransistorListInsert.cc
3 #include "mystdinclude.h"
4 #include "print.h"
5 #include "myenum.h"
6 #include "class_devices.h"
7
8 ///
9 int TransistorList::Insert( const char *name, double w, double l, TransistorType t, unsigned int s, unsigned int g, unsigned int d )
10 {
11 TransistorNode * tmp;
200 Appendix B. Source code
12 if ( !head )
13 {
14 head = new TransistorNode( name, w, l, t, s, d, g, NumTran );
15 if ( !head )
16 return NO_MEM;
17 head->next = 0;
18 tail = head;
19 }
20 else
21 {
22 tmp = new TransistorNode( name, w, l, t, s, d, g, NumTran );
23 if ( !tmp )
24 return NO_MEM;
25 tmp->next = 0;
26 tail->next = tmp;
27 tail = tmp;
28 }
29 NumTran++;
30 return OK;
31 }
TransistorNode.cc
3 #include "mystdinclude.h"
4 #include "print.h"
5 #include "myenum.h"
6 #include "class_devices.h"
7
8
9 ///
10 TransistorNode::TransistorNode( const char *name, double w, double l, TransistorType t, unsigned int s, unsigned int d, unsigned int g,
11 Name( 0 ), width( w ), length( l ), type( t ),
12 source( s ), drain( d ), gate( g ), hashindex( index ), next( 0 )
13 {
14 Name = new char[ strlen( name ) + 1 ];
15 if ( !Name )
16 {
17 print_log( "FATAL ERROR" );
18 print_log( ReturnMessage[ NO_MEM ] );
19 error( NO_MEM, errno, "PANIC! " );
20 }
21 strcpy( Name, name );
22 }
23
24 ///
25 TransistorNode::~TransistorNode()
26 {
27 delete[] Name;
28 }
main.cc
4 #include "mystdinclude.h"
5 #include <signal.h>
6 #include "myenum.h"
7 #include "print.h"
8 #include "class_options.h"
9 #include "class_devices.h"
10 #include "class_nodes.h"
11 #include "class_critical.h"
12 #include "class_circuit.h"
13 #include "class_simulator.h"
14 #include "class_optimizator.h"
15 #include "hspice.h"
16 #include "fast.h"
17 #include "test.h"
18 #include "main.h"
B.1. Main functions 201
19 #include "readt.h"
20
21
22 ///
23 extern char *optarg;
24 extern int optind;
25
26 ///
27 int main ( int argc, char **argv )
28 {
29 int c;
30 char *FileIn;
31 char *FileOptions;
32
33 time_t tm = time( 0 );
34 signal(15, catch_stop);
35 signal(2, catch_stop);
36 char log[ 256 ];
37 print_log( "\n*************************" );
38 sprintf( log, "%s Version: %s Copyrigth MFD 1998 ", argv[ 0 ], VERSION );
39 print_log( log );
40 print_log( "*************************" );
41 print_log( ctime( &tm ) );
42 // some default initialization
43 FileOptions = 0;
44 while ( ( c = getopt( argc, argv, "hf:t:" ) ) != -1 )
45 {
46 switch ( c )
47 {
48 case ’h’: //HELP
49 return print_help( argv[ 0 ] );
50 break;
51 case ’f’:
52 FileOptions = new char[ strlen( optarg ) + 1 ];
53 if ( !FileOptions )
54 {
55 print_log( "FATAL ERROR:" );
56 print_log( ReturnMessage[ NO_MEM ] );
57 error( NO_MEM, errno, "HEY! " );
58 }
59 strcpy( FileOptions, optarg );
60 break;
61 case ’?’:
62 default:
63 return print_help( argv[ 0 ] );
64 break;
65 }
66 }
67
68 if ( ( argc - optind ) != 1 )
69 return print_help( argv[ 0 ] );
70 else
71 {
72 FileIn = new char[ strlen( argv[ optind ] ) + 1 ];
73 if ( !FileIn )
74 {
75 print_log( "FATAL ERROR:" );
76 print_log( ReturnMessage[ NO_MEM ] );
77 error( NO_MEM, errno, "HEY! " );
78 }
79 strcpy( FileIn, argv[ optind ] );
80 if ( !FileOptions )
81 {
82 FileOptions = new char[ strlen( "options.conf" ) + 1 ];
83 strcpy( FileOptions, "options.conf" );
84 }
85 }
86 Options options;
87 int RetCode;
202 Appendix B. Source code
nrutil.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "nrutil.h"
6 #include "print.h"
7
8 ///
9 const int NR_END = 1;
10 #define FREE_ARG char*
11
12 ///
13 double *dvector ( long nl, long nh ) /* allocate a double vector with subscript range v[nl..nh] */
13
14 {
15 double * v;
16 17 v = new double[ nh - nl + 1 + NR_END ];
18 if ( !v )
19 {
20 print_log( "FATAL ERROR:" );
21 print_log( ReturnMessage[ NO_MEM ] );
22 //error(NO MEM, errno, ”HEY! ”);
23 return 0;
24 }
25 return v - nl + NR_END;
26 }
27 ///
28 double **dmatrix ( long nrl, long nrh, long ncl, long nch ) /* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch] */
28
29 {
30 long i, nrow = nrh - nrl + 1, ncol = nch - ncl + 1;
31 double **m; 31
32 33 m = new double * [ nrow + NR_END ];
34
35 if ( !m )
36 {
37 print_log( "FATAL ERROR:" );
38 print_log( ReturnMessage[ NO_MEM ] );
39 //error(NO MEM, errno, ”HEY! ”);
40 return 0;
41 }
42 m += NR_END;
43 m -= nrl; 43
44 45 m[ nrl ] = new double[ nrow * ncol + NR_END ];
46
47 if ( !m[ nrl ] )
48 {
204 Appendix B. Source code
print final.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11 #include "class_simulator.h"
12
13 ///
14 void print_final(const char* FileNetList, const Circuit& circuit, unsigned int NP, EvaluationAlgorithm& simulation, double* LastWidth )
15 {
16 unsigned int n = circuit.GetNTran();
17 char log[ 1024 ];
18 print_log( "Final Dimensions: " );
19 for ( unsigned int i = 0; i < n; i++ )
20 {
21 int pos = circuit.TranPos( circuit[ i ].DevName() );
22 sprintf( log, "W[%s] = %3.3gu", circuit[ i ].DevName(), LastWidth[ pos ] );
23 print_log( log );
24 }
25 print_log( "Final critical paths: " );
26 for ( unsigned int i = 0; i < NP; i++ )
27 {
28 sprintf( log, "%u) Delay=%g ps, Energy=%g pJ, Noise=%g", i,
29 simulation.GetDelay( i ),
30 simulation.GetPower( i ),
31 simulation.GetNoise( i ) );
32 print_log( log );
33 }
34 sprintf( log, "Area=%g ", simulation.GetArea() );
35 print_log(log);
36 char line[ 1024 ];
37 char line2[ 1024 ];
38 char* FileNetOut;
39 FileNetOut = new char[ strlen( FileNetList ) + strlen( NetListSuffix ) + 1 ];
40 if ( !FileNetOut )
41 {
42 print_log( "FATAL ERROR:" );
43 print_log( ReturnMessage[ NO_MEM ] );
B.1. Main functions 205
113 }
114 i_file.close();
115 o_file.close();
116 }
print init.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "class_options.h"
7 #include "class_devices.h"
8 #include "class_nodes.h"
9 #include "class_critical.h"
10 #include "class_circuit.h"
11
12 ///
13 void print_init( const Circuit& circuit, const Options& options, unsigned int NP )
14 {
15 unsigned int n = circuit.GetNTran();
16 char log[ 1024 ];
17 sprintf( log, "Circuit: %u Transistor || %u Critical paths", n, NP );
18 print_log( log );
19 print_log( "Initial Dimensions: " );
20 for ( unsigned int i = 0; i < n; i++ )
21 {
22 sprintf( log, "W[%s] = %3.3gu", circuit[ i ].DevName(), circuit[ i ].Width() );
23 print_log( log );
24 }
25 }
print log.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6
7 ///
8 void print_log( const char *OutString )
9 {
10 ofstream o_file( "OPT.log", ios::app );
11 if ( o_file )
12 {
13 o_file << OutString << endl;
14 o_file.close();
15 }
16 }
signal.cc
3 #include "mystdinclude.h"
4 #include <signal.h>
5
6
7
8 ///
9 void catch_stop(int n)
10 {
11 if (n == 15)
12 cerr << endl << "TERM" << endl;
13 if (n == 2)
14 {
15 cerr << endl << "TERM2" << endl;
16 exit(0);
17 }
18 }
B.1. Main functions 207
208 Appendix B. Source code
Slop.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "slop.h"
7
8 ///
9 Slop::Slop( const Circuit& circuit, const Options& options, EvaluationAlgorithm& simulation )
10 :
11 OptimizationAlgorithm( circuit, options, simulation ),
12 TMat(0), TMatOld(0), GMat(0), T(0), SaveW(0)
13 {
14 print_log( "Creating Slop instance..." );
15 TMat = new double * [ NumPath ];
16 TMatOld = new double * [ NumPath ];
17 GMat = new double * [ NumPath ];
18 T = new double [ NumPath ];
19 SaveW = new double[ NumTran ];
20 if ( ( !TMat ) || ( !TMatOld ) || ( !GMat ) || ( !T ) || ( !SaveW ) )
21 {
22 print_log( "FATAL ERROR:" );
23 print_log( ReturnMessage[ NO_MEM ] );
24 error( NO_MEM, errno, "HEY! " );
25 }
26 for ( unsigned int i = 0; i < NumPath; i++ )
27 {
28 TMat[ i ] = new double [ NumTran ];
29 TMatOld[ i ] = new double [ NumTran ];
30 GMat[ i ] = new double [ NumTran ];
31 if ( ( !TMat[ i ] ) || ( !TMatOld[ i ] ) || ( !GMat[ i ] ) )
32 {
33 print_log( "FATAL ERROR:" );
34 print_log( ReturnMessage[ NO_MEM ] );
35 error( NO_MEM, errno, "HEY! " );
36 }
37 }
38 }
39
40 ///
41 Slop::~Slop()
42 {
43 for ( unsigned int i = 0; i < NumPath; i++ )
44 {
45 delete[] TMat[ i ];
46 delete[] GMat[ i ];
47 }
48 delete[] TMat;
49 delete[] TMatOld;
50 delete[] GMat;
51 delete[] SaveW;
52 }
53
54 ///
55 int Slop::Run()
56 {
57 int Wbig;
58 int RetCode;
59 for ( unsigned int i = 0; i < NumTran; i++ )
60 SaveW[ i ] = Width[ i ];
61 double max = 0;
62 double TMax = 0;
63 unsigned int jmax;
64 double dummy;
65 unsigned int end_acc = 0;
66 for ( Steps = 1; ( Steps < options.GetOptOption( MAXSTEPS ) ) \
67 && (max >= 0.0) \
210 Appendix B. Source code
137 }
138 if ( Wbig != -1 )
139 SaveW[ Wbig ] += options.GetOptOption( DELTA );
140 else
141 max = -1.0; // so max ¡ 0
142 }
143
144 for ( unsigned int i = 0; i < NumTran; i++ )
145 {
146 Width[ i ] = SaveW[ i ];
147 }
148 dummy = SlopNormSim( Width, RetCode);
149 return RetCode;
150 }
SlopNorm.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "slop.h"
7
8
9 ///
10 double Slop::SlopNormSim( const double* NewWidth, int& RetCode)
11 {
12 return NormSim( NewWidth, RetCode);
13 }
212 Appendix B. Source code
Slop2.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "slop2.h"
7
8 ///
9 Slop2::Slop2( const Circuit& circuit, const Options& options, EvaluationAlgorithm& simulation )
10 :
11 OptimizationAlgorithm( circuit, options, simulation ),
12 TMat(0), TMatOld(0), GMat(0), SaveW(0)
13 {
14 print_log( "Creating Slop2 instance..." );
15 TMat = new double * [ NumPath ];
16 TMatOld = new double * [ NumPath ];
17 GMat = new double * [ NumPath ];
18 SaveW = new double[ NumTran ];
19 if ( ( !TMat ) || ( !TMatOld ) || ( !GMat ) || ( !SaveW ) )
20 {
21 print_log( "FATAL ERROR:" );
22 print_log( ReturnMessage[ NO_MEM ] );
23 error( NO_MEM, errno, "HEY! " );
24 }
25 for ( unsigned int i = 0; i < NumPath; i++ )
26 {
27 TMat[ i ] = new double [ NumTran ];
28 TMatOld[ i ] = new double [ NumTran ];
29 GMat[ i ] = new double [ NumTran ];
30 if ( ( !TMat[ i ] ) || ( !TMatOld[ i ] ) || ( !GMat[ i ] ) )
31 {
32 print_log( "FATAL ERROR:" );
33 print_log( ReturnMessage[ NO_MEM ] );
34 error( NO_MEM, errno, "HEY! " );
35 }
36 }
37 }
38
39 ///
40 Slop2::~Slop2()
41 {
42 for ( unsigned int i = 0; i < NumPath; i++ )
43 {
44 delete[] TMat[ i ];
45 delete[] GMat[ i ];
46 }
47 delete[] TMat;
48 delete[] TMatOld;
49 delete[] GMat;
50 delete[] SaveW;
51 }
52
53 ///
54 int Slop2::Run()
55 {
56 int Wbig;
57 int RetCode;
58 for ( unsigned int i = 0; i < NumTran; i++ )
59 SaveW[ i ] = Width[ i ];
60 double max = 0;
61 double dummy;
62 for ( unsigned int i = 0; i < NumTran; i++ )
63 Width[ i ] = SaveW[ i ];
64 dummy = Slop2NormSim( Width, RetCode);
65 if ( (RetCode != OK ) && (RetCode != CONT))
66 return RetCode;
67 for ( unsigned int i = 0; i < NumPath; i++ )
B.2. Optimization algorithms 213
68 {
69 for ( unsigned int j = 0; j < NumTran; j++ )
70 TMatOld[ i ][ j ] = dummy;
71 }
72 unsigned int end_acc = 0;
73 for ( Steps = 1; ( Steps < options.GetOptOption( MAXSTEPS ) ) \
74 && ( max >= 0.0 ) \
75 && ( InternalSteps < options.GetOptOption( MAXSTEPS ) \
76 && (end_acc == 0)); Steps++ )
77 {
78
79 for ( unsigned int i = 0; i < NumTran; i++ )
80 Width[ i ] = SaveW[ i ];
81 for ( unsigned int i = 0; i < NumTran; i++ )
82 {
83 Width[ i ] += options.GetOptOption( DELTA );
84 if (options.GetOptOption( WMAX ) > 0)
85 if ( Width[ i ] >= options.GetOptOption( WMAX ) )
86 Width[ i ] = options.GetOptOption( WMAX );
87 dummy = Slop2NormSim( Width, RetCode);
88 if ((RetCode != OK) && (RetCode != CONT) && (RetCode != MAX_STEPS) && (RetCode != END_ACC))
89 return RetCode;
90 else if ((RetCode == MAX_STEPS) || (RetCode == END_ACC))
91 end_acc = 1;
92 Width[ i ] = SaveW[ i ];
93 for ( unsigned int j = 0; j < NumPath; j++ )
94 {
95 TMat[ j ][ i ] = dummy;
96 }
97 }
98 Wbig = -1;
99 max = 0.0;
100 for ( unsigned int i = 0; i < NumPath; i++ )
101 for ( unsigned int j = 0; j < NumTran; j++ )
102 {
103 GMat[ i ][ j ] = TMatOld[ i ][ j ] - TMat[ i ][ j ];
104 if ( GMat[ i ][ j ] > max )
105 {
106 max = GMat[ i ][ j ];
107 Wbig = j;
108 }
109 TMatOld[ i ][ j ] = TMat[ i ][ j ];
110 }
111 if ( Wbig != -1 )
112 SaveW[ Wbig ] += options.GetOptOption( DELTA );
113 else
114 max = -1.0; // so max ¡ 0
115 }
116
117 for ( unsigned int i = 0; i < NumTran; i++ )
118 Width[ i ] = SaveW[ i ];
119 dummy = Slop2NormSim( Width, RetCode);
120 return RetCode;
121 }
Slop2Norm.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "slop2.h"
7
8
9 ///
10 double Slop2::Slop2NormSim( const double* NewWidth, int& RetCode)
11 {
12 return NormSim( NewWidth, RetCode);
13 }
214 Appendix B. Source code
B.2. Optimization algorithms 215
TestEv.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "test.h"
7
8 ///
9 TestEval::TestEval( const Circuit& circuit, const Options& options, EvaluationAlgorithm& simulation )
10 :
11 OptimizationAlgorithm( circuit, options, simulation ) ,
12 TryW(0)
13 {
14 print_log( "Creating TestEval instance..." );
15 TryW = new double[ NumTran ];
16 if ( !TryW )
17 {
18 print_log( "FATAL ERROR:" );
19 print_log( ReturnMessage[ NO_MEM ] );
20 error( NO_MEM, errno, "HEY! " );
21 }
22 }
23
24 ///
25 TestEval::~TestEval()
26 {
27 delete[] TryW;
28 }
29
30 ///
31 int TestEval::Run()
32 {
33 int RetCode;
34 double dummy;
35 for ( unsigned int i = 0; i < NumTran; i++ )
36 TryW[ i ] = options.GetOptOption( WMIN );
37 for ( Steps = 1; Steps < options.GetOptOption( MAXSTEPS ) ; Steps++ )
38 {
39
40 dummy = TestEvalNormSim( TryW, RetCode);
41 if ( (RetCode != OK ) && (RetCode != CONT))
42 return RetCode;
43 // if (Steps <= NumTran)
44 // TryW[(Steps - 1)] += options.GetOptOption( DELTA );
45 // else
46 // TryW[(Steps - 1) % NumTran] += options.GetOptOption(DELTA);
47 for (int i = 0; i < NumTran; i++)
48 TryW[i] += options.GetOptOption( DELTA );
49 }
50 return OK;
51 }
TestNorm.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "test.h"
7
8
9 ///
10 double TestEval::TestEvalNormSim( const double* NewWidth, int& RetCode)
11 {
12 return NormSim( NewWidth, RetCode);
13 }
216 Appendix B. Source code
B.3 Simulators
B.3. Simulators 217
Basicnet.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "hspice.h"
7
8 ///
9 int Hspice::BasicNetlist( const double* NewWidth, unsigned int Np, const Circuit& circuit )
10 {
11 char * FileHspice;
12 char log[ 1024 ];
13 char suffix[ 8 ];
14 sprintf( suffix, "_%u", Np );
15 FileHspice = new char[ strlen( WorkPath ) + strlen( SimFile ) + strlen( suffix ) + 1 ];
16 strcpy( FileHspice, WorkPath );
17 strcat( FileHspice, SimFile );
18 strcat( FileHspice, suffix );
19 ofstream o_file( FileHspice );
20 ifstream i_file( NetlistFile );
21 if ( !o_file )
22 {
23 sprintf( log, " ERROR opening file %s ", FileHspice );
24 print_log( log );
25 return NOT_FOUND;
26 }
27 if ( !i_file )
28 {
29 sprintf( log, " ERROR opening file %s ", NetlistFile );
30 print_log( log );
31 return NOT_FOUND;
32 }
33 char line[ 1024 ];
34 i_file.getline( line, 1023 );
35 o_file << endl << endl << endl << "****** INPUTS ******" << endl;
36 o_file << ".include inputs." << Np << endl;
37 o_file << "********************" << endl;
38 while ( i_file.getline( line, 1023 ) )
39 {
40 unsigned int i = 0;
41 while ( isspace( line[ i++ ] ) );
42 char s = line[ --i ];
43 char st1[ 16 ], st2[ 16 ], st3[ 16 ];
44 int n1, n2, n3, n4;
45 if ( ( s == ’M’ ) || ( s == ’m’ ) || ( s == ’X’ ) || ( s == ’x’ ) )
46 {
47 sscanf( line, "%s %d %d %d %d %s %*s %s", st1, &n1, &n2, &n3, &n4, st2, st3 );
48 int position = circuit.TranPos( st1 );
49 if ( position == -1 )
50 return NOT_FOUND;
51 o_file << st1 << " " << n1 << " " << n2 << " " << n3 << " " << n4 << \
52 " " << st2 << " " << st3 << " w=" << setprecision( 4 ) << NewWidth[ position ] << "u" << endl;
53 }
54 else
55 o_file << line << endl;
56 }
57 o_file.close();
58 i_file.close();
59 return OK;
60 }
Delayread.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
218 Appendix B. Source code
6 #include "hspice.h"
7
8 ///
9 int Hspice::DelayRead( double& del, double& energy, unsigned int Np )
10 {
11 char * FileMeas;
12 char suffix[ 8 ];
13 sprintf( suffix, "_%d", Np );
14 FileMeas = new char[ strlen( WorkPath ) + strlen( SimFile ) + strlen( suffix ) + strlen( SuffixFileMeasure ) + 1 ];
15 if ( !FileMeas )
16 return NO_MEM;
17 strcpy( FileMeas, WorkPath );
18 strcat( FileMeas, SimFile );
19 strcat( FileMeas, suffix );
20 strcat( FileMeas, SuffixFileMeasure );
21 ifstream i_file( FileMeas );
22 if ( !i_file )
23 {
24 print_log( "ERROR opening hspice measure file " );
25 return NOT_FOUND;
26 }
27 char line[ 1023 ];
28 for ( unsigned int i = 0; i <= 3; i++ )
29 if ( !i_file.getline( line, 1023 ) )
30 {
31 print_log( "ERROR parsing hspice measure file " );
32 return PARSE_ERROR;
33 }
34 sscanf( line, "%lg %lg", &del, &energy);
35 i_file.close();
36 del *= 1E12; // picosec.
37 energy *= ( 1E12); // pJ
38 delete[] FileMeas;
39 return OK;
40 }
Hspice.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "hspice.h"
7
8 //////////////////////////////////////////////////////////////////////////////
9 // //
10 // DELAY MODULE – HSPICE //
11 // //
12 // 1998 October 9 – Politecnico di Torino – VLSI LAB //
13 // //
14 // Mariagrazia Graziano – Ph.D. Student //
15 // //
16 ////////////////////////////////////////////////////////////////////////////////
17
18 Hspice::Hspice( const CritPathList& pathlist, const Options& options, const char* NE )
19 :
20 EvaluationAlgorithm( pathlist, options ), SimTime( 0.0 ),
21 WorkPath( 0 ), SimFile( 0 ),
22 InputFile( 0 ), NetlistFile( 0 ), SuffixFileMeasure( 0 )
23 {
24 print_log( "Creating Hspice instance..." );
25 WorkPath = new char[ strlen( options.Workpath() ) + 1 ];
26 SimFile = new char[ strlen( "net2use" ) + 1 ];
27 InputFile = new char[ strlen( "inputs" ) + 1 ];
28 NetlistFile = new char[ strlen( NE ) + strlen( NetListSuffix ) + 1 ];
29 if ( !SimFile || ! InputFile || !NetlistFile )
30 {
31 print_log( "FATAL ERROR:" );
32 print_log( ReturnMessage[ NO_MEM ] );
B.3. Simulators 219
HspiceArea.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "hspice.h"
7
8 ///
9 double Hspice::CalcArea( const double *NewWidth, unsigned int NT )
220 Appendix B. Source code
10 {
11 double A = 0.0;
12 for ( unsigned int i = 0; i < NT; i++ )
13 {
14 A += NewWidth[ i ];
15 }
16 return ( A );
17 }
Setinput.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "hspice.h"
7
8 ///
9 int Hspice::SetInput( unsigned int Np, double Val )
10 {
11 char suffix[ 8 ];
12 sprintf( suffix, ".%u", Np );
13 char *Inputs = new char[ strlen( WorkPath ) + strlen( InputFile ) + strlen( suffix ) + 1 ];
14 if ( !Inputs )
15 return NO_MEM;
16 strcpy( Inputs, WorkPath );
17 strcat( Inputs, InputFile );
18 strcat( Inputs, suffix );
19 ofstream input_file( Inputs );
20 if ( !input_file )
21 return NOT_FOUND;
22 unsigned int node_in = pathlist[ Np ].GetNodeIn();
23 unsigned int node_out = pathlist[ Np ].GetNodeOut();
24 TransitionType TIn = pathlist[ Np ].GetTransitionIn();
25 if ( TIn == RISE )
26 input_file << endl << "v_node_in " << node_in << \
27 " 0 " << " pwl(0 0 " << ( SimTime / 2.0 ) << \
28 "p 0 " << ( SimTime / 2.0 ) + pathlist[ Np ].GetInTime() << "p " << Val << ")";
29 else if ( TIn == FALL )
30 input_file << endl << "v_node_in " << node_in << \
31 " 0 " << " pwl(0 " << Val << " " << ( SimTime / 2.0 ) << \
32 "p " << Val << " " << ( SimTime / 2.0 ) + \
33 pathlist[ Np ].GetInTime() << "p 0)" ;
34 unsigned int node;
35 double nodeVal;
36 while ( pathlist[ Np ].TraverseActiveInputs( node, nodeVal ) )
37 {
38 input_file << endl << "v_ACTIVE_" << node << " " << \
39 node << " 0 dc " << nodeVal;
40 }
41 while ( pathlist[ Np ].TraverseNoActiveInputs( node, nodeVal ) )
42 {
43 input_file << endl << "v_NO_ACTIVE_" << node << " " << \
44 node << " 0 dc " << nodeVal;
45 }
46 while ( pathlist[ Np ].TraverseInitialConditions( node, nodeVal ) )
47 {
48 input_file << endl << endl << ".ic v(" << node << ")=" << \
49 nodeVal;
50 }
51 TransitionType TOut = pathlist[ Np ].GetTransitionOut();
52 if ( TOut == RISE )
53 input_file << endl << endl << ".ic v(" << node_out << ")=0";
54 else if ( TOut == FALL )
55 input_file << endl << endl << ".ic v(" << node_out << ")=" << Val;
56
57 // Delay meas.
58 input_file << endl << endl << ".measure tran path_n0_" << Np << "delay " << \
59 " trig v(" << node_in << ")" << " val=" << Val*0.5 << " " << TransitionString[ TIn ] << "=1" << \
B.3. Simulators 221
60 " targ v(" << node_out << ")" << " val=" << Val * 0.5 << " " << TransitionString[ TOut ] << "=1";
61 // Power meas.
62 input_file << endl << endl << ".measure tran path_n0_" << Np << "power " << \
63 " integ " << "POWER" << " from=0ps" << " to=" << SimTime << "ps ";
64 input_file << endl << endl << ".tran 10p " << SimTime << "p" << endl;
65 input_file.close();
66 return OK;
67 }
Simcall.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "hspice.h"
7
8 ///
9 int Hspice::SimCall( unsigned int Np )
10 {
11 char system_string[ 512 ];
12 sprintf( system_string, "cd %s && hspice %s_%d 1>./hspice.log.%d 2>&1", WorkPath, SimFile, Np, Np );
13 if ( system( system_string ) == -1 )
14 {
15 print_log( "ERROR invoking hspice simulator " );
16 return NO_MEM;
17 }
18 return OK;
19 }
222 Appendix B. Source code
Brackets.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8 const double FACTOR = 1.6;
9 const int NTRY = 50;
10 const double ZEPS = 1e-2;
11
12 ///
13 int Fast::Brackets( const Circuit& circuit, unsigned int NP, unsigned int NC, double& start, double& end, TransistorType type, unsigned
14 {
15 int jj;
16 double f1, f2, x1, x2;
17
18 if ( start == end )
19 {
20 x1 = x2 = 0;
21 RetCode = NOT_FOUND;
22 return 0;
23 }
24 if ( type == NMOS )
25 {
26 f1 = EqN( circuit, NP, NC, start, RetCode, j, n, p, NewWidth );
27 f2 = EqN( circuit, NP, NC, end, RetCode, j, n, p, NewWidth );
28 }
29 else if ( type == PMOS )
30 {
31 f1 = EqP( circuit, NP, NC, start, RetCode, j, n, p, NewWidth );
32 f2 = EqP( circuit, NP, NC, end, RetCode, j, n, p, NewWidth );
33 }
34 for ( jj = 1; jj <= NTRY; jj++ )
35 {
36 if ( f1 * f2 < 0.0 )
37 {
38 RetCode = OK;
39 return 1;
40 }
41 if ( fabs ( f1 ) < fabs ( f2 ) )
42 {
43 start += FACTOR * ( start - end );
44 if ( start <= 0.0 )
45 start = ZEPS;
46 if ( type == NMOS )
47 f1 = EqN( circuit, NP, NC, start, RetCode, j, n, p, NewWidth );
48 else if ( type == PMOS )
49 f1 = EqP( circuit, NP, NC, start, RetCode, j, n, p, NewWidth );
50 }
51 else
52 {
53 end += FACTOR * ( end - start );
54 if ( end <= 0.0 )
55 end = ZEPS;
56 if ( type == NMOS )
57 f2 = EqN( circuit, NP, NC, end, RetCode, j, n, p, NewWidth );
58 else if ( type == PMOS )
59 f2 = EqP( circuit, NP, NC, end, RetCode, j , n, p, NewWidth );
60 }
61 }
62 RetCode = NOT_FOUND;
63 return 0;
64 }
B.3. Simulators 223
CalcpowN.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8
9 ///
10 int Fast::CalcPowerN( const Circuit& circuit, unsigned int NP, unsigned int NC, double& Ecc, double& Esc, unsigned int n, unsigned int p, const double*
11 {
12
13 double H_1, I_1, Vc, t0_bs, C_n;
14 double J_1, K_1, M_1, N_1;
15 double t0 = t0_n[ n ];
16 double tauo = tauo_n[ n ];
17 double tin = taui_n[ 1 ];
18 t0_bs = tin * ( VDD + TECH.Vtp0 ) / VDD;
19 double tc = (VDD * tauo_n[n] * (t0_n[n] - taui_n[n]) + \
20 Vs_n[n] * taui_n[n] * (tauo_n[n] - t0_n[n])) / \
21 (VDD * (t0_n[n] - taui_n[n]) + Vs_n[n] * (tauo_n[n] - t0_n[n]));
22 Esc = 0;
23 Ecc = 0;
24 if (p > 0)
25 {
26 Vc = TECH.Ec_p * L_p[ p ];
27 H_1 = Vc * beta_p[ p ] * ( VDD * ( t0 - tauo ) * \
28 ( 2 * Vc * ( t0 - tauo ) - Vd_n[ n ] * tin ) - \
29 Vd_n[ n ] * tin * ( Vc * ( t0 - tauo ) - Vd_n[ n ] * tauo + 2 * TECH.Vtp0 * ( t0 - tauo ) ) ) / \
30 ( 2 * Vd_n[ n ] * tin * ( t0 - tauo ) );
31 I_1 = Vc * beta_p[ p ] * ( 2 * VDD * ( t0 - tauo ) - Vd_n[ n ] * tin ) / \
32 ( 2 * tin * ( t0 - tauo ) );
33 J_1 = ( Vc * Vc ) * beta_p[ p ] * ( t0 - tauo ) * ( 2 * ( VDD * VDD ) * ( t0 - tauo ) + \
34 2 * VDD * ( Vc * ( t0 - tauo ) + Vd_n[ n ] * ( tauo - tin ) ) - \
35 Vd_n[ n ] * tin * ( Vc + 2 * TECH.Vtp0 ) );
36 K_1 = 2 * Vd_n[ n ] * tin * ( VDD * ( t0 - tauo ) + \
37 Vc * ( t0 - tauo ) + Vd_n[ n ] * tauo );
38 M_1 = VDD * Vc * beta_p[ p ] * ( VDD + 2 * TECH.Vtp0 ) / ( 2 * ( VDD + Vc ) );
39 N_1 = VDD * VDD * Vc * beta_p[ p ] / ( tin * ( VDD + Vc ) );
40 if ( t0_bs < tauo )
41 {
42 Esc = ( J_1 * ( K_1 - 2 * Vd_n[ n ] * tin * ( VDD * ( t0 - tauo ) + Vd_n[ n ] * tauo ) ) * \
43 0.25 * LOG ( 2 * Vd_n[ n ] * Vd_n[ n ] * t0 * tin - K_1 ) / ( Vd_n[ n ] * Vd_n[ n ] * Vd_n[ n ] * \
44 ( tin * tin ) * ( tauo - t0 ) ) + \
45 J_1 * ( K_1 - 2 * Vd_n[ n ] * tin * ( VDD * ( t0 - tauo ) + Vd_n[ n ] * tauo ) ) * \
46 0.25 * LOG ( 2 * Vd_n[ n ] * Vd_n[ n ] * t0_bs * tin - K_1 ) / \
47 ( Vd_n[ n ] * Vd_n[ n ] * Vd_n[ n ] * ( tin * tin ) * ( t0 - tauo ) ) + \
48 ( ( t0 - t0_bs ) * \
49 ( 3 * H_1 * Vd_n[ n ] * tin * ( 2 * VDD * ( t0 - tauo ) - Vd_n[ n ] * ( t0 + t0_bs - 2 * tauo ) ) + \
50 I_1 * Vd_n[ n ] * tin * ( 3 * VDD * ( t0 + t0_bs ) * ( t0 - tauo ) - Vd_n[ n ] * ( 2 * ( t0 * t0 ) + \
51 t0 * ( 2 * t0_bs - 3 * tauo ) + t0_bs * ( 2 * t0_bs - 3 * tauo ) ) ) - 3 * J_1 ) ) / \
52 ( 6 * Vd_n[ n ] * tin * ( t0 - tauo ) ) );
53 }
54 else
55 {
56 Esc = ( J_1 * ( K_1 - 2 * Vd_n[ n ] * tin * ( VDD * ( t0 - tauo ) + Vd_n[ n ] * tauo ) ) * \
57 0.25 * LOG ( 2 * Vd_n[ n ] * Vd_n[ n ] * t0 * tin - K_1 ) / ( Vd_n[ n ] * Vd_n[ n ] * Vd_n[ n ] * \
58 ( tin * tin ) * ( tauo - t0 ) ) + \
59 J_1 * ( K_1 - 2 * Vd_n[ n ] * tin * ( VDD * ( t0 - tauo ) + Vd_n[ n ] * tauo ) ) * \
60 0.25 * LOG ( 2 * Vd_n[ n ] * Vd_n[ n ] * tauo * tin - K_1 ) / \
61 ( Vd_n[ n ] * Vd_n[ n ] * Vd_n[ n ] * ( tin * tin ) * ( t0 - tauo ) ) + \
62 ( 3 * H_1 * Vd_n[ n ] * tin * ( t0 - tauo ) * ( 2 * VDD - Vd_n[ n ] ) + \
63 I_1 * Vd_n[ n ] * tin * ( t0 - tauo ) * \
64 ( 3 * VDD * ( t0 + tauo ) - Vd_n[ n ] * ( 2 * t0 + tauo ) ) - 3 * J_1 ) / \
65 ( 6 * Vd_n[ n ] * tin ) );
66 }
67 Esc = fabs( Esc );
68 }
69 const char* name;
70 unsigned int node = 0;
224 Appendix B. Source code
CalcpowP.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8
9 ///
10 int Fast::CalcPowerP( const Circuit& circuit, unsigned int NP, unsigned int NC, double& Ecc, double& Esc, unsigned int n, unsigned int p, const double*
11 {
12 double H_1, I_1, Vc, t0_bs, C_p;
13 double J_1, K_1, M_1, N_1, O_1, P_1;
14
15 double t0 = t0_p[ p ];
16 double tauo = tauo_p[ p ];
17 double tin = taui_p[ 1 ];
18 t0_bs = tin * ( VDD - TECH.Vtn0 ) / VDD;
19 double tc = (VDD * tauo_p[p] * (t0_p[p] - taui_p[p]) + \
20 Vs_p[p] * taui_p[p] * (tauo_p[p] - t0_p[p])) / \
21 (VDD * (t0_p[p] - taui_p[p]) + Vs_p[p] * (tauo_p[p] - t0_p[p]));
22 Esc = 0;
23 Ecc = 0;
24 if (n > 0)
25 {
26 Vc = TECH.Ec_n * L_n[ n ];
27
28 H_1 = Vc * beta_n[ n ] * ( ( VDD * VDD ) * tin * ( t0 - 2 * tauo ) - \
29 VDD * ( Vc * ( t0 - tauo ) * ( 2 * t0 - tin - 2 * tauo ) + \
30 tin * ( Vd_p[ p ] * ( t0 - 3 * tauo ) + 2 * TECH.Vtn0 * ( t0 - tauo ) ) ) - \
31 Vd_p[ p ] * tin * ( Vc * ( t0 - tauo ) + Vd_p[ p ] * tauo + 2 * TECH.Vtn0 * ( tauo - t0 ) ) ) / \
32 ( 2 * tin * ( VDD - Vd_p[ p ] ) * ( t0 - tauo ) );
33 I_1 = Vc * beta_n[ n ] * ( VDD * ( 2 * t0 - tin - 2 * tauo ) + \
34 Vd_p[ p ] * tin ) / ( 2 * tin * ( tauo - t0 ) );
35 J_1 = ( Vc * Vc ) * beta_n[ n ] * ( tauo - t0 ) * \
36 ( 2 * ( VDD * VDD ) * ( t0 - tin ) + VDD * ( Vc * ( 2 * t0 - tin - 2 * tauo ) + \
37 2 * ( Vd_p[ p ] * ( tin - tauo ) + TECH.Vtn0 * tin ) ) + Vd_p[ p ] * tin * ( Vc - 2 * TECH.Vtn0 ) );
38 K_1 = 2 * tin * ( VDD - Vd_p[ p ] ) * ( VDD * t0 + Vc * ( t0 - tauo ) - \
39 Vd_p[ p ] * tauo );
40 M_1 = Vc * beta_n[ n ] * ( VDD * t0 + Vc * ( tauo - t0 ) - Vd_p[ p ] * tauo + 2 * TECH.Vtn0 * ( t0 - tauo ) ) / ( 2 * ( tauo - t0 ) );
41 N_1 = Vc * beta_n[ n ] * ( VDD - Vd_p[ p ] ) / ( 2 * ( t0 - tauo ) );
42 O_1 = ( Vc * Vc ) * beta_n[ n ] * ( Vc - 2 * TECH.Vtn0 ) * ( t0 - tauo );
43 P_1 = 2 * ( VDD * t0 + Vc * ( t0 - tauo ) - Vd_p[ p ] * tauo );
44
45 if ( t0_bs < tauo )
46 {
47 Esc = ( VDD * ( 3 * J_1 * ( K_1 - 2 * tin * t0 * ( VDD - Vd_p[ p ] ) * ( VDD - Vd_p[ p ] ) ) * \
48 LOG ( 2 * t0 * tin * ( ( VDD - Vd_p[ p ] ) * ( VDD - Vd_p[ p ] ) ) - K_1 ) + \
49 3 * J_1 * ( 2 * tin * t0 * ( VDD - Vd_p[ p ] ) * ( VDD - Vd_p[ p ] ) - K_1 ) * \
50 LOG ( 2 * t0_bs * tin * ( ( VDD - Vd_p[ p ] ) * ( VDD - Vd_p[ p ] ) ) - K_1 ) + \
51 2 * tin * ( ( VDD - Vd_p[ p ] ) * ( VDD - Vd_p[ p ] ) ) * \
52 ( t0_bs - t0 ) * ( 3 * H_1 * tin * ( VDD - Vd_p[ p ] ) * \
53 ( VDD - Vd_p[ p ] ) * ( t0 - t0_bs ) + \
54 I_1 * tin * ( VDD - Vd_p[ p ] ) * ( VDD - Vd_p[ p ] ) * \
55 ( t0 * t0 + t0 * t0_bs - 2 * t0_bs * t0_bs ) - 3 * J_1 ) ) / \
56 ( 12 * ( tin * tin ) * ( ( VDD - Vd_p[ p ] ) * ( VDD - Vd_p[ p ] ) * ( VDD - Vd_p[ p ] ) * ( VDD - Vd_p[ p ] ) ) * \
57 ( t0 - tauo ) ) );
58 }
59 else
60 {
61 Esc = ( ( 3 * J_1 * ( K_1 + 2 * tin * ( VDD - Vd_p[ p ] ) * ( Vd_p[ p ] * tauo - VDD * t0 ) ) * \
230 Appendix B. Source code
200 break;
201 case _D_:
202 C_p += Cg * (VDD - Vd_p[i]) * (VDD - Vd_p[i]) * (taui_p[i] - tauo_p[i]) * (taui_p[i] - tauo_p[i]) / \
203 (2 * (t0_p[i] - tauo_p[i]) * (t0_p[i] - tauo_p[i]));
204 break;
205 case _F_:
206 C_p += Cg * (Vd_p[i] - VDD) * (ts_p[i] - tauo_p[i]) * (ts_p[i] - tauo_p[i]) * (VDD * (t0_p[i] - taui_p[i] - tauo_p[i]) +
207 Vd_p[i] * taui_p[i]) / (2 * taui_p[i] * (t0_p[i] - tauo_p[i]) * (t0_p[i] - tauo_p[i]));
208 C_p += Cov * (Vd_p[i] - VDD) * ((t0_p[i] * t0_p[i]) - 2 * t0_p[i] * tauo_p[i] - ts_p[i]*\
209 (ts_p[i] - 2 * tauo_p[i])) * (VDD * (t0_p[i] - taui_p[i] - tauo_p[i]) + Vd_p[i] * taui_p
210 (2 * taui_p[i] * (t0_p[i] - tauo_p[i]) * (t0_p[i] - tauo_p[i]));
211 break;
212 case _G_:
213 C_p += Cg * (Vd_p[i] - VDD) * (VDD * (t0_p[i] - taui_p[i] - tauo_p[i]) + Vd_p[i] * taui_p[i]) / (2 * taui_p[i]);
214 break;
215 case _E_:
216 default:
217 C_p += 0.0;
218 break;
219 }
220 }
221 else if ( ( i < p - 1 ) && ( i > 1 ) )
222 {
223 C_p += ( TECH.Cgd0_p * ( W_p[ i ] + TECH.XW_p ) + 0.5 * TECH.Cox_p * W_p[ i ] * TECH.Lmin ) * \
224 ( VDD + Vd_p[ i ] ) * ( Vd_p[ i ] - VDD ) * 0.5;
225 C_p += ( TECH.Cgs0_p * ( W_p[ i + 1 ] + TECH.XW_p ) + 0.5 * TECH.Cox_p * W_p[ i + 1 ] * njp * TECH.Lmin ) * \
226 ( VDD + Vd_p[ i ] ) * ( Vd_p[ i ] - VDD ) * 0.5;
227 }
228 else if ( (i == 1) && (i == p - 1) )
229 {
230 double Cov = TECH.Cgd0_p * ( W_p[ i ] + TECH.XW_p );
231 double Cg = Cov + 0.5 * TECH.Cox_p * W_p[ i ] * L_p[ i ];
232 int Op, SOp;
233 Op = Calct0ts1P( circuit, NP, SOp, NewWidth );
234 if ( Op == _E_ )
235 {
236 Op = SOp;
237 }
238 switch ( Op )
239 {
240 case _A_:
241 C_p += Cov * (Vd_p[i] - VDD) * ((t0_p[i] * t0_p[i]) - 2 * t0_p[i] * tauo_p[i] - ts_p[i]*\
242 (ts_p[i] - 2 * tauo_p[i])) * (VDD * (t0_p[i] - taui_p[i] - tauo_p[i]) + \
243 Vd_p[i] * taui_p[i]) / \
244 (2 * taui_p[i] * (t0_p[i] - tauo_p[i]) * (t0_p[i] - tauo_p[i]));
245 C_p += -Cg * ((VDD * VDD) * ((t0_p[i] * t0_p[i]) * ((ts_p[i] * ts_p[i]) - (taui_p[i] * taui_p[i])) + \
246 t0_p[i] * ((taui_p[i] * taui_p[i]) - (ts_p[i] * ts_p[i])) * (taui_p[i] + 2 * tauo_p[i]) + \
247 (ts_p[i] * ts_p[i]) * tauo_p[i] * (taui_p[i] + tauo_p[i]) - (taui_p[i] * taui_p[i]) * ((tau
248 taui_p[i] * tauo_p[i] + 2 * (tauo_p[i] * tauo_p[i]))) + \
249 VDD * Vd_p[i] * taui_p[i] * (t0_p[i] * ((ts_p[i] * ts_p[i]) - (taui_p[i] * taui_p[i])) - (ts_p[i] * ts_p[i
250 taui_p[i] * (2 * (taui_p[i] * taui_p[i]) - 3 * taui_p[i] * tauo_p[i] + 2 * (t
251 (Vd_p[i] * Vd_p[i]) * (taui_p[i] * taui_p[i]) * ((taui_p[i] * taui_p[i]) - 2 * taui_p[i] * tauo_p[i] + (ta
252 (2 * (taui_p[i] * taui_p[i]) * (t0_p[i] - tauo_p[i]) * (t0_p[i] - tauo_p[i]));
253 break;
254 case _AA_:
255 C_p += Cg * (VDD - Vd_p[i]) * (VDD - Vd_p[i]) * (ts_p[i] - tauo_p[i]) * (ts_p[i] - tauo_p[i]) / \
256 (2 * (t0_p[i] - tauo_p[i]) * (t0_p[i] - tauo_p[i]));
257 C_p += Cov * (Vd_p[i] - VDD) * (VDD * ((t0_p[i] * t0_p[i] * t0_p[i]) - (t0_p[i] * t0_p[i]) * (taui_p[i] + \
258 3 * tauo_p[i]) - t0_p[i] * ((taui_p[i] * taui_p[i]) - 4 * taui_p[i] * tauo_p[i] -
259 taui_p[i] * ((ts_p[i] * ts_p[i]) - 2 * ts_p[i] * tauo_p[i] + tauo_p[i] * (taui_p[
260 Vd_p[i] * taui_p[i] * ((t0_p[i] * t0_p[i]) - 2 * t0_p[i] * tauo_p[i] - ts_p[i] * (ts_p[i
261 (2 * taui_p[i] * (t0_p[i] - tauo_p[i]) * (t0_p[i] - tauo_p[i]));
262 break;
263 case _B_:
264 C_p += Cg * (VDD - Vd_p[i]) * (VDD * ((t0_p[i] * t0_p[i]) - t0_p[i] * (taui_p[i] + 2 * tauo_p[i]) - \
265 (taui_p[i] * taui_p[i]) + 3 * taui_p[i] * tauo_p[i]) + Vd_p[i] * taui_p[i] * (t0_p
266 (2 * taui_p[i] * (tauo_p[i] - t0_p[i]));
267 break;
268 case _C_:
B.3. Simulators 233
269 C_p += Cg * (VDD - Vd_p[i]) * (VDD - Vd_p[i]) * (ts_p[i] - tauo_p[i]) * (ts_p[i] - tauo_p[i]) / (2 * (t0_p[i] - tauo_p[i]) * (t0_p[i] -
270 C_p += Cov * (VDD - Vd_p[i]) * (VDD - Vd_p[i]) * ((t0_p[i] * t0_p[i]) - 2 * t0_p[i] * tauo_p[i] - ts_p[i] * (ts_p[i] - 2 * tauo_p[i]))
271 (2 * (t0_p[i] - tauo_p[i]) * (t0_p[i] - tauo_p[i]));
272 break;
273 case _D_:
274 C_p += Cg * (VDD - Vd_p[i]) * (VDD - Vd_p[i]) * (taui_p[i] - tauo_p[i]) * (taui_p[i] - tauo_p[i]) / \
275 (2 * (t0_p[i] - tauo_p[i]) * (t0_p[i] - tauo_p[i]));
276 break;
277 case _F_:
278 C_p += Cg * (Vd_p[i] - VDD) * (ts_p[i] - tauo_p[i]) * (ts_p[i] - tauo_p[i]) * (VDD * (t0_p[i] - taui_p[i] - tauo_p[i]) + \
279 Vd_p[i] * taui_p[i]) / (2 * taui_p[i] * (t0_p[i] - tauo_p[i]) * (t0_p[i] - tauo_p[i]));
280 C_p += Cov * (Vd_p[i] - VDD) * ((t0_p[i] * t0_p[i]) - 2 * t0_p[i] * tauo_p[i] - ts_p[i]*\
281 (ts_p[i] - 2 * tauo_p[i])) * (VDD * (t0_p[i] - taui_p[i] - tauo_p[i]) + Vd_p[i] * taui_p[i]) / \
282 (2 * taui_p[i] * (t0_p[i] - tauo_p[i]) * (t0_p[i] - tauo_p[i]));
283 break;
284 case _G_:
285 C_p += Cg * (Vd_p[i] - VDD) * (VDD * (t0_p[i] - taui_p[i] - tauo_p[i]) + Vd_p[i] * taui_p[i]) / (2 * taui_p[i]);
286 break;
287 case _E_:
288 default:
289 C_p += 0.0;
290 break;
291 }
292 Op = Calct0tsnP( p, SOp);
293 if ( Op == _E_ )
294 {
295 Op = SOp;
296 }
297 Cov = ( TECH.Cgs0_p * ( W_p[ p ] + TECH.XW_p ) + 0.5 * TECH.Cox_p * W_p[ p ] * TECH.Lmin );
298 Cg = ( TECH.Cgs0_p * ( W_p[ p ] + TECH.XW_p ) + 0.66666 * TECH.Cox_p * W_p[ p ] * TECH.Lmin );
299 switch ( Op )
300 {
301 case _A_:
302 C_p += Cg * (VDD - Vs_p[p]) * (VDD - Vs_p[p]) * (ts_p[p] - taui_p[p]) * (ts_p[p] - taui_p[p]) / \
303 (2 * (t0_p[i] - taui_p[p]) * (t0_p[i] - taui_p[p]));
304 C_p += Cov * (VDD - Vs_p[p]) * (VDD - Vs_p[p])*\
305 ((t0_p[i] * t0_p[i]) - 2 * t0_p[i] * taui_p[p] - ts_p[p] * (ts_p[p] - 2 * taui_p[p])) / \
306 (2 * (t0_p[i] - taui_p[p]) * (t0_p[i] - taui_p[p]));
307 break;
308 case _B_:
309 C_p += Cov * (VDD - Vs_p[p]) * (VDD - Vs_p[p]) / 2;
310 break;
311 case _C_:
312 C_p += Cov * (VDD - Vs_p[p]) * (VDD - Vs_p[p])*\
313 ((t0_p[i] * t0_p[i]) - 2 * t0_p[i] * taui_p[p] - ts_p[p] * (ts_p[p] - 2 * taui_p[p])) / \
314 (2 * (t0_p[i] - taui_p[p]) * (t0_p[i] - taui_p[p]));
315 C_p += -Cg * (VDD - Vs_p[p]) * (VDD - Vs_p[p])*\
316 ((tc * tc) - 2 * tc * taui_p[p] - ts_p[p] * (ts_p[p] - 2 * taui_p[p])) / \
317 (2 * (t0_p[i] - taui_p[p]) * (t0_p[i] - taui_p[p]));
318 break;
319 case _D_:
320 C_p += Cov * (VDD - Vs_p[p]) * (VDD - Vs_p[p])*\
321 ((t0_p[i] * t0_p[i]) - 2 * t0_p[i] * taui_p[p] - tc * (tc - 2 * taui_p[p])) / \
322 (2 * (t0_p[i] - taui_p[p]) * (t0_p[i] - taui_p[p]));
323 break;
324 case _E_:
325 default:
326 break;
327 }
328 }
329 else if ((i == p - 1) && (p > 2))
330 {
331 C_p += ( TECH.Cgd0_p * ( W_p[ i ] + TECH.XW_p ) + 0.5 * TECH.Cox_p * W_p[ i ] * TECH.Lmin ) * \
332 ( VDD + Vd_p[ i ] ) * ( Vd_p[ i ] - VDD ) * 0.5;
333 int Op, SOp;
334 Op = Calct0tsnP( p, SOp);
335 if ( Op == _E_ )
336 {
337 Op = SOp;
234 Appendix B. Source code
338 }
339 double Cov = ( TECH.Cgs0_p * ( W_p[ p ] + TECH.XW_p ) + 0.5 * TECH.Cox_p * W_p[ p ] * TECH.Lmin );
340 double Cg = ( TECH.Cgs0_p * ( W_p[ p ] + TECH.XW_p ) + 0.66666 * TECH.Cox_p * W_p[ p ] * TECH.Lmin );
341 switch ( Op )
342 {
343 case _A_:
344 C_p += Cg * (VDD - Vs_p[p]) * (VDD - Vs_p[p]) * (ts_p[p] - taui_p[p]) * (ts_p[p] - taui_p[p]) / \
345 (2 * (t0_p[i] - taui_p[p]) * (t0_p[i] - taui_p[p]));
346 C_p += Cov * (VDD - Vs_p[p]) * (VDD - Vs_p[p])*\
347 ((t0_p[i] * t0_p[i]) - 2 * t0_p[i] * taui_p[p] - ts_p[p] * (ts_p[p] - 2 * taui_p[p])) / \
348 (2 * (t0_p[i] - taui_p[p]) * (t0_p[i] - taui_p[p]));
349 break;
350 case _B_:
351 C_p += Cov * (VDD - Vs_p[p]) * (VDD - Vs_p[p]) / 2;
352 break;
353 case _C_:
354 C_p += Cov * (VDD - Vs_p[p]) * (VDD - Vs_p[p])*\
355 ((t0_p[i] * t0_p[i]) - 2 * t0_p[i] * taui_p[p] - ts_p[p] * (ts_p[p] - 2 * taui_p[p])) / \
356 (2 * (t0_p[i] - taui_p[p]) * (t0_p[i] - taui_p[p]));
357 C_p += -Cg * (VDD - Vs_p[p]) * (VDD - Vs_p[p])*\
358 ((tc * tc) - 2 * tc * taui_p[p] - ts_p[p] * (ts_p[p] - 2 * taui_p[p])) / \
359 (2 * (t0_p[i] - taui_p[p]) * (t0_p[i] - taui_p[p]));
360 break;
361 case _D_:
362 C_p += Cov * (VDD - Vs_p[p]) * (VDD - Vs_p[p])*\
363 ((t0_p[i] * t0_p[i]) - 2 * t0_p[i] * taui_p[p] - tc * (tc - 2 * taui_p[p])) / \
364 (2 * (t0_p[i] - taui_p[p]) * (t0_p[i] - taui_p[p]));
365 break;
366 case _E_:
367 default:
368 break;
369 }
370 }
371 else if ( i == p )
372 {
373 double Cov = TECH.Cgd0_p * ( W_p[ p ] + TECH.XW_p );
374 double Cg = Cov + 0.5 * TECH.Cox_p * W_p[ p ] * L_p[ p ];
375 int Op, SOp;
376 Op = Calct0tsnP( p, SOp );
377 if ( Op == _E_ )
378 {
379 Op = SOp;
380 }
381 switch ( Op )
382 {
383 case _A_:
384 case _B_:
385 C_p += Cg * (VDD - Vd_p[i]) * (VDD - Vd_p[i]) * (ts_p[i] - tauo_p[i]) * (ts_p[i] - tauo_p[i]) / \
386 (2 * (t0_p[i] - tauo_p[i]) * (t0_p[i] - tauo_p[i]));
387 C_p += Cov * (VDD - Vd_p[i]) * (VDD - Vd_p[i])*\
388 ((t0_p[i] * t0_p[i]) - 2 * t0_p[i] * tauo_p[i] - ts_p[i] * (ts_p[i] - 2 * tauo_p[i])) / \
389 (2 * (t0_p[i] - tauo_p[i]) * (t0_p[i] - tauo_p[i]));
390 break;
391 case _C_:
392 C_p += Cov * (VDD - Vd_p[i]) * (VDD - Vd_p[i]) * ((t0_p[i] * t0_p[i]) - 2 * t0_p[i] * tauo_p[i] - ts_p[i]*\
393 (ts_p[i] - 2 * tauo_p[i])) / (2 * (t0_p[i] - tauo_p[i]) * (t0_p[i] - tauo_p[i]));
394 C_p += -Cg * (VDD - Vd_p[i]) * (VDD - Vd_p[i])*\
395 ((tc * tc) - 2 * tc * tauo_p[i] - ts_p[i] * (ts_p[i] - 2 * tauo_p[i])) / \
396 (2 * (t0_p[i] - tauo_p[i]) * (t0_p[i] - tauo_p[i]));
397 break;
398 case _D_:
399 C_p += Cov * (VDD - Vd_p[i]) * (VDD - Vd_p[i])*\
400 ((t0_p[i] * t0_p[i]) - 2 * t0_p[i] * tauo_p[i] - tc * (tc - 2 * tauo_p[i])) / \
401 (2 * (t0_p[i] - tauo_p[i]) * (t0_p[i] - tauo_p[i]));
402 break;
403 case _E_:
404 default:
405 break;
406
B.3. Simulators 235
407 }
408 }
409 if ( C_p < 0.0 )
410 C_p *= -1;
411 Ecc += C_p;
412 }
413 return OK;
414 }
Calcstart.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8 #define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
9
10 ///
11 double Fast::CalcStartTime( const Circuit& circuit, unsigned int NP, unsigned int NC, double start, double end, TransistorType type, const double* NewW
12 {
13 int iter;
14 double a = start, b = end, c = end, d, e, min1, min2;
15 double fa, fb, fc, pp, q, r, s, tol1, xm, last;
16 double tol = TOL;
17
18 if ( type == NMOS )
19 fb = t0N( circuit, NP, NC, b, NewWidth, RetCode );
20 else if ( type == PMOS )
21 fb = t0P( circuit, NP, NC, b, NewWidth, RetCode );
22 last = fb;
23 if ( type == NMOS )
24 fa = t0N( circuit, NP, NC, a, NewWidth, RetCode );
25 else if ( type == PMOS )
26 fa = t0P( circuit, NP, NC, a, NewWidth, RetCode );
27 if ( ( fa > 0.0 && fb > 0.0 ) || ( fa < 0.0 && fb < 0.0 ) )
28 {
29 RetCode = NOT_FOUND;
30 return 0.0;
31 }
32 fc = fb;
33 for ( iter = 1; iter <= ITERMAX; iter++ )
34 {
35 if ( ( fb > 0.0 && fc > 0.0 ) || ( fb < 0.0 && fc < 0.0 ) )
36 {
37 c = a;
38 fc = fa;
39 e = d = b - a;
40 }
41 if ( fabs ( fc ) < fabs ( fb ) )
42 {
43 a = b;
44 b = c;
45 c = a;
46 fa = fb;
47 fb = fc;
48 fc = fa;
49 }
50 tol1 = 2.0 * EPS * fabs ( b ) + 0.5 * tol;
51 xm = 0.5 * ( c - b );
52 if ( fabs ( xm ) <= tol1 || fb == 0.0 )
53 return b;
54 if ( fabs ( e ) >= tol1 && fabs ( fa ) > fabs ( fb ) )
55 {
56 s = fb / fa;
57 if ( a == c )
58 {
59 pp = 2.0 * xm * s;
236 Appendix B. Source code
60 q = 1.0 - s;
61 }
62 else
63 {
64 q = fa / fc;
65 r = fb / fc;
66 pp = s * ( 2.0 * xm * q * ( q - r ) - ( b - a ) * ( r - 1.0 ) );
67 q = ( q - 1.0 ) * ( r - 1.0 ) * ( s - 1.0 );
68 }
69 if ( pp > 0.0 )
70 q = -q;
71 pp = fabs ( pp );
72 min1 = 3.0 * xm * q - fabs ( tol1 * q );
73 min2 = fabs ( e * q );
74 if ( 2.0 * pp < ( min1 < min2 ? min1 : min2 ) )
75 {
76 e = d;
77 d = pp / q;
78 }
79 else
80 {
81 d = xm;
82 e = d;
83 }
84 }
85 else
86 {
87 d = xm;
88 e = d;
89 }
90 a = b;
91 fa = fb;
92 if ( fabs ( d ) > tol1 )
93 b += d;
94 else
95 b += SIGN ( tol1, xm );
96 if ( type == NMOS )
97 fb = t0N( circuit, NP, NC, b, NewWidth, RetCode );
98 else if ( type == PMOS )
99 fb = t0P( circuit, NP, NC, b, NewWidth, RetCode );
100 }
101 RetCode = NOT_FOUND;
102 return 0.0;
103 }
Calctst0N.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
Calctst0N.cc
14 int Fast::Calct0ts1N( const Circuit& circuit, unsigned int NP, int& SaveOpCondition, const double* NewWidth )
15 {
16 int OpCondition = _A_, LastOpCondition = 0;
17 double t0_bs, Vc, A_2_n, B_2_n, C_2_n, D_2_n, J_2_n, K_2_n, I_2_n, M_2_n;
18 double a, b, c, Cm1, Cm2, Cov, Cj, X, Y, alpha, beta, gamma, theta;
19
20 t0_bs = TECH.Vtn0 * taui_n[ 1 ] / VDD;
21 if ( taui_n[ 1 ] <= tauo_n[ 1 ] )
22 {
23 ts_n[ 1 ] = ( taui_n[ 1 ] - t0_n[ 1 ] ) * 0.5 + t0_n[ 1 ]; /* A */
23
24 }
25 else
B.3. Simulators 237
26 {
27 ts_n[ 1 ] = ( tauo_n[ 1 ] - t0_n[ 1 ] ) * 0.5 + t0_n[ 1 ]; /* F */
27
28 }
29
30 Vc = TECH.Ec_n * L_n[ 1 ];
31 Cov = TECH.Cgd0_n * ( W_n[ 1 ] + TECH.XW_n );
32 Cm1 = Cov;
33 Cm2 = Cm1 + 0.5 * TECH.Cox_n * W_n[ 1 ] * L_n[ 1 ];
34 unsigned int pp = pathlist[ NP ].GetNumTranP();
35 const char* name = pathlist[ NP ].TransistorName( 0 );
36 int node;
37 double Wjn, Wgn, Wjp, Wgp;
38 int njn, ngn, njp, ngp, nc;
39 if ( circuit[ name ].Source() == 0 )
40 {
41 node = circuit[ name ].Drain();
42 Wjn = circuit.JunctionNWidth( node, njn, NewWidth );
43 Wgn = circuit.GateNWidth( node, ngn, NewWidth );
44 Wjp = circuit.JunctionPWidth( node, njp, NewWidth );
45 Wgp = circuit.GatePWidth( node, ngp, NewWidth );
46 }
47 else if ( circuit[ name ].Drain() == 0 )
48 {
49 node = circuit[ name ].Source();
50 Wjn = circuit.JunctionNWidth( node, njn, NewWidth );
51 Wgn = circuit.GateNWidth( node, ngn, NewWidth );
52 Wjp = circuit.JunctionPWidth( node, njp, NewWidth );
53 Wgp = circuit.GatePWidth( node, ngp, NewWidth );
54 }
55 // Nmos
56 Cj = TECH.C_nj * Wjn * TECH.Df * pow ( 1 + Vd_n[ 1 ] / TECH.PB_n, -TECH.mj_n ) + \
57 TECH.C_np * 2 * ( Wjn + njn * TECH.Df ) * pow ( 1 + Vd_n[ 1 ] / TECH.PB_n, -TECH.mjsw_n );
58 Cj += TECH.Cgs0_n * ( Wjn + njn * TECH.XW_n );
59 // Pmos
60 if (pp > 0)
61 {
62 Cj += TECH.C_pj * Wjp * TECH.Df * pow ( 1 + ( VDD - Vd_n[ 1 ] ) / TECH.PB_p, -TECH.mj_p ) + \
63 TECH.C_pp * 2 * ( Wjp + njp * TECH.Df ) * pow ( 1 + ( VDD - Vd_n[ 1 ] ) / TECH.PB_p, -TECH.mjsw_p );
64 Cj += TECH.Cgd0_p * ( Wjp + njp * TECH.XW_p );
65 }
66 // static
67 Cj += circuit.CapStaticGnd( node, nc );
68 Cj += circuit.CapStaticVdd( node, nc );
69 Cj += Wgn * TECH.Lmin * TECH.Cox_n;
70 Cj += Wgp * TECH.Lmin * TECH.Cox_p;
71 A_2_n = Vc * beta_n[ 1 ] * ( Vc - TECH.Vtn0 );
72 B_2_n = VDD * Vc * beta_n[ 1 ] / taui_n[ 1 ];
73 C_2_n = 2 * VDD / ( Vc * taui_n[ 1 ] );
74 D_2_n = ( Vc - 2 * TECH.Vtn0 ) / Vc;
75 J_2_n = Vc * Vd_n[ 1 ] * beta_n[ 1 ] * ( Vd_n[ 1 ] + 2 * TECH.Vtn0 ) / ( 2 * ( Vc + Vd_n[ 1 ] ) );
76 K_2_n = VDD * Vc * Vd_n[ 1 ] * beta_n[ 1 ] / ( taui_n[ 1 ] * ( Vc + Vd_n[ 1 ] ) );
77 I_2_n = ( Vc * Vc ) * beta_n[ 1 ] * ( sqrt ( ( 2 * VDD + Vc - 2 * TECH.Vtn0 ) / Vc ) - 1 ) * \
78 ( sqrt ( ( 2 * VDD + Vc - 2 * TECH.Vtn0 ) / Vc ) - 1 ) / 2;
79 M_2_n = K_2_n * taui_n[ 1 ] - J_2_n;
80 X = Cj + Cm2;
81 Y = Cj + Cov;
82 while ( OpCondition != LastOpCondition )
83 {
84 if ( LastOpCondition != 0 )
85 LastOpCondition = OpCondition;
86 else
87 LastOpCondition = _E_;
88 if ( ( t0_n[ 1 ] <= ts_n[ 1 ] ) &&
89 ( ts_n[ 1 ] <= taui_n[ 1 ] ) &&
90 ( taui_n[ 1 ] <= tauo_n[ 1 ] ) )
91 {
92 OpCondition = SaveOpCondition = _A_;
93 if ( OpCondition != LastOpCondition )
238 Appendix B. Source code
94 {
95 #ifdef SAT
96 b = ( 2 * ( Vd_n[ 1 ] * taui_n[ 1 ] * \
97 ( Vc * ( t0_n[ 1 ] - tauo_n[ 1 ] ) - Vd_n[ 1 ] * tauo_n[ 1 ] ) - \
98 VDD * Vc * ( t0_n[ 1 ] - tauo_n[ 1 ] ) * ( t0_n[ 1 ] - tauo_n[ 1 ] ) ) ) / \
99 ( Vd_n[ 1 ] * Vd_n[ 1 ] * taui_n[ 1 ] );
100 c = ( 2 * Vc * ( t0_n[ 1 ] - tauo_n[ 1 ] ) * ( Vd_n[ 1 ] * tauo_n[ 1 ] + \
101 TECH.Vtn0 * ( tauo_n[ 1 ] - t0_n[ 1 ] ) ) - Vd_n[ 1 ] * Vd_n[ 1 ] * tauo_n[ 1 ] * tauo_n[ 1 ] ) / \
102 ( Vd_n[ 1 ] * Vd_n[ 1 ] );
103 if ( ( b * b + 4 * c ) >= 0 )
104 {
105 ts_n[ 1 ] = -( sqrt ( b * b + 4 * c ) + b ) * 0.5;
106 if ( ts_n[ 1 ] < 0 )
107 ts_n[ 1 ] = ( sqrt ( b * b + 4 * c ) - b ) * 0.5;
108 }
109 else
110 ts_n[ 1 ] = taui_n[ 1 ] * ( Vd_n[ 1 ] * tauo_n[ 1 ] + TECH.Vtn0 * ( tauo_n[ 1 ] - t0_n[ 1 ] ) ) / \
111 ( Vd_n[ 1 ] * taui_n[ 1 ] - VDD * ( t0_n[ 1 ] - tauo_n[ 1 ] ) );
112 #else
113 ts_n[ 1 ] = taui_n[ 1 ] * ( Vd_n[ 1 ] * tauo_n[ 1 ] + TECH.Vtn0 * ( tauo_n[ 1 ] - t0_n[ 1 ] ) ) / \
114 ( Vd_n[ 1 ] * taui_n[ 1 ] - VDD * ( t0_n[ 1 ] - tauo_n[ 1 ] ) );
115
116 #endif
117 }
118 }
119 else if ( ( t0_n[ 1 ] <= taui_n[ 1 ] ) &&
120 ( taui_n[ 1 ] <= ts_n[ 1 ] ) &&
121 ( ts_n[ 1 ] <= tauo_n[ 1 ] ) )
122 {
123 OpCondition = SaveOpCondition = _AA_;
124 if ( OpCondition != LastOpCondition )
125 {
126 #ifdef SAT
127 ts_n[ 1 ] = ( sqrt ( Vc ) * ( t0_n[ 1 ] - tauo_n[ 1 ] ) * \
128 sqrt ( 2 * VDD + Vc - 2 * TECH.Vtn0 ) + Vc * ( tauo_n[ 1 ] - t0_n[ 1 ] ) ) / \
129 Vd_n[ 1 ] + tauo_n[ 1 ];
130 #else
131 ts_n[ 1 ] = ( VDD * ( t0_n[ 1 ] - tauo_n[ 1 ] ) + Vd_n[ 1 ] * tauo_n[ 1 ] + \
132 TECH.Vtn0 * ( tauo_n[ 1 ] - t0_n[ 1 ] ) ) / Vd_n[ 1 ];
133 #endif
134 }
135 }
136 else if ( ( ts_n[ 1 ] <= t0_n[ 1 ] ) &&
137 ( t0_n[ 1 ] <= taui_n[ 1 ] ) &&
138 ( taui_n[ 1 ] <= tauo_n[ 1 ] ) )
139 {
140 OpCondition = SaveOpCondition = _B_;
141 if ( OpCondition != LastOpCondition )
142 {
143 #ifdef SAT
144 ts_n[ 1 ] = taui_n[ 1 ] * \
145 ( 2 * Vc * ( Vd_n[ 1 ] + TECH.Vtn0 ) + ( Vd_n[ 1 ] * Vd_n[ 1 ] ) ) / \
146 ( 2 * VDD * Vc );
147 #else
148 ts_n[ 1 ] = taui_n[ 1 ] * ( Vd_n[ 1 ] + TECH.Vtn0 ) / VDD;
149 #endif
150 a = 2 * ( Cm2 * VDD + J_2_n * taui_n[ 1 ] ) / ( K_2_n * taui_n[ 1 ]);
151 b = ( 6 * A_2_n * C_2_n * taui_n[1] * ( t0_bs - ts_n[ 1 ] ) + \
152 3 * B_2_n * C_2_n * taui_n[1] * ( t0_bs * t0_bs - ts_n[ 1 ] * ts_n[ 1 ] ) - \
153 4 * Vc * Vc * beta_n[ 1 ] * taui_n[1] * pow( C_2_n * t0_bs + D_2_n, 1.5 ) + \
154 4 * Vc * Vc * beta_n[ 1 ] * pow( C_2_n * ts_n[ 1 ] + D_2_n, 1.5 ) - \
155 3 * C_2_n * ts_n[ 1 ] * ( 2 * Cm2 * VDD - 2 * Cov * VDD + \
156 taui_n[1] * (2 * J_2_n - K_2_n * ts_n[1] ) ) ) / \
157 ( 3 * C_2_n * K_2_n * taui_n[ 1 ]);
158 if ( ( 4 * b + ( a * a ) ) >= 0 )
159 {
160 t0_n[ 1 ] = ( a - sqrt ( 4 * b + ( a * a ) ) ) / 2;
161 if ( t0_n[ 1 ] < 0 )
162 t0_n[ 1 ] = ( sqrt ( 4 * b + ( a * a ) ) + a ) / 2;
B.3. Simulators 239
163 }
164 else
165 t0_n[ 1 ] = t0_bs;
166 }
167 }
168 else if ( ( taui_n[ 1 ] <= t0_n[ 1 ] ) &&
169 ( t0_n[ 1 ] <= ts_n[ 1 ] ) &&
170 ( ts_n[ 1 ] <= tauo_n[ 1 ] ) )
171 {
172 OpCondition = SaveOpCondition = _C_;
173 if ( OpCondition != LastOpCondition )
174 {
175 alpha = C_2_n * t0_bs + D_2_n;
176 beta = C_2_n * ts_n[ 1 ] + D_2_n;
177 theta = pow( alpha, 1.5 ) - pow( beta, 1.5 );
178 t0_n[ 1 ] = ( 6 * A_2_n * C_2_n * ( t0_bs - taui_n[ 1 ] ) + \
179 3 * B_2_n * C_2_n * ( t0_bs * t0_bs - taui_n[ 1 ] * taui_n[ 1 ] ) - \
180 2 * ( 2 * Vc * Vc * beta_n[ 1 ] * theta - \
181 3 * C_2_n * (Cov * VDD + I_2_n * taui_n[1]))) /
182 ( 6 * C_2_n * I_2_n );
183
184 #ifdef SAT
185 ts_n[ 1 ] = ( sqrt ( Vc ) * ( t0_n[ 1 ] - tauo_n[ 1 ] ) * \
186 sqrt ( 2 * VDD + Vc - 2 * TECH.Vtn0 ) + Vc * ( tauo_n[ 1 ] - t0_n[ 1 ] ) ) / \
187 Vd_n[ 1 ] + tauo_n[ 1 ];
188 #else
189 ts_n[ 1 ] = ( VDD * ( t0_n[ 1 ] - tauo_n[ 1 ] ) + Vd_n[ 1 ] * tauo_n[ 1 ] + \
190 TECH.Vtn0 * ( tauo_n[ 1 ] - t0_n[ 1 ] ) ) / Vd_n[ 1 ];
191 #endif
192 }
193 }
194 else if ( ( ts_n[ 1 ] <= taui_n[ 1 ] ) &&
195 ( taui_n[ 1 ] <= t0_n[ 1 ] ) &&
196 ( t0_n[ 1 ] <= tauo_n[ 1 ] ) )
197 {
198 OpCondition = SaveOpCondition = _D_;
199 if ( OpCondition != LastOpCondition )
200 {
201 #ifdef SAT
202 ts_n[ 1 ] = taui_n[ 1 ] * \
203 ( 2 * Vc * ( Vd_n[ 1 ] + TECH.Vtn0 ) + ( Vd_n[ 1 ] * Vd_n[ 1 ] ) ) / \
204 ( 2 * VDD * Vc );
205 #else
206 ts_n[ 1 ] = taui_n[ 1 ] * ( Vd_n[ 1 ] + TECH.Vtn0 ) / VDD;
207 #endif
208 alpha = C_2_n * t0_bs + D_2_n;
209 beta = C_2_n * taui_n[ 1 ] + D_2_n;
210 gamma = C_2_n * ts_n[ 1 ] + D_2_n;
211 theta = -pow( alpha, 1.5 ) + pow( gamma, 1.5 );
212 t0_n[ 1 ] = ( 6 * A_2_n * C_2_n * taui_n[1] * ( t0_bs - ts_n[ 1 ] ) + \
213 3 * B_2_n * C_2_n * taui_n[1] * ( ( t0_bs * t0_bs ) - ( ts_n[ 1 ] * ts_n[ 1 ] ) ) + \
214 4 * Vc * Vc * beta_n[ 1 ] * taui_n[1] * theta - \
215 3 * C_2_n * ( 2 * Cm2 * VDD * (ts_n[1] - taui_n[1]) - \
216 2 * Cov * VDD * ts_n[1] + taui_n[1] * \
217 (2 * J_2_n * (ts_n[1]-taui_n[1]) + K_2_n * \
218 (taui_n[1] * taui_n[1] - ts_n[1] * ts_n[1]) - \
219 2 * M_2_n * taui_n[1]))) / \
220 ( 6 * C_2_n * M_2_n * taui_n[ 1 ] );
221 }
222 }
223 else if ( ( t0_n[ 1 ] <= ts_n[ 1 ] ) &&
224 ( ts_n[ 1 ] <= tauo_n[ 1 ] ) &&
225 ( tauo_n[ 1 ] <= taui_n[ 1 ] ) )
226 {
227 OpCondition = SaveOpCondition = _F_;
228 if ( OpCondition != LastOpCondition )
229 {
230 #ifdef SAT
231 b = ( 2 * ( Vd_n[ 1 ] * taui_n[ 1 ] * \
240 Appendix B. Source code
(ts
n[n] ¡ tc), not ’¡=’ !!!
Calctst0N.cc
385 OpCondition = SaveOpCondition = _C_;
386 if ( OpCondition != LastOpCondition )
387 {
388 #ifdef SAT
389 X = t0_n[ n ] - taui_n[ n ];
390 Y = tauo_n[ n ] - t0_n[ n ];
391 b = -( 2 * ( VDD * X * X * ( Vc * Y + VDD * tauo_n[ n ] ) + \
392 Vs_n[ n ] * X * Y * ( VDD * ( taui_n[ n ] + tauo_n[ n ] ) - A_1_n[ n ] * Vc * Y ) + \
393 Vs_n[ n ] * Vs_n[ n ] * taui_n[ n ] * Y * Y ) ) / \
394 ( ( VDD * X + Vs_n[ n ] * Y ) * ( VDD * X + Vs_n[ n ] * Y ) );
395 c = -( X * X * ( 2 * Y * Y * Vc * TECH.Vtn0 + 2 * Y * VDD * Vc * t0_n[ n ] + VDD * VDD * tauo_n[ n ] * tauo_n[ n ] ) + \
396 2 * Vs_n[ n ] * taui_n[ n ] * X * Y * ( VDD * tauo_n[ n ] - A_1_n[ n ] * Vc * Y ) + \
397 Vs_n[ n ] * Vs_n[ n ] * taui_n[ n ] * taui_n[ n ] * Y * Y ) / \
398 ( ( VDD * X + Vs_n[ n ] * Y ) * ( VDD * X + Vs_n[ n ] * Y ) );
399 if ( ( b * b + 4 * c ) >= 0 )
400 {
401 ts_n[ n ] = -( sqrt ( b * b + 4 * c ) + b ) * 0.5;
402 if ( ( ts_n[ n ] < 0 ) || ( ts_n[ n ] < t0_n[ n ] ) || ( ts_n[ n ] > tauo_n[ n ] ) )
403 ts_n[ n ] = ( sqrt ( b * b + 4 * c ) - b ) * 0.5;
404 if ( ( ts_n[ n ] < 0 ) || ( ts_n[ n ] < t0_n[ n ] ) || ( ts_n[ n ] > tauo_n[ n ] ) )
405 ts_n[ n ] = ( A_1_n[ n ] * Vs_n[ n ] * taui_n[ n ] * ( t0_n[ n ] - tauo_n[ n ] ) + \
406 ( t0_n[ n ] - taui_n[ n ] ) * ( VDD * t0_n[ n ] + TECH.Vtn0 * ( tauo_n[ n ] - t0_n[ n ] ) ) ) / \
407 ( A_1_n[ n ] * Vs_n[ n ] * ( t0_n[ n ] - tauo_n[ n ] ) + \
408 VDD * ( t0_n[ n ] - taui_n[ n ] ) );
409 }
410 else
411 {
412 ts_n[ n ] = ( A_1_n[ n ] * Vs_n[ n ] * taui_n[ n ] * ( t0_n[ n ] - tauo_n[ n ] ) + \
413 ( t0_n[ n ] - taui_n[ n ] ) * ( VDD * t0_n[ n ] + TECH.Vtn0 * ( tauo_n[ n ] - t0_n[ n ] ) ) ) / \
414 ( A_1_n[ n ] * Vs_n[ n ] * ( t0_n[ n ] - tauo_n[ n ] ) + \
415 VDD * ( t0_n[ n ] - taui_n[ n ] ) );
416 if ( ts_n[ n ] > tauo_n[ n ] )
417 ts_n[ n ] = tc;
418 }
419 #else
420 ts_n[ n ] = ( A_1_n[ n ] * Vs_n[ n ] * taui_n[ n ] * ( t0_n[ n ] - tauo_n[ n ] ) + \
421 ( t0_n[ n ] - taui_n[ n ] ) * ( VDD * t0_n[ n ] + TECH.Vtn0 * ( tauo_n[ n ] - t0_n[ n ] ) ) ) / \
422 ( A_1_n[ n ] * Vs_n[ n ] * ( t0_n[ n ] - tauo_n[ n ] ) + \
423 VDD * ( t0_n[ n ] - taui_n[ n ] ) );
424 if ( ts_n[ n ] > tauo_n[ n ] )
425 ts_n[ n ] = tc;
426 #endif
427 }
428 }
429 else if ( ( tauo_n[ n ] <= taui_n[ n ] ) &&
430 ( tc <= ts_n[ n ] ) &&
431 ( t0_n[ n ] <= ts_n[ n ] ) )
432 {
433 OpCondition = SaveOpCondition = _D_;
434 if ( OpCondition != LastOpCondition )
B.3. Simulators 243
435 {
436 ts_n[ n ] = tc;
437 }
438 }
439 else
440 {
441 OpCondition = _E_;
442 }
443 }
444 return OpCondition;
445 }
Calctst0P.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
Calctst0P.cc
15 int Fast::Calct0ts1P( const Circuit& circuit, unsigned int NP, int& SaveOpCondition, const double* NewWidth )
16 {
17 int OpCondition = _A_, LastOpCondition = 0;
18 double t0_bs, Vc, A_2_p, B_2_p, C_2_p, D_2_p, G_2_p, J_2_p, K_2_p, M_2_p;
19 double b, c, Cm1, Cm2, Cov, Cj, X, XX, Y, alpha, gamma, theta;
20
21 t0_bs = -TECH.Vtp0 * taui_p[ 1 ] / VDD;
22 if ( taui_p[ 1 ] <= tauo_p[ 1 ] )
23 {
24 ts_p[ 1 ] = ( taui_p[ 1 ] - t0_p[ 1 ] ) * 0.5 + t0_p[ 1 ]; /* A */
24
25 }
26 else
27 {
28 ts_p[ 1 ] = ( tauo_p[ 1 ] - t0_p[ 1 ] ) * 0.5 + t0_p[ 1 ]; /* F */
28
29 }
30
31 Vc = TECH.Ec_p * L_p[ 1 ];
32 Cov = TECH.Cgd0_p * ( W_p[ 1 ] + TECH.XW_p );
33 Cm1 = Cov;
34 Cm2 = Cm1 + 0.5 * TECH.Cox_p * W_p[ 1 ] * L_p[ 1 ];
35 unsigned int nn = pathlist[ NP ].GetNumTranN();
36 double Wjn, Wgn, Wjp, Wgp;
37 int node;
38 int njn, ngn, njp, ngp, nc;
39 if (nn > 0)
40 {
41 const char* name = pathlist[ NP ].TransistorName( nn - 1 );
42 if ( circuit[ name ].Source() == 0 )
43 {
44 node = circuit[ name ].Drain();
45 Wjn = circuit.JunctionNWidth( node, njn, NewWidth );
46 Wgn = circuit.GateNWidth( node, ngn, NewWidth );
47 Wjp = circuit.JunctionPWidth( node, njp, NewWidth );
48 Wgp = circuit.GatePWidth( node, ngp, NewWidth );
49 }
50 else if ( circuit[ name ].Drain() == 0 )
51 {
52 node = circuit[ name ].Source();
53 Wjn = circuit.JunctionNWidth( node, njn, NewWidth );
54 Wgn = circuit.GateNWidth( node, ngn, NewWidth );
55 Wjp = circuit.JunctionPWidth( node, njp, NewWidth );
56 Wgp = circuit.GatePWidth( node, ngp, NewWidth );
57 }
58 // Nmos
244 Appendix B. Source code
266 {
267 OpCondition = SaveOpCondition = _G_;
268 if ( OpCondition != LastOpCondition )
269 {
270 #ifdef SAT
271 ts_p[ 1 ] = taui_p[ 1 ] * ( VDD * VDD + 2 * VDD * ( Vc - Vd_p[ 1 ] ) - 2 * Vc * ( Vd_p[ 1 ] + TECH.Vtp0 ) + \
272 Vd_p[ 1 ] * Vd_p[ 1 ] ) / ( 2 * VDD * Vc );
273 #else
274 ts_p[ 1 ] = taui_p[ 1 ] * ( VDD - Vd_p[ 1 ] - TECH.Vtp0 ) / VDD;
275 #endif
276 theta = pow( ( D_2_p * ts_p[ 1 ] + C_2_p ), 1.5 );
277 b = 2 * ( Cm2 * VDD + J_2_p * taui_p[ 1 ] ) / \
278 ( K_2_p * taui_p[ 1 ] );
279 c = ( 6 * A_2_p * D_2_p * taui_p[ 1 ] * ( t0_bs - ts_p[ 1 ] ) + \
280 3 * B_2_p * D_2_p * taui_p[ 1 ] * ( t0_bs * t0_bs - ts_p[ 1 ] * ts_p[ 1 ] ) - \
281 4 * Vc * Vc * beta_p[ 1 ] * taui_p[ 1 ] * alpha + \
282 4 * Vc * Vc * beta_p[ 1 ] * taui_p[ 1 ] * theta - \
283 3 * D_2_p * ts_p[ 1 ] * \
284 ( 2 * Cm2 * VDD - 2 * Cov * VDD + taui_p[ 1 ] * \
285 ( 2 * J_2_p + K_2_p * ts_p[ 1 ] ) ) ) / \
286 ( 3 * D_2_p * K_2_p * taui_p[ 1 ] );
287 if ( ( b * b - 4 * c ) >= 0 )
288 {
289 t0_p[ 1 ] = ( sqrt ( ( b * b ) - 4 * c ) - b ) * 0.5;
290 if ( t0_p[ 1 ] < 0 )
291 t0_p[ 1 ] = -( sqrt ( ( b * b ) - 4 * c ) + b ) * 0.5;
292 }
293 else
294 t0_p[ 1 ] = t0_bs;
295 }
296 else
297 {
298 OpCondition = _E_;
299 }
300 }
301 }
302 return OpCondition;
303 }
304
305 ///
306 int Fast::Calct0tsnP( unsigned int p, int& SaveOpCondition )
307 {
308 int OpCondition = _A_, LastOpCondition = 0;
309 double Vc, tc, X, Y, H, K, det, alpha, beta;
310
311 Vc = TECH.Ec_p * L_p[ p ];
312 ts_p[ p ] = ( A_1_p[ p ] * ( t0_p[ p ] - tauo_p[ p ] ) * ( VDD * t0_p[ p ] - Vs_p[ p ] * taui_p[ p ] ) + \
313 ( t0_p[ p ] - taui_p[ p ] ) * ( B_1_p[ p ] * ( t0_p[ p ] - tauo_p[ p ] ) + \
314 VDD * t0_p[ p ] - Vd_p[ p ] * tauo_p[ p ] ) ) / \
315 ( A_1_p[ p ] * ( VDD - Vs_p[ p ] ) * ( t0_p[ p ] - tauo_p[ p ] ) + \
316 ( VDD - Vd_p[ p ] ) * ( t0_p[ p ] - taui_p[ p ] ) );
317 if ( taui_p[ p ] < tauo_p[ p ] )
318 {
319 SaveOpCondition = _A_;
320 }
321 else
322 {
323 tc = ( VDD * tauo_p[ p ] * ( t0_p[ p ] - taui_p[ p ] ) + \
324 Vs_p[ p ] * taui_p[ p ] * ( tauo_p[ p ] - t0_p[ p ] ) ) / \
325 ( VDD * ( t0_p[ p ] - taui_p[ p ] ) + Vs_p[ p ] * ( tauo_p[ p ] - t0_p[ p ] ) );
326 SaveOpCondition = _C_;
327 }
328 X = t0_p[ p ] - taui_p[ p ];
329 Y = tauo_p[ p ] - t0_p[ p ];
330 alpha = VDD - Vs_p[ p ];
331 beta = VDD - Vd_p[ p ];
332 while ( OpCondition != LastOpCondition )
333 {
334 if ( LastOpCondition != 0 )
248 Appendix B. Source code
Calctst0P.cc
401 OpCondition = SaveOpCondition = _C_;
402 if ( OpCondition != LastOpCondition )
403 {
404 #ifdef SAT
405 double AAA, BBB;
406 AAA = ( X * beta + Y * alpha ) / ( X * Y );
407 BBB = -( VDD * t0_p[ p ] * ( X + Y ) - Vd_p[ p ] * X * tauo_p[ p ] - Vs_p[ p ] * Y * taui_p[ p ] ) / ( X * Y );
408 AAA /= Vc;
409 BBB /= Vc;
410 BBB -= 1.0;
411 H = 2 * ( A_1_p[ p ] + 1 ) * ( Vs_p[ p ] - VDD ) / ( Vc * X );
412 K = ( 2 * A_1_p[ p ] * ( VDD * t0_p[ p ] - Vs_p[ p ] * taui_p[ p ] ) + \
413 2 * B_1_p[ p ] * X + 2 * VDD * t0_p[ p ] + Vc * X - 2 * Vs_p[ p ] * taui_p[ p ] ) / \
414 ( Vc * X );
415 det = 4 * K * AAA * AAA - 4 * H * AAA * BBB + H * H;
416 if ( det >= 0 )
417 {
418 ts_p[ p ] = ( SQRT ( det ) - 2 * AAA * BBB + H ) / ( 2 * AAA * AAA );
419 if ( ( ts_p[ p ] < 0 ) || ( ts_p[ p ] < t0_p[ p ] ) || ( ts_p[ p ] > tauo_p[ p ] ) )
420 ts_p[ p ] = -( SQRT ( det ) + 2 * AAA * BBB - H ) / ( 2 * AAA * AAA );
421 }
422 else
423 ts_p[ p ] = ( A_1_p[ p ] * ( t0_p[ p ] - tauo_p[ p ] ) * ( VDD * t0_p[ p ] - Vs_p[ p ] * taui_p[ p ] ) + \
424 ( t0_p[ p ] - taui_p[ p ] ) * ( B_1_p[ p ] * ( t0_p[ p ] - tauo_p[ p ] ) + \
425 VDD * t0_p[ p ] - Vd_p[ p ] * tauo_p[ p ] ) ) / \
426 ( A_1_p[ p ] * ( VDD - Vs_p[ p ] ) * ( t0_p[ p ] - tauo_p[ p ] ) + \
427 ( VDD - Vd_p[ p ] ) * ( t0_p[ p ] - taui_p[ p ] ) );
428 #else
429
430 ts_p[ p ] = ( A_1_p[ p ] * ( t0_p[ p ] - tauo_p[ p ] ) * ( VDD * t0_p[ p ] - Vs_p[ p ] * taui_p[ p ] ) + \
431 ( t0_p[ p ] - taui_p[ p ] ) * ( B_1_p[ p ] * ( t0_p[ p ] - tauo_p[ p ] ) + \
432 VDD * t0_p[ p ] - Vd_p[ p ] * tauo_p[ p ] ) ) / \
433 ( A_1_p[ p ] * ( VDD - Vs_p[ p ] ) * ( t0_p[ p ] - tauo_p[ p ] ) + \
434 ( VDD - Vd_p[ p ] ) * ( t0_p[ p ] - taui_p[ p ] ) );
435 #endif
436 }
437 }
438 else if ( ( tauo_p[ p ] <= taui_p[ p ] ) &&
439 ( tc <= ts_p[ p ] ) &&
440 ( t0_p[ p ] <= ts_p[ p ] ) )
441 {
442 OpCondition = SaveOpCondition = _D_;
443 if ( OpCondition != LastOpCondition )
444 {
445 ts_p[ p ] = tc;
446 }
447 }
448 else
449 {
450 OpCondition = _E_;
451 }
452 }
453 return OpCondition;
454 }
Delay.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8
9 ///
10 double Fast::CalcDelay( const Circuit& circuit,
11 unsigned int NP,
12 unsigned int NC,
250 Appendix B. Source code
13 unsigned int n,
14 unsigned int p,
15 const double* NewWidth,
16 double tin,
17 TransitionType TOut,
18 int& RetCode )
19 {
20
21
22 double t0_bs;
23 for ( unsigned int i = 1; i <= n; i++ )
24 {
25 tauo_n[ i ] = tin;
26 }
27 for ( unsigned int i = 1; i <= p; i++ )
28 {
29 tauo_p[ i ] = tin;
30 }
31 taui_n[ 1 ] = tin;
32 taui_p[ 1 ] = tin;
33 switch ( TOut )
34 {
35 case FALL: // n chain
36 t0_bs = TECH.Vtn0 * tin / VDD;
37 t0_n[ 1 ] = CalcStartTime( circuit, NP, NC, t0_bs, tauo_n[ 1 ], NMOS, NewWidth, RetCode );
38 if ( RetCode != OK )
39 t0_n[ 1 ] = t0_bs;
40 //return 0.0;
41 RetCode = IterSol( circuit, NMOS, NP, NC, n, p, NewWidth );
42 if ( RetCode != OK )
43 return 0.0;
44 else
45 return ( tauo_n[ n ] + t0_n[ n ] - tin );
46 break;
47 case RISE: // p chain
48 t0_bs = -TECH.Vtp0 * tin / VDD;
49 t0_p[ 1 ] = CalcStartTime( circuit, NP, NC, t0_bs, tauo_p[ 1 ], PMOS, NewWidth, RetCode );
50 if ( RetCode != OK )
51 t0_p[ 1 ] = t0_bs;
52 //return 0.0;
53 RetCode = IterSol( circuit, PMOS, NP, NC, n, p, NewWidth );
54 if ( RetCode != OK )
55 return 0.0;
56 else
57 return ( tauo_p[ p ] + t0_p[ p ] - tin );
58 break;
59 case NOTRANSITION:
60 default:
61 break;
62 }
63 return 0.0; // never get here
64 }
EqN.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8 ///
9 double Fast::EqN( const Circuit& circuit, unsigned int NP, unsigned int NC, double x, int& RetCode, unsigned int j, unsigned int n, unsi
10 {
11 int SaveOpCondition = _E_, OpCondition_1, OpCondition_i, OpCondition_n;
12 double y, C_n, Cov, Cgd1;
13
14
15 RetCode = OK;
B.3. Simulators 251
85 }
86 for ( unsigned int i = j; i <= n; i++ )
87 {
88 C_n = 0.0;
89 name = pathlist[ NP ].TransistorName( i - 1 , NC);
90 if ( circuit[ name ].Source() == node )
91 {
92 node = circuit[ name ].Drain();
93 Wjn = circuit.JunctionNWidth( node, njn, NewWidth );
94 Wgn = circuit.GateNWidth( node, ngn, NewWidth );
95 Wjp = circuit.JunctionPWidth( node, njp, NewWidth );
96 Wgp = circuit.GatePWidth( node, ngp, NewWidth );
97 }
98 else if ( circuit[ name ].Drain() == node )
99 {
100 node = circuit[ name ].Source();
101 Wjn = circuit.JunctionNWidth( node, njn, NewWidth );
102 Wgn = circuit.GateNWidth( node, ngn, NewWidth );
103 Wjp = circuit.JunctionPWidth( node, njp, NewWidth );
104 Wgp = circuit.GatePWidth( node, ngp, NewWidth );
105 }
106 if (i == n)
107 LastNode = node;
108 // Common capacitance
109 int nc; // dummy
110 // Cj
111 C_n += -TECH.C_nj * Wjn * TECH.Df * Vd_n[ i ] * pow ( ( 1 + Vd_n[ i ] / TECH.PB_n ), -TECH.mj_n ) - \
112 TECH.C_np * 2 * ( Wjn + njn * TECH.Df ) * Vd_n[ i ] * pow ( 1 + Vd_n[ i ] / TECH.PB_n, -TECH.mjsw_n );
113 // static capacitances
114 C_n += -circuit.CapStaticGnd( node, nc ) * Vd_n[i];
115 C_n += -circuit.CapStaticVdd( node, nc ) * Vd_n[i];
116 // gate capacitances
117 C_n += -Wgn * TECH.Lmin * TECH.Cox_n * Vd_n[i];
118 C_n += -Wgp * TECH.Lmin * TECH.Cox_p * Vd_n[i];
119 if ( ( i == 1 ) && ( i < n - 1 ) )
120 {
121 // Cgd & Cgs minus first mos
122 C_n += -( TECH.Cgs0_n * ( ( Wjn - W_n[ 1 ] ) + ( njn - 1 ) * TECH.XW_n ) + \
123 0.5 * TECH.Cox_n * ( Wjn - W_n[ 1 ] ) * ( njn - 1 ) * TECH.Lmin ) * Vd_n[ i ];
124 }
125 else if ( ( i < n - 1 ) && ( i > 1 ) )
126 {
127 // all Cgd & Cgs
128 C_n += -( TECH.Cgs0_n * ( Wjn + njn * TECH.XW_n ) + \
129 0.5 * TECH.Cox_n * Wjn * njn * TECH.Lmin ) * Vd_n[ i ];
130 }
131 else if ( (( i == n ) || ( i == n - 1 )) && (n > 1) )
132 {
133 // Cgd & Cgs minus last mos
134 C_n += -( TECH.Cgs0_n * ( ( Wjn - W_n[ n ] ) + ( njn - 1 ) * TECH.XW_n ) + \
135 0.5 * TECH.Cox_n * ( Wjn - W_n[ n ] ) * ( njn - 1 ) * TECH.Lmin ) * Vd_n[ i ];
136 }
137 // PMOS
138 C_n += ( TECH.C_pj * Wjp * TECH.Df * ( VDD - Vd_n[ i ] ) * \
139 pow ( ( 1 + ( VDD - Vd_n[ i ] ) / TECH.PB_p ), -TECH.mj_p ) );
140 C_n += ( TECH.C_pp * 2 * ( Wjp + njp * TECH.Df ) * ( VDD - Vd_n[ i ] ) * \
141 pow ( ( 1 + ( VDD - Vd_n[ i ] ) / TECH.PB_p ), TECH.mjsw_p ) );
142 C_n += -VDD * njp * TECH.C_pj * Wjp * TECH.Df * \
143 pow ( ( 1 + VDD / TECH.PB_p ), -TECH.mj_p );
144 C_n += -VDD * TECH.C_pp * 2 * ( Wjp + njp * TECH.Df ) * \
145 pow ( ( 1 + VDD / TECH.PB_p ), -TECH.mjsw_p );
146 // Cgs & Cgd PMOS
147 C_n += -( TECH.Cgd0_p * ( Wjp + njp * TECH.XW_p ) * Vd_n[ i ] );
148 // capacitance with voltages
149 if ( (( i == 1 ) && ( i < n - 1 )) || ((i == 1) && (n == 1)) )
150 {
151 // Cgd
152 Cov = TECH.Cgd0_n * ( W_n[ i ] + TECH.XW_n );
153 Cgd1 = Cov + 0.5 * TECH.Cox_n * W_n[ i ] * L_n[ i ];
B.3. Simulators 253
EqP.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8 ///
9 double Fast::EqP( const Circuit& circuit, unsigned int NP, unsigned int NC, double x, int& RetCode, unsigned int j, unsigned int n, unsi
10 {
11 int SaveOpCondition = _E_, OpCondition_1, OpCondition_i, OpCondition_p;
12 double y, C_p, Cov, Cgd1;
13
14
15 RetCode = OK;
16 double* FY = new double[p + 1];
17 tauo_p[ j ] = x;
18 double t0_bs = -TECH.Vtp0 / VDD * taui_p[ 1 ];
19 double tc = (VDD * tauo_p[p] * (t0_p[p] - taui_p[p]) + \
20 Vs_p[p] * taui_p[p] * (tauo_p[p] - t0_p[p])) / \
21 (VDD * (t0_p[p] - taui_p[p]) + Vs_p[p] * (tauo_p[p] - t0_p[p]));
22 // tc cross-time : Vd = Vs
23 if ( j == 1 )
24 {
25 OpCondition_1 = Calct0ts1P( circuit, NP, SaveOpCondition, NewWidth );
26 if ( ( OpCondition_1 == _E_ ) || ( t0_p[ 1 ] < t0_bs ) )
27 {
28 RetCode = PARSE_ERROR;
29 if ( SaveOpCondition == _E_ )
30 OpCondition_1 = _A_;
31 else
32 OpCondition_1 = SaveOpCondition;
33 }
34 FY[ 1 ] = FirstEqP( OpCondition_1, tauo_p[ j ] );
35 }
36 for ( unsigned int i = 2; i <= p; i++ )
37 {
B.3. Simulators 257
38 t0_p[ i ] = t0_p[ i - 1 ];
39 taui_p[ i ] = tauo_p[ i - 1 ];
40 }
41 // middle equations
42 if ( ( j > 1 ) && ( j < p ) )
43 {
44 if ( taui_p[ j ] <= tauo_p[ j ] )
45 OpCondition_i = _A_;
46 else
47 OpCondition_i = _E_;
48 if ( OpCondition_i == _E_ )
49 {
50 RetCode = PARSE_ERROR;
51 OpCondition_i = _A_;
52 }
53 FY[ j ] = MiddleEqP( OpCondition_i, j, tauo_p[ j ] );
54 }
55 // last equation
56 if ( p > 1 )
57 {
58 OpCondition_p = Calct0tsnP( n, SaveOpCondition );
59 if ( ( OpCondition_p == _E_ ) || ( OpCondition_p == _C_ ) || ( OpCondition_p == _D_ ) )
60 {
61 RetCode = PARSE_ERROR;
62 if ( SaveOpCondition == _E_ )
63 OpCondition_p = _A_;
64 else
65 OpCondition_p = SaveOpCondition;
66 }
67 if ( j == p )
68 FY[ p ] = LastEqP( OpCondition_p, p, tauo_p[ p ] );
69 }
70 y = FY[ j ];
71 // evaluate capacitance at each node
72 unsigned int node; // it’s the common node used to traverse the path
73 unsigned int LastNode;
74 const char* name = pathlist[ NP ].TransistorName( n + p - 1, NC ); // first pmos in path
75 int njn, ngn, njp, ngp;
76 double Wjn, Wgn, Wjp, Wgp;
77 node = circuit.ValimNode();
78 for ( unsigned int i = j, k = 1; i > 1; i--, k++ )
79 {
80 if ( circuit[ name ].Source() == node )
81 node = circuit[ name ].Drain();
82 else if ( circuit[ name ].Drain() == node )
83 node = circuit[ name ].Source();
84 name = pathlist[ NP ].TransistorName( n + p - 1 - k, NC );
85 }
86 for ( unsigned int i = j; i <= p; i++ )
87 {
88 C_p = 0.0;
89 name = pathlist[ NP ].TransistorName( n + p - i, NC ); // first there are n nmos
90 // the there are the pmos, in REVERSE order
91 if ( circuit[ name ].Source() == node )
92 {
93 node = circuit[ name ].Drain();
94 Wjn = circuit.JunctionNWidth( node, njn, NewWidth );
95 Wgn = circuit.GateNWidth( node, ngn, NewWidth );
96 Wjp = circuit.JunctionPWidth( node, njp, NewWidth );
97 Wgp = circuit.GatePWidth( node, ngp, NewWidth );
98 }
99 else if ( circuit[ name ].Drain() == node )
100 {
101 node = circuit[ name ].Source();
102 Wjn = circuit.JunctionNWidth( node, njn, NewWidth );
103 Wgn = circuit.GateNWidth( node, ngn, NewWidth );
104 Wjp = circuit.JunctionPWidth( node, njp, NewWidth );
105 Wgp = circuit.GatePWidth( node, ngp, NewWidth );
106 }
258 Appendix B. Source code
107 if (i == p)
108 LastNode = node;
109 // Common capacitance
110 int nc; // dummy
111 // Cj
112 C_p += TECH.C_pj * Wjp * TECH.Df * ( VDD - Vd_p[ i ]) * pow ( ( 1 + ( VDD - Vd_p[ i ] ) / TECH.PB_p ), -TECH.mj_p );
113 C_p += TECH.C_pp * 2 * ( Wjp + njp * TECH.Df ) * ( VDD - Vd_p[ i ]) * pow ( 1 + ( VDD - Vd_p[ i ] ) / TECH.PB_p, -TECH.mjsw_p );
114 // static capacitances
115 C_p += circuit.CapStaticGnd( node, nc ) * ( VDD - Vd_p[ i ]);
116 C_p += circuit.CapStaticVdd( node, nc ) * ( VDD - Vd_p[ i ]);
117 // gate capacitances
118 C_p += Wgn * TECH.Lmin * TECH.Cox_n * ( VDD - Vd_p[ i ]);
119 C_p += Wgp * TECH.Lmin * TECH.Cox_p * ( VDD - Vd_p[ i ]);
120 if ( ( i == 1 ) && ( i < p - 1 ) )
121 {
122 // Cgd & Cgs minus first mos
123 C_p += ( TECH.Cgs0_p * ( ( Wjp - W_p[ 1 ] ) + ( njp - 1 ) * TECH.XW_p ) + \
124 0.5 * TECH.Cox_p * ( Wjp - W_p[ 1 ] ) * ( njp - 1 ) * TECH.Lmin ) * ( VDD - Vd_p[ i ] );
125 }
126 else if ( ( i < p - 1 ) && ( i > 1 ) )
127 {
128 // all Cgd & Cgs
129 C_p += ( TECH.Cgs0_p * ( Wjp + njp * TECH.XW_p ) + \
130 0.5 * TECH.Cox_p * Wjp * njp * TECH.Lmin ) * ( VDD - Vd_p[ i ] );
131 }
132 else if ( (( i == p ) || ( i == p - 1 )) && (p > 1) )
133 {
134 // Cgd & Cgs minus last mos
135 C_p += ( TECH.Cgs0_p * ( ( Wjp - W_p[ p ] ) + ( njp - 1 ) * TECH.XW_p ) + \
136 0.5 * TECH.Cox_p * ( Wjp - W_p[ p ] ) * ( njp - 1 ) * TECH.Lmin ) * ( VDD - Vd_p[ i ] );
137 }
138 // NMOS
139 C_p += -( TECH.C_nj * Wjn * TECH.Df * Vd_p[ i ] ) * \
140 pow ( ( 1 + Vd_p[ i ] / TECH.PB_n ), -TECH.mj_n );
141 C_p += -( TECH.C_np * 2 * ( Wjn + njn * TECH.Df ) * Vd_p[ i ] ) * \
142 pow ( ( 1 + Vd_p[ i ] / TECH.PB_n ), -TECH.mjsw_n );
143 C_p += ( TECH.C_nj * Wjn * TECH.Df * VDD ) * \
144 pow ( ( 1 + VDD / TECH.PB_n ), -TECH.mj_n );
145 C_p += ( TECH.C_np * 2 * ( Wjn + njn * TECH.Df ) * VDD ) * \
146 pow ( ( 1 + VDD / TECH.PB_n ), -TECH.mjsw_n );
147 // Cgs & Cgd
148 C_p += TECH.Cgd0_n * ( Wjn + njn * TECH.XW_n ) * ( VDD - Vd_p[ i ]);
149 // capacitance with voltages
150 if ( (( i == 1 ) && ( i < p - 1 )) || ((i == 1) && (p == 1)) )
151 {
152 // Cgd
153 Cov = TECH.Cgd0_p * ( W_p[ i ] + TECH.XW_p );
154 Cgd1 = Cov + 0.5 * TECH.Cox_p * W_p[ i ] * L_p[ i ];
155 switch ( OpCondition_1 )
156 {
157 case _A_:
158 C_p += Cov * ( t0_p[ i ] - ts_p[ i ] ) * \
159 ( VDD * ( t0_p[ i ] - tauo_p[ i ] - taui_p[i]) + Vd_p[ i ] * taui_p[ i ] ) / \
160 ( taui_p[ i ] * ( tauo_p[ i ] - t0_p[i]) );
161 C_p += Cgd1 * ( VDD * ( t0_p[ i ] * ( ts_p[ i ] - taui_p[ i ] ) - \
162 ts_p[ i ] * ( taui_p[ i ] + tauo_p[ i ] ) + 2 * taui_p[ i ] * tauo_p[ i ] ) + \
163 Vd_p[ i ] * taui_p[ i ] * ( ts_p[ i ] - tauo_p[ i ] ) ) / \
164 ( taui_p[ i ] * ( tauo_p[ i ] - t0_p[i]) );
165 break;
166 case _AA_:
167 C_p += Cov * ( VDD * ( t0_p[ i ] * t0_p[ i ] - t0_p[ i ] * ( 2 * taui_p[ i ] + tauo_p[ i ] ) + \
168 taui_p[ i ] * ( ts_p[ i ] + tauo_p[ i ] ) ) + \
169 Vd_p[ i ] * taui_p[ i ] * ( t0_p[ i ] - ts_p[ i ] ) ) / \
170 ( taui_p[ i ] * ( tauo_p[ i ] - t0_p[i]) );
171 C_p += Cgd1 * ( VDD - Vd_p[ i ] ) * ( ts_p[ i ] - tauo_p[ i ] ) / \
172 ( t0_p[i] - tauo_p[ i ]);
173 break;
174 case _B_:
175 C_p += -Cgd1 * ( VDD * ( t0_p[ i ] - 2 * taui_p[ i ] ) + Vd_p[ i ] * taui_p[ i ] ) / \
B.3. Simulators 259
176 taui_p[ i ];
177 break;
178 case _C_:
179 C_p += Cov * ( VDD - Vd_p[ i ] ) * ( t0_p[ i ] - ts_p[ i ] ) / \
180 ( t0_p[i] - tauo_p[ i ]);
181 C_p += Cgd1 * ( VDD - Vd_p[ i ] ) * ( ts_p[ i ] - tauo_p[ i ] ) / \
182 ( t0_p[i] - tauo_p[ i ]);
183 break;
184 case _D_:
185 C_p += Cgd1 * ( VDD - Vd_p[ i ] );
186 break;
187 case _F_:
188 C_p += Cov * ( t0_p[ i ] - ts_p[ i ] ) * \
189 ( VDD * ( t0_p[ i ] - taui_p[ i ] - tauo_p[ i ] ) + Vd_p[ i ] * taui_p[ i ] ) / \
190 ( taui_p[ i ] * ( tauo_p[ i ] - t0_p[i]) );
191 C_p += Cgd1 * ( tauo_p[ i ] - ts_p[ i ] ) * \
192 ( VDD * ( t0_p[ i ] - taui_p[ i ] - tauo_p[ i ] ) + Vd_p[ i ] * taui_p[ i ] ) / \
193 ( taui_p[ i ] * ( t0_p[i] - tauo_p[ i ] ) );
194 break;
195 case _G_:
196 C_p += -Cgd1 * ( VDD * ( t0_p[ i ] - taui_p[ i ] - tauo_p[ i ] ) + Vd_p[ i ] * taui_p[ i ] ) / \
197 taui_p[ i ];
198 break;
199 case _E_:
200 default:
201 break;
202 }
203 }
204 else if ( ( i == 1 ) && ( i == p - 1 ) )
205 {
206 // Cgd
207 Cov = TECH.Cgd0_p * ( W_p[ i ] + TECH.XW_p );
208 Cgd1 = Cov + 0.5 * TECH.Cox_p * W_p[ i ] * L_p[ i ];
209 switch ( OpCondition_1 )
210 {
211 case _A_:
212 C_p += Cov * ( t0_p[ i ] - ts_p[ i ] ) * \
213 ( VDD * ( t0_p[ i ] - tauo_p[ i ] - taui_p[i]) + Vd_p[ i ] * taui_p[ i ] ) / \
214 ( taui_p[ i ] * ( tauo_p[ i ] - t0_p[i]) );
215 C_p += Cgd1 * ( VDD * ( t0_p[ i ] * ( ts_p[ i ] - taui_p[ i ] ) - \
216 ts_p[ i ] * ( taui_p[ i ] + tauo_p[ i ] ) + 2 * taui_p[ i ] * tauo_p[ i ] ) + \
217 Vd_p[ i ] * taui_p[ i ] * ( ts_p[ i ] - tauo_p[ i ] ) ) / \
218 ( taui_p[ i ] * ( tauo_p[ i ] - t0_p[i]) );
219 break;
220 case _AA_:
221 C_p += Cov * ( VDD * ( t0_p[ i ] * t0_p[ i ] - t0_p[ i ] * ( 2 * taui_p[ i ] + tauo_p[ i ] ) + \
222 taui_p[ i ] * ( ts_p[ i ] + tauo_p[ i ] ) ) + \
223 Vd_p[ i ] * taui_p[ i ] * ( t0_p[ i ] - ts_p[ i ] ) ) / \
224 ( taui_p[ i ] * ( tauo_p[ i ] - t0_p[i]) );
225 C_p += Cgd1 * ( VDD - Vd_p[ i ] ) * ( ts_p[ i ] - tauo_p[ i ] ) / \
226 ( t0_p[i] - tauo_p[ i ]);
227 break;
228 case _B_:
229 C_p += -Cgd1 * ( VDD * ( t0_p[ i ] - 2 * taui_p[ i ] ) + Vd_p[ i ] * taui_p[ i ] ) / \
230 taui_p[ i ];
231 break;
232 case _C_:
233 C_p += Cov * ( VDD - Vd_p[ i ] ) * ( t0_p[ i ] - ts_p[ i ] ) / \
234 ( t0_p[i] - tauo_p[ i ]);
235 C_p += Cgd1 * ( VDD - Vd_p[ i ] ) * ( ts_p[ i ] - tauo_p[ i ] ) / \
236 ( t0_p[i] - tauo_p[ i ]);
237 break;
238 case _D_:
239 C_p += Cgd1 * ( VDD - Vd_p[ i ] );
240 break;
241 case _F_:
242 C_p += Cov * ( t0_p[ i ] - ts_p[ i ] ) * \
243 ( VDD * ( t0_p[ i ] - taui_p[ i ] - tauo_p[ i ] ) + Vd_p[ i ] * taui_p[ i ] ) / \
244 ( taui_p[ i ] * ( tauo_p[ i ] - t0_p[i]) );
260 Appendix B. Source code
314 }
315 else if ( i == p )
316 {
317 // Cgd
318 Cov = ( TECH.Cgd0_p * ( W_p[ p ] + TECH.XW_p ) );
319 Cgd1 = ( TECH.Cgd0_p * ( W_p[ p ] + TECH.XW_p ) + 0.5 * TECH.Cox_p * W_p[ p ] * L_p[ p ] );
320 switch ( OpCondition_p )
321 {
322 case _A_:
323 case _B_:
324 C_p += Cov * \
325 ( VDD - Vd_p[ i ] ) * ( t0_p[ i ] - ts_p[ i ] ) / ( t0_p[i] - tauo_p[ i ]);
326 C_p += Cgd1 * \
327 ( VDD - Vd_p[ i ] ) * ( ts_p[i] - tauo_p[ i ]) / ( t0_p[ i ] - tauo_p[ i ] );
328 break;
329 case _C_:
330 C_p += Cov * \
331 ( VDD - Vd_p[ i ] ) * ( t0_p[ i ] - ts_p[ i ] ) / ( t0_p[i] - tauo_p[ i ]);
332 C_p += Cgd1 * \
333 ( VDD - Vd_p[ i ] ) * ( ts_p[ i ] - tc) / ( t0_p[ i ] - tauo_p[ i ] );
334 break;
335 case _D_:
336 C_p += Cov * \
337 ( VDD - Vd_p[ i ] ) * ( t0_p[ i ] - tc ) / ( t0_p[i] - tauo_p[ i ]);
338 break;
339 case _E_:
340 default:
341 break;
342 }
343 }
344 y += C_p;
345 }
346 node = LastNode;
347 C_p = 0;
348 for (unsigned int i = 0; (i < n - 1) && (n > 0); i++)
349 {
350 name = pathlist[ NP ].TransistorName( n - 1 - i, NC );
351 if ( circuit[ name ].Source() == node )
352 {
353 node = circuit[ name ].Drain();
354 Wjn = circuit.JunctionNWidth( node, njn, NewWidth );
355 Wgn = circuit.GateNWidth( node, ngn, NewWidth );
356 Wjp = circuit.JunctionPWidth( node, njp, NewWidth );
357 Wgp = circuit.GatePWidth( node, ngp, NewWidth );
358 }
359 else if ( circuit[ name ].Drain() == node )
360 {
361 node = circuit[ name ].Source();
362 Wjn = circuit.JunctionNWidth( node, njn, NewWidth );
363 Wgn = circuit.GateNWidth( node, ngn, NewWidth );
364 Wjp = circuit.JunctionPWidth( node, njp, NewWidth );
365 Wgp = circuit.GatePWidth( node, ngp, NewWidth );
366 }
367 // Cj
368 C_p += TECH.C_pj * Wjp * TECH.Df * ( VDD - Vd_p[ p ]) * pow ( ( 1 + ( VDD - Vd_p[ p ] ) / TECH.PB_p ), -TECH.mj_p );
369 C_p += TECH.C_pp * 2 * ( Wjp + njp * TECH.Df ) * ( VDD - Vd_p[ p ]) * pow ( 1 + ( VDD - Vd_p[ p ] ) / TECH.PB_p, -TECH.mjsw_p );
370 // static capacitances
371 int nc;
372 C_p += circuit.CapStaticGnd( node, nc ) * ( VDD - Vd_p[ p ]);
373 C_p += circuit.CapStaticVdd( node, nc ) * ( VDD - Vd_p[ p ]);
374 // gate capacitances
375 C_p += Wgn * TECH.Lmin * TECH.Cox_n * ( VDD - Vd_p[ p ] );
376 C_p += Wgp * TECH.Lmin * TECH.Cox_p * ( VDD - Vd_p[ p ] );
377 // NMOS in chain
378 C_p += -( TECH.C_nj * Wjn * TECH.Df * Vd_p[ p ] ) * \
379 pow ( ( 1 + Vd_p[ p ] / TECH.PB_n ), -TECH.mj_n );
380 C_p += -( TECH.C_np * 2 * ( Wjn + njn * TECH.Df ) * Vd_p[ p ] ) * \
381 pow ( ( 1 + Vd_p[ p ] / TECH.PB_n ), -TECH.mjsw_n );
382 C_p += ( TECH.C_nj * Wjn * TECH.Df * VDD ) * \
262 Appendix B. Source code
Fast.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8
9 ///
10 Fast::Fast( const CritPathList& pathlist, const Options& options )
11 :
12 EvaluationAlgorithm( pathlist, options ),
13 A_1_n( 0 ), ts_n( 0 ), tauo_n( 0 ), taui_n( 0 ), t0_n( 0 ),
14 beta_n( 0 ), Vd_n( 0 ), Vs_n( 0 ), W_n( 0 ), L_n( 0 ),
15 A_1_p( 0 ), B_1_p( 0 ), ts_p( 0 ), tauo_p( 0 ), taui_p( 0 ), t0_p( 0 ),
16 beta_p( 0 ), Vd_p( 0 ), Vs_p( 0 ), W_p( 0 ), L_p( 0 ), VDD( 0 )
17 {
18 print_log( "Creating Fast instance..." );
19 }
20
21 ///
22 Fast::~Fast()
23 {}
24
25 ///
26
27 int Fast::Run( const Circuit& circuit, const double *NewWidth, const unsigned* ValidPath )
28 {
29 VDD = circuit.Valim();
30 Calls++;
31 int RetCode;
32 double tin;
33 unsigned int n;
34 unsigned int p;
35 double TotalDelay;
36 double TotalPower;
37 double TotalNoise;
38 for ( unsigned int NP = 0; NP < NumPath; NP++ )
39 {
40 if (ValidPath[NP])
41 {
42 unsigned int NumChain = pathlist[ NP ].GetNumListTran();
43 TransitionType TIn;
44 TransitionType TOut;
45 TotalDelay = 0.0;
46 TotalPower = 0.0;
47 TotalNoise = 0.0;
48 for ( unsigned int NC = 0; NC < NumChain; NC++ )
49 {
50 if ( NC == 0 )
51 {
52 TIn = pathlist[ NP ].GetTransitionIn();
53 tin = pathlist[ NP ].GetInTime() / 1000;
54 }
55 else
56 {
B.3. Simulators 263
57 if ( TIn == FALL )
58 tin = tauo_n[ n ];
59 else if ( TIn == RISE )
60 tin = tauo_p[ p ];
61 }
62 if ( TIn == FALL )
63 {
64 TOut = RISE;
65 }
66 else if ( TIn == RISE )
67 {
68 TOut = FALL;
69 }
70 n = pathlist[ NP ].GetNumTranN( NC );
71 p = pathlist[ NP ].GetNumTranP( NC );
72 if ( ( RetCode = InitCircuitVar( n, p ) ) != OK )
73 return RetCode;
74 unsigned int in = 1;
75 unsigned int ip = 1;
76 while ( const char * tn = pathlist[ NP ].TraverseTransistorNameList( NC ) )
77 {
78 int position = circuit.TranPos( tn );
79 if ( position == -1 )
80 return NOT_FOUND;
81 if ( in <= n )
82 {
83 W_n[ in ] = NewWidth[ position ];
84 L_n[ in++ ] = circuit[ position ].Length();
85 }
86 else if ( ip <= p )
87 {
88 W_p[ p - ip + 1 ] = NewWidth[ position ];
89 L_p[ p - ip + 1 ] = circuit[ position ].Length();
90 ip++;
91 }
92 else
93 return NOT_FOUND;
94 }
95 CalcParamCircuit( n, p );
96
97
98 TotalDelay += CalcDelay( circuit, NP, NC, n, p, NewWidth, tin, TOut, RetCode );
99 if ( RetCode != OK )
100 return RetCode;
101 TotalPower += CalcPower( circuit, NP, NC, n, p, NewWidth, TOut, RetCode );
102 if ( RetCode != OK )
103 return RetCode;
104 TotalNoise = 0.0;
105 FreeCircuitPar( n, p );
106 TIn = TOut;
107 }
108 if (NumChain > 0)
109 for (unsigned int i = 0; i < NumChain; i++)
110 TotalDelay *= 1.85;
111 else if (NumChain > 1)
112 for (unsigned int i = 0; i < NumChain; i++)
113 TotalDelay *= 3.1; // 1.07 tech 07
114 CPDelay[ NP ] = TotalDelay * 1000; // ps
115 CPPower[ NP ] = TotalPower / 1000.0; // pJ
116 CPNoise[ NP ] = TotalNoise;
117 }
118 }
119 Area = CalcArea( NewWidth, circuit.GetNTran() );
120 if ( RetCode != OK )
121 return RetCode;
122 return OK;
123 }
264 Appendix B. Source code
FastArea.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8 ///
9 double Fast::CalcArea( const double *NewWidth, unsigned int NT )
10 {
11 double A = 0.0;
12 for ( unsigned int i = 0; i < NT; i++ )
13 {
14 A += NewWidth[ i ];
15 }
16 return ( A );
17 }
FirstEqN.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8 ///
9 double Fast::FirstEqN( int OpCondition, double tauon )
10 {
11 double Vc, t0_bs, temp;
12 double A_2_n, B_2_n, C_2_n, D_2_n, I_2_n;
13 double N_2_n, O_2_n, P_2_n;
14 double Q_2_n, R_2_n, S_2_n, T_2_n, U_2_n;
15
16 t0_bs = TECH.Vtn0 * taui_n[ 1 ] / VDD;
17 Vc = TECH.Ec_n * L_n[ 1 ];
18 if ( OpCondition == _E_ )
19 if ( taui_n[ 1 ] <= tauon )
20 OpCondition = _A_;
21 else
22 OpCondition = _F_;
23 A_2_n = Vc * beta_n[ 1 ] * ( Vc - TECH.Vtn0 );
24 B_2_n = VDD * Vc * beta_n[ 1 ] / taui_n[ 1 ];
25 C_2_n = 2 * VDD / ( Vc * taui_n[ 1 ] );
26 D_2_n = ( Vc - 2 * TECH.Vtn0 ) / Vc;
27 I_2_n = ( Vc * Vc ) * beta_n[ 1 ] * ( sqrt ( ( 2 * VDD + Vc - 2 * TECH.Vtn0 ) / Vc ) - 1 ) * \
28 ( sqrt ( ( 2 * VDD + Vc - 2 * TECH.Vtn0 ) / Vc ) - 1 ) * 0.5;
29 N_2_n = Vc * beta_n[ 1 ] * ( 2 * VDD * Vc * ( ( t0_n[ 1 ] - tauon ) * ( t0_n[ 1 ] - tauon ) ) - \
30 Vd_n[ 1 ] * taui_n[ 1 ] * ( Vc * ( t0_n[ 1 ] - tauon ) + \
31 Vd_n[ 1 ] * tauon + 2 * TECH.Vtn0 * ( tauon - t0_n[ 1 ] ) ) ) / \
32 ( 2 * Vd_n[ 1 ] * taui_n[ 1 ] * ( tauon - t0_n[ 1 ] ) );
33 O_2_n = Vc * beta_n[ 1 ] * ( 2 * VDD * ( t0_n[ 1 ] - tauon ) - Vd_n[ 1 ] * taui_n[ 1 ] ) / \
34 ( 2 * taui_n[ 1 ] * ( t0_n[ 1 ] - tauon ) );
35 P_2_n = ( Vc * Vc ) * beta_n[ 1 ] * ( t0_n[ 1 ] - tauon ) * \
36 ( 2 * VDD * ( Vc * ( t0_n[ 1 ] - tauon ) - Vd_n[ 1 ] * tauon ) - Vd_n[ 1 ] * taui_n[ 1 ] * ( Vc - 2 * TECH.Vtn0 ) );
37 Q_2_n = 2 * Vd_n[ 1 ] * taui_n[ 1 ] * ( Vc * ( t0_n[ 1 ] - tauon ) - Vd_n[ 1 ] * tauon );
38 R_2_n = Vc * beta_n[ 1 ] * ( 2 * VDD * ( t0_n[ 1 ] - tauon ) + \
39 Vc * ( t0_n[ 1 ] - tauon ) + \
40 Vd_n[ 1 ] * tauon + 2 * TECH.Vtn0 * ( tauon - t0_n[ 1 ] ) ) / \
41 ( 2 * ( t0_n[ 1 ] - tauon ) );
42 S_2_n = Vc * Vd_n[ 1 ] * beta_n[ 1 ] / ( 2 * ( tauon - t0_n[ 1 ] ) );
43 T_2_n = ( Vc * Vc ) * beta_n[ 1 ] * ( tauon - t0_n[ 1 ] ) * ( 2 * VDD + Vc - 2 * TECH.Vtn0 );
44 U_2_n = 2 * ( Vc * ( t0_n[ 1 ] - tauon ) - Vd_n[ 1 ] * tauon );
45 switch ( OpCondition )
46 {
47 case _A_:
48 temp = -P_2_n * LOG2 ( Q_2_n + 2 * ( Vd_n[ 1 ] * Vd_n[ 1 ] ) * ts_n[ 1 ] * taui_n[ 1 ] ) / ( ( Vd_n[ 1 ] * Vd_n[ 1 ] ) * taui_n[
49 P_2_n * LOG2 ( Q_2_n + 2 * ( Vd_n[ 1 ] * Vd_n[ 1 ] ) * ( taui_n[ 1 ] * taui_n[ 1 ] ) ) / ( ( Vd_n[ 1 ] * Vd_n[ 1 ] ) * ta
50 T_2_n * LOG2 ( U_2_n + 2 * Vd_n[ 1 ] * taui_n[ 1 ] ) / Vd_n[ 1 ] + \
51 T_2_n * LOG2 ( U_2_n + 2 * Vd_n[ 1 ] * tauon ) / Vd_n[ 1 ] - \
B.3. Simulators 265
FirstEqP.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
266 Appendix B. Source code
5 #include "print.h"
6 #include "fast.h"
7
8 ///
9 double Fast::FirstEqP( int OpCondition, double tauop )
10 {
11 double Vc, t0_bs, temp, x, y;
12 double A_2_p, B_2_p, C_2_p, D_2_p, G_2_p, J_2_p;
13 double K_2_p, M_2_p, N_2_p, O_2_p, P_2_p;
14 double Q_2_p, R_2_p, S_2_p, T_2_p;
15
16 t0_bs = -TECH.Vtp0 * taui_p[ 1 ] / VDD;
17 Vc = TECH.Ec_p * L_p[ 1 ];
18 if ( OpCondition == _E_ )
19 if ( taui_p[ 1 ] <= tauop )
20 OpCondition = _A_;
21 else
22 OpCondition = _F_;
23 x = t0_p[ 1 ] - taui_p[ 1 ];
24 y = t0_p[ 1 ] - tauop;
25 A_2_p = Vc * beta_p[ 1 ] * ( Vc + TECH.Vtp0 );
26 B_2_p = VDD * Vc * beta_p[ 1 ] / taui_p[ 1 ];
27 C_2_p = ( Vc + 2 * TECH.Vtp0 ) / Vc;
28 D_2_p = 2 * VDD / ( Vc * taui_p[ 1 ] );
29 G_2_p = Vc * Vc * beta_p[ 1 ] * SQRT ( ( 2 * VDD + Vc + 2 * TECH.Vtp0 ) / Vc ) - \
30 VDD * Vc * beta_p[ 1 ] - Vc * Vc * beta_p[ 1 ] - Vc * TECH.Vtp0 * beta_p[ 1 ];
31 J_2_p = Vc * beta_p[ 1 ] * ( ( VDD * VDD ) * taui_p[ 1 ] * tauop - \
32 VDD * ( Vc * y * ( x + y - tauop ) + \
33 2 * taui_p[ 1 ] * ( Vd_p[ 1 ] * tauop - TECH.Vtp0 * y ) ) - \
34 Vd_p[ 1 ] * taui_p[ 1 ] * ( Vc * y - \
35 Vd_p[ 1 ] * tauop + 2 * TECH.Vtp0 * y ) ) / \
36 ( 2 * taui_p[ 1 ] * ( Vd_p[ 1 ] - VDD ) * y );
37 K_2_p = -Vc * beta_p[ 1 ] * ( VDD * ( x + y - tauop ) + \
38 Vd_p[ 1 ] * taui_p[ 1 ] ) / \
39 ( 2 * taui_p[ 1 ] * y );
40 M_2_p = ( Vc * Vc ) * beta_p[ 1 ] * y * ( 2 * ( VDD * VDD ) * tauop - \
41 VDD * ( Vc * ( x + y - tauop ) + \
42 2 * ( Vd_p[ 1 ] * tauop - TECH.Vtp0 * taui_p[ 1 ] ) ) - \
43 Vd_p[ 1 ] * taui_p[ 1 ] * ( Vc + 2 * TECH.Vtp0 ) );
44 N_2_p = 2 * taui_p[ 1 ] * ( VDD - Vd_p[ 1 ] ) * \
45 ( VDD * tauop - Vc * y - Vd_p[ 1 ] * tauop );
46 O_2_p = 2 * taui_p[ 1 ] * ( ( VDD - Vd_p[ 1 ] ) * ( VDD - Vd_p[ 1 ] ) );
47 P_2_p = -Vc * beta_p[ 1 ] * ( VDD * ( t0_p[ 1 ] + y ) + \
48 Vc * y - Vd_p[ 1 ] * tauop + 2 * TECH.Vtp0 * y ) / \
49 ( 2 * y );
50 Q_2_p = Vc * beta_p[ 1 ] * ( VDD - Vd_p[ 1 ] ) / ( 2 * y );
51 R_2_p = ( Vc * Vc ) * beta_p[ 1 ] * y * ( 2 * VDD + Vc + 2 * TECH.Vtp0 );
52 S_2_p = 2 * ( VDD * tauop - Vc * y - Vd_p[ 1 ] * tauop );
53
54 T_2_p = 2 * ( VDD - Vd_p[ 1 ] );
55 switch ( OpCondition )
56 {
57 case _A_:
58 temp = -M_2_p * LOG ( O_2_p * ts_p[ 1 ] - N_2_p ) / O_2_p + \
59 M_2_p * LOG ( O_2_p * taui_p[ 1 ] - N_2_p ) / O_2_p - \
60 R_2_p * LOG ( T_2_p * taui_p[ 1 ] - S_2_p ) / T_2_p + \
61 R_2_p * LOG ( T_2_p * tauop - S_2_p ) / T_2_p + \
62 ( 6 * A_2_p * D_2_p * ( t0_p[ 1 ] - ts_p[ 1 ] ) + \
63 3 * B_2_p * D_2_p * ( t0_p[ 1 ] * t0_p[ 1 ] - ts_p[ 1 ] * ts_p[ 1 ] ) - \
64 4 * Vc * Vc * beta_p[ 1 ] * pow( ( C_2_p + D_2_p * t0_p[ 1 ] ), 1.5 ) + \
65 4 * Vc * Vc * beta_p[ 1 ] * pow( ( C_2_p + D_2_p * ts_p[ 1 ] ), 1.5 ) - \
66 3 * D_2_p * ( 2 * J_2_p * ( ts_p[ 1 ] - taui_p[ 1 ] ) + \
67 K_2_p * ( ts_p[ 1 ] * ts_p[ 1 ] - taui_p[ 1 ] * taui_p[ 1 ] ) + \
68 2 * P_2_p * ( taui_p[ 1 ] - tauop ) + \
69 Q_2_p * ( taui_p[ 1 ] * taui_p[ 1 ] - tauop * tauop ) ) ) / \
70 ( 6 * D_2_p );
71 break;
72 case _AA_:
73 temp = -R_2_p * LOG ( T_2_p * ts_p[ 1 ] - S_2_p ) / T_2_p + \
B.3. Simulators 267
Init.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8 ///
9 int Fast::InitCircuitVar( unsigned int n, unsigned int p )
268 Appendix B. Source code
10 {
11 // NMOS
12 if (n == 0)
13 n = 1;
14 A_1_n = dvector ( 1, n );
15 ts_n = dvector ( 1, n );
16 tauo_n = dvector ( 1, n );
17 taui_n = dvector ( 1, n );
18 t0_n = dvector ( 1, n );
19 beta_n = dvector ( 1, n );
20 Vd_n = dvector ( 1, n );
21 Vs_n = dvector ( 1, n );
22 W_n = dvector ( 1, n );
23 L_n = dvector ( 1, n );
24 if ( !A_1_n || !ts_n || !tauo_n || !taui_n || !t0_n || !beta_n || !Vd_n || !Vs_n || !W_n || !L_n )
25 return NO_MEM;
26 TECH.u0_n = TECH.Kp_n / TECH.Cox_n;
27 TECH.Ec_n = TECH.vmax_n / TECH.u0_n * ( 1 + TECH.theta_n * ( VDD - TECH.Vtn0 ) );
28 double phip_n = TECH.phi_n;
29 double gamma_n = TECH.gamma_n;
30 double Vsb1_n = -0.5 * gamma_n * sqrt ( 4 * gamma_n * sqrt ( 2 * phip_n ) + \
31 8 * phip_n + 4 * VDD - 4 * TECH.Vtn0 + gamma_n * gamma_n ) + \
32 gamma_n * sqrt ( 2 * phip_n ) + VDD - TECH.Vtn0 + gamma_n * gamma_n * 0.5;
33 double Vt_n = TECH.Vtn0 + gamma_n * ( sqrt ( 2 * phip_n + Vsb1_n ) - \
34 sqrt ( 2 * phip_n ) );
35 for ( unsigned int i = 1; i <= n; i++ )
36 {
37 A_1_n[ i ] = ( Vt_n - TECH.Vtn0 ) / Vsb1_n;
38 ts_n[ i ] = t0_n[ i ] = taui_n[ i ] = tauo_n[ i ] = 0.0;
39 }
40 for ( unsigned int i = 1; i < n; i++ )
41 Vd_n[ i ] = Vsb1_n;
42 for ( unsigned int i = 2; i <= n; i++ )
43 Vs_n[ i ] = Vsb1_n;
44 Vd_n[ n ] = VDD;
45 Vs_n[ 1 ] = 0;
46 if (p == 0)
47 p = 1;
48 // PMOS
49 A_1_p = dvector ( 1, p );
50 B_1_p = dvector ( 1, p );
51 ts_p = dvector ( 1, p );
52 tauo_p = dvector ( 1, p );
53 taui_p = dvector ( 1, p );
54 t0_p = dvector ( 1, p );
55 beta_p = dvector ( 1, p );
56 Vd_p = dvector ( 1, p );
57 Vs_p = dvector ( 1, p );
58 W_p = dvector ( 1, p );
59 L_p = dvector ( 1, p );
60 if ( !A_1_p || !ts_p || !tauo_p || !taui_p || !t0_p || !beta_p || !Vd_p || !Vs_p || !W_p || !L_p )
61 return NO_MEM;
62 TECH.u0_p = TECH.Kp_p / TECH.Cox_p;
63 TECH.Ec_p = TECH.vmax_p / TECH.u0_p * ( 1 - TECH.theta_p * ( -VDD - TECH.Vtp0 ) );
64 //double phip p = fabs ( TECH.VT * log ( TECH.Nd / TECH.ni ) );
65 double phip_p = TECH.phi_p;
66 //double gamma p = sqrt ( 2 * TECH.epss * TECH.q * TECH.Nd ) / TECH.Cox p;
67 double gamma_p = TECH.gamma_p;
68 double Vsb1_p = 0.5 * gamma_p * sqrt ( 4 * gamma_p * sqrt ( 2 * phip_p ) + \
69 8 * phip_p + 4 * VDD + 4 * TECH.Vtp0 + gamma_p * gamma_p ) - \
70 gamma_p * sqrt ( 2 * phip_p ) - VDD - TECH.Vtp0 + gamma_p * gamma_p * 0.5;
71 //
72 double Vt_p = TECH.Vtp0 - gamma_p * ( sqrt ( 2 * phip_p - Vsb1_p ) - \
73 sqrt ( 2 * phip_p ) );
74 for ( unsigned int i = 1; i <= p; i++ )
75 {
76 A_1_p[ i ] = ( TECH.Vtp0 - Vt_p ) / ( VDD + Vt_p );
77 B_1_p[ i ] = ( Vt_p * ( VDD + TECH.Vtp0 ) ) / ( VDD + Vt_p );
78 ts_p[ i ] = t0_p[ i ] = taui_p[ i ] = tauo_p[ i ] = 0.0;
B.3. Simulators 269
79 }
80 for ( unsigned int i = 1; i < p; i++ )
81 Vd_p[ i ] = VDD + Vsb1_p;
82 for ( unsigned int i = 2; i <= p; i++ )
83 Vs_p[ i ] = VDD + Vsb1_p;
84 Vd_p[ p ] = 0;
85 Vs_p[ 1 ] = VDD;
86 return OK;
87 }
88
89 ///
90 void Fast::FreeCircuitPar( unsigned int n, unsigned int p )
91 {
92 if (n == 0)
93 n = 1;
94 free_dvector ( A_1_n);
95 free_dvector ( ts_n);
96 free_dvector ( tauo_n);
97 free_dvector ( taui_n);
98 free_dvector ( t0_n);
99 free_dvector ( beta_n);
100 free_dvector ( Vd_n);
101 free_dvector ( Vs_n);
102 free_dvector ( W_n);
103 free_dvector ( L_n);
104 if (p == 0)
105 p = 1;
106 free_dvector ( A_1_p);
107 free_dvector ( B_1_p);
108 free_dvector ( ts_p);
109 free_dvector ( tauo_p);
110 free_dvector ( taui_p);
111 free_dvector ( t0_p);
112 free_dvector ( beta_p);
113 free_dvector ( Vd_p);
114 free_dvector ( Vs_p);
115 free_dvector ( W_p);
116 free_dvector ( L_p);
117 }
118
119 ///
120 void Fast::CalcParamCircuit( unsigned int n, unsigned int p )
121 {
122
123 for ( unsigned int i = 1; i <= n; i++ )
124 {
125 L_n[ i ] = L_n[ i ] - 2 * TECH.LD_n + TECH.XL_n;
126 W_n[ i ] = W_n[ i ] - 2 * TECH.WD_n + TECH.XW_n;
127 beta_n[ i ] = ( TECH.u0_n * TECH.Cox_n * W_n[ i ] / L_n[ i ] ) / ( 1 + TECH.theta_n * ( VDD - TECH.Vtn0 ) );
128 }
129 for ( unsigned int i = 1; i <= p; i++ )
130 {
131 L_p[ i ] = L_p[ i ] - 2 * TECH.LD_p + TECH.XL_p;
132 W_p[ i ] = W_p[ i ] - 2 * TECH.WD_p + TECH.XW_p;
133 beta_p[ i ] = ( TECH.u0_p * TECH.Cox_p * W_p[ i ] / L_p[ i ] ) / ( 1 - TECH.theta_p * ( -VDD - TECH.Vtp0 ) );
134 }
135 }
Iter.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8
9 ///
10 int Fast::IterSol( const Circuit& circuit, TransistorType type, unsigned int NP, unsigned int NC, unsigned int n, unsigned int p, const double* NewWidt
270 Appendix B. Source code
11 {
12 unsigned int found = 0, n_tol;
13 int num_sol;
14 int iter = 0;
15 double tin;
16 int RetCode;
17 unsigned int k;
18 if ( type == NMOS )
19 {
20 k = n;
21 tin = taui_n[ 1 ];
22 }
23 else if ( type == PMOS )
24 {
25 k = p;
26 tin = taui_p[ 1 ];
27 }
28 double* to = new double[ k + 1 ];
29 double* to_old = new double[ k + 1 ];
30 double* t0 = new double[ k + 1 ];
31 for ( unsigned int i = 1; i <= k; i++ )
32 {
33 to_old[ i ] = to[ i ] = tin;
34 t0[ i ] = 0;
35 }
36 if ( type == NMOS )
37 t0[ 1 ] = t0_n[ 1 ];
38 else if ( type == PMOS )
39 t0[ 1 ] = t0_p[ 1 ];
40 double xb1, xb2;
41 while ( !found )
42 {
43 iter++;
44 n_tol = 0;
45 for ( unsigned int i = 1; i <= k; i++ )
46 {
47 num_sol = 1;
48 xb1 = to_old[ i ] - STEP_SOL;
49 xb2 = to_old[ i ] + STEP_SOL;
50 to[ i ] = SolveEq( circuit, NP, NC, type, ( t0[ i ] + STEP_SOL ), MAX_SOL, RetCode, i, n, p, NewWidth );
51 //if(RetCode != OK)
52 // return RetCode;
53
54 if ( to[ i ] == 0.0 )
55 {
56 num_sol = Brackets( circuit, NP, NC, xb1, xb2, type, i, n, p, NewWidth, RetCode );
57 //if(RetCode != OK)
58 // return RetCode;
59 if ( xb1 < 0.0 )
60 xb1 = 0.0;
61 if ( num_sol == 0 )
62 {
63 if ( i == 1 )
64 to[ i ] = tin;
65 else
66 to[ i ] = to[ i - 1 ] + tin;
67 }
68 else
69 {
70 to[ i ] = SolveEq( circuit, NP, NC, type, xb1, xb2, RetCode, i, n, p, NewWidth );
71 //if(RetCode != OK)
72 // return RetCode;
73 if ( to[ i ] == 0.0 )
74 {
75 if ( i == 1 )
76 to[ i ] = tin;
77 else
78 to[ i ] = to[ i - 1 ] + tin;
79 }
B.3. Simulators 271
80 }
81 }
82 if ( type == NMOS )
83 {
84 tauo_n[ i ] = to[ i ];
85 }
86 else if ( type == PMOS )
87 {
88 tauo_p[ i ] = to[ i ];
89 }
90 int Sop, Op; // Dummy
91 if ( i == 1 )
92 if ( type == NMOS )
93 Op = Calct0ts1N ( circuit, NP, Sop, NewWidth );
94 else
95 Op = Calct0ts1P ( circuit, NP, Sop, NewWidth );
96 if ( ( i == k ) && ( k > 1 ) )
97 if ( type == NMOS )
98 Op = Calct0tsnN( n, Sop );
99 else
100 Op = Calct0tsnP( n, Sop );
101 if ( type == NMOS )
102 {
103 for ( unsigned int j = 1; j <= n; j++ )
104 t0[ j ] = t0_n[ j ];
105 }
106 else if ( type == PMOS )
107 {
108 for ( unsigned int j = 1; j <= p; j++ )
109 t0[ j ] = t0_p[ j ];
110 }
111
112 if ( ( fabs ( to[ i ] - to_old[ i ] ) <= STEP_SOL ) && ( iter > 1 ) )
113 n_tol++;
114 to_old[ i ] = to[ i ];
115 }
116 if ( ( n_tol == k ) || ( iter > ITERMAX ) )
117 found = 1;
118 }
119 delete[] to;
120 delete[] to_old;
121 return OK;
122 }
LastEqN.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8 ///
9 double Fast::LastEqN( int OpCondition, unsigned int n, double tauon )
10 {
11 double Vc, temp, tc;
12 double C, D, F, G, H, I, J, K, M, N, O, P, R, S;
13 Vc = TECH.Ec_n * L_n[ n ];
14 double x = t0_n[ n ] - taui_n[ n ];
15 double y = t0_n[ n ] - tauon;
16 tc = ( VDD * tauon * ( t0_n[ n ] - taui_n[ n ] ) + \
17 Vs_n[ n ] * taui_n[ n ] * ( tauon - t0_n[ n ] ) ) / \
18 ( VDD * ( t0_n[ n ] - taui_n[ n ] ) + Vs_n[ n ] * ( tauon - t0_n[ n ] ) );
19 C = -Vc * Vs_n[ n ] * beta_n[ n ] * ( A_1_n[ n ] + 1 ) / x;
20 I = ( 2 * A_1_n[ n ] * Vs_n[ n ] * taui_n[ n ] + \
21 2 * VDD * x + Vc * x + \
22 2 * ( Vs_n[ n ] * taui_n[ n ] - TECH.Vtn0 * x ) ) / \
23 ( Vc * x );
24 H = -2 * Vs_n[ n ] * ( A_1_n[ n ] + 1 ) / ( Vc * x );
272 Appendix B. Source code
94 3 * H * ( 2 * J * ( tc - ts_n[ n ] ) + \
95 K * ( ( tc * tc ) - ( ts_n[ n ] * ts_n[ n ] ) ) ) ) / \
96 ( 6 * H );
97 break;
98 case _D_:
99 temp = F * ( tc - t0_n[ n ] ) + C * 0.5 * ( tc * tc - t0_n[ n ] * t0_n[ n ] ) + \
100 2 * Vc * Vc * beta_n[ n ] * pow ( ( H * t0_n[ n ] + I ), 1.5 ) / ( 3 * H ) - \
101 2 * Vc * Vc * pow ( ( H * tc + I ), 1.5 ) / ( 3 * H );
102 break;
103 case _E_:
104 default:
105 temp = 0;
106 break;
107 }
108 return temp;
109 }
LastEqP.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8 ///
9 double Fast::LastEqP( int OpCondition, unsigned int p, double tauop )
10 {
11 double Vc, temp, tc;
12 double C, D, F, G, I, J, K, M, N, O, P, R, S, X, x, y;
13 Vc = TECH.Ec_p * L_p[ p ];
14 tc = ( VDD * t0_p[ p ] * ( taui_p[ p ] - tauop ) + Vd_p[ p ] * tauop * ( t0_p[ p ] - taui_p[ p ] ) + \
15 Vs_p[ p ] * taui_p[ p ] * ( tauop - t0_p[ p ] ) ) / ( VDD * ( taui_p[ p ] - tauop ) + Vd_p[ p ] * ( t0_p[ p ] - taui_p[ p ] ) + Vs_p[ p ] *
16 x = t0_p[ p ] - taui_p[ p ];
17 y = t0_p[ p ] - tauop;
18 X = VDD * t0_p[ p ] - Vs_p[ p ] * taui_p[ p ];
19 C = -Vc * beta_p[ p ] * ( A_1_p[ p ] * X + \
20 B_1_p[ p ] * x + \
21 VDD * t0_p[ p ] + Vc * x - Vs_p[ p ] * taui_p[ p ] ) / x;
22 D = Vc * beta_p[ p ] * ( A_1_p[ p ] + 1 ) * ( VDD - Vs_p[ p ] ) / x;
23 F = Vc * ( 2 * A_1_p[ p ] * X + \
24 2 * B_1_p[ p ] * x + \
25 2 * VDD * t0_p[ p ] + Vc * x - \
26 2 * Vs_p[ p ] * taui_p[ p ] ) / x;
27 G = Vc * beta_p[ p ] * SQRT ( Vc * ( 2 * VDD + Vc + 2 * TECH.Vtp0 ) ) - \
28 VDD * Vc * beta_p[ p ] - ( Vc * Vc ) * beta_p[ p ] - Vc * TECH.Vtp0 * beta_p[ p ];
29 J = VDD * ( y - x ) + Vd_p[ p ] * x - Vs_p[ p ] * y;
30 K = Vc * beta_p[ p ] * ( 2 * A_1_p[ p ] * y * \
31 ( ( VDD * VDD ) * t0_p[ p ] * ( x - y ) + \
32 VDD * ( Vc * x * y - Vd_p[ p ] * t0_p[ p ] * x + \
33 Vs_p[ p ] * ( t0_p[ p ] * y - \
34 taui_p[ p ] * ( x - y ) ) ) - \
35 Vs_p[ p ] * ( Vc * x * y - taui_p[ p ] * ( Vd_p[ p ] * x - \
36 Vs_p[ p ] * y ) ) ) - \
37 2 * B_1_p[ p ] * J * x * y + \
38 ( VDD * VDD ) * t0_p[ p ] * ( x - y ) * ( x + y ) + \
39 VDD * ( Vc * x * y * ( x + y ) - \
40 Vd_p[ p ] * x * ( t0_p[ p ] * ( x + y ) + tauop * ( x - y ) ) + \
41 Vs_p[ p ] * y * ( t0_p[ p ] * ( x + y ) - taui_p[ p ] * ( x - y ) ) ) - \
42 Vc * x * y * ( Vd_p[ p ] * x + Vs_p[ p ] * y ) + \
43 ( Vd_p[ p ] * Vd_p[ p ] ) * tauop * x * x + \
44 Vs_p[ p ] * Vd_p[ p ] * x * y * ( y - x ) - \
45 Vs_p[ p ] * Vs_p[ p ] * y * y * taui_p[ p ] ) / \
46 ( 2 * J * x * y );
47 I = Vc * beta_p[ p ] * ( 2 * A_1_p[ p ] * ( VDD - Vs_p[ p ] ) * y + \
48 VDD * ( x + y ) - Vd_p[ p ] * x - Vs_p[ p ] * y ) / \
49 ( 2 * x * y );
50 M = ( Vc * Vc ) * beta_p[ p ] * x * y * \
51 ( 2 * A_1_p[ p ] * ( VDD * ( Vc * y - Vd_p[ p ] * y + Vs_p[ p ] * x ) - \
274 Appendix B. Source code
52 Vs_p[ p ] * ( Vc * y + Vd_p[ p ] * ( x - y ) ) ) - \
53 2 * B_1_p[ p ] * J + VDD * ( Vc * ( x + y ) - \
54 2 * ( Vd_p[ p ] * y - Vs_p[ p ] * x ) ) - \
55 Vc * ( Vd_p[ p ] * x + Vs_p[ p ] * y ) + \
56 2 * Vd_p[ p ] * Vs_p[ p ] * ( y - x ) );
57 N = 2 * J * ( VDD * t0_p[ p ] * ( y - x ) + \
58 Vc * x * y + \
59 Vd_p[ p ] * tauop * x - \
60 Vs_p[ p ] * taui_p[ p ] * y );
61 O = -Vc * beta_p[ p ] * ( VDD * ( t0_p[ p ] + y ) + \
62 Vc * y - Vd_p[ p ] * tauop + 2 * TECH.Vtp0 * y ) / \
63 ( 2 * y );
64 P = Vc * beta_p[ p ] * ( VDD - Vd_p[ p ] ) / ( 2 * y );
65 R = ( Vc * Vc ) * beta_p[ p ] * y * ( 2 * VDD + Vc + 2 * TECH.Vtp0 );
66 S = 2 * ( VDD * tauop - Vc * y - Vd_p[ p ] * tauop );
67 switch ( OpCondition )
68 {
69 case _A_:
70 temp = -M * LOG2 ( ( 2 * ( J * J ) * ts_p[ p ] - N ) ) / ( J * J ) + \
71 M * LOG2 ( ( 2 * ( J * J ) * taui_p[ p ] - N ) ) / ( J * J ) + \
72 R * LOG2 ( ( 2 * taui_p[ p ] * ( VDD - Vd_p[ p ] ) - S ) ) / ( Vd_p[ p ] - VDD ) + \
73 R * LOG2 ( ( 2 * tauop * ( VDD - Vd_p[ p ] ) - S ) ) / ( VDD - Vd_p[ p ] ) - \
74 ( 2 * Vc * beta_p[ p ] * ( 2 * D * t0_p[ p ] - F * beta_p[ p ] ) * \
75 SQRT ( ( F * beta_p[ p ] - 2 * D * t0_p[ p ] ) / beta_p[ p ] ) + \
76 2 * Vc * beta_p[ p ] * ( F * beta_p[ p ] - 2 * D * ts_p[ p ] ) * \
77 SQRT ( ( F * beta_p[ p ] - 2 * D * ts_p[ p ] ) / beta_p[ p ] ) + \
78 3 * D * ( 2 * C * ( t0_p[ p ] - ts_p[ p ] ) + D * ( ( t0_p[ p ] * t0_p[ p ] ) - ( ts_p[ p ] * ts_p[ p ] ) ) + \
79 I * ( ( ts_p[ p ] * ts_p[ p ] ) - ( taui_p[ p ] * taui_p[ p ] ) ) + \
80 2 * K * ( ts_p[ p ] - taui_p[ p ] ) + \
81 2 * O * ( taui_p[ p ] - tauop ) + \
82 P * ( ( taui_p[ p ] * taui_p[ p ] ) - ( tauop * tauop ) ) ) ) / ( 6 * D );
83
84 break;
85 case _B_:
86 temp = R * LOG2 ( ( 2 * ts_p[ p ] * ( VDD - Vd_p[ p ] ) - S ) ) / ( Vd_p[ p ] - VDD ) + \
87 R * LOG2 ( ( 2 * tauop * ( VDD - Vd_p[ p ] ) - S ) ) / ( VDD - Vd_p[ p ] ) - \
88 ( 2 * Vc * beta_p[ p ] * ( 2 * D * t0_p[ p ] - F * beta_p[ p ] ) * \
89 SQRT ( ( F * beta_p[ p ] - 2 * D * t0_p[ p ] ) / beta_p[ p ] ) + \
90 2 * Vc * beta_p[ p ] * ( F * beta_p[ p ] - 2 * D * taui_p[ p ] ) * \
91 SQRT ( ( F * beta_p[ p ] - 2 * D * taui_p[ p ] ) / beta_p[ p ] ) + \
92 3 * D * ( 2 * C * ( t0_p[ p ] - taui_p[ p ] ) + \
93 D * ( ( t0_p[ p ] * t0_p[ p ] ) - ( taui_p[ p ] * taui_p[ p ] ) ) + \
94 2 * G * ( taui_p[ p ] - ts_p[ p ] ) + \
95 2 * O * ( ts_p[ p ] - tauop ) + \
96 P * ( ( ts_p[ p ] * ts_p[ p ] ) - ( tauop * tauop ) ) ) ) / ( 6 * D );
97
98 break;
99 case _C_:
100 temp = M * LOG2 ( ( 2 * ( J * J ) * tc - N ) ) / ( J * J ) - \
101 M * LOG2 ( ( 2 * ( J * J ) * ts_p[ p ] - N ) ) / ( J * J ) - \
102 ( 2 * Vc * beta_p[ p ] * ( 2 * D * t0_p[ p ] - F * beta_p[ p ] ) * \
103 SQRT ( ( F * beta_p[ p ] - 2 * D * t0_p[ p ] ) / beta_p[ p ] ) + \
104 2 * Vc * beta_p[ p ] * ( F * beta_p[ p ] - 2 * D * ts_p[ p ] ) * \
105 SQRT ( ( F * beta_p[ p ] - 2 * D * ts_p[ p ] ) / beta_p[ p ] ) + \
106 3 * D * ( 2 * C * ( t0_p[ p ] - ts_p[ p ] ) + \
107 D * ( ( t0_p[ p ] * t0_p[ p ] ) - ( ts_p[ p ] * ts_p[ p ] ) ) + \
108 I * ( ( ts_p[ p ] * ts_p[ p ] ) - ( tc * tc ) ) + \
109 2 * K * ( ts_p[ p ] - tc ) ) ) / ( 6 * D );
110
111 break;
112 case _D_:
113 temp = -( 2 * Vc * beta_p[ p ] * ( 2 * D - F * beta_p[ p ] ) * \
114 SQRT ( ( F * beta_p[ p ] - 2 * D * t0_p[ p ] ) / beta_p[ p ] ) + \
115 2 * Vc * beta_p[ p ] * ( F * beta_p[ p ] - 2 * D * tc ) * \
116 SQRT ( ( F * beta_p[ p ] - 2 * D * tc ) / beta_p[ p ] ) + \
117 3 * D * ( 2 * C * ( t0_p[ p ] - tc ) + D * ( t0_p[ p ] * t0_p[ p ] - tc * tc ) ) ) / \
118 ( 6 * D );
119 break;
120 case _E_:
B.3. Simulators 275
121 default:
122 temp = 0;
123 break;
124 }
125 return temp;
126 }
MiddleEqN.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8 ///
9 double Fast::MiddleEqN( int OpCondition, unsigned int i, double tauon )
10 {
11 double Vc, temp;
12 double D, F, G, H, I, J, K, M, N;
13 Vc = TECH.Ec_n * L_n[ i ];
14 switch ( OpCondition )
15 {
16 case _A_:
17 D = Vd_n[ i ] * ( t0_n[ i ] - taui_n[ i ] ) + \
18 Vs_n[ i ] * ( tauon - t0_n[ i ] );
19 F = Vc * beta_n[ i ] * \
20 ( 2 * A_1_n[ i ] * Vs_n[ i ] * ( t0_n[ i ] - tauon ) * \
21 ( D * taui_n[ i ] + Vc * ( t0_n[ i ] - taui_n[ i ] ) * ( t0_n[ i ] - tauon ) ) + \
22 2 * D * VDD * ( t0_n[ i ] - taui_n[ i ] ) * ( t0_n[ i ] - tauon ) + \
23 Vc * ( t0_n[ i ] - taui_n[ i ] ) * ( t0_n[ i ] - tauon ) * \
24 ( Vd_n[ i ] * ( t0_n[ i ] - taui_n[ i ] ) + Vs_n[ i ] * ( t0_n[ i ] - tauon ) ) + \
25 ( Vd_n[ i ] * Vd_n[ i ] ) * tauon * ( ( t0_n[ i ] - taui_n[ i ] ) * ( t0_n[ i ] - taui_n[ i ] ) ) + \
26 Vd_n[ i ] * ( t0_n[ i ] - taui_n[ i ] ) * ( t0_n[ i ] - tauon ) * \
27 ( Vs_n[ i ] * ( taui_n[ i ] - tauon ) + 2 * TECH.Vtn0 * ( taui_n[ i ] - t0_n[ i ] ) ) - \
28 Vs_n[ i ] * ( ( t0_n[ i ] - tauon ) * ( t0_n[ i ] - tauon ) ) * \
29 ( Vs_n[ i ] * taui_n[ i ] + 2 * TECH.Vtn0 * ( taui_n[ i ] - t0_n[ i ] ) ) ) / \
30 ( 2 * D * ( t0_n[ i ] - taui_n[ i ] ) * ( t0_n[ i ] - tauon ) );
31 G = Vc * beta_n[ i ] * \
32 ( 2 * A_1_n[ i ] * Vs_n[ i ] * ( t0_n[ i ] - tauon ) + \
33 Vd_n[ i ] * ( t0_n[ i ] - taui_n[ i ] ) + Vs_n[ i ] * ( t0_n[ i ] - tauon ) ) / \
34 ( 2 * ( t0_n[ i ] - taui_n[ i ] ) * ( tauon - t0_n[ i ] ) );
35 H = ( Vc * Vc ) * beta_n[ i ] * ( t0_n[ i ] - taui_n[ i ] ) * \
36 ( tauon - t0_n[ i ] ) * \
37 ( 2 * A_1_n[ i ] * Vs_n[ i ] * ( Vc * ( t0_n[ i ] - tauon ) + \
38 Vd_n[ i ] * ( taui_n[ i ] - tauon ) ) + 2 * D * VDD + Vc * \
39 ( Vd_n[ i ] * ( t0_n[ i ] - taui_n[ i ] ) + Vs_n[ i ] * ( t0_n[ i ] - tauon ) ) + \
40 2 * ( Vd_n[ i ] * ( Vs_n[ i ] * ( taui_n[ i ] - tauon ) + \
41 TECH.Vtn0 * ( taui_n[ i ] - t0_n[ i ] ) ) + Vs_n[ i ] * TECH.Vtn0 * ( t0_n[ i ] - tauon ) ) );
42 I = 2 * D * ( Vc * ( t0_n[ i ] - taui_n[ i ] ) * \
43 ( t0_n[ i ] - tauon ) + Vd_n[ i ] * tauon * ( taui_n[ i ] - t0_n[ i ] ) + \
44 Vs_n[ i ] * taui_n[ i ] * ( t0_n[ i ] - tauon ) );
45 J = Vc * beta_n[ i ] * ( 2 * VDD * ( t0_n[ i ] - tauon ) + \
46 Vc * ( t0_n[ i ] - tauon ) + Vd_n[ i ] * tauon + \
47 2 * TECH.Vtn0 * ( tauon - t0_n[ i ] ) ) / ( 2 * ( t0_n[ i ] - tauon ) );
48 K = Vc * Vd_n[ i ] * beta_n[ i ] / ( 2 * ( tauon - t0_n[ i ] ) );
49 M = ( Vc * Vc ) * beta_n[ i ] * ( tauon - t0_n[ i ] ) * \
50 ( 2 * VDD + Vc - 2 * TECH.Vtn0 );
51 N = 2 * ( Vc * ( t0_n[ i ] - tauon ) - Vd_n[ i ] * tauon );
52 temp = -H * LOG2 ( 2 * ( D * D ) * t0_n[ i ] + I ) / ( D * D ) + \
53 H * LOG2 ( 2 * ( D * D ) * taui_n[ i ] + I ) / ( D * D ) - \
54 M * LOG2 ( N + 2 * Vd_n[ i ] * taui_n[ i ] ) / Vd_n[ i ] + \
55 M * LOG2 ( N + 2 * Vd_n[ i ] * tauon ) / Vd_n[ i ] - \
56 ( 2 * F * ( t0_n[ i ] - taui_n[ i ] ) + G * ( ( t0_n[ i ] * t0_n[ i ] ) - ( taui_n[ i ] * taui_n[ i ] ) ) + 2 * J * ( taui_n[ i ] - tauo
57 break;
58 case _E_:
59 default:
60 temp = 0;
61 break;
276 Appendix B. Source code
62 }
63 return temp;
64 }
MiddleEqP.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8 ///
9 double Fast::MiddleEqP( int OpCondition, unsigned int i, double tauop )
10 {
11 double Vc, temp;
12 double D, J, K, M, N, O, P, R, S, T;
13 Vc = TECH.Ec_p * L_p[ i ];
14 switch ( OpCondition )
15 {
16 case _A_:
17
18 D = VDD * ( taui_p[ i ] - tauop ) + \
19 Vd_p[ i ] * ( t0_p[ i ] - taui_p[ i ] ) + \
20 Vs_p[ i ] * ( tauop - t0_p[ i ] );
21 J = Vc * beta_p[ i ] * \
22 ( 2 * A_1_p[ i ] * ( t0_p[ i ] - tauop ) * ( ( VDD * VDD ) * t0_p[ i ] * ( taui_p[ i ] - tauop ) - \
23 VDD * ( Vc * ( t0_p[ i ] - taui_p[ i ] ) * ( t0_p[ i ] - tauop ) + \
24 Vd_p[ i ] * t0_p[ i ] * ( taui_p[ i ] - t0_p[ i ] ) + \
25 Vs_p[ i ] * ( ( t0_p[ i ] * t0_p[ i ] ) - t0_p[ i ] * tauop + taui_p[ i ] * ( taui_p[ i ] - tauop ) ) ) + \
26 Vs_p[ i ] * ( Vc * ( t0_p[ i ] - taui_p[ i ] ) * ( t0_p[ i ] - tauop ) - \
27 taui_p[ i ] * ( Vd_p[ i ] * ( t0_p[ i ] - taui_p[ i ] ) + Vs_p[ i ] * ( tauop - t0_p[ i ] ) ) ) ) + \
28 2 * B_1_p[ i ] * D * ( t0_p[ i ] - taui_p[ i ] ) * ( t0_p[ i ] - tauop ) + \
29 ( VDD * VDD ) * t0_p[ i ] * ( taui_p[ i ] - tauop ) * \
30 ( 2 * t0_p[ i ] - taui_p[ i ] - tauop ) - VDD * ( Vc * ( t0_p[ i ] - taui_p[ i ] ) * \
31 ( t0_p[ i ] - tauop ) * ( 2 * t0_p[ i ] - taui_p[ i ] - tauop ) + \
32 Vd_p[ i ] * ( taui_p[ i ] - t0_p[ i ] ) * \
33 ( 2 * ( t0_p[ i ] * t0_p[ i ] ) - t0_p[ i ] * ( taui_p[ i ] + tauop ) - \
34 tauop * ( taui_p[ i ] - tauop ) ) + Vs_p[ i ] * ( t0_p[ i ] - tauop ) * \
35 ( 2 * ( t0_p[ i ] * t0_p[ i ] ) - t0_p[ i ] * ( taui_p[ i ] + tauop ) + taui_p[ i ] * ( taui_p[ i ] - tauop ) ) )
36 Vc * ( t0_p[ i ] - taui_p[ i ] ) * ( t0_p[ i ] - tauop ) * ( Vd_p[ i ] * ( t0_p[ i ] - taui_p[ i ] ) + \
37 Vs_p[ i ] * ( t0_p[ i ] - tauop ) ) - ( Vd_p[ i ] * Vd_p[ i ] ) * tauop * ( ( t0_p[ i ] - taui_p[ i ] ) * ( t0_p[
38 Vs_p[ i ] * ( tauop - t0_p[ i ] ) * ( Vd_p[ i ] * ( t0_p[ i ] - taui_p[ i ] ) * \
39 ( taui_p[ i ] - tauop ) + Vs_p[ i ] * taui_p[ i ] * ( tauop - t0_p[ i ] ) ) ) / \
40 ( 2 * D * ( t0_p[ i ] - taui_p[ i ] ) * ( tauop - t0_p[ i ] ) );
41 K = Vc * beta_p[ i ] * ( 2 * A_1_p[ i ] * ( VDD - Vs_p[ i ] ) * ( t0_p[ i ] - tauop ) + \
42 VDD * ( 2 * t0_p[ i ] - taui_p[ i ] - tauop ) + \
43 Vd_p[ i ] * ( taui_p[ i ] - t0_p[ i ] ) + \
44 Vs_p[ i ] * ( tauop - t0_p[ i ] ) ) / ( 2 * ( t0_p[ i ] - taui_p[ i ] ) * ( t0_p[ i ] - tauop ) );
45 M = ( Vc * Vc ) * beta_p[ i ] * ( t0_p[ i ] - taui_p[ i ] ) * ( t0_p[ i ] - tauop ) * \
46 ( 2 * A_1_p[ i ] * ( VDD * ( Vc * ( t0_p[ i ] - tauop ) + \
47 Vd_p[ i ] * ( tauop - t0_p[ i ] ) + Vs_p[ i ] * ( t0_p[ i ] - taui_p[ i ] ) ) - \
48 Vs_p[ i ] * ( Vc * ( t0_p[ i ] - tauop ) + Vd_p[ i ] * ( tauop - taui_p[ i ] ) ) ) - \
49 2 * B_1_p[ i ] * D + VDD * ( Vc * ( 2 * t0_p[ i ] - taui_p[ i ] - tauop ) - \
50 2 * ( Vd_p[ i ] * ( t0_p[ i ] - tauop ) + Vs_p[ i ] * ( taui_p[ i ] - t0_p[ i ] ) ) ) - \
51 Vc * ( Vd_p[ i ] * ( t0_p[ i ] - taui_p[ i ] ) + \
52 Vs_p[ i ] * ( t0_p[ i ] - tauop ) ) + 2 * Vd_p[ i ] * Vs_p[ i ] * ( taui_p[ i ] - tauop ) );
53 N = 2 * D * ( VDD * t0_p[ i ] * ( taui_p[ i ] - tauop ) + \
54 Vc * ( t0_p[ i ] - taui_p[ i ] ) * ( t0_p[ i ] - tauop ) + \
55 Vd_p[ i ] * tauop * ( t0_p[ i ] - taui_p[ i ] ) + Vs_p[ i ] * taui_p[ i ] * ( tauop - t0_p[ i ] ) );
56 O = Vc * beta_p[ i ] * ( VDD * ( 2 * t0_p[ i ] - tauop ) + \
57 Vc * ( t0_p[ i ] - tauop ) - Vd_p[ i ] * tauop + 2 * TECH.Vtp0 * ( t0_p[ i ] - tauop ) ) / \
58 ( 2 * ( tauop - t0_p[ i ] ) );
59 P = Vc * beta_p[ i ] * ( VDD - Vd_p[ i ] ) / ( 2 * ( t0_p[ i ] - tauop ) );
60 R = ( Vc * Vc ) * beta_p[ i ] * ( t0_p[ i ] - tauop ) * ( 2 * VDD + Vc + 2 * TECH.Vtp0 );
61 S = 2 * ( VDD * tauop + Vc * ( tauop - t0_p[ i ] ) - Vd_p[ i ] * tauop );
62 T = 2 * ( VDD - Vd_p[ i ] );
63 temp = -M * LOG2 ( 2 * ( D * D ) * t0_p[ i ] - N ) / ( D * D ) + \
64 M * LOG2 ( 2 * ( D * D ) * taui_p[ i ] - N ) / ( D * D ) - \
B.3. Simulators 277
65 R * LOG ( T * taui_p[ i ] - S ) / T + \
66 R * LOG ( T * tauop - S ) / T - \
67 ( 2 * J * ( t0_p[ i ] - taui_p[ i ] ) + \
68 K * ( ( t0_p[ i ] * t0_p[ i ] ) - ( taui_p[ i ] * taui_p[ i ] ) ) + \
69 2 * O * ( taui_p[ i ] - tauop ) + \
70 P * ( ( taui_p[ i ] * taui_p[ i ] ) - ( tauop * tauop ) ) ) / 2;
71
72 break;
73 case _E_:
74 default:
75 temp = 0;
76 break;
77 }
78 return temp;
79 }
Power.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8
9 ///
10 double Fast::CalcPower( const Circuit& circuit,
11 unsigned int NP,
12 unsigned int NC,
13 unsigned int n,
14 unsigned int p,
15 const double* NewWidth,
16 TransitionType TOut,
17 int& RetCode )
18 {
19
20 double Ecc, Esc;
21 switch ( TOut )
22 {
23 case FALL: // n chain
24 RetCode = CalcPowerN( circuit, NP, NC, Ecc, Esc, n, p, NewWidth );
25 if ( RetCode != OK )
26 return 0.0;
27 break;
28 case RISE: // p chain
29 RetCode = CalcPowerP( circuit, NP, NC, Ecc, Esc, n, p, NewWidth );
30 if ( RetCode != OK )
31 return 0.0;
32 break;
33 case NOTRANSITION:
34 default:
35 break;
36 }
37 return ( Ecc + Esc );
38 }
QnP.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8 ///
9 double Fast::QnP(unsigned int n, unsigned int p)
10 {
11 double D_n, E_n, F_n, G_n;
12 double to;
278 Appendix B. Source code
13 double Vc, y;
14
15 if (n != 0)
16 {
17 Vc = TECH.Ec_n * L_n[1];
18 to = taui_n[1] * (1 - TECH.Vtn0 / VDD);
19 if (to > tauo_p[p])
20 to = tauo_p[p];
21 D_n = Vc * beta_n[1] * (VDD * VDD * taui_p[1] * (t0_p[p] - 2 * tauo_p[p]) - \
22 VDD * (Vc * (t0_p[p] - tauo_p[p]) * \
23 (2 * t0_p[p] - taui_p[1] - 2 * tauo_p[p]) + \
24 taui_p[1] * (Vd_p[p] * (t0_p[p] - 3 * tauo_p[p]) + \
25 2 * TECH.Vtn0 * (t0_p[p] - tauo_p[p]))) - \
26 Vd_p[p] * taui_p[1] * (Vc * (t0_p[p] - tauo_p[p]) + \
27 Vd_p[p] * tauo_p[p] + 2 * TECH.Vtn0 * \
28 (tauo_p[p] - t0_p[p]))) / \
29 (2 * taui_p[1] * (VDD - Vd_p[p]) * (t0_p[p] - tauo_p[p]));
30 E_n = Vc * beta_n[1] * (VDD * (2 * t0_p[p] - taui_p[1] - 2 * tauo_p[p]) + \
31 Vd_p[p] * taui_p[1]) / \
32 (2 * taui_p[1] * (tauo_p[p] - t0_p[p]));
33 F_n = Vc * Vc * beta_n[1] * (tauo_p[p] - t0_p[p]) * \
34 (2 * VDD * VDD * (t0_p[p] - taui_p[1]) + \
35 VDD * (Vc * (2 * t0_p[p] - taui_p[1] - 2 * tauo_p[p]) + \
36 2 * (Vd_p[p] * (taui_p[1] - tauo_p[p]) + TECH.Vtn0 * taui_p[1])) + \
37 Vd_p[p] * taui_p[1] * (Vc - 2 * TECH.Vtn0));
38 G_n = 2 * taui_p[1] * (VDD - Vd_p[p]) * (VDD * t0_p[p] + \
39 Vc * (t0_p[p] - tauo_p[p]) - \
40 Vd_p[p] * tauo_p[p]);
41 y = -F_n * (LOG2(2 * t0_p[p] * taui_p[1] * (VDD - Vd_p[p]) * \
42 (VDD - Vd_p[p]) - G_n)) / \
43 (taui_p[1] * (VDD - Vd_p[p]) * \
44 (VDD - Vd_p[p])) + \
45 F_n * (LOG2(2 * to * taui_p[1] * (VDD - Vd_p[p]) * \
46 (VDD - Vd_p[p]) - G_n)) / \
47 (taui_p[1] * (VDD - Vd_p[p]) * \
48 (VDD - Vd_p[p])) - \
49 (2 * D_n * (t0_p[p] - to) + E_n * (t0_p[p] * t0_p[p] - to * to)) * 0.5;
50 return y;
51 }
52 else
53 return 0.0;
54 }
QpN.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8 ///
9 double Fast::QpN(unsigned int n, unsigned int p)
10 {
11 double D_p, E_p, F_p, G_p;
12 double to;
13 double Vc, y;
14
15 if (p != 0)
16 {
17 Vc = TECH.Ec_p * L_p[1];
18 to = taui_n[1] * (1 + TECH.Vtp0 / VDD);
19 if (to > tauo_n[n])
20 to = tauo_n[n];
21 D_p = Vc * beta_p[1] * (VDD * (t0_n[n] - tauo_n[n]) * \
22 (2 * Vc * (t0_n[n] - tauo_n[n]) - Vd_n[n] * taui_n[1]) - \
23 Vd_n[n] * taui_n[1] * (Vc * (t0_n[n] - tauo_n[n]) - \
24 Vd_n[n] * tauo_n[n] + 2 * TECH.Vtp0 * (t0_n[n] - tauo_n[n]))) / \
25 (2 * Vd_n[n] * taui_n[1] * (t0_n[n] - tauo_n[n]));
B.3. Simulators 279
26
27 E_p = Vc *
beta_p[1] * (2 * VDD * (t0_n[n] - tauo_n[n]) - Vd_n[n] * taui_n[1]) / \
28 (2 *
taui_n[1] * (t0_n[n] - tauo_n[n]));
29 F_p = Vc *
Vc * beta_p[1] * (t0_n[n] - tauo_n[n]) * \
30 (2 *
VDD * VDD * (t0_n[n] - tauo_n[n]) + \
31 2 *
VDD * (Vc * (t0_n[n] - tauo_n[n]) + \
32 Vd_n[n] * (tauo_n[n] - taui_n[1])) - Vd_n[n] * taui_n[1] * (Vc + 2 * TECH.Vtp0));
33 G_p = 2 * Vd_n[n] * taui_n[1] * (VDD * (t0_n[n] - tauo_n[n]) + \
34 Vc * (t0_n[n] - tauo_n[n]) + Vd_n[n] * tauo_n[n]);
35 y = -F_p * (LOG2(2 * Vd_n[n] * Vd_n[n] * t0_n[n] * taui_n[1] - G_p)) / \
36 (Vd_n[n] * Vd_n[n] * taui_n[1]) + \
37 (F_p * LOG2(2 * Vd_n[n] * Vd_n[n] * to * taui_n[1] - G_p)) / \
38 (Vd_n[n] * Vd_n[n] * taui_n[1]) - \
39 (2 * D_p * (t0_n[n] - to) + E_p * (t0_n[n] * t0_n[n] - to * to)) * 0.5;
40 return y;
41 }
42 else
43 return 0.0;
44 }
Solve.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8 #define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
9
10 ///
11 double Fast::SolveEq( const Circuit& circuit, unsigned int NP, unsigned int NC, TransistorType type, double start, double end, int& RetCode, unsigned i
12 {
13 int iter;
14 double a = start, b = end, c = end, d, e, min1, min2;
15 double fa, fb, fc, pp, q, r, s, tol1, xm, last;
16 double tol = TOL;
17
18 if ( type == NMOS )
19 fb = EqN( circuit, NP, NC, b, RetCode, i, n, p, NewWidth );
20 else if ( type == PMOS )
21 fb = EqP( circuit, NP, NC, b, RetCode, i, n, p, NewWidth );
22 last = fb;
23 if ( type == NMOS )
24 fa = EqN( circuit, NP, NC, a, RetCode, i, n, p, NewWidth );
25 else if ( type == PMOS )
26 fa = EqP( circuit, NP, NC, a, RetCode, i, n, p, NewWidth );
27 if ( ( fa > 0.0 && fb > 0.0 ) || ( fa < 0.0 && fb < 0.0 ) )
28 {
29 RetCode = NOT_FOUND;
30 return 0.0;
31 }
32 fc = fb;
33 for ( iter = 1; iter <= ITERMAX; iter++ )
34 {
35 if ( ( fb > 0.0 && fc > 0.0 ) || ( fb < 0.0 && fc < 0.0 ) )
36 {
37 c = a;
38 fc = fa;
39 e = d = b - a;
40 }
41 if ( fabs ( fc ) < fabs ( fb ) )
42 {
43 a = b;
44 b = c;
45 c = a;
46 fa = fb;
47 fb = fc;
48 fc = fa;
280 Appendix B. Source code
49 }
50 tol1 = 2.0 * EPS * fabs ( b ) + 0.5 * tol;
51 xm = 0.5 * ( c - b );
52 if ( fabs ( xm ) <= tol1 || fb == 0.0 )
53 return b;
54 if ( fabs ( e ) >= tol1 && fabs ( fa ) > fabs ( fb ) )
55 {
56 s = fb / fa;
57 if ( a == c )
58 {
59 pp = 2.0 * xm * s;
60 q = 1.0 - s;
61 }
62 else
63 {
64 q = fa / fc;
65 r = fb / fc;
66 pp = s * ( 2.0 * xm * q * ( q - r ) - ( b - a ) * ( r - 1.0 ) );
67 q = ( q - 1.0 ) * ( r - 1.0 ) * ( s - 1.0 );
68 }
69 if ( pp > 0.0 )
70 q = -q;
71 pp = fabs ( pp );
72 min1 = 3.0 * xm * q - fabs ( tol1 * q );
73 min2 = fabs ( e * q );
74 if ( 2.0 * pp < ( min1 < min2 ? min1 : min2 ) )
75 {
76 e = d;
77 d = pp / q;
78 }
79 else
80 {
81 d = xm;
82 e = d;
83 }
84 }
85 else
86 {
87 d = xm;
88 e = d;
89 }
90 a = b;
91 fa = fb;
92 if ( fabs ( d ) > tol1 )
93 b += d;
94 else
95 b += SIGN ( tol1, xm );
96 if ( type == NMOS )
97 fb = EqN( circuit, NP, NC, b, RetCode, i, n, p, NewWidth );
98 else if ( type == PMOS )
99 fb = EqP( circuit, NP, NC, b, RetCode, i, n, p, NewWidth );
100 }
101 RetCode = NOT_FOUND;
102 return 0.0;
103 }
t0N.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8 ///
9 double Fast::t0N( const Circuit& circuit, unsigned int NP, unsigned int NC, double t, const double* NewWidth, int& RetCode )
10 {
11 // compute the time at which the first n-mos start conducting, using
12 // bootstrap
B.3. Simulators 281
13 double A_2_n, B_2_n, C_2_n, D_2_n, Vc, y, Cm1, Cov, Cj, t0_bs;
14
15 Vc = TECH.Ec_n * L_n[ 1 ];
16 Cov = TECH.Cgd0_n * ( W_n[ 1 ] + TECH.XW_n );
17 Cm1 = Cov;
18 Cj = 0.0;
19 int njn, ngn, njp, ngp;
20 double Wjn, Wgn, Wjp, Wgp;
21 unsigned int node;
22 const char* name = pathlist[ NP ].TransistorName( 0, NC );
23 if ( circuit[ name ].Source() == 0 )
24 {
25 node = circuit[ name ].Drain();
26 Wjn = circuit.JunctionNWidth( node, njn, NewWidth );
27 Wgn = circuit.GateNWidth( node, ngn, NewWidth );
28 Wjp = circuit.JunctionPWidth( node, njp, NewWidth );
29 Wgp = circuit.GatePWidth( node, ngp, NewWidth );
30 }
31 else if ( circuit[ name ].Drain() == 0 )
32 {
33 node = circuit[ name ].Source();
34 Wjn = circuit.JunctionNWidth( node, njn, NewWidth );
35 Wgn = circuit.GateNWidth( node, ngn, NewWidth );
36 Wjp = circuit.JunctionPWidth( node, njp, NewWidth );
37 Wgp = circuit.GatePWidth( node, ngp, NewWidth );
38 }
39 Cj += TECH.C_nj * Wjn * TECH.Df * pow ( 1 + Vd_n[ 1 ] / TECH.PB_n, -TECH.mj_n ) + \
40 TECH.C_np * 2 * ( Wjn + njn * TECH.Df ) * pow ( 1 + Vd_n[ 1 ] / TECH.PB_n, -TECH.mjsw_n );
41 Cj += TECH.Cgs0_n * ( Wjn + njn * TECH.XW_n );
42 // evaluate Cgs Cgd @ V node 1 for pmos
43 Cj += TECH.C_pj * Wjp * TECH.Df * pow ( 1 + ( VDD - Vd_n[ 1 ] ) / TECH.PB_p, -TECH.mj_p ) + \
44 TECH.C_pp * 2 * ( Wjp + njp * TECH.Df ) * pow ( 1 + ( VDD - Vd_n[ 1 ] ) / TECH.PB_p, -TECH.mjsw_p );
45 Cj += TECH.Cgd0_p * ( Wjp + njp * TECH.XW_p );
46 // evaluate other capacitances
47 int nc;
48 Cj += circuit.CapStaticGnd( node, nc );
49 Cj += circuit.CapStaticVdd( node, nc );
50 // evaluate gate capacitances
51 Cj += Wgn * TECH.Lmin * TECH.Cox_n;
52 Cj += Wgp * TECH.Lmin * TECH.Cox_p;
53 t0_bs = TECH.Vtn0 * taui_n[ 1 ] / VDD;
54 A_2_n = Vc * beta_n[ 1 ] * ( Vc - TECH.Vtn0 );
55 B_2_n = VDD * Vc * beta_n[ 1 ] / taui_n[ 1 ];
56 C_2_n = 2 * VDD / ( Vc * taui_n[ 1 ] );
57 D_2_n = ( Vc - 2 * TECH.Vtn0 ) / Vc;
58 y = -2 * ( Vc * Vc ) * beta_n[ 1 ] * pow ( C_2_n * t + D_2_n, 1.5 ) / ( 3 * C_2_n ) + \
59 B_2_n * ( t * t ) * 0.5 + t * ( A_2_n * taui_n[ 1 ] - Cov * VDD ) / ( taui_n[ 1 ] ) - \
60 ( 6 * A_2_n * C_2_n * t0_bs + 3 * B_2_n * C_2_n * ( t0_bs * t0_bs ) - \
61 4 * ( Vc * Vc ) * beta_n[ 1 ] * pow ( C_2_n * t0_bs + D_2_n, 1.5 ) ) / ( 6 * C_2_n );
62 RetCode = OK;
63 return y;
64 }
t0P.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "fast.h"
7
8 ///
9 double Fast::t0P( const Circuit& circuit, unsigned int NP, unsigned int NC, double t, const double* NewWidth, int& RetCode )
10 {
11 double A_2_p, B_2_p, C_2_p, D_2_p, Vc, y, Cm1, Cov, t0_bs, Cj;
12 double alpha, theta, Y;
13
14 Vc = TECH.Ec_p * L_p[ 1 ];
15 Cov = TECH.Cgd0_p * ( W_p[ 1 ] + TECH.XW_p );
282 Appendix B. Source code
16 Cm1 = Cov;
17 Cj = 0.0;
18 int njn, ngn, njp, ngp;
19 double Wjn, Wgn, Wjp, Wgp;
20 unsigned int nn = pathlist[ NP ].GetNumTranN( NC );
21 unsigned int pp = pathlist[ NP ].GetNumTranP( NC );
22 unsigned int node;
23 const char* name = pathlist[ NP ].TransistorName( nn + pp - 1, NC ); // first pmos
24 unsigned int VDDNode = circuit.ValimNode();
25 if ( circuit[ name ].Source() == VDDNode )
26 {
27 node = circuit[ name ].Drain();
28 Wjn = circuit.JunctionNWidth( node, njn, NewWidth );
29 Wgn = circuit.GateNWidth( node, ngn, NewWidth );
30 Wjp = circuit.JunctionPWidth( node, njp, NewWidth );
31 Wgp = circuit.GatePWidth( node, ngp, NewWidth );
32 }
33 else if ( circuit[ name ].Drain() == VDDNode )
34 {
35 node = circuit[ name ].Source();
36 Wjn = circuit.JunctionNWidth( node, njn, NewWidth );
37 Wgn = circuit.GateNWidth( node, ngn, NewWidth );
38 Wjp = circuit.JunctionPWidth( node, njp, NewWidth );
39 Wgp = circuit.GatePWidth( node, ngp, NewWidth );
40 }
41 else
42 {
43 RetCode = NOT_FOUND;
44 return 0.0;
45 }
46 // evaluate Cgs Cgd @ V node 1 for pmos
47 Cj += TECH.C_pj * Wjp * TECH.Df * pow ( 1 + ( VDD - Vd_p[ 1 ] ) / TECH.PB_p, -TECH.mj_p ) + \
48 TECH.C_pp * 2 * ( Wjp + njp * TECH.Df ) * pow ( 1 + ( VDD - Vd_p[ 1 ] ) / TECH.PB_p, -TECH.mjsw_p );
49 Cj += TECH.Cgs0_p * ( Wjp + njp * TECH.XW_p );
50 // evaluate Cgs Cgd @ V node 1 for nmos
51 Cj += TECH.C_nj * Wjn * TECH.Df * pow ( 1 + Vd_p[ 1 ] / TECH.PB_n, -TECH.mj_n ) + \
52 TECH.C_np * 2 * ( Wjn + njn * TECH.Df ) * pow ( 1 + Vd_p[ 1 ] / TECH.PB_n, -TECH.mjsw_n );
53 Cj += TECH.Cgd0_n * ( Wjn + njn * TECH.XW_p );
54 // evaluate other capacitances
55 int nc;
56 Cj += circuit.CapStaticGnd( node, nc );
57 Cj += circuit.CapStaticVdd( node, nc );
58 // evaluate gate capacitances
59 Cj += Wgn * TECH.Lmin * TECH.Cox_n;
60 Cj += Wgp * TECH.Lmin * TECH.Cox_p;
61 t0_bs = -TECH.Vtp0 * taui_p[ 1 ] / VDD;
62 A_2_p = Vc * beta_p[ 1 ] * ( Vc + TECH.Vtp0 );
63 B_2_p = VDD * Vc * beta_p[ 1 ] / taui_p[ 1 ];
64 C_2_p = ( Vc + 2 * TECH.Vtp0 ) / Vc;
65 D_2_p = 2 * VDD / ( Vc * taui_p[ 1 ] );
66 Y = Cj + Cov;
67 alpha = pow( ( D_2_p * t0_bs + C_2_p ), 1.5 );
68 theta = pow( ( D_2_p * t + C_2_p ), 1.5 );
69 y = ( 2 * Vc * Vc * beta_p[ 1 ] * theta ) / \
70 ( 3 * D_2_p ) - \
71 B_2_p * t * t * 0.5 +
72 t * ( -A_2_p * taui_p[ 1 ] + Cov * VDD ) / \
73 ( taui_p[ 1 ] ) + \
74 ( 6 * A_2_p * D_2_p * t0_bs + 3 * B_2_p * D_2_p * t0_bs * t0_bs - \
75 4 * Vc * Vc * beta_p[ 1 ] * alpha ) / ( 6 * D_2_p );
76 RetCode = OK;
77 return y;
78 }
B.3. Simulators 283
TestOpt.cc
3 #include "mystdinclude.h"
4 #include "myenum.h"
5 #include "print.h"
6 #include "test.h"
7
8 ///
9 TestOpt::TestOpt( const CritPathList& pathlist, const Options& options)
10 :
11 EvaluationAlgorithm( pathlist, options )
12 {
13 print_log( "Creating TestOpt instance..." );
14 }
15
16 ///
17 TestOpt::~TestOpt()
18 {}
19
20 ///
21
22 int TestOpt::Run( const Circuit& circuit, const double *NewWidth, const unsigned* ValidPath )
23 {
24 Calls++;
25 for ( unsigned int NP = 0; NP < NumPath; NP++ )
26 {
27 if (ValidPath[NP])
28 {
29 int RetCode;
30 CPDelay[ NP ] = 0.0;
31 CPPower[ NP ] = 0.0;
32 CPNoise[ NP ] = 0.0;
33 Area = 0.0;
34 for (unsigned int i = 0; i < circuit.GetNTran(); i++)
35 {
36 double x = NewWidth[i];
37 double f, g, h , l;
38 // f
39 f = x * x * x * x * 3.0 / 8000.0;
40 f += -x * x * x * 11.0 / 400.0;
41 f += x * x * 27.0 / 40.0;
42 f += -x * 27.0 / 4.0;
43 f += 165.0 / 4.0;
44 // l
45 l = x * x * x * x * 3.0 / 7700.0;
46 l += -x * x * x * 11.0 / 402.0;
47 l += x * x * 27.0 / 39.5;
48 l += -x * 27.0 / 4.0;
49 l += 150.0 / 4.0;
50 // g
51 g = x * x * x * x * 3.0 / 8000.0;
52 g += -x * x * x * 13.0 / 400.0;
53 g += x * x * 39.0 / 40.0;
54 g += -x * 45.0 / 4.0;
55 g += 205.0 / 4.0;
56 // h
57 h = x * x * x * x * x * x * 5.01264E-8;
58 h += -x * x * x * x * x * 1.60540E-5;
59 h += x * x * x * x * 0.001948124;
60 h += -x * x * x * 0.111669;
61 h += x * x * 3.05849;
62 h += -x * 34.6888;
63 h += 164.782;
64 //CPDelay[ NP ] = f;
65 if (f > i)
66 CPDelay[ NP ] = f;
67 else
284 Appendix B. Source code
68 CPDelay[ NP ] = l;
69 CPPower[ NP ] = NewWidth[i] * NewWidth[i] * NewWidth[i];
70 Area += NewWidth[i];
71 }
72 CPNoise[ NP ] = 0.0;
73 }
74 }
75 return OK;
76 }
BIBLIOGRAPHY
[2] J. Yuan, “High speed circuit techniques for pipelining and for one–
clock–cycle decision.” Eurochip advanced course, high speed silicon
design, Apr. 1994.
[9] T. Sakurai and A. R. Newton, “A simple mosfet model for circuit ana-
lysis,” IEEE Transactions on Electron Devices, vol. 38, pp. 887–894, Apr.
1991.
[31] D. Zhou and X. Y. Liu, “On the optimal drivers of high–speed low
power ics,” International journal of High Speed Electronics and Systems,
vol. 7, no. 2, pp. 287–303, 1996.
[33] H. Liao and W. W. Dai, “A new cmos driver model for transient ana-
lysis and power dissipation,” International journal of High Speed Elec-
tronics and Systems, vol. 7, no. 2, pp. 269–285, 1996.
[42] L. T. Wurtz, “An efficient scaling procedure for domino cmos logic,”
IEEE Journal of Solid State Circuits, vol. 28, pp. 979–982, Sept. 1993.
[43] J. Yuan, “Ultimate cmos speeds and device sizing.” Eurochip ad-
vanced course, high speed silicon design, Apr. 1994.
[44] D. Chen and M. Sarrafzadeh, “An exact algorithm for low power
library–specific gate re–sizing,” in Proceedings of Conference on Design
Automation (DAC), 1996.
[51] O. Coudert, R. Haddad, and S. Manne, “New algorithms for gate siz-
ing: a comparative study,” in Proceedings of Conference on Design Auto-
mation (DAC), 1996.