1 /**CFile****************************************************************
2 
3   FileName    [sclLoad.c]
4 
5   SystemName  [ABC: Logic synthesis and verification system.]
6 
7   PackageName [Standard-cell library representation.]
8 
9   Synopsis    [Wire/gate load computations.]
10 
11   Author      [Alan Mishchenko, Niklas Een]
12 
13   Affiliation [UC Berkeley]
14 
15   Date        [Ver. 1.0. Started - August 24, 2012.]
16 
17   Revision    [$Id: sclLoad.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include "sclSize.h"
22 
23 ABC_NAMESPACE_IMPL_START
24 
25 
26 ////////////////////////////////////////////////////////////////////////
27 ///                        DECLARATIONS                              ///
28 ////////////////////////////////////////////////////////////////////////
29 
30 ////////////////////////////////////////////////////////////////////////
31 ///                     FUNCTION DEFINITIONS                         ///
32 ////////////////////////////////////////////////////////////////////////
33 
34 /**Function*************************************************************
35 
36   Synopsis    [Returns estimated wire capacitances for each fanout count.]
37 
38   Description []
39 
40   SideEffects []`
41 
42   SeeAlso     []
43 
44 ***********************************************************************/
Abc_SclFindWireCaps(SC_WireLoad * pWL,int nFanoutMax)45 Vec_Flt_t * Abc_SclFindWireCaps( SC_WireLoad * pWL, int nFanoutMax )
46 {
47     Vec_Flt_t * vCaps = NULL;
48     float EntryPrev, EntryCur, Slope;
49     int i, iPrev, k, Entry, EntryMax;
50     assert( pWL != NULL );
51     // find the biggest fanout count
52     EntryMax = 0;
53     Vec_IntForEachEntry( &pWL->vFanout, Entry, i )
54         EntryMax = Abc_MaxInt( EntryMax, Entry );
55     // create the array
56     vCaps = Vec_FltStart( Abc_MaxInt(nFanoutMax, EntryMax) + 1 );
57     Vec_IntForEachEntry( &pWL->vFanout, Entry, i )
58         Vec_FltWriteEntry( vCaps, Entry, Vec_FltEntry(&pWL->vLen, i) * pWL->cap );
59     if ( Vec_FltEntry(vCaps, 1) == 0 )
60         return vCaps;
61     // interpolate between the values
62     assert( Vec_FltEntry(vCaps, 1) != 0 );
63     iPrev = 1;
64     EntryPrev = Vec_FltEntry(vCaps, 1);
65     Vec_FltForEachEntryStart( vCaps, EntryCur, i, 2 )
66     {
67         if ( EntryCur == 0 )
68             continue;
69         Slope = (EntryCur - EntryPrev) / (i - iPrev);
70         for ( k = iPrev + 1; k < i; k++ )
71             Vec_FltWriteEntry( vCaps, k, EntryPrev + Slope * (k - iPrev) );
72         EntryPrev = EntryCur;
73         iPrev = i;
74     }
75     // extrapolate after the largest value
76     Slope = pWL->cap * pWL->slope;
77     for ( k = iPrev + 1; k < i; k++ )
78         Vec_FltWriteEntry( vCaps, k, EntryPrev + Slope * (k - iPrev) );
79     // show
80 //    Vec_FltForEachEntry( vCaps, EntryCur, i )
81 //        printf( "%3d : %f\n", i, EntryCur );
82     return vCaps;
83 }
84 
85 /**Function*************************************************************
86 
87   Synopsis    [Computes load for all nodes in the network.]
88 
89   Description []
90 
91   SideEffects []
92 
93   SeeAlso     []
94 
95 ***********************************************************************/
Abc_SclFindWireLoad(Vec_Flt_t * vWireCaps,int nFans)96 float Abc_SclFindWireLoad( Vec_Flt_t * vWireCaps, int nFans )
97 {
98     if ( vWireCaps == NULL )
99         return 0;
100     return Vec_FltEntry( vWireCaps, Abc_MinInt(nFans, Vec_FltSize(vWireCaps)-1) );
101 }
Abc_SclAddWireLoad(SC_Man * p,Abc_Obj_t * pObj,int fSubtr)102 void Abc_SclAddWireLoad( SC_Man * p, Abc_Obj_t * pObj, int fSubtr )
103 {
104     float Load = Abc_SclFindWireLoad( p->vWireCaps, Abc_ObjFanoutNum(pObj) );
105     Abc_SclObjLoad(p, pObj)->rise += fSubtr ? -Load : Load;
106     Abc_SclObjLoad(p, pObj)->fall += fSubtr ? -Load : Load;
107 }
Abc_SclComputeLoad(SC_Man * p)108 void Abc_SclComputeLoad( SC_Man * p )
109 {
110     Abc_Obj_t * pObj, * pFanin;
111     int i, k;
112     // clear load storage
113     Abc_NtkForEachObj( p->pNtk, pObj, i )
114     {
115         SC_Pair * pLoad = Abc_SclObjLoad( p, pObj );
116         if ( !Abc_ObjIsPo(pObj) )
117             pLoad->rise = pLoad->fall = 0.0;
118     }
119     // add cell load
120     Abc_NtkForEachNode1( p->pNtk, pObj, i )
121     {
122         SC_Cell * pCell = Abc_SclObjCell( pObj );
123         Abc_ObjForEachFanin( pObj, pFanin, k )
124         {
125             SC_Pair * pLoad = Abc_SclObjLoad( p, pFanin );
126             SC_Pin * pPin = SC_CellPin( pCell, k );
127             pLoad->rise += pPin->rise_cap;
128             pLoad->fall += pPin->fall_cap;
129         }
130     }
131     // add PO load
132     Abc_NtkForEachCo( p->pNtk, pObj, i )
133     {
134         SC_Pair * pLoadPo = Abc_SclObjLoad( p, pObj );
135         SC_Pair * pLoad = Abc_SclObjLoad( p, Abc_ObjFanin0(pObj) );
136         pLoad->rise += pLoadPo->rise;
137         pLoad->fall += pLoadPo->fall;
138     }
139     // add wire load
140     if ( p->pWLoadUsed != NULL )
141     {
142         if ( p->vWireCaps == NULL )
143             p->vWireCaps = Abc_SclFindWireCaps( p->pWLoadUsed, Abc_NtkGetFanoutMax(p->pNtk) );
144         Abc_NtkForEachNode1( p->pNtk, pObj, i )
145             Abc_SclAddWireLoad( p, pObj, 0 );
146         Abc_NtkForEachPi( p->pNtk, pObj, i )
147             Abc_SclAddWireLoad( p, pObj, 0 );
148     }
149     // check input loads
150     if ( p->vInDrive != NULL )
151     {
152         Abc_NtkForEachPi( p->pNtk, pObj, i )
153         {
154             SC_Pair * pLoad = Abc_SclObjLoad( p, pObj );
155             if ( Abc_SclObjInDrive(p, pObj) != 0 && (pLoad->rise > Abc_SclObjInDrive(p, pObj) || pLoad->fall > Abc_SclObjInDrive(p, pObj)) )
156                 printf( "Maximum input drive strength is exceeded at primary input %d.\n", i );
157         }
158     }
159 /*
160     // transfer load from barbufs
161     Abc_NtkForEachBarBuf( p->pNtk, pObj, i )
162     {
163         SC_Pair * pLoad = Abc_SclObjLoad( p, pObj );
164         SC_Pair * pLoadF = Abc_SclObjLoad( p, Abc_ObjFanin(pObj, 0) );
165         SC_PairAdd( pLoadF, pLoad );
166     }
167 */
168     // calculate average load
169 //    if ( p->EstLoadMax )
170     {
171         double TotalLoad = 0;
172         int nObjs = 0;
173         Abc_NtkForEachNode1( p->pNtk, pObj, i )
174         {
175             SC_Pair * pLoad = Abc_SclObjLoad( p, pObj );
176             TotalLoad += 0.5 * pLoad->fall + 0.5 * pLoad->rise;
177             nObjs++;
178         }
179         Abc_NtkForEachPi( p->pNtk, pObj, i )
180         {
181             SC_Pair * pLoad = Abc_SclObjLoad( p, pObj );
182             TotalLoad += 0.5 * pLoad->fall + 0.5 * pLoad->rise;
183             nObjs++;
184         }
185         p->EstLoadAve = (float)(TotalLoad / nObjs);
186 //        printf( "Average load = %.2f\n", p->EstLoadAve );
187     }
188 }
189 
190 /**Function*************************************************************
191 
192   Synopsis    [Updates load of the node's fanins.]
193 
194   Description []
195 
196   SideEffects []
197 
198   SeeAlso     []
199 
200 ***********************************************************************/
Abc_SclUpdateLoad(SC_Man * p,Abc_Obj_t * pObj,SC_Cell * pOld,SC_Cell * pNew)201 void Abc_SclUpdateLoad( SC_Man * p, Abc_Obj_t * pObj, SC_Cell * pOld, SC_Cell * pNew )
202 {
203     Abc_Obj_t * pFanin;
204     int k;
205     Abc_ObjForEachFanin( pObj, pFanin, k )
206     {
207         SC_Pair * pLoad = Abc_SclObjLoad( p, pFanin );
208         SC_Pin * pPinOld = SC_CellPin( pOld, k );
209         SC_Pin * pPinNew = SC_CellPin( pNew, k );
210         pLoad->rise += pPinNew->rise_cap - pPinOld->rise_cap;
211         pLoad->fall += pPinNew->fall_cap - pPinOld->fall_cap;
212     }
213 }
Abc_SclUpdateLoadSplit(SC_Man * p,Abc_Obj_t * pBuffer,Abc_Obj_t * pFanout)214 void Abc_SclUpdateLoadSplit( SC_Man * p, Abc_Obj_t * pBuffer, Abc_Obj_t * pFanout )
215 {
216     SC_Pin * pPin;
217     SC_Pair * pLoad;
218     int iFanin = Abc_NodeFindFanin( pFanout, pBuffer );
219     assert( iFanin >= 0 );
220     assert( Abc_ObjFaninNum(pBuffer) == 1 );
221     pPin = SC_CellPin( Abc_SclObjCell(pFanout), iFanin );
222     // update load of the buffer
223     pLoad = Abc_SclObjLoad( p, pBuffer );
224     pLoad->rise -= pPin->rise_cap;
225     pLoad->fall -= pPin->fall_cap;
226     // update load of the fanin
227     pLoad = Abc_SclObjLoad( p, Abc_ObjFanin0(pBuffer) );
228     pLoad->rise += pPin->rise_cap;
229     pLoad->fall += pPin->fall_cap;
230 }
231 
232 ////////////////////////////////////////////////////////////////////////
233 ///                       END OF FILE                                ///
234 ////////////////////////////////////////////////////////////////////////
235 
236 
237 ABC_NAMESPACE_IMPL_END
238 
239