/***********************************/ /* Module de calcul de la Netliste */ /***********************************/ #include "fctsys.h" #include "gr_basic.h" #include "common.h" #include "program.h" #include "libcmp.h" #include "general.h" #include "netlist.h" /* Definitions generales liees au calcul de netliste */ #include "protos.h" /* Routines locales */ static void PropageNetCode( int OldNetCode, int NewNetCode, int IsBus ); static void SheetLabelConnection(ObjetNetListStruct *SheetLabel); static int ListeObjetConnection(WinEDA_SchematicFrame * frame, SCH_SCREEN *screen, ObjetNetListStruct *ObjNet); static int ConvertBusToMembers(ObjetNetListStruct *ObjNet); static void PointToPointConnect(ObjetNetListStruct *RefObj, int IsBus, int start); static void SegmentToPointConnect(ObjetNetListStruct *Jonction, int IsBus, int start); static void LabelConnection(ObjetNetListStruct *Label); static int TriNetCode(ObjetNetListStruct *Objet1, ObjetNetListStruct *Objet2); static void ConnectBusLabels( ObjetNetListStruct *Label, int NbItems ); static void SetUnconnectedFlag( ObjetNetListStruct *ObjNet, int NbItems ); static int TriBySheet(ObjetNetListStruct *Objet1, ObjetNetListStruct *Objet2); /* Variable locales */ static int FirstNumWireBus, LastNumWireBus, RootBusNameLength; static int LastNetCode, LastBusNetCode; static int s_PassNumber; /***********************************************************************/ void FreeTabNetList(ObjetNetListStruct * TabNetItems, int NbrNetItems) /***********************************************************************/ /* Routine de liberation memoire des tableaux utilises pour le calcul de la netliste TabNetItems = pointeur sur le tableau principal (liste des items ) NbrNetItems = nombre d'elements */ { int i; /* Liberation memoire des strings du champ Label reserve par ConvertBusToMembers */ for (i = 0; i < NbrNetItems; i++) { switch( TabNetItems[i].m_Type ) { case NET_PIN: case NET_SHEETLABEL: case NET_SEGMENT: case NET_JONCTION: case NET_BUS: case NET_LABEL: case NET_GLOBLABEL: case NET_PINLABEL: case NET_NOCONNECT: break; case NET_GLOBBUSLABELMEMBER: case NET_SHEETBUSLABELMEMBER: case NET_BUSLABELMEMBER: delete TabNetItems[i].m_Label; break; } } MyFree(TabNetItems); } /*****************************************************/ void * WinEDA_SchematicFrame::BuildNetListBase(void) /*****************************************************/ /* Routine qui construit le tableau des elements connectes du projet met a jour: g_TabObjNet g_NbrObjNet */ { int NetNumber, SheetNumber; int i, istart, NetCode; SCH_SCREEN * screen; ObjetNetListStruct * BaseTabObjNet; wxString msg; wxBusyCursor Busy; NetNumber = 1; s_PassNumber = 0; MsgPanel->EraseMsgBox(); Affiche_1_Parametre(this, 1,_("List"), wxEmptyString, LIGHTRED); /* Build the screen list */ EDA_ScreenList ScreenList(NULL); /* 1ere passe : Comptage du nombre d'objet de Net */ g_NbrObjNet = 0; g_TabObjNet = NULL; /* Init pour le 1er passage dans ListeObjetConnection */ /* Update the sheet number, sheet count and date and count nelist items */ ScreenSch->SetModify(); int kk = 1; for ( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() ) { screen->m_SheetNumber = kk++; screen->m_NumberOfSheet = ScreenList.GetCount(); screen->m_Date = GenDate(); g_NbrObjNet += ListeObjetConnection(this, screen, NULL); } if( g_NbrObjNet == 0 ) { DisplayError(this, _("No component"), 20); return(NULL); } i = sizeof(ObjetNetListStruct) * g_NbrObjNet; BaseTabObjNet = g_TabObjNet = (ObjetNetListStruct *) MyZMalloc(i); if( BaseTabObjNet == NULL ) return(NULL); /* 2eme passe : Remplissage des champs des structures des objets de Net */ s_PassNumber ++; Affiche_1_Parametre(this, 1,_("List"), wxEmptyString,RED); for ( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() ) { g_TabObjNet += ListeObjetConnection(this, screen, g_TabObjNet ); } Affiche_1_Parametre(this, -1, wxEmptyString,_("Done"),RED); msg.Printf( wxT("%d"), g_NbrObjNet); Affiche_1_Parametre(this, 8, _("NbItems"),msg,GREEN); /* Recherche des connections pour les Segments et les Pins */ /* Tri du Tableau des objets de Net par Sheet */ qsort(BaseTabObjNet, g_NbrObjNet, sizeof(ObjetNetListStruct), (int (*)(const void *, const void *)) TriBySheet); Affiche_1_Parametre(this, 18,_("Conn"), wxEmptyString,CYAN); g_TabObjNet = BaseTabObjNet; SheetNumber = g_TabObjNet[0].m_SheetNumber; LastNetCode = LastBusNetCode = 1; for (i = istart = 0; i < g_NbrObjNet; i++) { if(g_TabObjNet[i].m_SheetNumber != SheetNumber ) { SheetNumber = g_TabObjNet[i].m_SheetNumber; istart = i; } switch( g_TabObjNet[i].m_Type ) { case NET_PIN: case NET_PINLABEL: case NET_SHEETLABEL: case NET_NOCONNECT: if ( g_TabObjNet[i].m_NetCode != 0 ) break; /* Deja connecte */ case NET_SEGMENT: /* Controle des connexions type point a point ( Sans BUS ) */ if( g_TabObjNet[i].m_NetCode == 0 ) { g_TabObjNet[i].m_NetCode = LastNetCode; LastNetCode++; } PointToPointConnect(g_TabObjNet+i, 0, istart); break; case NET_JONCTION: /* Controle des jonction , hors BUS */ if( g_TabObjNet[i].m_NetCode == 0 ) { g_TabObjNet[i].m_NetCode = LastNetCode; LastNetCode++; } SegmentToPointConnect( g_TabObjNet+i, 0, istart); /* Controle des jonction , sur BUS */ if( g_TabObjNet[i].m_BusNetCode == 0 ) { g_TabObjNet[i].m_BusNetCode = LastBusNetCode; LastBusNetCode++; } SegmentToPointConnect( g_TabObjNet+i, ISBUS, istart ); break; case NET_LABEL: case NET_GLOBLABEL: /* Controle des connexions type jonction ( Sans BUS ) */ if( g_TabObjNet[i].m_NetCode == 0 ) { g_TabObjNet[i].m_NetCode = LastNetCode; LastNetCode++; } SegmentToPointConnect( g_TabObjNet+i, 0, istart ); break; case NET_SHEETBUSLABELMEMBER: if ( g_TabObjNet[i].m_BusNetCode != 0 ) break; /* Deja connecte */ case NET_BUS: /* Controle des connexions type point a point mode BUS */ if( g_TabObjNet[i].m_BusNetCode == 0 ) { g_TabObjNet[i].m_BusNetCode = LastBusNetCode; LastBusNetCode++; } PointToPointConnect(g_TabObjNet+i, ISBUS, istart); break; case NET_BUSLABELMEMBER: case NET_GLOBBUSLABELMEMBER: /* Controle des connexions semblables a des sur BUS */ if( g_TabObjNet[i].m_NetCode == 0 ) { g_TabObjNet[i].m_BusNetCode = LastBusNetCode; LastBusNetCode++; } SegmentToPointConnect( g_TabObjNet+i, ISBUS, istart); break; } } Affiche_1_Parametre(this, -1, wxEmptyString,_("Done"),CYAN); /* Mise a jour des NetCodes des Bus Labels connectes par les Bus */ ConnectBusLabels( g_TabObjNet, g_NbrObjNet); Affiche_1_Parametre(this, 26,_("Labels"), wxEmptyString,CYAN); /* Connections des groupes d'objets par labels identiques */ for (i = 0; i < g_NbrObjNet; i++) { switch( g_TabObjNet[i].m_Type ) { case NET_PIN: case NET_SHEETLABEL: case NET_SEGMENT: case NET_JONCTION: case NET_BUS: case NET_NOCONNECT: break; case NET_LABEL: case NET_GLOBLABEL: case NET_PINLABEL: case NET_BUSLABELMEMBER: case NET_GLOBBUSLABELMEMBER: LabelConnection( g_TabObjNet+i ); break; case NET_SHEETBUSLABELMEMBER: break; } } Affiche_1_Parametre(this, -1, wxEmptyString,_("Done"),CYAN); /* Connexion des hierarchies */ Affiche_1_Parametre(this, 36,_("Hierar."), wxEmptyString,LIGHTRED); for (i = 0; i < g_NbrObjNet; i++) { if( (g_TabObjNet[i].m_Type == NET_SHEETLABEL ) || ( g_TabObjNet[i].m_Type == NET_SHEETBUSLABELMEMBER ) ) SheetLabelConnection(g_TabObjNet + i); } /* Tri du Tableau des objets de Net par NetCode */ qsort(g_TabObjNet, g_NbrObjNet, sizeof(ObjetNetListStruct), (int (*)(const void *, const void *)) TriNetCode); Affiche_1_Parametre(this, -1, wxEmptyString,_("Done"),RED); /* Compression des numeros de NetCode a des valeurs consecutives */ Affiche_1_Parametre(this, 46,_("Sorting"), wxEmptyString,GREEN); LastNetCode = NetCode = 0; for (i = 0; i < g_NbrObjNet; i++) { if(g_TabObjNet[i].m_NetCode != LastNetCode) { NetCode++; LastNetCode = g_TabObjNet[i].m_NetCode; } g_TabObjNet[i].m_NetCode = NetCode; } Affiche_1_Parametre(this, -1, wxEmptyString,_("Done"),GREEN); /* Affectation du m_FlagOfConnection en fonction de connection ou non */ SetUnconnectedFlag( BaseTabObjNet, g_NbrObjNet); return( (void*) BaseTabObjNet); } /************************************************************* * Routine qui connecte les sous feuilles par les sheetLabels * **************************************************************/ static void SheetLabelConnection(ObjetNetListStruct *SheetLabel) { int i; ObjetNetListStruct *ObjetNet; if( SheetLabel->m_NetCode == 0 ) return; /* Calcul du numero de sous feuille correspondante au sheetlabel */ /* Comparaison du SheetLabel avec les GLABELS de la sous feuille pour regroupement des NetCodes */ for (i = 0, ObjetNet = g_TabObjNet; i < g_NbrObjNet; i++) { if( ObjetNet[i].m_SheetNumber != SheetLabel->m_NumInclude ) continue; if( (ObjetNet[i].m_Type != NET_GLOBLABEL ) && (ObjetNet[i].m_Type != NET_GLOBBUSLABELMEMBER ) ) continue; if( ObjetNet[i].m_NetCode == SheetLabel->m_NetCode ) continue; if( ObjetNet[i].m_Label->CmpNoCase(*SheetLabel->m_Label) != 0) continue; /* Propagation du Netcode a tous les Objets de meme NetCode */ if( ObjetNet[i].m_NetCode ) PropageNetCode(ObjetNet[i].m_NetCode, SheetLabel->m_NetCode, 0); else ObjetNet[i].m_NetCode = SheetLabel->m_NetCode; } } /*****************************************************************************/ static int ListeObjetConnection(WinEDA_SchematicFrame * frame, SCH_SCREEN *screen, ObjetNetListStruct *ObjNet) /*****************************************************************************/ /* Routine generant la liste des objets relatifs aux connection entree: screen: pointeur sur l'ecran a traiter ObjNet: si NULL: la routine compte seulement le nombre des objets sinon: pointe le tableau a remplir */ { int ii, NbrItem = 0, NumSheet; EDA_BaseStruct *DrawList; EDA_SchComponentStruct *DrawLibItem; int TransMat[2][2], PartX, PartY, x2, y2; EDA_LibComponentStruct *Entry; LibEDA_BaseStruct *DEntry; DrawSheetLabelStruct *SheetLabel; int NumInclude; NumSheet = screen->m_SheetNumber; DrawList = screen->EEDrawList; while ( DrawList ) { switch( DrawList->m_StructType ) { case DRAW_SEGMENT_STRUCT_TYPE : #undef STRUCT #define STRUCT ((EDA_DrawLineStruct *) DrawList) if( ObjNet) { if ( (STRUCT->m_Layer != LAYER_BUS) && (STRUCT->m_Layer != LAYER_WIRE) ) break; ObjNet[NbrItem].m_Comp = STRUCT; ObjNet[NbrItem].m_Screen = screen; ObjNet[NbrItem].m_SheetNumber = NumSheet; ObjNet[NbrItem].m_Start = STRUCT->m_Start; ObjNet[NbrItem].m_End = STRUCT->m_End; if (STRUCT->m_Layer == LAYER_BUS) { ObjNet[NbrItem].m_Type = NET_BUS; } else /* Cas des WIRE */ { ObjNet[NbrItem].m_Type = NET_SEGMENT; } } NbrItem++; break; case DRAW_JUNCTION_STRUCT_TYPE : #undef STRUCT #define STRUCT ((DrawJunctionStruct *) DrawList) if( ObjNet) { ObjNet[NbrItem].m_Comp = STRUCT; ObjNet[NbrItem].m_Screen = screen; ObjNet[NbrItem].m_Type = NET_JONCTION; ObjNet[NbrItem].m_SheetNumber = NumSheet; ObjNet[NbrItem].m_Start = STRUCT->m_Pos; ObjNet[NbrItem].m_End = ObjNet[NbrItem].m_Start; } NbrItem++; break; case DRAW_NOCONNECT_STRUCT_TYPE : #undef STRUCT #define STRUCT ((DrawNoConnectStruct *) DrawList) if( ObjNet) { ObjNet[NbrItem].m_Comp = STRUCT; ObjNet[NbrItem].m_Screen = screen; ObjNet[NbrItem].m_Type = NET_NOCONNECT; ObjNet[NbrItem].m_SheetNumber = NumSheet; ObjNet[NbrItem].m_Start = STRUCT->m_Pos; ObjNet[NbrItem].m_End = ObjNet[NbrItem].m_Start; } NbrItem++; break; case DRAW_LABEL_STRUCT_TYPE : #undef STRUCT #define STRUCT ((DrawLabelStruct *) DrawList) ii = IsBusLabel( STRUCT->m_Text); if( ObjNet) { ObjNet[NbrItem].m_Comp = STRUCT; ObjNet[NbrItem].m_Screen = screen; ObjNet[NbrItem].m_Type = NET_LABEL; if (STRUCT->m_Layer == LAYER_GLOBLABEL) ObjNet[NbrItem].m_Type = NET_GLOBLABEL; ObjNet[NbrItem].m_Label = & STRUCT->m_Text; ObjNet[NbrItem].m_SheetNumber = NumSheet; ObjNet[NbrItem].m_Start = STRUCT->m_Pos; ObjNet[NbrItem].m_End = ObjNet[NbrItem].m_Start; /* Si c'est un Bus, eclatement en Label */ if ( ii ) ConvertBusToMembers(ObjNet + NbrItem); } NbrItem += ii+1; break; case DRAW_GLOBAL_LABEL_STRUCT_TYPE : #undef STRUCT #define STRUCT ((DrawGlobalLabelStruct *) DrawList) ii = IsBusLabel( STRUCT->m_Text); if( ObjNet) { ObjNet[NbrItem].m_Comp = STRUCT; ObjNet[NbrItem].m_Screen = screen; ObjNet[NbrItem].m_Type = NET_LABEL; if (STRUCT->m_Layer == LAYER_GLOBLABEL) ObjNet[NbrItem].m_Type = NET_GLOBLABEL; ObjNet[NbrItem].m_Label = & STRUCT->m_Text; ObjNet[NbrItem].m_SheetNumber = NumSheet; ObjNet[NbrItem].m_Start = STRUCT->m_Pos; ObjNet[NbrItem].m_End = ObjNet[NbrItem].m_Start; /* Si c'est un Bus, eclatement en Label */ if ( ii ) ConvertBusToMembers(ObjNet + NbrItem); } NbrItem += ii+1; break; case DRAW_LIB_ITEM_STRUCT_TYPE : DrawLibItem = (EDA_SchComponentStruct *) DrawList; memcpy(TransMat, DrawLibItem->m_Transform, sizeof(TransMat)); PartX = DrawLibItem->m_Pos.x; PartY = DrawLibItem->m_Pos.y; Entry = FindLibPart(DrawLibItem->m_ChipName, wxEmptyString, FIND_ROOT); if( Entry == NULL) break; if(Entry->m_Drawings == NULL) break ; DEntry = Entry->m_Drawings; for ( ;DEntry != NULL; DEntry = DEntry->Next()) { LibDrawPin * Pin = (LibDrawPin *) DEntry; if( DEntry->m_StructType != COMPONENT_PIN_DRAW_TYPE) continue; if( DEntry->m_Unit && (DEntry->m_Unit != DrawLibItem->m_Multi) ) continue; if( DEntry->m_Convert && (DEntry->m_Convert != DrawLibItem->m_Convert)) continue; x2 = PartX + TransMat[0][0] * Pin->m_Pos.x + TransMat[0][1] * Pin->m_Pos.y; y2 = PartY + TransMat[1][0] * Pin->m_Pos.x + TransMat[1][1] * Pin->m_Pos.y; if( ObjNet) { ObjNet[NbrItem].m_Comp = DEntry; ObjNet[NbrItem].m_Type = NET_PIN; ObjNet[NbrItem].m_Link = DrawLibItem; ObjNet[NbrItem].m_Screen = screen; ObjNet[NbrItem].m_ElectricalType = Pin->m_PinType; ObjNet[NbrItem].m_PinNum = Pin->m_PinNum; ObjNet[NbrItem].m_Label = & Pin->m_PinName; ObjNet[NbrItem].m_SheetNumber = NumSheet; ObjNet[NbrItem].m_Start.x = x2; ObjNet[NbrItem].m_Start.y = y2; ObjNet[NbrItem].m_End = ObjNet[NbrItem].m_Start; } NbrItem++; if( ( (int) Pin->m_PinType == (int) PIN_POWER_IN ) && ( Pin->m_Attributs & PINNOTDRAW ) ) { /* Il y a un PIN_LABEL Associe */ if( ObjNet) { ObjNet[NbrItem].m_Comp = NULL; ObjNet[NbrItem].m_Type = NET_PINLABEL; ObjNet[NbrItem].m_Screen = screen; ObjNet[NbrItem].m_SheetNumber = NumSheet; ObjNet[NbrItem].m_Label = & Pin->m_PinName; ObjNet[NbrItem].m_Start.x = x2; ObjNet[NbrItem].m_Start.y = y2; ObjNet[NbrItem].m_End = ObjNet[NbrItem].m_Start; } NbrItem++; } } break; case DRAW_PICK_ITEM_STRUCT_TYPE : case DRAW_POLYLINE_STRUCT_TYPE : case DRAW_BUSENTRY_STRUCT_TYPE : case DRAW_MARKER_STRUCT_TYPE : case DRAW_TEXT_STRUCT_TYPE : break; case DRAW_SHEET_STRUCT_TYPE : #undef STRUCT #define STRUCT ((DrawSheetStruct *) DrawList) NumInclude = STRUCT->m_SheetNumber; SheetLabel = STRUCT->m_Label; for ( ; SheetLabel != NULL; SheetLabel = (DrawSheetLabelStruct*) SheetLabel->Pnext) { ii = IsBusLabel(SheetLabel->m_Text); if( ObjNet) { ObjNet[NbrItem].m_Comp = SheetLabel; ObjNet[NbrItem].m_Link = DrawList; ObjNet[NbrItem].m_Type = NET_SHEETLABEL; ObjNet[NbrItem].m_Screen = screen; ObjNet[NbrItem].m_ElectricalType = SheetLabel->m_Shape; ObjNet[NbrItem].m_Label = & SheetLabel->m_Text; ObjNet[NbrItem].m_SheetNumber = NumSheet; ObjNet[NbrItem].m_NumInclude = NumInclude; ObjNet[NbrItem].m_Start = SheetLabel->m_Pos; ObjNet[NbrItem].m_End = ObjNet[NbrItem].m_Start; /* Si c'est un Bus, eclatement en Label */ if ( ii ) ConvertBusToMembers(ObjNet + NbrItem); } NbrItem += ii+1; } break; case DRAW_SHEETLABEL_STRUCT_TYPE : DisplayError(frame, wxT("Netlist: Type DRAW_SHEETLABEL inattendu")); break; default: { wxString msg; msg.Printf( wxT("Netlist: unexpected type struct %d"), DrawList->m_StructType); DisplayError(frame, msg); break; } } DrawList = DrawList->Pnext; } return(NbrItem); } /************************************************************************/ static void ConnectBusLabels( ObjetNetListStruct *Label, int NbItems ) /************************************************************************/ /* Routine qui analyse les labels type xxBUSLABELMEMBER Propage les Netcodes entre labels correspondants ( c'est a dire lorsque leur numero de membre est identique) lorsqu'ils sont connectes globalement par leur BusNetCode Utilise et met a jour la variable LastNetCode */ { ObjetNetListStruct *LabelInTst, *Lim; Lim = Label + NbItems; for ( ; Label < Lim; Label++) { if( (Label->m_Type == NET_SHEETBUSLABELMEMBER) || (Label->m_Type == NET_BUSLABELMEMBER) || (Label->m_Type == NET_GLOBBUSLABELMEMBER) ) { if( Label->m_NetCode == 0 ) { Label->m_NetCode = LastNetCode; LastNetCode++; } for ( LabelInTst = Label+1; LabelInTst < Lim; LabelInTst++) { if( (LabelInTst->m_Type == NET_SHEETBUSLABELMEMBER) || (LabelInTst->m_Type == NET_BUSLABELMEMBER) || (LabelInTst->m_Type == NET_GLOBBUSLABELMEMBER) ) { if( LabelInTst->m_BusNetCode != Label->m_BusNetCode ) continue; if( LabelInTst->m_Member != Label->m_Member ) continue; if( LabelInTst->m_NetCode == 0 ) LabelInTst->m_NetCode = Label->m_NetCode; else PropageNetCode( LabelInTst->m_NetCode, Label->m_NetCode,0); } } } } } /**************************************************/ int IsBusLabel( const wxString & LabelDrawList ) /**************************************************/ /* Routine qui verifie si le Label a une notation de type Bus Retourne 0 si non nombre de membres si oui met a jour FirstNumWireBus, LastNumWireBus et RootBusNameLength */ { unsigned Num; int ii; wxString BufLine; long tmp; bool error = FALSE; /* Search for '[' because a bus label is like "busname[nn..mm]" */ ii = LabelDrawList.Find('['); if ( ii < 0 ) return(0); Num = (unsigned) ii; FirstNumWireBus = LastNumWireBus = 9; RootBusNameLength = Num; Num++; while ( LabelDrawList[Num] != '.' && Num < LabelDrawList.Len()) { BufLine.Append(LabelDrawList[Num]); Num++; } if ( ! BufLine.ToLong(&tmp) ) error = TRUE;; FirstNumWireBus = tmp; while ( LabelDrawList[Num] == '.' && Num < LabelDrawList.Len() ) Num++; BufLine.Empty(); while ( LabelDrawList[Num] != ']' && Num < LabelDrawList.Len()) { BufLine.Append(LabelDrawList[Num]); Num++; } if ( ! BufLine.ToLong(&tmp) ) error = TRUE;; LastNumWireBus = tmp; if( FirstNumWireBus < 0 ) FirstNumWireBus = 0; if( LastNumWireBus < 0 ) LastNumWireBus = 0; if( FirstNumWireBus > LastNumWireBus ) { EXCHG( FirstNumWireBus, LastNumWireBus); } if ( error && (s_PassNumber == 0) ) { wxString msg = _("Bad Bus Label: ") + LabelDrawList; DisplayError(NULL, msg); } return(LastNumWireBus - FirstNumWireBus + 1 ); } /***************************************************************/ static int ConvertBusToMembers(ObjetNetListStruct * BusLabel) /***************************************************************/ /* Routine qui eclate un label type Bus en autant de Label qu'il contient de membres, et qui cree les structures avec le type NET_GLOBBUSLABELMEMBER, NET_BUSLABELMEMBER ou NET_SHEETBUSLABELMEMBER entree = pointeur sur l'ObjetNetListStruct initialise corresp au buslabel suppose que FirstNumWireBus, LastNumWireBus et RootBusNameLength sont a jour modifie l'ObjetNetListStruct de base et remplit les suivants m_Label is a pointer to a new wxString m_Label must be deallocated by the user (only for a NET_GLOBBUSLABELMEMBER, NET_BUSLABELMEMBER or a NET_SHEETBUSLABELMEMBER object type) */ { int NumItem, BusMember; wxString BufLine; if( BusLabel->m_Type == NET_GLOBLABEL ) BusLabel->m_Type = NET_GLOBBUSLABELMEMBER; else if (BusLabel->m_Type == NET_SHEETLABEL) BusLabel->m_Type = NET_SHEETBUSLABELMEMBER; else BusLabel->m_Type = NET_BUSLABELMEMBER; /* Convertion du BusLabel en la racine du Label + le numero du fil */ BufLine = BusLabel->m_Label->Left(RootBusNameLength); BusMember = FirstNumWireBus; BufLine << BusMember; BusLabel->m_Label = new wxString(BufLine); BusLabel->m_Member = BusMember; NumItem = 1; for ( BusMember++; BusMember <= LastNumWireBus; BusMember++) { *(BusLabel+1) = *BusLabel; BusLabel ++; NumItem++; /* Convertion du BusLabel en la racine du Label + le numero du fil */ BufLine = BusLabel->m_Label->Left(RootBusNameLength); BufLine << BusMember; BusLabel->m_Label = new wxString(BufLine); BusLabel->m_Member = BusMember; } return( NumItem); } /**********************************************************************/ static void PropageNetCode( int OldNetCode, int NewNetCode, int IsBus ) /**********************************************************************/ /* PropageNetCode propage le netcode NewNetCode sur tous les elements appartenant a l'ancien netcode OldNetCode Si IsBus == 0; c'est le membre NetCode qui est propage Si IsBus != 0; c'est le membre BusNetCode qui est propage */ { int jj; ObjetNetListStruct * Objet = g_TabObjNet; if( OldNetCode == NewNetCode ) return; if( IsBus == 0 ) /* Propagation du NetCode */ { for (jj = 0; jj < g_NbrObjNet; jj++, Objet++) { if ( Objet->m_NetCode == OldNetCode ) { Objet->m_NetCode = NewNetCode; } } } else /* Propagation du BusNetCode */ { for (jj = 0; jj < g_NbrObjNet; jj++, Objet++) { if ( Objet->m_BusNetCode == OldNetCode ) { Objet->m_BusNetCode = NewNetCode; } } } } /***************************************************************************/ static void PointToPointConnect(ObjetNetListStruct *Ref, int IsBus, int start) /***************************************************************************/ /* Routine qui verifie si l'element *Ref est connecte a d'autres elements de la liste des objets du schema, selon le mode Point a point ( Extremites superposees ) si IsBus: la connexion ne met en jeu que des elements type bus ( BUS ou BUSLABEL ou JONCTION ) sinon la connexion ne met en jeu que des elements type non bus ( autres que BUS ou BUSLABEL ) L'objet Ref doit avoir un NetCode valide. La liste des objets est supposee classe par NumSheet Croissants, et la recherche se fait a partir de l'element start, 1er element de la feuille de schema ( il ne peut y avoir connexion physique entre elements de differentes sheets) */ { int i, NetCode; ObjetNetListStruct *Point = g_TabObjNet; if ( IsBus == 0 ) /* Objets autres que BUS et BUSLABELS */ { NetCode = Ref->m_NetCode; for (i = start; i < g_NbrObjNet; i++) { if( Point[i].m_SheetNumber > Ref->m_SheetNumber ) break; switch( Point[i].m_Type ) { case NET_SEGMENT: case NET_PIN: case NET_LABEL: case NET_GLOBLABEL: case NET_SHEETLABEL: case NET_PINLABEL: case NET_JONCTION: case NET_NOCONNECT: if( (((Ref->m_Start.x == Point[i].m_Start.x) && (Ref->m_Start.y == Point[i].m_Start.y))) || (((Ref->m_Start.x == Point[i].m_End.x) && (Ref->m_Start.y == Point[i].m_End.y))) || (((Ref->m_End.x == Point[i].m_Start.x) && (Ref->m_End.y == Point[i].m_Start.y))) || (((Ref->m_End.x == Point[i].m_End.x) && (Ref->m_End.y == Point[i].m_End.y))) ) { if( Point[i].m_NetCode == 0 ) Point[i].m_NetCode = NetCode; else PropageNetCode( Point[i].m_NetCode, NetCode , 0); } break; case NET_BUS: case NET_BUSLABELMEMBER: case NET_SHEETBUSLABELMEMBER: case NET_GLOBBUSLABELMEMBER: break; } } } else /* Objets type BUS et BUSLABELS ( et JONCTIONS )*/ { NetCode = Ref->m_BusNetCode; for (i = start; i < g_NbrObjNet; i++) { if( Point[i].m_SheetNumber > Ref->m_SheetNumber ) break; switch( Point[i].m_Type ) { case NET_SEGMENT: case NET_PIN: case NET_LABEL: case NET_GLOBLABEL: case NET_SHEETLABEL: case NET_PINLABEL: case NET_NOCONNECT: break; case NET_BUS: case NET_BUSLABELMEMBER: case NET_SHEETBUSLABELMEMBER: case NET_GLOBBUSLABELMEMBER: case NET_JONCTION: if( (((Ref->m_Start.x == Point[i].m_Start.x) && (Ref->m_Start.y == Point[i].m_Start.y))) || (((Ref->m_Start.x == Point[i].m_End.x) && (Ref->m_Start.y == Point[i].m_End.y))) || (((Ref->m_End.x == Point[i].m_Start.x) && (Ref->m_End.y == Point[i].m_Start.y))) || (((Ref->m_End.x == Point[i].m_End.x) && (Ref->m_End.y == Point[i].m_End.y))) ) { if( Point[i].m_BusNetCode == 0 ) Point[i].m_BusNetCode = NetCode; else PropageNetCode( Point[i].m_BusNetCode, NetCode,1 ); } break; } } } } /**************************************************************/ static void SegmentToPointConnect(ObjetNetListStruct *Jonction, int IsBus, int start) /***************************************************************/ /* Routine qui recherche si un point (jonction) est connecte a des segments, et regroupe les NetCodes des objets connectes a la jonction. Le point de jonction doit avoir un netcode valide La liste des objets est supposee classe par NumSheet Croissants, et la recherche se fait a partir de l'element start, 1er element de la feuille de schema ( il ne peut y avoir connexion physique entre elements de differentes sheets) */ { int i; ObjetNetListStruct *Segment = g_TabObjNet; for (i = start; i < g_NbrObjNet; i++) { if( Segment[i].m_SheetNumber > Jonction->m_SheetNumber ) break; if( IsBus == 0) { if ( Segment[i].m_Type != NET_SEGMENT ) continue; } else { if ( Segment[i].m_Type != NET_BUS ) continue; } if ( SegmentIntersect(Segment[i].m_Start.x, Segment[i].m_Start.y, Segment[i].m_End.x, Segment[i].m_End.y, Jonction->m_Start.x, Jonction->m_Start.y) ) { /* Propagation du Netcode a tous les Objets de meme NetCode */ if( IsBus == 0 ) { if( Segment[i].m_NetCode ) PropageNetCode(Segment[i].m_NetCode, Jonction->m_NetCode, IsBus); else Segment[i].m_NetCode = Jonction->m_NetCode; } else { if( Segment[i].m_BusNetCode ) PropageNetCode(Segment[i].m_BusNetCode, Jonction->m_BusNetCode, IsBus); else Segment[i].m_BusNetCode = Jonction->m_BusNetCode; } } } } /***************************************************************** * Routine qui connecte les groupes d'objets si labels identiques * *******************************************************************/ static void LabelConnection(ObjetNetListStruct *LabelRef) { int i, NetCode; ObjetNetListStruct *ObjetNet; if( LabelRef->m_NetCode == 0 ) return; ObjetNet = g_TabObjNet; for (i = 0; i < g_NbrObjNet; i++) { NetCode = ObjetNet[i].m_NetCode; if( NetCode == LabelRef->m_NetCode ) continue; if( ObjetNet[i].m_SheetNumber != LabelRef->m_SheetNumber ) { if (ObjetNet[i].m_Type != NET_PINLABEL ) continue; } if( (ObjetNet[i].m_Type == NET_LABEL ) || (ObjetNet[i].m_Type == NET_GLOBLABEL ) || (ObjetNet[i].m_Type == NET_BUSLABELMEMBER ) || (ObjetNet[i].m_Type == NET_GLOBBUSLABELMEMBER ) || (ObjetNet[i].m_Type == NET_PINLABEL ) ) { if( ObjetNet[i].m_Label->CmpNoCase(*LabelRef->m_Label) != 0) continue; /* Ici 2 labels identiques */ /* Propagation du Netcode a tous les Objets de meme NetCode */ if( ObjetNet[i].m_NetCode ) PropageNetCode(ObjetNet[i].m_NetCode, LabelRef->m_NetCode, 0); else ObjetNet[i].m_NetCode = LabelRef->m_NetCode; } } } /****************************************************************************/ static int TriNetCode(ObjetNetListStruct *Objet1, ObjetNetListStruct *Objet2) /****************************************************************************/ /* Routine de comparaison pour le tri par NetCode croissant du tableau des elements connectes ( TabPinSort ) par qsort() */ { return (Objet1->m_NetCode - Objet2->m_NetCode); } /*****************************************************************************/ static int TriBySheet(ObjetNetListStruct *Objet1, ObjetNetListStruct *Objet2) /*****************************************************************************/ /* Routine de comparaison pour le tri par NumSheet du tableau des elements connectes ( TabPinSort ) par qsort() */ { return (Objet1->m_SheetNumber - Objet2->m_SheetNumber); } /**********************************************************************/ static void SetUnconnectedFlag( ObjetNetListStruct *ListObj, int NbItems ) /**********************************************************************/ /* Routine positionnant le membre .FlagNoConnect des elements de la liste des objets netliste, tries par ordre de NetCode */ { ObjetNetListStruct * NetItemRef, * NetItemTst, *ItemPtr; ObjetNetListStruct * NetStart, * NetEnd, * Lim; int Nb; IsConnectType StateFlag; NetStart = NetEnd = ListObj; Lim = ListObj + NbItems; NetItemRef = NetStart; Nb = 0; StateFlag = UNCONNECT; for ( ; NetItemRef < Lim; NetItemRef++ ) { if( NetItemRef->m_Type == NET_NOCONNECT ) if( StateFlag != CONNECT ) StateFlag = NOCONNECT; /* Analyse du net en cours */ NetItemTst = NetItemRef + 1; if( (NetItemTst >= Lim) || (NetItemRef->m_NetCode != NetItemTst->m_NetCode) ) { /* Net analyse: mise a jour de m_FlagOfConnection */ NetEnd = NetItemTst; for( ItemPtr = NetStart; ItemPtr < NetEnd; ItemPtr++ ) { ItemPtr->m_FlagOfConnection = StateFlag; } if(NetItemTst >= Lim) return; /* Start Analyse Nouveau Net */ StateFlag = UNCONNECT; NetStart = NetItemTst; continue; } for ( ; ; NetItemTst ++) { if( (NetItemTst >= Lim) || (NetItemRef->m_NetCode != NetItemTst->m_NetCode) ) break; switch( NetItemTst->m_Type ) { case NET_SEGMENT: case NET_LABEL: case NET_GLOBLABEL: case NET_SHEETLABEL: case NET_PINLABEL: case NET_BUS: case NET_BUSLABELMEMBER: case NET_SHEETBUSLABELMEMBER: case NET_GLOBBUSLABELMEMBER: case NET_JONCTION: break; case NET_PIN: if( NetItemRef->m_Type == NET_PIN ) StateFlag = CONNECT; break; case NET_NOCONNECT: if( StateFlag != CONNECT ) StateFlag = NOCONNECT; break; } } } }