1045 lines
30 KiB
C++
1045 lines
30 KiB
C++
/***********************************/
|
|
/* 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->Type() )
|
|
{
|
|
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->Type() != 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->Type());
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|