/* * This file is part of the Alliance CAD System * Copyright (C) Laboratoire LIP6 - Département ASIM * Universite Pierre et Marie Curie * * Home page : http://www-asim.lip6.fr/alliance/ * E-mail : mailto:alliance-users@asim.lip6.fr * * This progam is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * Alliance VLSI CAD System is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along * with the GNU C Library; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /****************************************************************************/ /* */ /* ALLIANCE CAO & VLSI CAD */ /* */ /* Product : (S)ymbolic (2)to (R)eal translater */ /* File : rdsacces+.c */ /* */ /* (c) copyright 1992 MASI laboratory CAO & VLSI team */ /* All Right Reserved */ /* Support : e-mail cao-vlsi@masi.ibp.fr */ /* */ /****************************************************************************/ /* */ /* Access functions to the rds database objects */ /* */ /****************************************************************************/ #include "generic.h" #include #include #include #include #include #include "rdsacces.h" #include "statistics.h" int s2rdebug = 0; rdsrec_list *Free_List = NULL; /* a global variable pointing to the free list of rectangles */ void view_rec (rec) rdsrec_list *rec; { viewrdsrec (rec); } /**************************************************************************** * rds_rectangle_in: adds the rectangle given by its data to the given list * and returns a pointer to the new list. * Before allocating memory for the new rectangle, the free * list is checked and if it is not empty : we use the memory * area pointed by the first element of this list. ****************************************************************************/ rdsrec_list *rds_rectangle_in (layer_list, x, y, dx, dy, layer_num, flags, name) rdsrec_list *layer_list; long x, y, dx, dy; int layer_num; long flags; char *name; { rdsrec_list *npr; STAT_RECT_REQRD++; if (Free_List) npr = pull_free_list (); else { npr = allocrdsrec (0); STAT_RECT_ALLOC++; } flags = flags & 0xFFFFFF00; npr->NEXT = layer_list; npr->X = x; npr->Y = y; npr->DX = dx; npr->DY = dy; npr->FLAGS = flags | (long) (layer_num); npr->NAME = name; return layer_list = npr; } /**************************************************************************** * rds_instance_in: adds the instance given by its data to the given list * and returns a pointer to the new list. ****************************************************************************/ rdsins_list *rds_instance_in (instance, model, name, x, y, sym) rdsins_list *instance; char *model, *name; long x, y; char sym; { rdsins_list *npr; int i; npr = allocrdsins (); npr->NEXT = instance; npr->FIGNAME = namealloc (model); npr->INSNAME = namealloc (name); npr->X = x; npr->Y = y; npr->TRANSF = sym; for (i = 0; i < RDS_MAX_LAYER; i++) npr->COURONNE[i] = NULL; return instance = npr; } /****************************************************************************** * rds_remove_model: removes the model with the specified name from the list * of models. ****************************************************************************/ void rds_remove_model (name) char *name; { rds_figurep_typ *modelp; name = namealloc (name); for (modelp = &(HEAD_RDSFIG); *modelp;) if ((*modelp)->NAME == name) *modelp = (*modelp)->NEXT; /***************************************************** *** return to system the free memory would be cue *** *****************************************************/ else modelp = &((*modelp)->NEXT); } /**************************************************************************** * rds_create_model: creates a new model with the given name and adds it to * the list of models pointed by HeadFigureRds and returns * a pointer to the created model. * Note: if the model exists it creates a new model and * remove the existing one. ****************************************************************************/ rdsfig_list *rds_create_model (name) char *name; { rdsfig_list *npr; rds_remove_model (name); npr = allocrdsfig (); npr->NEXT = HEAD_RDSFIG; npr->NAME = namealloc (name); npr->INSTANCE = NULL; return HEAD_RDSFIG = npr; } /****************************************************************************** * rds_model_out: given a model name it returns a pointer to it by inspecting * the model list pointed by HeadFigureRds. ****************************************************************************/ rdsfig_list *rds_model_out (name) char *name; { rdsfig_list *pt; name = namealloc (name); for (pt = HEAD_RDSFIG; pt; pt = pt->NEXT) if (pt->NAME == name) return pt; return NULL; } /***************************************************************************** * rds_instance_out: given an instance name and a pointer to its father model * it returns a poiner to the instance. ****************************************************************************/ rdsins_list *rds_instance_out (rds_model, name) rdsfig_list *rds_model; char *name; { rdsins_list *pt; name = namealloc (name); for (pt = rds_model->INSTANCE; pt; pt = pt->NEXT) if (pt->INSNAME == name) return pt; return NULL; } /***************************************************************************** * rds_mbk_kill: destroies mbk database. May take time ... *****************************************************************************/ void rds_mbk_kill () { phfig_list *pt, *pt_next; for (pt = HEAD_PHFIG; pt; pt = pt_next) { pt_next = pt->NEXT; delphfig (pt->NAME); } } /******************************************************************************* * mark_remove: marks the given rectangle as to be removed ******************************************************************************/ void mark_remove (rectangle) rdsrec_list *rectangle; { if (!(is_remove (rectangle))) rectangle->FLAGS += REMOVE; } /******************************************************************************* * demark_flattenres: removes the flag of the given rectangle ******************************************************************************/ void demark_flattenres (rectangle) rdsrec_list *rectangle; { if (is_flattenres (rectangle)) rectangle->FLAGS -= FLATTENRES; } /******************************************************************************* * mark_flattenres: marks the given rectangle as a result of a flatten operation ******************************************************************************/ void mark_flattenres (rectangle) rdsrec_list *rectangle; { if (!(is_flattenres (rectangle))) rectangle->FLAGS += FLATTENRES; } /******************************************************************************* * demark_used: removes the used flag ******************************************************************************/ void demark_used (rectangle) rdsrec_list *rectangle; { if (is_used (rectangle)) rectangle->FLAGS -= USED; } /******************************************************************************* * mark_used: marks the given rectangle as used ******************************************************************************/ void mark_used (rectangle) rdsrec_list *rectangle; { if (!(is_used (rectangle))) rectangle->FLAGS += USED; } /****************************************************************************** * mark_scotch: marks the given rectangle as a scotch. ******************************************************************************/ void mark_scotch (rectangle) rdsrec_list *rectangle; { if (!(is_scotch (rectangle))) { rectangle->FLAGS += SCOTCH; } } /****************************************************************************** * demark_scotch: removes the scotch flag from the rectangle. ******************************************************************************/ void demark_scotch (rectangle) rdsrec_list *rectangle; { if (is_scotch (rectangle)) rectangle->FLAGS -= SCOTCH; } /****************************************************************************** * mark_old_scotch: marks the given rectangle as an old scotch ******************************************************************************/ void mark_old_scotch (rectangle) rdsrec_list *rectangle; { if (!(is_old_scotch (rectangle))) rectangle->FLAGS += OLD_SCOTCH; } /***************************************************************************** * mark_empty: marks the given model at the specified layer as empty ****************************************************************************/ void mark_empty (model, layer_num) rdsfig_list *model; int layer_num; { if (!(is_empty (model, layer_num))) model->FLAGTAB[layer_num] += EMPTY; } /***************************************************************************** * mark_post: marks the given model at the specified layer as post_treated ****************************************************************************/ void mark_treat (model) rdsfig_list *model; { model->FLAGS = S2R_TREAT; } /******************************************************************************* * push_free_list: pushes the given pointer to a deleted rectangle into the free * list. ******************************************************************************/ void push_free_list (rectp) rdsrec_list *rectp; { rectp->NEXT = Free_List; Free_List = rectp; } /******************************************************************************* * pull_free_list: pulls from the free list - if not empty - a pointer to * a ( rectangle) memory space area not used anymore. ******************************************************************************/ rdsrec_list *pull_free_list () { rdsrec_list *temp; if (Free_List) { temp = Free_List; Free_List = Free_List->NEXT; temp->X = 0; temp->Y = 0; temp->DX = 0; temp->DY = 0; temp->NAME = NULL; temp->USER = (void *) NULL; temp->FLAGS = 0; return (temp); } else return (NULL); } /*************************************************************************** * rds_remove_rectangle: removes from the specified list at the specified * layer all the rectangles that are marked to be removed. * The removed rectangles are put in a free list, to minimize * memory consumption: if we need to allocate memory for a new * rectangle we check the free list first. ***************************************************************************/ void rds_remove_rectangle (list) rds_rectanglep_typ *list; { register rds_rectanglep_typ *rectanglep; register rdsrec_list *temp; for (rectanglep = list; *rectanglep;) { if (is_remove (*rectanglep)) { temp = (*rectanglep)->NEXT; push_free_list ((*rectanglep)); *rectanglep = temp; } else rectanglep = &((*rectanglep)->NEXT); } } /*************************************************************************** * rds_clean_layer: removes from the specified model at the specified layer * all the rectangles that have been flattened and were not used. * The removed rectangles are put in a free list, to minimize * memory consumption: if we need to allocate memory for a new * rectangle we check the free list first. ***************************************************************************/ void rds_clean_layer (list) rds_rectanglep_typ *list; { register rds_rectanglep_typ *rectanglep; register rdsrec_list *temp; for (rectanglep = list; *rectanglep;) { /* when a rectangle is issued from a subcell after a ring flattening if is to be erased if it was not used by merge */ if ((is_flattenres (*rectanglep)) && (!(is_used (*rectanglep)))) { /**** remove it ****/ temp = (*rectanglep)->NEXT; push_free_list ((*rectanglep)); *rectanglep = temp; } else { /**** just erase using flag and flattenres ****/ /**** the rectangle owns to the current hierararchical level ***/ demark_flattenres (*rectanglep); demark_used (*rectanglep); rectanglep = &((*rectanglep)->NEXT); } } } /***************************************************************************** * side_intersec: determines if 2 rectangles could intersect in the dimension * of the specified sides. * If yes it returns (1) and puts where and how long is the side * of their intersection in rs and rds respectively. * If not it returns (0). *****************************************************************************/ int side_intersec (s1, s2, ds1, ds2, rs, rds) long s1, s2, ds1, ds2, *rs, *rds; { if ((s2 >= s1) && (s2 <= (s1 + ds1))) { if ((s2 + ds2) >= (s1 + ds1)) { *rs = s2; *rds = s1 + ds1 - s2; } else { *rs = s2; *rds = ds2; } return (1); } if ((s2 <= s1) && ((s2 + ds2) >= s1)) { if ((s2 + ds2) >= (s1 + ds1)) { *rs = s1; *rds = ds1; } else { *rs = s1; *rds = s2 + ds2 - s1; } return (1); } return (0); } /***************************************************************************** * rect_intersec: determines if 2 rectangles intersect. * If yes it returns (1) and puts the data of the rectangle * of their intersection in rx, ry, rdx and rdy. * If not it returns (0). *****************************************************************************/ int rect_intersec (x1, x2, dx1, dx2, y1, y2, dy1, dy2, rx, rdx, ry, rdy) long x1, x2, dx1, dx2, y1, y2, dy1, dy2, *rx, *rdx, *ry, *rdy; { if (side_intersec (x1, x2, dx1, dx2, rx, rdx)) return (side_intersec (y1, y2, dy1, dy2, ry, rdy)); else return (0); } static chain_list *MODEL_CHAIN; static chain_list *rmake_model_list (pt_phfig) phfig_list *pt_phfig; { phins_list *pt_ins; chain_list *pt_chain; for (pt_ins = pt_phfig->PHINS; pt_ins != NULL; pt_ins = pt_ins->NEXT) { for (pt_chain = MODEL_CHAIN; pt_chain != NULL; pt_chain = pt_chain->NEXT) { if (((phfig_list *) pt_chain->DATA)->NAME == pt_ins->FIGNAME) { break; } } if (pt_chain == NULL) { /* if not already in model list , add a new model to it */ phfig_list *pt_model; pt_model = getphfig (pt_ins->FIGNAME, 'A'); /* cells whose have got gds equivalent must have been shifted to zero */ if (incataloggds (pt_model->NAME)) zero (pt_model); (void) rmake_model_list (pt_model); } } MODEL_CHAIN = addchain (MODEL_CHAIN, (char *) pt_phfig); return (MODEL_CHAIN); } static chain_list *make_model_list (fig) phfig_list *fig; { if (MODEL_CHAIN != NULL) freechain (MODEL_CHAIN); MODEL_CHAIN = NULL; return rmake_model_list (fig); } /*------------------------------------------------------\ | Transform a hierarchy Mbk -> Rds | \------------------------------------------------------*/ rdsfig_list *S2Rfigmbkrds (FigureMbk, All,SubConn) phfig_list *FigureMbk; char All; char SubConn; { rdsfig_list *FigureRds; chain_list *Pt; /* dupplique tous les CALUx en ALUx dans le père pour permettre l'unification des pastilles de metal de VIA et des ALU associés */ { phseg_list * phseg; for (phseg = FigureMbk->PHSEG; phseg; phseg=phseg->NEXT) { phseg_list * dupseg = addphseg(FigureMbk, phseg->LAYER, phseg->WIDTH, phseg->X1, phseg->Y1, phseg->X2, phseg->Y2, phseg->NAME); switch (phseg->LAYER) { case CALU1 : dupseg->LAYER = ALU1; break; case CALU2 : dupseg->LAYER = ALU2; break; case CALU3 : dupseg->LAYER = ALU3; break; case CALU4 : dupseg->LAYER = ALU4; break; case CALU5 : dupseg->LAYER = ALU5; break; case CALU6 : dupseg->LAYER = ALU6; break; case CALU7 : dupseg->LAYER = ALU7; break; case CALU8 : dupseg->LAYER = ALU8; break; case CALU9 : dupseg->LAYER = ALU9; break; } dupseg->NAME = NULL; } } if (All) { Pt = make_model_list (FigureMbk); if (s2rdebug) { chain_list *pc = Pt; fprintf (stderr, "MODELS :\n"); for (; pc; pc = pc->NEXT) { fprintf (stderr, " %s\t", ((phfig_list *) (pc->DATA))->NAME); if ((((phfig_list *) (pc->DATA))->PHINS) == NULL) fprintf (stderr, "FEUILLE"); fprintf (stderr, "\n"); } } FigureRds = figmbkrds ((phfig_list *) Pt->DATA, 0, 0); for (Pt = Pt->NEXT; Pt != NULL; Pt = Pt->NEXT) { if (SubConn == 0) /* puisqu'on ne veut pas de connecteurs intermediaires, on remplace les CALU par les ALU associés FW 200205 */ { phseg_list * phseg; for (phseg = ((phfig_list *) Pt->DATA)->PHSEG; phseg; phseg=phseg->NEXT) { switch (phseg->LAYER) { case CALU1 : phseg->LAYER = ALU1; break; case CALU2 : phseg->LAYER = ALU2; break; case CALU3 : phseg->LAYER = ALU3; break; case CALU4 : phseg->LAYER = ALU4; break; case CALU5 : phseg->LAYER = ALU5; break; case CALU6 : phseg->LAYER = ALU6; break; case CALU7 : phseg->LAYER = ALU7; break; case CALU8 : phseg->LAYER = ALU8; break; case CALU9 : phseg->LAYER = ALU9; break; } } } else /* sinon on le duplique dans le metal associé pour qu'il absorbe les vias inclus lors que la phase d'unification */ { phseg_list * phseg; for (phseg = ((phfig_list *) Pt->DATA)->PHSEG; phseg; phseg=phseg->NEXT) { phseg_list * dupseg = addphseg((phfig_list *) Pt->DATA, phseg->LAYER, phseg->WIDTH, phseg->X1, phseg->Y1, phseg->X2, phseg->Y2, phseg->NAME); switch (phseg->LAYER) { case CALU1 : dupseg->LAYER = ALU1; break; case CALU2 : dupseg->LAYER = ALU2; break; case CALU3 : dupseg->LAYER = ALU3; break; case CALU4 : dupseg->LAYER = ALU4; break; case CALU5 : dupseg->LAYER = ALU5; break; case CALU6 : dupseg->LAYER = ALU6; break; case CALU7 : dupseg->LAYER = ALU7; break; case CALU8 : dupseg->LAYER = ALU8; break; case CALU9 : dupseg->LAYER = ALU9; break; } dupseg->NAME = NULL; } } figmbkrds ((phfig_list *) Pt->DATA, 0, 0); } } else { FigureRds = figmbkrds (FigureMbk, 0, 0); for (Pt = FigureMbk->MODELCHAIN; Pt != NULL; Pt = Pt->NEXT) figmbkrds (getphfig ((char *) Pt->DATA, 'P'), 0, 0); } return FigureRds; } void zero (phfig) phfig_list *phfig; { long x, y; phins_list *phins; phcon_list *phcon; phseg_list *phseg; phvia_list *phvia; phref_list *phref; x = phfig->XAB1; y = phfig->YAB1; phfig->XAB1 = phfig->YAB1 = 0; phfig->XAB2 -= x; phfig->YAB2 -= y; for (phins = phfig->PHINS; phins != NULL; phins = phins->NEXT) { phins->XINS -= x; phins->YINS -= y; } for (phcon = phfig->PHCON; phcon != NULL; phcon = phcon->NEXT) { phcon->XCON -= x; phcon->YCON -= y; } for (phseg = phfig->PHSEG; phseg != NULL; phseg = phseg->NEXT) { phseg->X1 -= x; phseg->Y1 -= y; phseg->X2 -= x; phseg->Y2 -= y; } for (phvia = phfig->PHVIA; phvia != NULL; phvia = phvia->NEXT) { phvia->XVIA -= x; phvia->YVIA -= y; } for (phref = phfig->PHREF; phref != NULL; phref = phref->NEXT) { phref->XREF -= x; phref->YREF -= y; } }