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