1 /*
2  *   Copyright (C) 1990-1992 Yale University
3  *
4  *   This work is distributed in the hope that it will be useful; you can
5  *   redistribute it and/or modify it under the terms of the
6  *   GNU General Public License as published by the Free Software Foundation;
7  *   either version 2 of the License,
8  *   or any later version, on the following conditions:
9  *
10  *   (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS
11  *   ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE,
12  *   SALE OR
13  *   OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY
14  *   PATENT OR
15  *   OTHER RIGHTS NOT VESTED IN YALE.
16  *
17  *   (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND
18  *   WARRANTIES
19  *   WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED,
20  *   INCLUDING,
21  *   BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
22  *   PARTICULAR
23  *   PURPOSE.
24  *
25  *   (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES
26  *   WHATSOEVER TO
27  *   ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN
28  *   ARTICLE
29  *   (a) AND (b) above.
30  *
31  *   (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS,
32  *   EMPLOYEES AND
33  *   AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR
34  *   INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE
35  *   ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE
36  *   POSSIBILITY OF THE FOREGOING.
37  *
38  */
39 
40 /* -----------------------------------------------------------------
41 FILE:	    graphics.c
42 DESCRIPTION:graphics routines
43 CONTENTS:
44 DATE:	    Jun 14, 1990
45 REVISIONS:  Jun 21, 1990 - added graphics abort macro.
46 	    Oct 20, 1990 - fixed graphics update mode.
47 	    Nov 23, 1990 - now draw rectilinear cell properly.
48 	    Fri Feb 15 15:14:34 EST 1991 - added check to prevent
49 		drawing data before proper initialization.
50 	    Tue Mar 19 16:25:17 CST 1991 - now output cell name
51 		during drawLabel.
52 	    Thu Apr 18 01:47:00 EDT 1991 - now set graphics update
53 		to its correct state and fixed draw_single_cell_move.
54 	    Tue May  7 00:09:43 EDT 1991 - added TWsetFrame
55 		initialization and draw orientation markers.
56 ----------------------------------------------------------------- */
57 
58 #include "standard.h"
59 #include "main.h"
60 #include "readpar.h"
61 #include "pads.h"
62 
63 #ifndef NOGRAPHICS
64 
65 #include <yalecad/debug.h>
66 #include <yalecad/message.h>
67 #include <yalecad/colors.h>
68 #include <yalecad/draw.h>
69 #include <yalecad/relpos.h>
70 
71 
72 #define INTRO            "Welcome to TimberWolfSC"
73 #define GRAPHICSABORT    if(!(doGraphicsG))  return ;
74 
75 
76 #define NETCOLOR           TWRED
77 #define PINCOLOR           TWBLACK
78 #define BLACK              TWBLACK
79 #define FCOLOR             TWYELLOW
80 
81 #define MODE         2
82 #define MENUP        "sc_menu"
83 
84 /* #define DEVELOPMENU */
85 /* During development use TWread_menus in place of menuS */
86 /* to create menu record, ie.  TWread_menus(MENUP) */
87 #ifdef DEVELOPMENU
88 #define MENUREAD()   menuS = TWread_menus(MENUP) ;
89 #else
90 #define MENUREAD()
91 #endif
92 
93 #include <menus.h>
94 
95 
96 extern INT actual_feed_thru_cells_addedG ;
97 /* ***************************************************************** */
98 static BOOL avoidDump = FALSE ;
99 static BOOL drawPinS = FALSE ;   /* whether or not to draw pins */
100 static BOOL drawLabelS = FALSE ; /* whether to draw labels or not */
101 static BOOL drawBlockS = TRUE ;  /* whether to draw blocks or not */
102 static BOOL drawCellS = TRUE ;   /* whether to draw stdcells or not */
103 static BOOL auto_drawS = TRUE ;  /* whether to draw immediately after exp.*/
104 static BOOL updateS = TRUE ;     /* normally in the update mode */
105 static BOOL single_cell_moveS = FALSE ; /* whether we have single cell moves */
106 static BOOL drawOrientS = FALSE ; /* whether to draw orientation mark */
107 static BOOL initS = FALSE ;    /* true if all initialization complete */
108 static INT  *heat_indexS ;     /* how much the cells are moving */
109 static INT  *heat_attemptS ;     /* how many attempts during the run */
110 static INT  heat_allocS ;     /* size of temperature index array */
111 static INT  drawNetS = 0 ; /* draw nets 0:none 1...n:net >numnets:all */
112 static INT  pinsizeS ;     /* size of the pin */
113 
114 
115 static void draw_fs();
116 extern VOID draw_a_cell( INT );
117 extern void draw_the_data() ;
118 void graphics_dump();
119 void reset_heat_index();
120 void closegraphics();
121 
122 void setGraphicWindow();
123 
initGraphics(argc,argv,windowId)124 void initGraphics( argc, argv, windowId )
125 INT argc ;
126 char *argv[] ;
127 INT windowId ;
128 {
129 
130     char *host ;
131     char *Ygetenv() ;
132     extern INT horizontal_track_pitchG ;
133     extern INT vertical_track_pitchG ;
134 
135     GRAPHICSABORT ;
136 
137     /* we need to find host for display */
138     if(!(host = Ygetenv("DISPLAY"))) {
139 	M(WARNMSG,"initGraphics","Can't get environment variable ");
140 	M(MSG,NULL, "for display.  Aborting graphics...\n\n" ) ;
141 	avoidDump = TRUE ;
142 	doGraphicsG = FALSE ;
143 	return ;
144     }
145 
146     MENUREAD() ;
147     /* initialize the boolean menu entries according to current state */
148     /* "Graphics Update On","Graphics Update Off",1,0,8,9, is the 8 line */
149     menuS[7].bool_init = updateS ;
150 
151     if( windowId ){
152 	/* init windows as a parasite */
153 	if(!(TWinitParasite(argc,argv,TWnumcolors(),TWstdcolors(),
154 	    FALSE,menuS, (INT (*)()) draw_the_data, windowId ))){
155 	    M(ERRMSG,"initGraphics","Aborting graphics.");
156 	    doGraphicsG = FALSE ;
157 	    avoidDump = TRUE ;
158 	    return ;
159 	}
160     } else {
161 	/* init window as a master */
162 	if(!(TWinitGraphics(argc,argv,TWnumcolors(),TWstdcolors(),FALSE,
163 	    menuS, (INT (*)()) draw_the_data ))){
164 	    M(ERRMSG,"initGraphics","Aborting graphics.");
165 	    doGraphicsG = FALSE ;
166 	    avoidDump = TRUE ;
167 	    return ;
168 	}
169     }
170     TWsetwindow( 0, 0, 10, 10 ) ;
171     TWsetFrame(0) ;
172     TWdrawCell( 0, 0,0,11,11, TWBLUE, INTRO ) ;
173     setGraphicWindow() ;
174     TWdrawMenus() ;
175     TWmessage("To interrupt program click on top menu window") ;
176     TWflushFrame() ;
177     /* use TWinterupt to turn off window enter/leave lights */
178     TWinterupt() ;
179     /* set the default pin size */
180     pinsizeS = (vertical_track_pitchG + horizontal_track_pitchG) / 4 - 1 ;
181     pinsizeS = MAX( 1, pinsizeS ) ;
182 
183 } /* end initGraphics */
184 
init_heat_index()185 void init_heat_index()
186 {
187     GRAPHICSABORT ;
188 
189     heat_allocS = lastpadG + 1;
190     heat_indexS = (INT *) Ysafe_malloc( heat_allocS * sizeof(INT) ) ;
191     heat_attemptS = (INT *) Ysafe_malloc( heat_allocS * sizeof(INT) ) ;
192     reset_heat_index() ;
193     initS = TRUE ;
194 } /* end init_heat_index */
195 
expand_heat_index()196 void expand_heat_index()
197 {
198     INT oldnum, i;
199 
200     GRAPHICSABORT ;
201 
202     oldnum = heat_allocS;
203     heat_allocS = lastpadG + actual_feed_thru_cells_addedG + 1;
204     if (oldnum < heat_allocS) {
205        heat_indexS = (INT *) Ysafe_realloc( heat_indexS, heat_allocS * sizeof(INT) ) ;
206        heat_attemptS = (INT *) Ysafe_realloc( heat_attemptS, heat_allocS * sizeof(INT) ) ;
207        for( i = oldnum; i < heat_allocS ; i++ ){
208 	   heat_indexS[i] = 0 ;
209 	   heat_attemptS[i] = 0 ;
210        }
211     }
212 } /* end expand_heat_index */
213 
setGraphicWindow()214 void setGraphicWindow()
215 {
216     INT  expand ;
217     INT  minx ;
218     INT  maxx ;
219     INT  miny ;
220     INT  maxy ;
221     INT  xc, yc ;      /* cell center */
222     INT  i ;           /* counter */
223     CBOXPTR cptr ;  /* cell record pointer */
224 
225     minx = INT_MAX ;
226     miny = INT_MAX ;
227     maxx = INT_MIN ;
228     maxy = INT_MIN ;
229 
230     /* look thru cells to find overall bounding box */
231     for( i = 1; i <= lastpadG ; i++ ){
232 	cptr = carrayG[i] ;
233 	xc = cptr->cxcenter ;
234 	yc = cptr->cycenter ;
235 	if( yc == GATE_ARRAY_MAGIC_CONSTANT ){
236 	    /* don't draw these */
237 	    continue ;
238 	}
239 	minx = MIN( minx, cptr->tileptr->left + xc ) ;
240 	miny = MIN( miny, cptr->tileptr->bottom + yc ) ;
241 	maxx = MAX( maxx, cptr->tileptr->right + xc ) ;
242 	maxy = MAX( maxy, cptr->tileptr->top + yc ) ;
243     }
244 
245     expand = MAX( maxy - miny, maxx - minx ) ;
246     expand = (INT) (0.1 * (DOUBLE) expand ) ;
247     TWsetwindow( minx - expand, miny - expand,
248 	maxx + expand, maxy + expand ) ;
249 } /* end setGraphicWindow */
250 
251 /* heart of the graphic syskem processes user input */
process_graphics()252 void process_graphics()
253 {
254 
255     INT x, y ;           /* coordinates from pointer */
256     INT selection ;     /* the users pick */
257     char *reply ;       /* user reply to a querry */
258     BOOL ok ;           /* loop until this value is true */
259 
260     /* data might have changed so show user current config */
261     /* any function other that the draw controls need to worry about */
262     /* this concurrency problem -  show user current config */
263     GRAPHICSABORT ;
264     setGraphicWindow() ;
265     draw_the_data() ;
266     /* use TWcheckExposure to flush exposure events since we just */
267     /* drew the data */
268     TWcheckExposure() ;
269     TWmessage( "TimberWolfSC is waiting for your response..." ) ;
270 
271     selection  = CANCEL ;
272     while( selection != CONTINUE_PGM ){ /* loop until exit */
273 	selection = TWcheckMouse() ;
274 	switch( selection ){
275 	case CANCEL:
276 	    /* do nothing */
277 	    break ;
278 	case AUTO_REDRAW_ON:
279 	    auto_drawS = TRUE ;
280 	    break ;
281 	case AUTO_REDRAW_OFF:
282 	    auto_drawS = FALSE ;
283 	    break ;
284 	case COLORS:
285 	    TWtoggleColors() ;
286 	    break ;
287 	case CONTINUE_PGM:
288 	    break ;
289 	case DUMP_GRAPHICS:
290 	    graphics_dump() ;
291 	    break ;
292 	case FULLVIEW:
293 	    TWfullView() ;
294 	    break ;
295 	case GRAPHICS_UPDATE_ON:
296 	    updateS = TRUE ;
297 	    break ;
298 	case GRAPHICS_UPDATE_OFF:
299 	    updateS = FALSE ;
300 	    selection = CONTINUE_PGM ; /* exit loop */
301 	    break ;
302 	case CLOSE_GRAPHICS:
303 	    closegraphics() ;
304 	    return ;
305 	case REDRAW:
306 	    draw_the_data() ;
307 	    /* use TWcheckExposure to flush exposure events since */
308 	    /* we just drew the data */
309 	    TWcheckExposure() ;
310 	    break ;
311 	case TELL_POINT:
312 	    TWmessage( "Pick a point" ) ;
313 	    TWgetPt( &x, &y ) ;
314 	    sprintf( YmsgG,"The point is (%d,%d)",x,y ) ;
315 	    TWmessage( YmsgG ) ;
316 	    break ;
317 	case TRANSLATE:
318 	    TWtranslate() ;
319 	    break ;
320 	case ZOOM:
321 	    TWzoom() ;
322 	    break ;
323 	case DRAW_BLOCKS:
324 	    drawBlockS = TRUE ;
325 	    TWmessage( "Standard cell rows will be drawn" ) ;
326 	    TWforceRedraw() ;
327 	    break ;
328 	case IGNORE_BLOCKS:
329 	    drawBlockS = FALSE ;
330 	    TWmessage( "Standard cell rows will be omitted from drawing");
331 	    TWforceRedraw() ;
332 	    break ;
333 	case DRAW_STDCELLS:
334 	    drawCellS = TRUE ;
335 	    TWmessage( "Standard cells will be drawn" ) ;
336 	    TWforceRedraw() ;
337 	    break ;
338 	case IGNORE_STDCELLS:
339 	    drawCellS = FALSE ;
340 	    TWmessage( "Standard cells will be omitted from drawing");
341 	    TWforceRedraw() ;
342 	    break ;
343 	case DRAW_LABELS:
344 	    drawLabelS = TRUE ;
345 	    TWmessage( "Labels will be drawn" ) ;
346 	    TWforceRedraw() ;
347 	    break ;
348 	case IGNORE_LABELS:
349 	    drawLabelS = FALSE ;
350 	    TWmessage( "Labels will be omitted from drawing" ) ;
351 	    TWforceRedraw() ;
352 	    break ;
353 	case DRAW_NETS:
354 	    drawNetS = INT_MAX ;
355 	    TWmessage( "Nets will be drawn" ) ;
356 	    TWforceRedraw() ;
357 	    break ;
358 	case IGNORE_NETS:
359 	    drawNetS = FALSE ;
360 	    TWmessage( "Nets will be omitted from drawing" ) ;
361 	    TWforceRedraw() ;
362 	    break ;
363 	case DRAW_PINS:
364 	    drawPinS = TRUE ;
365 	    TWmessage( "Pins will be drawn" ) ;
366 	    TWforceRedraw() ;
367 	    break ;
368 	case IGNORE_PINS:
369 	    drawPinS = FALSE ;
370 	    TWmessage( "Pins will be omitted from drawing" ) ;
371 	    TWforceRedraw() ;
372 	    break ;
373 	case DRAW_SINGLE_NET:
374 	    /* get a net from the user */
375 	    ok = FALSE ;
376 	    do {
377 		/* get string from user */
378 		reply = TWgetString( "Enter net number:") ;
379 		if(!(reply)){
380 		    continue ;
381 		}
382 		drawNetS = atoi( reply ) ;
383 		if( drawNetS > 0 && drawNetS <= numnetsG ){
384 		    ok = TRUE ;
385 		    TWforceRedraw() ;
386 		} else {
387 		    TWmessage( "ERROR:invalid net number!" ) ;
388 		    (void) sleep( (unsigned) 2 ) ;
389 		}
390 	    } while ( !(ok) ) ;
391 	    break ;
392 	case DRAW_SINGLE_CELL_MOVES:
393 	    single_cell_moveS = TRUE ;
394 	    break ;
395 	case IGNORE_SINGLE_MOVES:
396 	    single_cell_moveS = FALSE ;
397 	    break ;
398 	case DRAW_ORIENT:
399 	    drawOrientS = TRUE ;
400 	    TWmessage( "Orientation markers will be drawn" ) ;
401 	    TWforceRedraw() ;
402 	    break ;
403 	case IGNORE_ORIENT:
404 	    drawOrientS = FALSE ;
405 	    TWmessage("Orientation markers will be omitted from drawing");
406 	    TWforceRedraw() ;
407 	    break ;
408 
409 	} /*********************** end graphics SWITCH *****************/
410 	if( auto_drawS && TWcheckExposure() ){
411 	    draw_the_data() ;
412 	}
413 
414     }
415     TWmessage("Continuing - to interrupt program click on top menu window") ;
416     /* use TWinterupt to turn off window enter/leave lights */
417     TWinterupt() ;
418 
419 } /* end process_graphics */
420 
421 
422 /* the graphics program can draw the results at each desired */
423 /* timestep. */
draw_the_data()424 void draw_the_data()
425 {
426 
427     INT  i ;
428     INT  x ;
429     INT  y ;
430     INT  l, r, b, t ;
431     INT  layer ;
432     INT last_cell ;     /* end of cells to be drawn */
433     PINBOXPTR  curPin ;
434     char *pinname, *find_layer( /* pinname, layer */ ) ;
435 
436     if( avoidDump || !(doGraphicsG) || !(initS) ){
437 	return ;
438     }
439     TWstartFrame() ;
440     TWmessage( "Drawing the data...Please wait" ) ;
441 
442     if( drawBlockS ){
443 	/* draw the desired standard cell rows if necessary */
444 	for( i = 1 ; i <= numRowsG ; i++ ) {
445 	    x = barrayG[i]->bxcenter ;
446 	    y = barrayG[i]->bycenter ;
447 	    l = x + barrayG[i]->bleft;
448 	    r = x + barrayG[i]->bright;
449 	    b = y + barrayG[i]->bbottom;
450 	    t = y + barrayG[i]->btop;
451 	    TWdrawCell( i, l,b,r,t, TWWHITE, NULL ) ;
452 	}
453     }
454 
455     /* DRAW the CELLS */
456     if( drawCellS ){
457 	i = 1 ; /* start with standard cells */
458     } else {
459 	i = numcellsG + 1 ; /* start with pads and macros */
460     }
461     last_cell = lastpadG + actual_feed_thru_cells_addedG ;
462 
463     for( ; i <= last_cell ; i++ ) {
464 	draw_a_cell( i ) ;
465     }
466 
467     /* now build net file */
468     /* nets are the interconnections between the cells */
469     if( drawNetS ){
470 	Ymst_init( get_max_pin() ) ;
471 	for( i=1;i<=numnetsG;i++){
472 	    /* this is the single net case */
473 	    if( drawNetS <= numnetsG && i != drawNetS ){
474 		continue ;
475 	    }
476 	    Ymst_clear() ;
477 	    for(curPin=netarrayG[i]->pins;curPin;curPin=curPin->next){
478 		Ymst_addpt( curPin->xpos, curPin->ypos ) ;
479 	    }
480 	    Ymst_draw() ;
481 	}
482 	Ymst_free() ;
483     }
484 
485     /* now output pins */
486     /* pins are the terminal points on a net */
487     if( drawPinS ){
488 	for( i = 1 ; i <= maxtermG ; i++ ) {
489 	    curPin = tearrayG[i] ;
490 	    if( !(curPin)){
491 		continue ;
492 	    }
493 	    x =  curPin->xpos ;
494 	    y =  curPin->ypos ;
495 	    if( drawLabelS ){
496 		pinname = find_layer( curPin->pinname, &layer ) ;
497 		TWdrawPin( curPin->net,x-pinsizeS,y-pinsizeS,
498 		    x+pinsizeS,y+pinsizeS, PINCOLOR, pinname ) ;
499 	    } else {
500 		TWdrawPin( curPin->net,x-pinsizeS,y-pinsizeS,
501 		    x+pinsizeS,y+pinsizeS, PINCOLOR, NULL ) ;
502 	    }
503 	}
504     }
505 
506     /* clear wait message and FLUSH OUTPUT BUFFER */
507     TWmessage( NULL ) ;
508     TWflushFrame() ;
509 
510 } /* end draw_the_data */
511 
draw_a_cell(cell)512 VOID draw_a_cell( cell )
513 INT cell ;
514 {
515     INT  x ;
516     INT  y ;
517     INT  l, r, b, t ;
518     INT  pt ;
519     INT  color ;
520     INT  cell_temp ; /* cell temperature */
521     INT  attempts ;
522     CBOXPTR cptr ;
523     PADBOXPTR  padptr ;
524     char label[LRECL] ;
525     char *labelptr ;
526     FLOAT acc_rate ;
527 
528     cptr = carrayG[cell] ;
529     x =  cptr->cxcenter ;
530     y =  cptr->cycenter ;
531     if( y == GATE_ARRAY_MAGIC_CONSTANT ){
532 	/* don't draw these */
533 	return ;
534     }
535     /* name the cell */
536     /* draw cell labels if requested */
537     if( drawLabelS ){
538 	sprintf(label,"C%d:%s",cell, carrayG[cell]->cname ) ;
539 	labelptr = label ;
540     } else {
541 	labelptr = NIL(char *) ;
542     }
543     cell_temp = heat_indexS[cell] ;
544     attempts = heat_attemptS[cell] ;
545     if( attempts <= 0 ){
546 	if( strncmp(carrayG[cell]->cname,"twfeed",6) == STRINGEQ ) {
547 	    color = TWYELLOW ;
548 	} else {
549 	    color = TWGREEN ;
550 	}
551     } else {
552 	/* don't need to be very accurate here */
553 	acc_rate = (FLOAT) cell_temp / (FLOAT) attempts ;
554 	/* now pick the color base on acceptance rate */
555 	/* 44% + 10% error margin */
556 	if( acc_rate > (FLOAT) 0.48 ){
557 	    color = TWRED ;
558 	} else if( acc_rate < (FLOAT) 0.40 ){
559 	    /* 44% - 10% error margin */
560 	    color = TWBLUE ;
561 	} else {
562 	    /* in the 44% region */
563 	    color = TWORANGE ;
564 	}
565     }
566     padptr = cptr->padptr ;
567     if( padptr && padptr->numcorners > 4 ){
568 	/* way to draw a rectilinear cell */
569 	TWarb_init() ;
570 
571 	for( pt = 0; pt < padptr->numcorners; pt++ ){
572 	    /* rel position is a macro which calculates */
573 	    /* absolute pin loc - defined in relpos.h */
574 	    REL_POS( (INT) cptr->corient,
575 		l, b,                               /* result */
576 		padptr->xpoints[pt],
577 		padptr->ypoints[pt],             /* cell relative */
578 		x, y ) ;                        /* cell center */
579 
580 	    TWarb_addpt( l, b ) ;
581 	}
582 	TWdrawArb( cell, color, labelptr ) ;
583 
584     } else {
585 	l = cptr->tileptr->left ;
586 	r = cptr->tileptr->right ;
587 	b = cptr->tileptr->bottom ;
588 	t = cptr->tileptr->top ;
589 	YtranslateT( &l, &b, &r, &t, (INT) cptr->corient ) ;
590 	l += x ;
591 	r += x ;
592 	b += y ;
593 	t += y ;
594 	TWdrawCell( cell, l,b,r,t, color, labelptr ) ;
595     }
596     if( drawOrientS && padptr ){
597 	draw_fs( cptr ) ;
598     }
599 } /* end draw a cell */
600 
601 
draw_fs(cptr)602 static void draw_fs( cptr )
603 CBOXPTR cptr ;
604 {
605     INT x[10], y[10] ;   /* only 10 points to an F */
606     INT l, b, r, t ;     /* bounding box points */
607     INT xout, yout ;     /* rotated points */
608     INT wid ;            /* with of the F */
609     INT pt ;             /* point counter */
610     TIBOXPTR bounptr ;   /* cell's boundary */
611 
612     bounptr = cptr->tileptr ;
613     l = bounptr->left ;
614     b = bounptr->bottom ;
615     r = bounptr->right ;
616     t = bounptr->top ;
617     wid = (INT) (0.25 * (DOUBLE)( t - b ) ) ;
618     /* now set the points */
619     x[0] = l ;         y[0] = b ;
620     x[1] = l ;         y[1] = t ;
621     x[2] = r ;         y[2] = t ;
622     x[3] = r ;         y[3] = t - wid ;
623     x[4] = l + wid ;   y[4] = y[3] ;
624     x[5] = x[4] ;      y[5] = y[4] - wid ;
625     x[6] = l + 2*wid ; y[6] = y[5] ;
626     x[7] = x[6] ;      y[7] = y[6] - wid ;
627     x[8] = x[5] ;      y[8] = y[7] ;
628     x[9] = x[4] ;      y[9] = b ;
629     TWarb_init() ;
630     for( pt = 0; pt <= 9; pt++ ){
631 	/* rel position is a macro which calculates */
632 	/* absolute pin loc - defined in relpos.h */
633 	REL_POS( (INT) cptr->corient,
634 	    xout, yout,                              /* result */
635 	    x[pt], y[pt],                        /* cell relative */
636 	    cptr->cxcenter, cptr->cycenter ) ;   /* cell center */
637 
638 	TWarb_addpt( xout, yout ) ;
639     }
640     TWdrawArb( 0, FCOLOR, NIL(char *) ) ;
641 } /* end draw_fs */
642 
erase_a_cell(cell,x,y)643 void erase_a_cell( cell, x, y )
644 INT cell ;
645 INT x, y ;
646 {
647     INT  i, j ;
648     INT  l, r, b, t ;
649     INT  block ;
650     INT  lobin, hibin ;
651     INT  *cells_in_bins ;
652     CBOXPTR cptr ;
653 
654     GRAPHICSABORT ;
655     if( !(binptrG) || !(single_cell_moveS) || !(updateS) ){
656 	/* won't work if binptr is not valid */
657 	return ;
658     }
659 
660     cptr = carrayG[cell] ;
661     l = x + cptr->tileptr->left ;
662     r = x + cptr->tileptr->right ;
663     b = y + cptr->tileptr->bottom ;
664     t = y + cptr->tileptr->top ;
665     TWdrawCell( cell, l,b,r,t, TWWHITE, NULL ) ;
666     /* now find the bins that it overlaps and redraw all the cells */
667     /* in these bins */
668     lobin = SetBin( l ) ;
669     hibin = SetBin( r ) ;
670     block = cptr->cblock ;
671     for( i = lobin; i <= hibin ; i++ ){
672 	cells_in_bins = binptrG[block][i]->cell ;
673 	for( j = 1 ; j <= *cells_in_bins ; j++ ) {
674 	    draw_a_cell( cells_in_bins[j] ) ;
675 	}
676     }
677 } /* end draw a cell */
678 
679 
680 /* dumps the data to a file for future study */
graphics_dump()681 void graphics_dump()
682 {
683     /* now change mode to dump to file */
684     TWsetMode(1) ;
685     /* dump the data to a file now instead of screen */
686     draw_the_data() ;
687     /* restore the state to previous condition and set draw to screen */
688     TWsetMode(0) ;
689 }
690 
691 /* see if uses wishes an interrupt otherwise just draw the data */
check_graphics(drawFlag)692 void check_graphics( drawFlag )
693 BOOL drawFlag ;
694 {
695     if( doGraphicsG ){
696 	if( TWinterupt() ){
697 	    process_graphics() ;
698 	} else if( drawFlag && updateS ){
699 	    setGraphicWindow() ;
700 	    draw_the_data() ;
701 	}
702     }
703 } /* end check_graphics */
704 
graphics_cell_update(cell)705 void graphics_cell_update( cell )
706 INT cell ;
707 {
708     GRAPHICSABORT ;
709     if( !(single_cell_moveS) || !(updateS) ){
710 	return ;
711     }
712     ASSERTNRETURN( cell > 0 && cell < heat_allocS, "graphics_cell_update",
713 	"cell out of bounds\n" ) ;
714     heat_indexS[cell]++ ;
715     heat_attemptS[cell]++ ;
716     draw_a_cell( cell ) ;
717 } /* end graphics_cell_update */
718 
graphics_cell_attempt(cell)719 void graphics_cell_attempt( cell )
720 INT cell ;
721 {
722     GRAPHICSABORT ;
723     ASSERTNRETURN( cell > 0 && cell < heat_allocS, "graphics_cell_update",
724 	"cell out of bounds\n" ) ;
725     heat_attemptS[cell]++ ;
726 } /* end graphics_cell_attempt */
727 
reset_heat_index()728 void reset_heat_index()
729 {
730     INT i ; /* counter */
731 
732     GRAPHICSABORT ;
733     for( i = 0; i < heat_allocS ; i++ ){
734 	heat_indexS[i] = 0 ;
735 	heat_attemptS[i] = 0 ;
736     }
737 } /* end reset_heat_index */
738 
set_update(flag)739 void set_update( flag )
740 BOOL flag ;
741 {
742     updateS = flag ;
743 } /* end set_update */
744 
745 #endif /* NOGRAPHICS */
746 
747 /* close graphics window on fault */
closegraphics()748 void closegraphics( )
749 {
750     if( doGraphicsG ){
751 	G( TWcloseGraphics() ) ;
752 	doGraphicsG = FALSE ;
753     }
754 } /* end closegraphics */
755