1 /*------------------------------------------------------------\
2 | |
3 | This file is part of the Alliance CAD System Copyright |
4 | (C) Laboratoire LIP6 - D�partement ASIM Universite P&M Curie|
5 | |
6 | Home page : http://www-asim.lip6.fr/alliance/ |
7 | E-mail : mailto:alliance-users@asim.lip6.fr |
8 | |
9 | This progam is free software; you can redistribute it |
10 | and/or modify it under the terms of the GNU General Public |
11 | License as published by the Free Software Foundation; |
12 | either version 2 of the License, or (at your option) any |
13 | later version. |
14 | |
15 | Alliance VLSI CAD System is distributed in the hope that |
16 | it will be useful, but WITHOUT ANY WARRANTY; |
17 | without even the implied warranty of MERCHANTABILITY or |
18 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
19 | Public License for more details. |
20 | |
21 | You should have received a copy of the GNU General Public |
22 | License along with the GNU C Library; see the file COPYING. |
23 | If not, write to the Free Software Foundation, Inc., |
24 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
25 | |
26 \------------------------------------------------------------*/
27
28 #include "mut.h"
29 #include "mlo.h"
30 #include "rcn.h"
31 #include "rds.h"
32 #include "lynxrcn.h"
33 #include "Windows95.h"
34 #include "znc.h"
35
36 znc *HEAD_FREE_ZNC;
37 #define BUFZNCSIZE 5
38 /*
39 #define ZNCDEBUG
40 */
41 void freeznc __P((znc*)); /* Libere une structure znc. Cette structure
42 est remise dans la liste des structures
43 libres */
44 znc* getznc __P((void)); /* Recupere une structure znc par allocation
45 par tas */
46 void addwinznc __P((znc*, WinZnc*)); /* Cette fonction ajoute une znc dans le
47 fenetrage prevus a cet effet */
48 void delwinznc __P((znc*,WinZnc*)); /* Efface un znc du fenetrage */
49 long getmx __P((znc*,WinZnc*));
50 long getmy __P((znc*,WinZnc*));
51 long getMx __P((znc*,WinZnc*));
52 long getMy __P((znc*,WinZnc*));
53
addznc(x1,y1,x2,y2,layer,winznc)54 long addznc(x1,y1,x2,y2,layer,winznc)
55 long x1;
56 long y1;
57 long x2;
58 long y2;
59 long layer;
60 WinZnc *winznc;
61 {
62 chain_list *interznc,*schinter;
63 znc *nouveau,*ancien,*recouvre;
64 znc last;
65
66 nouveau=getznc();
67 nouveau->x1=x1;
68 nouveau->x2=x2;
69 nouveau->y1=y1;
70 nouveau->y2=y2;
71 nouveau->layer=layer;
72
73 #ifdef ZNCDEBUG
74 fprintf(stderr,"*** addznc ***\n");
75 fprintf(stderr,"Zone ( %ld; %ld)-( %ld; %ld) sur layer %ld \n",x1,y1,x2,y2,nouveau->layer);
76 #endif
77
78 do
79 {
80 last=*nouveau;
81
82 interznc=getwininterznc(nouveau,winznc,1);
83
84 for(schinter=interznc;schinter;schinter=schinter->NEXT)
85 {
86 recouvre=(znc*)(schinter->DATA);
87
88 if(recouvre->x1 < nouveau->x1) nouveau->x1=recouvre->x1;
89 if(recouvre->y1 < nouveau->y1) nouveau->y1=recouvre->y1;
90 if(recouvre->x2 > nouveau->x2) nouveau->x2=recouvre->x2;
91 if(recouvre->y2 > nouveau->y2) nouveau->y2=recouvre->y2;
92 }
93
94 #ifdef ZNCDEBUG
95 fprintf(stderr,"Nouvelle znc apres recouvrements\n");
96 fprintf(stderr,"Zone ( %ld; %ld)-( %ld; %ld) sur layer %ld \n",nouveau->x1,nouveau->y1,nouveau->x2,nouveau->y2,nouveau->layer);
97 fprintf(stderr,"\n\nAjout de la nouvelle zone dans le fenetrage\n");
98 #endif
99
100
101 #ifdef ZNCDEBUG
102 fprintf(stderr,"\nEffacement eventuel des zones recouvrantes\n\n");
103 #endif
104
105 if(interznc)
106 {
107 ancien=NULL;
108 for(schinter=interznc;schinter;schinter=schinter->NEXT)
109 {
110 if(ancien)
111 {
112 delwinznc(ancien,winznc);
113 freeznc(ancien);
114 }
115 ancien=(znc*)(schinter->DATA);
116 }
117
118 if(ancien)
119 {
120 delwinznc(ancien,winznc);
121 freeznc(ancien);
122 }
123 freechain(interznc);
124 }
125 }
126 while(last.x1!=nouveau->x1 ||
127 last.y1!=nouveau->y1 ||
128 last.x2!=nouveau->x2 ||
129 last.y2!=nouveau->y2 );
130
131 /* Attention lors de l'utilisation du connect : il ne devrait plus y
132 avoir de recouvrement sur cette znc. L'utilisateur doit prendre ces
133 precautions */
134
135 addwinznc(nouveau,winznc);
136 return(nouveau->node);
137 }
138
getznc()139 znc* getznc()
140 {
141 int i;
142 znc *newznc;
143
144 if(HEAD_FREE_ZNC==NULL)
145 {
146 HEAD_FREE_ZNC=(znc*)mbkalloc(sizeof(znc)*BUFZNCSIZE);
147 newznc=HEAD_FREE_ZNC;
148 for(i=1;i<BUFZNCSIZE;i++)
149 {
150 newznc->NEXT=newznc+1;
151 newznc++;
152 }
153 newznc->NEXT=NULL;
154 }
155 newznc=HEAD_FREE_ZNC;
156 HEAD_FREE_ZNC=HEAD_FREE_ZNC->NEXT;
157 newznc->NEXT=NULL;
158 newznc->Win=NULL;
159 newznc->rec=NULL;
160 newznc->node=0;
161 return(newznc);
162 }
163
freeznc(z)164 void freeznc(z)
165 znc *z;
166 {
167 if(z->rec) freechain(z->rec);
168 if(z->Win) freechain(z->Win);
169 z->NEXT=HEAD_FREE_ZNC;
170 HEAD_FREE_ZNC=z;
171 }
172
addwinznc(elem,wininfo)173 void addwinznc(elem,wininfo)
174 znc *elem;
175 WinZnc *wininfo;
176 {
177 long x1,y1,x2,y2;
178 long nx1,ny1;
179 chain_list *ptchain;
180
181
182 x1=getmx(elem,wininfo);
183 y1=getmy(elem,wininfo);
184 x2=getMx(elem,wininfo);
185 y2=getMy(elem,wininfo);
186
187 /* Ajout de la znc dans les ChZnc qui vont bien */
188
189 for(nx1=x1;nx1<=x2;nx1++)
190 {
191 for(ny1=y1;ny1<=y2;ny1++)
192 {
193 /* Ajoute l'element dans le fenetrage */
194 #ifdef ZNCDEBUG
195 fprintf(stderr,"Ajout de l'element dans la fenetre %ld\n",ny1*wininfo->nx + nx1);
196 #endif
197
198 ptchain=*(wininfo->ChZnc + ny1*wininfo->nx + nx1);
199 ptchain=addchain(ptchain,elem);
200 *(wininfo->ChZnc + ny1*wininfo->nx + nx1)=ptchain;
201
202 /* Fait pointer cet element vers ses fenetrages */
203
204 elem->Win=addchain(elem->Win,wininfo->ChZnc + ny1*wininfo->nx + nx1);
205 }
206 }
207 }
208
getwininterznc(elem,wininfo,chklayer)209 chain_list* getwininterznc(elem,wininfo,chklayer)
210 znc *elem;
211 WinZnc *wininfo;
212 short chklayer; /* si chklayer != 0, alors une verification de layer
213 est effectuee */
214 {
215 chain_list *fenetre;
216 chain_list *candidats;
217 znc *zonecandidate;
218 chain_list *elus,*cleanelus;
219 long x1,y1,x2,y2,x,y;
220
221 elus=NULL;
222 #ifdef ZNCDEBUG
223 fprintf(stderr,"Debut de recherche des intersections\n");
224 #endif
225
226 x1=getmx(elem,wininfo);
227 y1=getmy(elem,wininfo);
228 x2=getMx(elem,wininfo);
229 y2=getMy(elem,wininfo);
230
231 for(x=x1;x<=x2;x++)
232 {
233 for(y=y1;y<=y2;y++)
234 {
235 fenetre=*(wininfo->ChZnc + y*wininfo->nx + x);
236
237 #ifdef ZNCDEBUG
238 fprintf(stderr,"Examine fenetre %ld\n",y*wininfo->nx + x);
239 #endif
240
241 for(candidats=fenetre;
242 candidats;
243 candidats=candidats->NEXT)
244 {
245 zonecandidate=(znc*)(candidats->DATA);
246
247 #ifdef ZNCDEBUG
248 fprintf(stderr,"Zone : (%ld ; %ld)-(%ld ; %ld) layer %ld\n",zonecandidate->x1,zonecandidate->y1,zonecandidate->x2,zonecandidate->y2,zonecandidate->layer);
249 #endif
250
251 /* On regarde les intersections */
252 if( zonecandidate->x1 <= elem->x2 &&
253 elem->x1 <= zonecandidate->x2 &&
254 elem->y1 <= zonecandidate->y2 &&
255 zonecandidate->y1 <= elem->y2 &&
256 ( !chklayer || (chklayer && (zonecandidate->layer==elem->layer))) )
257 {
258 if(zonecandidate->NEXT==NULL)
259 {
260 elus=addchain(elus,zonecandidate);
261 zonecandidate->NEXT=(znc*)1;
262 #ifdef ZNCDEBUG
263 fprintf(stderr,"---> OK\n");
264 #endif
265 }
266 }
267 }
268 }
269 }
270 for(cleanelus=elus;cleanelus;cleanelus=cleanelus->NEXT)
271 ((znc*)(cleanelus->DATA))->NEXT=NULL;
272
273 return(elus);
274 }
275
creatwinznc(mx,my,MX,MY,PX,PY,nx,ny)276 WinZnc* creatwinznc(mx,my,MX,MY,PX,PY,nx,ny)
277 long mx,my,MX,MY,PX,PY,nx,ny;
278 {
279 WinZnc *wznc;
280 long i,j;
281
282 wznc = (WinZnc*)mbkalloc(sizeof(WinZnc));
283 wznc->mx = mx;
284 wznc->my = my;
285 wznc->MX = MX;
286 wznc->MY = MY;
287 wznc->PX = PX;
288 wznc->PY = PY;
289 wznc->nx = nx;
290 wznc->ny = ny;
291 wznc->ChZnc = (chain_list**)mbkalloc(sizeof(chain_list*)*nx*ny);
292
293 j=nx*ny;
294 for(i=0;i<j;i++)
295 wznc->ChZnc[i]=NULL;
296
297 #ifdef ZNCDEBUG
298 fprintf(stderr,"Creation du fenetrage znc\n");
299 fprintf(stderr,"Nombre des fenetres : %ld x %ld\n",wznc->nx,wznc->ny);
300 fprintf(stderr,"Taille des fenetres : %ld x %ld\n",wznc->PX,wznc->PY);
301 fprintf(stderr,"Origine des fenetres : %ld x %ld\n",wznc->mx,wznc->my);
302 #endif
303 return(wznc);
304 }
305
freewinznc(winfo)306 void freewinznc(winfo)
307 WinZnc *winfo;
308 {
309 long i,j;
310
311 j=winfo->nx*winfo->ny;
312
313 for(i=0;i<j;i++)
314 if(winfo->ChZnc[i]!=NULL)
315 freechain(winfo->ChZnc[i]);
316
317 mbkfree(winfo->ChZnc);
318 mbkfree(winfo);
319
320 }
321
delwinznc(elem,info)322 void delwinznc(elem,info)
323 znc *elem;
324 WinZnc *info;
325 {
326 chain_list *chl,*chlw,*last=NULL;
327 chain_list **fenetre;
328
329 #ifdef ZNCDEBUG
330 fprintf(stderr,"Elimination de fenetrage de la znc ( %ld; %ld)-( %ld; %ld) sur layer %ld\n",elem->x1,elem->y1,elem->x2,elem->y2,elem->layer);
331 #endif
332
333 for(chl=elem->Win;chl;chl=chl->NEXT)
334 {
335 fenetre=(chain_list**)(chl->DATA);
336
337 #ifdef ZNCDEBUG
338 fprintf(stderr," -> fenetre : %ld\n",(((long)fenetre)-((long)(info->ChZnc)))/sizeof(void*));
339 #endif
340
341 /* Libere l'element dans la fenetre pointant vers elem */
342
343 if( (*fenetre)->DATA == elem )
344 {
345 last=*fenetre;
346 *fenetre=last->NEXT;
347 last->NEXT=NULL;
348 freechain(last);
349 }
350 else
351 {
352 for(chlw=*fenetre;chlw;chlw=chlw->NEXT)
353 {
354 if(chlw->DATA == elem)
355 break;
356 last=chlw;
357 }
358 if(!chlw)
359 {
360 fprintf(stderr,"Erreur impossible (1).\n");
361 exit(-2);
362 }
363 last->NEXT=chlw->NEXT;
364 chlw->NEXT=NULL;
365 freechain(chlw);
366 }
367 }
368 freechain(elem->Win);
369 elem->Win=NULL;
370 }
371
getMx(elem,wininfo)372 long getMx(elem,wininfo)
373 znc *elem;
374 WinZnc *wininfo;
375 {
376 long x2;
377 x2=(elem->x2-wininfo->mx)/wininfo->PX;
378 return(x2);
379 }
380
getMy(elem,wininfo)381 long getMy(elem,wininfo)
382 znc *elem;
383 WinZnc *wininfo;
384 {
385 long y2;
386 y2=(elem->y2-wininfo->my)/wininfo->PY;
387 return(y2);
388 }
389
getmx(elem,wininfo)390 long getmx(elem,wininfo)
391 znc *elem;
392 WinZnc *wininfo;
393 {
394 long x1,y1,nx1;
395 long ix1,ix2,iy1,iy2;
396
397 x1=(elem->x1-wininfo->mx)/wininfo->PX;
398 y1=(elem->y1-wininfo->my)/wininfo->PY;
399 nx1=x1;
400 if(x1>=1)
401 {
402 ix1=(x1-1)*wininfo->PX+wininfo->mx;
403 iy1=y1*wininfo->PY+wininfo->my;
404 ix2=ix1+wininfo->PX;
405 iy2=iy1+wininfo->PY;
406
407 /* verifie l'intersection des deux rectangles */
408 if( elem->x1<=ix2 && ix1<=elem->x2 && iy1<=elem->y2 && elem->y1<=iy2 )
409 nx1=x1-1;
410 }
411 return(nx1);
412 }
413
getmy(elem,wininfo)414 long getmy(elem,wininfo)
415 znc *elem;
416 WinZnc *wininfo;
417 {
418 long x1,y1,ny1;
419 long ix1,ix2,iy1,iy2;
420
421 y1=(elem->y1-wininfo->my)/wininfo->PY;
422 x1=(elem->x1-wininfo->mx)/wininfo->PX;
423 ny1=y1;
424 if(y1>=1)
425 {
426 ix1=x1*wininfo->PX+wininfo->mx;
427 iy1=(y1-1)*wininfo->PY+wininfo->my;
428 ix2=ix1+wininfo->PX;
429 iy2=iy1+wininfo->PY;
430
431 /* verifie l'intersection des deuy rectangles */
432 if( elem->x1<=ix2 && ix1<=elem->x2 && iy1<=elem->y2 && elem->y1<=iy2 )
433 ny1=y1-1;
434 }
435 return(ny1);
436 }
437
makezncnode(win,ptsig)438 void makezncnode(win,ptsig)
439 WinZnc *win;
440 losig_list *ptsig;
441 {
442 /* Pour parcourir toutes les znc, on se sert du fenetrage */
443 chain_list *scanwin;
444 znc *zone;
445 long i;
446
447 for(i=0;i<(win->nx*win->ny);i++)
448 {
449 for(scanwin=*(win->ChZnc+i);scanwin;scanwin=scanwin->NEXT)
450 {
451 zone=(znc*)(scanwin->DATA);
452 if(! zone->node)
453 zone->node=addlonode(ptsig,NULL);
454 }
455 }
456 }
457
linklonodelocon(connect,ptsig,wz,gwin)458 void linklonodelocon(connect, ptsig, wz, gwin)
459 chain_list *connect;
460 losig_list *ptsig;
461 WinZnc *wz;
462 GrgWindow *gwin;
463 {
464 chain_list *scanchain;
465 rdsrec_list *rec;
466 rdsrec_list *zncrec;
467 znc test;
468 chain_list *interznc;
469 long noeud;
470 locon_list *connecteur;
471 locon_list *tstlocon;
472 ptype_list *ptrdslocon;
473 chain_list *scanzncrec;
474 chain_list *headzncrec;
475
476 for(scanchain=connect;scanchain;scanchain=scanchain->NEXT)
477 {
478 rec=(rdsrec_list*)(scanchain->DATA);
479 ptrdslocon = getptype( rec->USER, RDSLOCON );
480 connecteur = ((locon_list*)(ptrdslocon->DATA));
481 if( !connecteur )
482 continue; /* cas ou plusieurs rectangles connecteurs sont superposes */
483
484 /* La znc test ne sert qu'� r�cup�rer la 'vraie' qui regroupe celles
485 qu'il faut pour avoir le lonode */
486
487 test.x1=rec->X;
488 test.y1=rec->Y;
489 test.x2=rec->X+rec->DX;
490 test.y2=rec->Y+rec->DY;
491 test.layer = (GetRdsLayer(rec)==RDS_GATE) ? RDS_POLY : GetRdsLayer(rec);
492
493 interznc=getwininterznc(&test,wz,1);
494
495 if(interznc->NEXT)
496 {
497 chain_list *scanznc;
498 fprintf(stderr,"Un locon correspond � plusieurs ZNC.\n");
499 fprintf(stderr,"Rectangle : (%ld,%ld)-(%ld,%ld) [%s]\n",test.x1,test.y1,
500 test.x2,test.y2,
501 RDS_LAYER_NAME[test.layer]);
502 for(scanznc=interznc;scanznc;scanznc=scanznc->NEXT)
503 fprintf(stderr,"ZNC : (%ld,%ld)-(%ld,%ld) [%s]\n",
504 ((znc*)(scanznc->DATA))->x1,
505 ((znc*)(scanznc->DATA))->y1,
506 ((znc*)(scanznc->DATA))->x2,
507 ((znc*)(scanznc->DATA))->y2,
508 RDS_LAYER_NAME[((znc*)(scanznc->DATA))->layer]);
509 exit(-1);
510 }
511
512 noeud=((znc*)(interznc->DATA))->node;
513
514 setloconnode(connecteur, noeud);
515
516 headzncrec = GrgGetInterWindows( rec, gwin );
517 for( scanzncrec = headzncrec ; scanzncrec ; scanzncrec = scanzncrec->NEXT )
518 {
519 zncrec = (rdsrec_list*)( scanzncrec->DATA );
520 ptrdslocon = getptype( zncrec->USER, RDSLOCON );
521 if( ptrdslocon )
522 {
523 tstlocon = ((locon_list*)(ptrdslocon->DATA));
524 if( tstlocon == connecteur )
525 ptrdslocon->DATA = NULL;
526 }
527 }
528 freechain( headzncrec );
529 /* pour pouvoir trier les connecteurs dans l'ordre */
530
531 rec->USER=addptype(rec->USER,TMPLONODE,(void*)noeud);
532 }
533 }
534
535 /* =============================================================================
536 ! FONCTION DE DEBUGGAGE !
537 ==============================================================================*/
538
dbg_affznc(winznc)539 void dbg_affznc(winznc)
540 WinZnc *winznc;
541 {
542 chain_list *scanwin;
543 znc *zone;
544 long i;
545
546 for(i=0;i<(winznc->nx*winznc->ny);i++)
547 {
548 fprintf(stderr,"fenetre %ld\n",i);
549 for(scanwin=*(winznc->ChZnc+i);scanwin;scanwin=scanwin->NEXT)
550 {
551 zone=(znc*)(scanwin->DATA);
552 fprintf(stderr,"\t%lX : (%ld,%ld)-(%ld,%ld) [%s]\n", (long)zone,
553 zone->x1,
554 zone->y1,
555 zone->x2,
556 zone->y2,
557 RDS_LAYER_NAME[zone->layer]);
558 }
559 }
560 }
561