You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1044 lines
30 KiB

  1. /***********************************/
  2. /* Module de calcul de la Netliste */
  3. /***********************************/
  4. #include "fctsys.h"
  5. #include "gr_basic.h"
  6. #include "common.h"
  7. #include "program.h"
  8. #include "libcmp.h"
  9. #include "general.h"
  10. #include "netlist.h" /* Definitions generales liees au calcul de netliste */
  11. #include "protos.h"
  12. /* Routines locales */
  13. static void PropageNetCode( int OldNetCode, int NewNetCode, int IsBus );
  14. static void SheetLabelConnection(ObjetNetListStruct *SheetLabel);
  15. static int ListeObjetConnection(WinEDA_SchematicFrame * frame, SCH_SCREEN *screen, ObjetNetListStruct *ObjNet);
  16. static int ConvertBusToMembers(ObjetNetListStruct *ObjNet);
  17. static void PointToPointConnect(ObjetNetListStruct *RefObj, int IsBus,
  18. int start);
  19. static void SegmentToPointConnect(ObjetNetListStruct *Jonction, int IsBus,
  20. int start);
  21. static void LabelConnection(ObjetNetListStruct *Label);
  22. static int TriNetCode(ObjetNetListStruct *Objet1, ObjetNetListStruct *Objet2);
  23. static void ConnectBusLabels( ObjetNetListStruct *Label, int NbItems );
  24. static void SetUnconnectedFlag( ObjetNetListStruct *ObjNet, int NbItems );
  25. static int TriBySheet(ObjetNetListStruct *Objet1, ObjetNetListStruct *Objet2);
  26. /* Variable locales */
  27. static int FirstNumWireBus, LastNumWireBus, RootBusNameLength;
  28. static int LastNetCode, LastBusNetCode;
  29. static int s_PassNumber;
  30. /***********************************************************************/
  31. void FreeTabNetList(ObjetNetListStruct * TabNetItems, int NbrNetItems)
  32. /***********************************************************************/
  33. /*
  34. Routine de liberation memoire des tableaux utilises pour le calcul
  35. de la netliste
  36. TabNetItems = pointeur sur le tableau principal (liste des items )
  37. NbrNetItems = nombre d'elements
  38. */
  39. {
  40. int i;
  41. /* Liberation memoire des strings du champ Label reserve par ConvertBusToMembers */
  42. for (i = 0; i < NbrNetItems; i++)
  43. {
  44. switch( TabNetItems[i].m_Type )
  45. {
  46. case NET_PIN:
  47. case NET_SHEETLABEL:
  48. case NET_SEGMENT:
  49. case NET_JONCTION:
  50. case NET_BUS:
  51. case NET_LABEL:
  52. case NET_GLOBLABEL:
  53. case NET_PINLABEL:
  54. case NET_NOCONNECT:
  55. break;
  56. case NET_GLOBBUSLABELMEMBER:
  57. case NET_SHEETBUSLABELMEMBER:
  58. case NET_BUSLABELMEMBER:
  59. delete TabNetItems[i].m_Label;
  60. break;
  61. }
  62. }
  63. MyFree(TabNetItems);
  64. }
  65. /*****************************************************/
  66. void * WinEDA_SchematicFrame::BuildNetListBase(void)
  67. /*****************************************************/
  68. /* Routine qui construit le tableau des elements connectes du projet
  69. met a jour:
  70. g_TabObjNet
  71. g_NbrObjNet
  72. */
  73. {
  74. int NetNumber, SheetNumber;
  75. int i, istart, NetCode;
  76. SCH_SCREEN * screen;
  77. ObjetNetListStruct * BaseTabObjNet;
  78. wxString msg;
  79. wxBusyCursor Busy;
  80. NetNumber = 1;
  81. s_PassNumber = 0;
  82. MsgPanel->EraseMsgBox();
  83. Affiche_1_Parametre(this, 1,_("List"), wxEmptyString, LIGHTRED);
  84. /* Build the screen list */
  85. EDA_ScreenList ScreenList(NULL);
  86. /* 1ere passe : Comptage du nombre d'objet de Net */
  87. g_NbrObjNet = 0;
  88. g_TabObjNet = NULL; /* Init pour le 1er passage dans ListeObjetConnection */
  89. /* Update the sheet number, sheet count and date and count nelist items */
  90. ScreenSch->SetModify();
  91. int kk = 1;
  92. for ( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
  93. {
  94. screen->m_SheetNumber = kk++;
  95. screen->m_NumberOfSheet = ScreenList.GetCount();
  96. screen->m_Date = GenDate();
  97. g_NbrObjNet += ListeObjetConnection(this, screen, NULL);
  98. }
  99. if( g_NbrObjNet == 0 )
  100. {
  101. DisplayError(this, _("No component"), 20);
  102. return(NULL);
  103. }
  104. i = sizeof(ObjetNetListStruct) * g_NbrObjNet;
  105. BaseTabObjNet = g_TabObjNet = (ObjetNetListStruct *) MyZMalloc(i);
  106. if( BaseTabObjNet == NULL ) return(NULL);
  107. /* 2eme passe : Remplissage des champs des structures des objets de Net */
  108. s_PassNumber ++;
  109. Affiche_1_Parametre(this, 1,_("List"), wxEmptyString,RED);
  110. for ( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
  111. {
  112. g_TabObjNet += ListeObjetConnection(this, screen, g_TabObjNet );
  113. }
  114. Affiche_1_Parametre(this, -1, wxEmptyString,_("Done"),RED);
  115. msg.Printf( wxT("%d"), g_NbrObjNet);
  116. Affiche_1_Parametre(this, 8, _("NbItems"),msg,GREEN);
  117. /* Recherche des connections pour les Segments et les Pins */
  118. /* Tri du Tableau des objets de Net par Sheet */
  119. qsort(BaseTabObjNet, g_NbrObjNet, sizeof(ObjetNetListStruct),
  120. (int (*)(const void *, const void *)) TriBySheet);
  121. Affiche_1_Parametre(this, 18,_("Conn"), wxEmptyString,CYAN);
  122. g_TabObjNet = BaseTabObjNet;
  123. SheetNumber = g_TabObjNet[0].m_SheetNumber;
  124. LastNetCode = LastBusNetCode = 1;
  125. for (i = istart = 0; i < g_NbrObjNet; i++)
  126. {
  127. if(g_TabObjNet[i].m_SheetNumber != SheetNumber )
  128. {
  129. SheetNumber = g_TabObjNet[i].m_SheetNumber; istart = i;
  130. }
  131. switch( g_TabObjNet[i].m_Type )
  132. {
  133. case NET_PIN:
  134. case NET_PINLABEL:
  135. case NET_SHEETLABEL:
  136. case NET_NOCONNECT:
  137. if ( g_TabObjNet[i].m_NetCode != 0 ) break; /* Deja connecte */
  138. case NET_SEGMENT:
  139. /* Controle des connexions type point a point ( Sans BUS ) */
  140. if( g_TabObjNet[i].m_NetCode == 0 )
  141. {
  142. g_TabObjNet[i].m_NetCode = LastNetCode;
  143. LastNetCode++;
  144. }
  145. PointToPointConnect(g_TabObjNet+i, 0, istart);
  146. break;
  147. case NET_JONCTION:
  148. /* Controle des jonction , hors BUS */
  149. if( g_TabObjNet[i].m_NetCode == 0 )
  150. {
  151. g_TabObjNet[i].m_NetCode = LastNetCode;
  152. LastNetCode++;
  153. }
  154. SegmentToPointConnect( g_TabObjNet+i, 0, istart);
  155. /* Controle des jonction , sur BUS */
  156. if( g_TabObjNet[i].m_BusNetCode == 0 )
  157. {
  158. g_TabObjNet[i].m_BusNetCode = LastBusNetCode;
  159. LastBusNetCode++;
  160. }
  161. SegmentToPointConnect( g_TabObjNet+i, ISBUS, istart );
  162. break;
  163. case NET_LABEL:
  164. case NET_GLOBLABEL:
  165. /* Controle des connexions type jonction ( Sans BUS ) */
  166. if( g_TabObjNet[i].m_NetCode == 0 )
  167. {
  168. g_TabObjNet[i].m_NetCode = LastNetCode;
  169. LastNetCode++;
  170. }
  171. SegmentToPointConnect( g_TabObjNet+i, 0, istart );
  172. break;
  173. case NET_SHEETBUSLABELMEMBER:
  174. if ( g_TabObjNet[i].m_BusNetCode != 0 ) break; /* Deja connecte */
  175. case NET_BUS:
  176. /* Controle des connexions type point a point mode BUS */
  177. if( g_TabObjNet[i].m_BusNetCode == 0 )
  178. {
  179. g_TabObjNet[i].m_BusNetCode = LastBusNetCode;
  180. LastBusNetCode++;
  181. }
  182. PointToPointConnect(g_TabObjNet+i, ISBUS, istart);
  183. break;
  184. case NET_BUSLABELMEMBER:
  185. case NET_GLOBBUSLABELMEMBER:
  186. /* Controle des connexions semblables a des sur BUS */
  187. if( g_TabObjNet[i].m_NetCode == 0 )
  188. {
  189. g_TabObjNet[i].m_BusNetCode = LastBusNetCode;
  190. LastBusNetCode++;
  191. }
  192. SegmentToPointConnect( g_TabObjNet+i, ISBUS, istart);
  193. break;
  194. }
  195. }
  196. Affiche_1_Parametre(this, -1, wxEmptyString,_("Done"),CYAN);
  197. /* Mise a jour des NetCodes des Bus Labels connectes par les Bus */
  198. ConnectBusLabels( g_TabObjNet, g_NbrObjNet);
  199. Affiche_1_Parametre(this, 26,_("Labels"), wxEmptyString,CYAN);
  200. /* Connections des groupes d'objets par labels identiques */
  201. for (i = 0; i < g_NbrObjNet; i++)
  202. {
  203. switch( g_TabObjNet[i].m_Type )
  204. {
  205. case NET_PIN:
  206. case NET_SHEETLABEL:
  207. case NET_SEGMENT:
  208. case NET_JONCTION:
  209. case NET_BUS:
  210. case NET_NOCONNECT:
  211. break;
  212. case NET_LABEL:
  213. case NET_GLOBLABEL:
  214. case NET_PINLABEL:
  215. case NET_BUSLABELMEMBER:
  216. case NET_GLOBBUSLABELMEMBER:
  217. LabelConnection( g_TabObjNet+i );
  218. break;
  219. case NET_SHEETBUSLABELMEMBER:
  220. break;
  221. }
  222. }
  223. Affiche_1_Parametre(this, -1, wxEmptyString,_("Done"),CYAN);
  224. /* Connexion des hierarchies */
  225. Affiche_1_Parametre(this, 36,_("Hierar."), wxEmptyString,LIGHTRED);
  226. for (i = 0; i < g_NbrObjNet; i++)
  227. {
  228. if( (g_TabObjNet[i].m_Type == NET_SHEETLABEL ) ||
  229. ( g_TabObjNet[i].m_Type == NET_SHEETBUSLABELMEMBER ) )
  230. SheetLabelConnection(g_TabObjNet + i);
  231. }
  232. /* Tri du Tableau des objets de Net par NetCode */
  233. qsort(g_TabObjNet, g_NbrObjNet, sizeof(ObjetNetListStruct),
  234. (int (*)(const void *, const void *)) TriNetCode);
  235. Affiche_1_Parametre(this, -1, wxEmptyString,_("Done"),RED);
  236. /* Compression des numeros de NetCode a des valeurs consecutives */
  237. Affiche_1_Parametre(this, 46,_("Sorting"), wxEmptyString,GREEN);
  238. LastNetCode = NetCode = 0;
  239. for (i = 0; i < g_NbrObjNet; i++)
  240. {
  241. if(g_TabObjNet[i].m_NetCode != LastNetCode)
  242. {
  243. NetCode++; LastNetCode = g_TabObjNet[i].m_NetCode;
  244. }
  245. g_TabObjNet[i].m_NetCode = NetCode;
  246. }
  247. Affiche_1_Parametre(this, -1, wxEmptyString,_("Done"),GREEN);
  248. /* Affectation du m_FlagOfConnection en fonction de connection ou non */
  249. SetUnconnectedFlag( BaseTabObjNet, g_NbrObjNet);
  250. return( (void*) BaseTabObjNet);
  251. }
  252. /*************************************************************
  253. * Routine qui connecte les sous feuilles par les sheetLabels *
  254. **************************************************************/
  255. static void SheetLabelConnection(ObjetNetListStruct *SheetLabel)
  256. {
  257. int i;
  258. ObjetNetListStruct *ObjetNet;
  259. if( SheetLabel->m_NetCode == 0 ) return;
  260. /* Calcul du numero de sous feuille correspondante au sheetlabel */
  261. /* Comparaison du SheetLabel avec les GLABELS de la sous feuille
  262. pour regroupement des NetCodes */
  263. for (i = 0, ObjetNet = g_TabObjNet; i < g_NbrObjNet; i++)
  264. {
  265. if( ObjetNet[i].m_SheetNumber != SheetLabel->m_NumInclude ) continue;
  266. if( (ObjetNet[i].m_Type != NET_GLOBLABEL ) &&
  267. (ObjetNet[i].m_Type != NET_GLOBBUSLABELMEMBER ) )
  268. continue;
  269. if( ObjetNet[i].m_NetCode == SheetLabel->m_NetCode ) continue;
  270. if( ObjetNet[i].m_Label->CmpNoCase(*SheetLabel->m_Label) != 0) continue;
  271. /* Propagation du Netcode a tous les Objets de meme NetCode */
  272. if( ObjetNet[i].m_NetCode )
  273. PropageNetCode(ObjetNet[i].m_NetCode, SheetLabel->m_NetCode, 0);
  274. else ObjetNet[i].m_NetCode = SheetLabel->m_NetCode;
  275. }
  276. }
  277. /*****************************************************************************/
  278. static int ListeObjetConnection(WinEDA_SchematicFrame * frame, SCH_SCREEN *screen,
  279. ObjetNetListStruct *ObjNet)
  280. /*****************************************************************************/
  281. /* Routine generant la liste des objets relatifs aux connection
  282. entree:
  283. screen: pointeur sur l'ecran a traiter
  284. ObjNet:
  285. si NULL: la routine compte seulement le nombre des objets
  286. sinon: pointe le tableau a remplir
  287. */
  288. {
  289. int ii, NbrItem = 0, NumSheet;
  290. EDA_BaseStruct *DrawList;
  291. EDA_SchComponentStruct *DrawLibItem;
  292. int TransMat[2][2], PartX, PartY, x2, y2;
  293. EDA_LibComponentStruct *Entry;
  294. LibEDA_BaseStruct *DEntry;
  295. DrawSheetLabelStruct *SheetLabel;
  296. int NumInclude;
  297. NumSheet = screen->m_SheetNumber;
  298. DrawList = screen->EEDrawList;
  299. while ( DrawList )
  300. {
  301. switch( DrawList->m_StructType )
  302. {
  303. case DRAW_SEGMENT_STRUCT_TYPE :
  304. #undef STRUCT
  305. #define STRUCT ((EDA_DrawLineStruct *) DrawList)
  306. if( ObjNet)
  307. {
  308. if ( (STRUCT->m_Layer != LAYER_BUS) &&
  309. (STRUCT->m_Layer != LAYER_WIRE) )
  310. break;
  311. ObjNet[NbrItem].m_Comp = STRUCT;
  312. ObjNet[NbrItem].m_Screen = screen;
  313. ObjNet[NbrItem].m_SheetNumber = NumSheet;
  314. ObjNet[NbrItem].m_Start = STRUCT->m_Start;
  315. ObjNet[NbrItem].m_End = STRUCT->m_End;
  316. if (STRUCT->m_Layer == LAYER_BUS)
  317. {
  318. ObjNet[NbrItem].m_Type = NET_BUS;
  319. }
  320. else /* Cas des WIRE */
  321. {
  322. ObjNet[NbrItem].m_Type = NET_SEGMENT;
  323. }
  324. }
  325. NbrItem++;
  326. break;
  327. case DRAW_JUNCTION_STRUCT_TYPE :
  328. #undef STRUCT
  329. #define STRUCT ((DrawJunctionStruct *) DrawList)
  330. if( ObjNet)
  331. {
  332. ObjNet[NbrItem].m_Comp = STRUCT;
  333. ObjNet[NbrItem].m_Screen = screen;
  334. ObjNet[NbrItem].m_Type = NET_JONCTION;
  335. ObjNet[NbrItem].m_SheetNumber = NumSheet;
  336. ObjNet[NbrItem].m_Start = STRUCT->m_Pos;
  337. ObjNet[NbrItem].m_End = ObjNet[NbrItem].m_Start;
  338. }
  339. NbrItem++;
  340. break;
  341. case DRAW_NOCONNECT_STRUCT_TYPE :
  342. #undef STRUCT
  343. #define STRUCT ((DrawNoConnectStruct *) DrawList)
  344. if( ObjNet)
  345. {
  346. ObjNet[NbrItem].m_Comp = STRUCT;
  347. ObjNet[NbrItem].m_Screen = screen;
  348. ObjNet[NbrItem].m_Type = NET_NOCONNECT;
  349. ObjNet[NbrItem].m_SheetNumber = NumSheet;
  350. ObjNet[NbrItem].m_Start = STRUCT->m_Pos;
  351. ObjNet[NbrItem].m_End = ObjNet[NbrItem].m_Start;
  352. }
  353. NbrItem++;
  354. break;
  355. case DRAW_LABEL_STRUCT_TYPE :
  356. #undef STRUCT
  357. #define STRUCT ((DrawLabelStruct *) DrawList)
  358. ii = IsBusLabel( STRUCT->m_Text);
  359. if( ObjNet)
  360. {
  361. ObjNet[NbrItem].m_Comp = STRUCT;
  362. ObjNet[NbrItem].m_Screen = screen;
  363. ObjNet[NbrItem].m_Type = NET_LABEL;
  364. if (STRUCT->m_Layer == LAYER_GLOBLABEL)
  365. ObjNet[NbrItem].m_Type = NET_GLOBLABEL;
  366. ObjNet[NbrItem].m_Label = & STRUCT->m_Text;
  367. ObjNet[NbrItem].m_SheetNumber = NumSheet;
  368. ObjNet[NbrItem].m_Start = STRUCT->m_Pos;
  369. ObjNet[NbrItem].m_End = ObjNet[NbrItem].m_Start;
  370. /* Si c'est un Bus, eclatement en Label */
  371. if ( ii ) ConvertBusToMembers(ObjNet + NbrItem);
  372. }
  373. NbrItem += ii+1;
  374. break;
  375. case DRAW_GLOBAL_LABEL_STRUCT_TYPE :
  376. #undef STRUCT
  377. #define STRUCT ((DrawGlobalLabelStruct *) DrawList)
  378. ii = IsBusLabel( STRUCT->m_Text);
  379. if( ObjNet)
  380. {
  381. ObjNet[NbrItem].m_Comp = STRUCT;
  382. ObjNet[NbrItem].m_Screen = screen;
  383. ObjNet[NbrItem].m_Type = NET_LABEL;
  384. if (STRUCT->m_Layer == LAYER_GLOBLABEL)
  385. ObjNet[NbrItem].m_Type = NET_GLOBLABEL;
  386. ObjNet[NbrItem].m_Label = & STRUCT->m_Text;
  387. ObjNet[NbrItem].m_SheetNumber = NumSheet;
  388. ObjNet[NbrItem].m_Start = STRUCT->m_Pos;
  389. ObjNet[NbrItem].m_End = ObjNet[NbrItem].m_Start;
  390. /* Si c'est un Bus, eclatement en Label */
  391. if ( ii ) ConvertBusToMembers(ObjNet + NbrItem);
  392. }
  393. NbrItem += ii+1;
  394. break;
  395. case DRAW_LIB_ITEM_STRUCT_TYPE :
  396. DrawLibItem = (EDA_SchComponentStruct *) DrawList;
  397. memcpy(TransMat, DrawLibItem->m_Transform, sizeof(TransMat));
  398. PartX = DrawLibItem->m_Pos.x; PartY = DrawLibItem->m_Pos.y;
  399. Entry = FindLibPart(DrawLibItem->m_ChipName, wxEmptyString, FIND_ROOT);
  400. if( Entry == NULL) break;
  401. if(Entry->m_Drawings == NULL) break ;
  402. DEntry = Entry->m_Drawings;
  403. for ( ;DEntry != NULL; DEntry = DEntry->Next())
  404. {
  405. LibDrawPin * Pin = (LibDrawPin *) DEntry;
  406. if( DEntry->m_StructType != COMPONENT_PIN_DRAW_TYPE) continue;
  407. if( DEntry->m_Unit &&
  408. (DEntry->m_Unit != DrawLibItem->m_Multi) ) continue;
  409. if( DEntry->m_Convert &&
  410. (DEntry->m_Convert != DrawLibItem->m_Convert)) continue;
  411. x2 = PartX + TransMat[0][0] * Pin->m_Pos.x
  412. + TransMat[0][1] * Pin->m_Pos.y;
  413. y2 = PartY + TransMat[1][0] * Pin->m_Pos.x
  414. + TransMat[1][1] * Pin->m_Pos.y;
  415. if( ObjNet)
  416. {
  417. ObjNet[NbrItem].m_Comp = DEntry;
  418. ObjNet[NbrItem].m_Type = NET_PIN;
  419. ObjNet[NbrItem].m_Link = DrawLibItem;
  420. ObjNet[NbrItem].m_Screen = screen;
  421. ObjNet[NbrItem].m_ElectricalType = Pin->m_PinType;
  422. ObjNet[NbrItem].m_PinNum = Pin->m_PinNum;
  423. ObjNet[NbrItem].m_Label = & Pin->m_PinName;
  424. ObjNet[NbrItem].m_SheetNumber = NumSheet;
  425. ObjNet[NbrItem].m_Start.x = x2;
  426. ObjNet[NbrItem].m_Start.y = y2;
  427. ObjNet[NbrItem].m_End = ObjNet[NbrItem].m_Start;
  428. }
  429. NbrItem++;
  430. if( ( (int) Pin->m_PinType == (int) PIN_POWER_IN ) &&
  431. ( Pin->m_Attributs & PINNOTDRAW ) )
  432. { /* Il y a un PIN_LABEL Associe */
  433. if( ObjNet)
  434. {
  435. ObjNet[NbrItem].m_Comp = NULL;
  436. ObjNet[NbrItem].m_Type = NET_PINLABEL;
  437. ObjNet[NbrItem].m_Screen = screen;
  438. ObjNet[NbrItem].m_SheetNumber = NumSheet;
  439. ObjNet[NbrItem].m_Label = & Pin->m_PinName;
  440. ObjNet[NbrItem].m_Start.x = x2;
  441. ObjNet[NbrItem].m_Start.y = y2;
  442. ObjNet[NbrItem].m_End = ObjNet[NbrItem].m_Start;
  443. }
  444. NbrItem++;
  445. }
  446. }
  447. break;
  448. case DRAW_PICK_ITEM_STRUCT_TYPE :
  449. case DRAW_POLYLINE_STRUCT_TYPE :
  450. case DRAW_BUSENTRY_STRUCT_TYPE :
  451. case DRAW_MARKER_STRUCT_TYPE :
  452. case DRAW_TEXT_STRUCT_TYPE :
  453. break;
  454. case DRAW_SHEET_STRUCT_TYPE :
  455. #undef STRUCT
  456. #define STRUCT ((DrawSheetStruct *) DrawList)
  457. NumInclude = STRUCT->m_SheetNumber;
  458. SheetLabel = STRUCT->m_Label;
  459. for ( ; SheetLabel != NULL;
  460. SheetLabel = (DrawSheetLabelStruct*) SheetLabel->Pnext)
  461. {
  462. ii = IsBusLabel(SheetLabel->m_Text);
  463. if( ObjNet)
  464. {
  465. ObjNet[NbrItem].m_Comp = SheetLabel;
  466. ObjNet[NbrItem].m_Link = DrawList;
  467. ObjNet[NbrItem].m_Type = NET_SHEETLABEL;
  468. ObjNet[NbrItem].m_Screen = screen;
  469. ObjNet[NbrItem].m_ElectricalType = SheetLabel->m_Shape;
  470. ObjNet[NbrItem].m_Label = & SheetLabel->m_Text;
  471. ObjNet[NbrItem].m_SheetNumber = NumSheet;
  472. ObjNet[NbrItem].m_NumInclude = NumInclude;
  473. ObjNet[NbrItem].m_Start = SheetLabel->m_Pos;
  474. ObjNet[NbrItem].m_End = ObjNet[NbrItem].m_Start;
  475. /* Si c'est un Bus, eclatement en Label */
  476. if ( ii ) ConvertBusToMembers(ObjNet + NbrItem);
  477. }
  478. NbrItem += ii+1;
  479. }
  480. break;
  481. case DRAW_SHEETLABEL_STRUCT_TYPE :
  482. DisplayError(frame, wxT("Netlist: Type DRAW_SHEETLABEL inattendu"));
  483. break;
  484. default:
  485. {
  486. wxString msg;
  487. msg.Printf( wxT("Netlist: unexpected type struct %d"),
  488. DrawList->m_StructType);
  489. DisplayError(frame, msg);
  490. break;
  491. }
  492. }
  493. DrawList = DrawList->Pnext;
  494. }
  495. return(NbrItem);
  496. }
  497. /************************************************************************/
  498. static void ConnectBusLabels( ObjetNetListStruct *Label, int NbItems )
  499. /************************************************************************/
  500. /* Routine qui analyse les labels type xxBUSLABELMEMBER
  501. Propage les Netcodes entre labels correspondants ( c'est a dire lorsque
  502. leur numero de membre est identique) lorsqu'ils sont connectes
  503. globalement par leur BusNetCode
  504. Utilise et met a jour la variable LastNetCode
  505. */
  506. {
  507. ObjetNetListStruct *LabelInTst, *Lim;
  508. Lim = Label + NbItems;
  509. for ( ; Label < Lim; Label++)
  510. {
  511. if( (Label->m_Type == NET_SHEETBUSLABELMEMBER) ||
  512. (Label->m_Type == NET_BUSLABELMEMBER) ||
  513. (Label->m_Type == NET_GLOBBUSLABELMEMBER) )
  514. {
  515. if( Label->m_NetCode == 0 )
  516. {
  517. Label->m_NetCode = LastNetCode; LastNetCode++;
  518. }
  519. for ( LabelInTst = Label+1; LabelInTst < Lim; LabelInTst++)
  520. {
  521. if( (LabelInTst->m_Type == NET_SHEETBUSLABELMEMBER) ||
  522. (LabelInTst->m_Type == NET_BUSLABELMEMBER) ||
  523. (LabelInTst->m_Type == NET_GLOBBUSLABELMEMBER) )
  524. {
  525. if( LabelInTst->m_BusNetCode != Label->m_BusNetCode ) continue;
  526. if( LabelInTst->m_Member != Label->m_Member ) continue;
  527. if( LabelInTst->m_NetCode == 0 )
  528. LabelInTst->m_NetCode = Label->m_NetCode;
  529. else
  530. PropageNetCode( LabelInTst->m_NetCode, Label->m_NetCode,0);
  531. }
  532. }
  533. }
  534. }
  535. }
  536. /**************************************************/
  537. int IsBusLabel( const wxString & LabelDrawList )
  538. /**************************************************/
  539. /* Routine qui verifie si le Label a une notation de type Bus
  540. Retourne 0 si non
  541. nombre de membres si oui
  542. met a jour FirstNumWireBus, LastNumWireBus et RootBusNameLength
  543. */
  544. {
  545. unsigned Num;
  546. int ii;
  547. wxString BufLine;
  548. long tmp;
  549. bool error = FALSE;
  550. /* Search for '[' because a bus label is like "busname[nn..mm]" */
  551. ii = LabelDrawList.Find('[');
  552. if ( ii < 0 ) return(0);
  553. Num = (unsigned) ii;
  554. FirstNumWireBus = LastNumWireBus = 9;
  555. RootBusNameLength = Num;
  556. Num++;
  557. while ( LabelDrawList[Num] != '.' && Num < LabelDrawList.Len())
  558. {
  559. BufLine.Append(LabelDrawList[Num]);
  560. Num++;
  561. }
  562. if ( ! BufLine.ToLong(&tmp) ) error = TRUE;;
  563. FirstNumWireBus = tmp;
  564. while ( LabelDrawList[Num] == '.' && Num < LabelDrawList.Len() )
  565. Num++;
  566. BufLine.Empty();
  567. while ( LabelDrawList[Num] != ']' && Num < LabelDrawList.Len())
  568. {
  569. BufLine.Append(LabelDrawList[Num]);
  570. Num++;
  571. }
  572. if ( ! BufLine.ToLong(&tmp) ) error = TRUE;;
  573. LastNumWireBus = tmp;
  574. if( FirstNumWireBus < 0 ) FirstNumWireBus = 0;
  575. if( LastNumWireBus < 0 ) LastNumWireBus = 0;
  576. if( FirstNumWireBus > LastNumWireBus )
  577. {
  578. EXCHG( FirstNumWireBus, LastNumWireBus);
  579. }
  580. if ( error && (s_PassNumber == 0) )
  581. {
  582. wxString msg = _("Bad Bus Label: ") + LabelDrawList;
  583. DisplayError(NULL, msg);
  584. }
  585. return(LastNumWireBus - FirstNumWireBus + 1 );
  586. }
  587. /***************************************************************/
  588. static int ConvertBusToMembers(ObjetNetListStruct * BusLabel)
  589. /***************************************************************/
  590. /* Routine qui eclate un label type Bus en autant de Label qu'il contient de membres,
  591. et qui cree les structures avec le type NET_GLOBBUSLABELMEMBER, NET_BUSLABELMEMBER
  592. ou NET_SHEETBUSLABELMEMBER
  593. entree = pointeur sur l'ObjetNetListStruct initialise corresp au buslabel
  594. suppose que FirstNumWireBus, LastNumWireBus et RootBusNameLength sont a jour
  595. modifie l'ObjetNetListStruct de base et remplit les suivants
  596. m_Label is a pointer to a new wxString
  597. m_Label must be deallocated by the user (only for a NET_GLOBBUSLABELMEMBER,
  598. NET_BUSLABELMEMBER or a NET_SHEETBUSLABELMEMBER object type)
  599. */
  600. {
  601. int NumItem, BusMember;
  602. wxString BufLine;
  603. if( BusLabel->m_Type == NET_GLOBLABEL )
  604. BusLabel->m_Type = NET_GLOBBUSLABELMEMBER;
  605. else if (BusLabel->m_Type == NET_SHEETLABEL)
  606. BusLabel->m_Type = NET_SHEETBUSLABELMEMBER;
  607. else BusLabel->m_Type = NET_BUSLABELMEMBER;
  608. /* Convertion du BusLabel en la racine du Label + le numero du fil */
  609. BufLine = BusLabel->m_Label->Left(RootBusNameLength);
  610. BusMember = FirstNumWireBus;
  611. BufLine << BusMember;
  612. BusLabel->m_Label = new wxString(BufLine);
  613. BusLabel->m_Member = BusMember;
  614. NumItem = 1;
  615. for ( BusMember++; BusMember <= LastNumWireBus; BusMember++)
  616. {
  617. *(BusLabel+1) = *BusLabel; BusLabel ++; NumItem++;
  618. /* Convertion du BusLabel en la racine du Label + le numero du fil */
  619. BufLine = BusLabel->m_Label->Left(RootBusNameLength);
  620. BufLine << BusMember;
  621. BusLabel->m_Label = new wxString(BufLine);
  622. BusLabel->m_Member = BusMember;
  623. }
  624. return( NumItem);
  625. }
  626. /**********************************************************************/
  627. static void PropageNetCode( int OldNetCode, int NewNetCode, int IsBus )
  628. /**********************************************************************/
  629. /* PropageNetCode propage le netcode NewNetCode sur tous les elements
  630. appartenant a l'ancien netcode OldNetCode
  631. Si IsBus == 0; c'est le membre NetCode qui est propage
  632. Si IsBus != 0; c'est le membre BusNetCode qui est propage
  633. */
  634. {
  635. int jj;
  636. ObjetNetListStruct * Objet = g_TabObjNet;
  637. if( OldNetCode == NewNetCode ) return;
  638. if( IsBus == 0 ) /* Propagation du NetCode */
  639. {
  640. for (jj = 0; jj < g_NbrObjNet; jj++, Objet++)
  641. {
  642. if ( Objet->m_NetCode == OldNetCode )
  643. {
  644. Objet->m_NetCode = NewNetCode;
  645. }
  646. }
  647. }
  648. else /* Propagation du BusNetCode */
  649. {
  650. for (jj = 0; jj < g_NbrObjNet; jj++, Objet++)
  651. {
  652. if ( Objet->m_BusNetCode == OldNetCode )
  653. {
  654. Objet->m_BusNetCode = NewNetCode;
  655. }
  656. }
  657. }
  658. }
  659. /***************************************************************************/
  660. static void PointToPointConnect(ObjetNetListStruct *Ref, int IsBus, int start)
  661. /***************************************************************************/
  662. /* Routine qui verifie si l'element *Ref est connecte a
  663. d'autres elements de la liste des objets du schema, selon le mode Point
  664. a point ( Extremites superposees )
  665. si IsBus:
  666. la connexion ne met en jeu que des elements type bus
  667. ( BUS ou BUSLABEL ou JONCTION )
  668. sinon
  669. la connexion ne met en jeu que des elements type non bus
  670. ( autres que BUS ou BUSLABEL )
  671. L'objet Ref doit avoir un NetCode valide.
  672. La liste des objets est supposee classe par NumSheet Croissants,
  673. et la recherche se fait a partir de l'element start, 1er element
  674. de la feuille de schema
  675. ( il ne peut y avoir connexion physique entre elements de differentes sheets)
  676. */
  677. {
  678. int i, NetCode;
  679. ObjetNetListStruct *Point = g_TabObjNet;
  680. if ( IsBus == 0 ) /* Objets autres que BUS et BUSLABELS */
  681. {
  682. NetCode = Ref->m_NetCode;
  683. for (i = start; i < g_NbrObjNet; i++)
  684. {
  685. if( Point[i].m_SheetNumber > Ref->m_SheetNumber ) break;
  686. switch( Point[i].m_Type )
  687. {
  688. case NET_SEGMENT:
  689. case NET_PIN:
  690. case NET_LABEL:
  691. case NET_GLOBLABEL:
  692. case NET_SHEETLABEL:
  693. case NET_PINLABEL:
  694. case NET_JONCTION:
  695. case NET_NOCONNECT:
  696. if( (((Ref->m_Start.x == Point[i].m_Start.x) && (Ref->m_Start.y == Point[i].m_Start.y))) ||
  697. (((Ref->m_Start.x == Point[i].m_End.x) && (Ref->m_Start.y == Point[i].m_End.y))) ||
  698. (((Ref->m_End.x == Point[i].m_Start.x) && (Ref->m_End.y == Point[i].m_Start.y))) ||
  699. (((Ref->m_End.x == Point[i].m_End.x) && (Ref->m_End.y == Point[i].m_End.y))) )
  700. {
  701. if( Point[i].m_NetCode == 0 ) Point[i].m_NetCode = NetCode;
  702. else PropageNetCode( Point[i].m_NetCode, NetCode , 0);
  703. }
  704. break;
  705. case NET_BUS:
  706. case NET_BUSLABELMEMBER:
  707. case NET_SHEETBUSLABELMEMBER:
  708. case NET_GLOBBUSLABELMEMBER:
  709. break;
  710. }
  711. }
  712. }
  713. else /* Objets type BUS et BUSLABELS ( et JONCTIONS )*/
  714. {
  715. NetCode = Ref->m_BusNetCode;
  716. for (i = start; i < g_NbrObjNet; i++)
  717. {
  718. if( Point[i].m_SheetNumber > Ref->m_SheetNumber ) break;
  719. switch( Point[i].m_Type )
  720. {
  721. case NET_SEGMENT:
  722. case NET_PIN:
  723. case NET_LABEL:
  724. case NET_GLOBLABEL:
  725. case NET_SHEETLABEL:
  726. case NET_PINLABEL:
  727. case NET_NOCONNECT:
  728. break;
  729. case NET_BUS:
  730. case NET_BUSLABELMEMBER:
  731. case NET_SHEETBUSLABELMEMBER:
  732. case NET_GLOBBUSLABELMEMBER:
  733. case NET_JONCTION:
  734. if( (((Ref->m_Start.x == Point[i].m_Start.x) && (Ref->m_Start.y == Point[i].m_Start.y))) ||
  735. (((Ref->m_Start.x == Point[i].m_End.x) && (Ref->m_Start.y == Point[i].m_End.y))) ||
  736. (((Ref->m_End.x == Point[i].m_Start.x) && (Ref->m_End.y == Point[i].m_Start.y))) ||
  737. (((Ref->m_End.x == Point[i].m_End.x) && (Ref->m_End.y == Point[i].m_End.y))) )
  738. {
  739. if( Point[i].m_BusNetCode == 0 )
  740. Point[i].m_BusNetCode = NetCode;
  741. else PropageNetCode( Point[i].m_BusNetCode, NetCode,1 );
  742. }
  743. break;
  744. }
  745. }
  746. }
  747. }
  748. /**************************************************************/
  749. static void SegmentToPointConnect(ObjetNetListStruct *Jonction,
  750. int IsBus, int start)
  751. /***************************************************************/
  752. /*
  753. Routine qui recherche si un point (jonction) est connecte a des segments,
  754. et regroupe les NetCodes des objets connectes a la jonction.
  755. Le point de jonction doit avoir un netcode valide
  756. La liste des objets est supposee classe par NumSheet Croissants,
  757. et la recherche se fait a partir de l'element start, 1er element
  758. de la feuille de schema
  759. ( il ne peut y avoir connexion physique entre elements de differentes sheets)
  760. */
  761. {
  762. int i;
  763. ObjetNetListStruct *Segment = g_TabObjNet;
  764. for (i = start; i < g_NbrObjNet; i++)
  765. {
  766. if( Segment[i].m_SheetNumber > Jonction->m_SheetNumber ) break;
  767. if( IsBus == 0)
  768. {
  769. if ( Segment[i].m_Type != NET_SEGMENT ) continue;
  770. }
  771. else
  772. {
  773. if ( Segment[i].m_Type != NET_BUS ) continue;
  774. }
  775. if ( SegmentIntersect(Segment[i].m_Start.x, Segment[i].m_Start.y,
  776. Segment[i].m_End.x, Segment[i].m_End.y,
  777. Jonction->m_Start.x, Jonction->m_Start.y) )
  778. {
  779. /* Propagation du Netcode a tous les Objets de meme NetCode */
  780. if( IsBus == 0 )
  781. {
  782. if( Segment[i].m_NetCode )
  783. PropageNetCode(Segment[i].m_NetCode,
  784. Jonction->m_NetCode, IsBus);
  785. else Segment[i].m_NetCode = Jonction->m_NetCode;
  786. }
  787. else
  788. {
  789. if( Segment[i].m_BusNetCode )
  790. PropageNetCode(Segment[i].m_BusNetCode,
  791. Jonction->m_BusNetCode, IsBus);
  792. else Segment[i].m_BusNetCode = Jonction->m_BusNetCode;
  793. }
  794. }
  795. }
  796. }
  797. /*****************************************************************
  798. * Routine qui connecte les groupes d'objets si labels identiques *
  799. *******************************************************************/
  800. static void LabelConnection(ObjetNetListStruct *LabelRef)
  801. {
  802. int i, NetCode;
  803. ObjetNetListStruct *ObjetNet;
  804. if( LabelRef->m_NetCode == 0 ) return;
  805. ObjetNet = g_TabObjNet;
  806. for (i = 0; i < g_NbrObjNet; i++)
  807. {
  808. NetCode = ObjetNet[i].m_NetCode;
  809. if( NetCode == LabelRef->m_NetCode ) continue;
  810. if( ObjetNet[i].m_SheetNumber != LabelRef->m_SheetNumber )
  811. {
  812. if (ObjetNet[i].m_Type != NET_PINLABEL ) continue;
  813. }
  814. if( (ObjetNet[i].m_Type == NET_LABEL ) ||
  815. (ObjetNet[i].m_Type == NET_GLOBLABEL ) ||
  816. (ObjetNet[i].m_Type == NET_BUSLABELMEMBER ) ||
  817. (ObjetNet[i].m_Type == NET_GLOBBUSLABELMEMBER ) ||
  818. (ObjetNet[i].m_Type == NET_PINLABEL ) )
  819. {
  820. if( ObjetNet[i].m_Label->CmpNoCase(*LabelRef->m_Label) != 0) continue;
  821. /* Ici 2 labels identiques */
  822. /* Propagation du Netcode a tous les Objets de meme NetCode */
  823. if( ObjetNet[i].m_NetCode )
  824. PropageNetCode(ObjetNet[i].m_NetCode, LabelRef->m_NetCode, 0);
  825. else ObjetNet[i].m_NetCode = LabelRef->m_NetCode;
  826. }
  827. }
  828. }
  829. /****************************************************************************/
  830. static int TriNetCode(ObjetNetListStruct *Objet1, ObjetNetListStruct *Objet2)
  831. /****************************************************************************/
  832. /* Routine de comparaison pour le tri par NetCode croissant
  833. du tableau des elements connectes ( TabPinSort ) par qsort()
  834. */
  835. {
  836. return (Objet1->m_NetCode - Objet2->m_NetCode);
  837. }
  838. /*****************************************************************************/
  839. static int TriBySheet(ObjetNetListStruct *Objet1, ObjetNetListStruct *Objet2)
  840. /*****************************************************************************/
  841. /* Routine de comparaison pour le tri par NumSheet
  842. du tableau des elements connectes ( TabPinSort ) par qsort() */
  843. {
  844. return (Objet1->m_SheetNumber - Objet2->m_SheetNumber);
  845. }
  846. /**********************************************************************/
  847. static void SetUnconnectedFlag( ObjetNetListStruct *ListObj, int NbItems )
  848. /**********************************************************************/
  849. /* Routine positionnant le membre .FlagNoConnect des elements de
  850. la liste des objets netliste, tries par ordre de NetCode
  851. */
  852. {
  853. ObjetNetListStruct * NetItemRef, * NetItemTst, *ItemPtr;
  854. ObjetNetListStruct * NetStart, * NetEnd, * Lim;
  855. int Nb;
  856. IsConnectType StateFlag;
  857. NetStart = NetEnd = ListObj;
  858. Lim = ListObj + NbItems;
  859. NetItemRef = NetStart;
  860. Nb = 0; StateFlag = UNCONNECT;
  861. for ( ; NetItemRef < Lim; NetItemRef++ )
  862. {
  863. if( NetItemRef->m_Type == NET_NOCONNECT )
  864. if( StateFlag != CONNECT ) StateFlag = NOCONNECT;
  865. /* Analyse du net en cours */
  866. NetItemTst = NetItemRef + 1;
  867. if( (NetItemTst >= Lim) ||
  868. (NetItemRef->m_NetCode != NetItemTst->m_NetCode) )
  869. { /* Net analyse: mise a jour de m_FlagOfConnection */
  870. NetEnd = NetItemTst;
  871. for( ItemPtr = NetStart; ItemPtr < NetEnd; ItemPtr++ )
  872. {
  873. ItemPtr->m_FlagOfConnection = StateFlag;
  874. }
  875. if(NetItemTst >= Lim) return;
  876. /* Start Analyse Nouveau Net */
  877. StateFlag = UNCONNECT;
  878. NetStart = NetItemTst;
  879. continue;
  880. }
  881. for ( ; ; NetItemTst ++)
  882. {
  883. if( (NetItemTst >= Lim) ||
  884. (NetItemRef->m_NetCode != NetItemTst->m_NetCode) )
  885. break;
  886. switch( NetItemTst->m_Type )
  887. {
  888. case NET_SEGMENT:
  889. case NET_LABEL:
  890. case NET_GLOBLABEL:
  891. case NET_SHEETLABEL:
  892. case NET_PINLABEL:
  893. case NET_BUS:
  894. case NET_BUSLABELMEMBER:
  895. case NET_SHEETBUSLABELMEMBER:
  896. case NET_GLOBBUSLABELMEMBER:
  897. case NET_JONCTION:
  898. break;
  899. case NET_PIN:
  900. if( NetItemRef->m_Type == NET_PIN )
  901. StateFlag = CONNECT;
  902. break;
  903. case NET_NOCONNECT:
  904. if( StateFlag != CONNECT ) StateFlag = NOCONNECT;
  905. break;
  906. }
  907. }
  908. }
  909. }