Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / tas / stb / stb_clock_tree.c
1 #include <stdlib.h>
2
3 #include MUT_H
4 #include STB_H
5 #include "stb_clocks.h"
6 #include "stb_clock_tree.h"
7
8 static void stb_clock_tree_mark_diverging_node(stbfig_list *stbfig, ttvevent_list *event)
9 {
10 stbnode *cknode;
11 ttvevent_list *ckevent;
12 ttvline_list *line;
13 char level;
14
15 if ((stbfig->STABILITYMODE & STB_STABILITY_LAST) == STB_STABILITY_LAST)
16 level = stbfig->FIG->INFO->LEVEL;
17 else
18 level = event->ROOT->ROOT->INFO->LEVEL;
19
20 if (stbfig->GRAPH == STB_RED_GRAPH)
21 {
22 ttv_expfigsig (stbfig->FIG, event->ROOT, level, stbfig->FIG->INFO->LEVEL,
23 TTV_STS_CL_PJT, TTV_FILE_TTX);
24 line = event->INPATH;
25 }
26 else
27 {
28 ttv_expfigsig (stbfig->FIG, event->ROOT, level, stbfig->FIG->INFO->LEVEL,
29 TTV_STS_CLS_FED, TTV_FILE_DTX);
30 line = event->INLINE;
31 }
32
33 for (; line; line = line->NEXT)
34 {
35 if (((line->TYPE & TTV_LINE_CONT) == TTV_LINE_CONT) ||
36 (((line->TYPE & (TTV_LINE_D | TTV_LINE_T)) != 0) &&
37 (line->FIG != stbfig->FIG)) ||
38 (((line->TYPE & (TTV_LINE_P | TTV_LINE_F)) != 0) &&
39 (line->FIG != stbfig->FIG) &&
40 ((stbfig->STABILITYMODE & STB_STABILITY_LAST) == STB_STABILITY_LAST)))
41 continue;
42
43 ckevent = line->NODE;
44 if (getptype(ckevent->USER, TTV_NODE_MARQUE)!=NULL)
45 {
46 if ((cknode = stb_getstbnode (ckevent))!=NULL)
47 cknode->FLAG|=STB_NODE_DIVERGING;
48 }
49 else ckevent->USER=addptype(ckevent->USER, TTV_NODE_MARQUE, 0);
50 }
51 }
52
53 void stb_free_clock_tree_info(ttvevent_list *node)
54 {
55 node->USER=testanddelptype(node->USER, STB_CLOCK_TREE_INFO);
56 }
57
58 void stb_clock_tree_mark_divergence(stbfig_list *stbfig)
59 {
60 chain_list *cl;
61 ttvevent_list *node;
62 ptype_list *pt;
63 for (cl=stbfig->NODE; cl!=NULL; cl=cl->NEXT)
64 {
65 node=(ttvevent_list *)cl->DATA;
66 stb_clock_tree_mark_diverging_node(stbfig, node);
67 }
68 for (cl=stbfig->NODE; cl!=NULL; cl=cl->NEXT)
69 {
70 node=(ttvevent_list *)cl->DATA;
71 node->USER=testanddelptype(node->USER, TTV_NODE_MARQUE);
72 if ((pt=getptype(node->USER, STB_CLOCK_TREE_INFO))!=NULL)
73 {
74 DelHeapItem(&stbfig->CLOCK_TREE_HEAP, pt->DATA);
75 stb_free_clock_tree_info(node);
76 }
77 }
78 }
79
80 static inline stb_clock_tree *stb_get_clock_tree(ttvevent_list *node)
81 {
82 ptype_list *pt;
83
84 if (node==NULL) return NULL;
85 if ((pt=getptype(node->USER, STB_CLOCK_TREE_INFO))!=NULL)
86 return (stb_clock_tree *)pt->DATA;
87 return NULL;
88 }
89
90
91 static stb_clock_tree *stb_give_clock_tree(stbfig_list *sbf, ttvevent_list *node)
92 {
93 stb_clock_tree *sct;
94
95 if ((sct=stb_get_clock_tree(node))==NULL)
96 {
97 sct=(stb_clock_tree *)AddHeapItem(&sbf->CLOCK_TREE_HEAP);
98 sct->level=-1;
99 sct->delaymin=sct->delaymax=TTV_NOTIME;
100 sct->previous_divergence=sct->previous_divergence_hz=NULL;
101 node->USER=addptype(node->USER, STB_CLOCK_TREE_INFO, sct);
102 }
103 return sct;
104 }
105
106
107 static int importantnode(stbnode *node)
108 {
109 if (node!=NULL &&
110 ((node->FLAG & STB_NODE_DIVERGING)!=0
111 || (node->EVENT->ROOT->TYPE & TTV_SIG_Q)!=0)) return 1;
112 return 0;
113 }
114
115 void stb_mark_path_diverging_node(stbfig_list *sbf, ttvpath_list *pth)
116 {
117 long delay;
118 ttvcritic_list *tc;
119 ttvevent_list *prev;
120 stb_clock_tree *sct;
121 stbnode *node;
122 int level=0;
123
124 delay=0;
125 prev=NULL;
126
127 for (tc=pth->CRITIC; tc!=NULL; tc=tc->NEXT)
128 {
129 delay+=tc->DELAY;
130 node=stb_getstbnode (tc->NODE);
131 if (tc==pth->CRITIC || tc->NEXT==NULL || importantnode(node)!=0)
132 {
133 sct=stb_give_clock_tree(sbf, tc->NODE);
134 sct->level=level++;
135 if (tc->NEXT==NULL && (pth->TYPE & TTV_FIND_HZ)==TTV_FIND_HZ) sct->previous_divergence_hz=prev;
136 else sct->previous_divergence=prev;
137 prev=tc->NODE;
138 if ((pth->TYPE & TTV_FIND_MAX)==TTV_FIND_MAX)
139 {
140 if (sct->delaymax==TTV_NOTIME || sct->delaymax<delay)
141 {
142 sct->delaymax=delay;
143 if (sct->delaymin==TTV_NOTIME) sct->delaymin=delay;
144 }
145 }
146 else
147 {
148 if (sct->delaymin==TTV_NOTIME || sct->delaymin>delay)
149 {
150 sct->delaymin=delay;
151 if (sct->delaymax==TTV_NOTIME || sct->delaymax<delay) sct->delaymax=delay;
152 }
153 }
154 }
155 }
156 }
157
158 static stb_clock_tree *stb_find_common_node(ttvevent_list *a, ttvevent_list *b, int maxdepth, ttvevent_list **common_node, int hza, int hzb)
159 {
160 stb_clock_tree *sct_a, *sct_b;
161 ttvevent_list *sct_up;
162 int depth=0, firsta=1, firstb=1;
163
164 if (maxdepth==0) return NULL;
165
166 *common_node=a;
167 if ((sct_a=stb_get_clock_tree(a))==NULL) return NULL;
168 if ((sct_b=stb_get_clock_tree(b))==NULL) return NULL;
169
170 while (depth<maxdepth && sct_a!=NULL && sct_b!=NULL && sct_a!=sct_b)
171 {
172 if (sct_a->level==sct_b->level)
173 {
174 if (firsta && hza) sct_up=sct_a->previous_divergence_hz;
175 else sct_up=sct_a->previous_divergence;
176 *common_node=sct_up;
177 sct_a=stb_get_clock_tree(sct_up);
178 if (firstb && hzb) sct_up=sct_b->previous_divergence_hz;
179 else sct_up=sct_b->previous_divergence;
180 sct_b=stb_get_clock_tree(sct_up);
181 firsta=0;
182 firstb=0;
183 }
184 else if (sct_a->level<sct_b->level)
185 {
186 if (firstb && hzb) sct_up=sct_b->previous_divergence_hz;
187 else sct_up=sct_b->previous_divergence;
188 *common_node=sct_up;
189 sct_b=stb_get_clock_tree(sct_up);
190 firstb=0;
191 }
192 else
193 {
194 if (firsta && hza) sct_up=sct_a->previous_divergence_hz;
195 else sct_up=sct_a->previous_divergence;
196 *common_node=sct_up;
197 sct_a=stb_get_clock_tree(sct_up);
198 firsta=0;
199 }
200 depth++;
201 }
202 if (sct_a==NULL || sct_b==NULL || depth>=maxdepth) return NULL;
203 return sct_a;
204 }
205
206 int stb_get_common_node_info(ttvevent_list *a, ttvevent_list *b, int maxdepth, long *min, long *max, ttvevent_list **common_node, int hza, int hzb)
207 {
208 stb_clock_tree *sct;
209 if ((sct=stb_find_common_node(a, b, maxdepth, common_node, hza, hzb))==NULL)
210 {
211 *min=*max=0;
212 *common_node=NULL;
213 return 0;
214 }
215 *min=sct->delaymin;
216 *max=sct->delaymax;
217 // printf("common: for %s %s at node %s : %d %d\n", a->ROOT->NAME, b->ROOT->NAME, (*common_node)->ROOT->NAME, *min, *max);
218 return 1;
219 }
220
221 ttvevent_list *stb_get_top_node(ttvevent_list *a, int hza)
222 {
223 stb_clock_tree *sct_a;
224 ttvevent_list *sct_up;
225 ttvevent_list *top=NULL;
226 int firsta=0;
227
228 top=a;
229 if ((sct_a=stb_get_clock_tree(a))==NULL) return top;
230
231 if (hza) sct_up=sct_a->previous_divergence_hz;
232 else sct_up=sct_a->previous_divergence;
233 while (sct_up!=NULL)
234 {
235 top=sct_up;
236 sct_a=stb_get_clock_tree(sct_up);
237 sct_up=sct_a->previous_divergence;
238 }
239 return top;
240 }
241
242 long stb_get_generated_clock_common_node_info(ptype_list *geneclockinfo, ttvevent_list *a, ttvevent_list *b, int hza, int hzb, ttvevent_list **common)
243 {
244 ttvevent_list *clocka, *clockb;
245 long minmax;
246 clocka=stb_get_top_node(a, hza);
247 clockb=stb_get_top_node(b, hzb);
248 minmax=stb_get_generated_clock_skew(geneclockinfo, clocka, clockb, common);
249 if (minmax==TTV_NOTIME) return 0;
250 return minmax;
251 }
252