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.

1141 lines
39 KiB

18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
  1. /*******************************************************/
  2. /* Module de generation de la Netliste , selon Formats */
  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"
  11. #include "protos.h"
  12. #include "schframe.h"
  13. /* Routines locales */
  14. static void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& FullFileName );
  15. static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f,
  16. bool with_pcbnew );
  17. static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f );
  18. static void WriteListOfNetsCADSTAR( FILE* f, ObjetNetListStruct* ObjNet );
  19. static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_netnames );
  20. static void WriteGENERICListOfNets( FILE* f, ObjetNetListStruct* ObjNet );
  21. static void AddPinToComponentPinList( EDA_SchComponentStruct* Component,
  22. DrawSheetPath* sheet,
  23. LibDrawPin* PinEntry );
  24. static void FindOthersUnits( EDA_SchComponentStruct* Component, DrawSheetPath* Sheet_in);
  25. static int SortPinsByNum( ObjetNetListStruct** Pin1, ObjetNetListStruct** Pin2 );
  26. static void EraseDuplicatePins( ObjetNetListStruct** TabPin, int NbrPin );
  27. static void ClearUsedFlags( WinEDA_SchematicFrame* frame );
  28. /* Variable locales */
  29. static int s_SortedPinCount;
  30. static ObjetNetListStruct** s_SortedComponentPinList;
  31. /******************************************************************************/
  32. void WriteNetList( WinEDA_SchematicFrame* frame, const wxString& FileNameNL,
  33. bool use_netnames )
  34. /*******************************************************************************/
  35. /* Create the netlist file ( Format is given by g_NetFormat )
  36. * bool use_netnames is used only for Spice netlist
  37. */
  38. {
  39. FILE* f = NULL;
  40. if( g_NetFormat < NET_TYPE_CUSTOM1 )
  41. {
  42. if( ( f = wxFopen( FileNameNL, wxT( "wt" ) ) ) == NULL )
  43. {
  44. wxString msg = _( "Failed to create file " ) + FileNameNL;
  45. DisplayError( frame, msg );
  46. return;
  47. }
  48. }
  49. wxBusyCursor Busy;
  50. switch( g_NetFormat )
  51. {
  52. case NET_TYPE_PCBNEW:
  53. WriteNetListPCBNEW( frame, f, TRUE );
  54. fclose( f );
  55. break;
  56. case NET_TYPE_ORCADPCB2:
  57. WriteNetListPCBNEW( frame, f, FALSE );
  58. fclose( f );
  59. break;
  60. case NET_TYPE_CADSTAR:
  61. WriteNetListCADSTAR( frame, f );
  62. fclose( f );
  63. break;
  64. case NET_TYPE_SPICE:
  65. WriteNetListPspice( frame, f, use_netnames );
  66. fclose( f );
  67. break;
  68. default:
  69. Write_GENERIC_NetList( frame, FileNameNL );
  70. break;
  71. }
  72. }
  73. /****************************************************************************/
  74. static EDA_SchComponentStruct* FindNextComponentAndCreatPinList(
  75. EDA_BaseStruct* DrawList, DrawSheetPath* sheet)
  76. /****************************************************************************/
  77. /* Find a "suitable" component from the DrawList
  78. * build its pin list s_SortedComponentPinList.
  79. * The list is sorted by pin num
  80. * A suitable component is a "new" real component (power symbols are not considered)
  81. *
  82. * alloc memory for s_SortedComponentPinList if s_SortedComponentPinList == NULL
  83. * Must be deallocated by the user
  84. */
  85. {
  86. EDA_SchComponentStruct* Component = NULL;
  87. EDA_LibComponentStruct* Entry;
  88. LibEDA_BaseStruct* DEntry;
  89. s_SortedPinCount = 0;
  90. for( ; DrawList != NULL; DrawList = DrawList->Next() )
  91. {
  92. if( DrawList->Type() != DRAW_LIB_ITEM_STRUCT_TYPE )
  93. continue;
  94. Component = (EDA_SchComponentStruct*) DrawList;
  95. /* already tested ? : */
  96. bool found = false;
  97. for(unsigned int i =0; i<Component->m_UsedOnSheets.GetCount(); i++){
  98. if( Component->m_UsedOnSheets.Item(i) == *sheet ){
  99. found = true;
  100. break;
  101. }
  102. }
  103. if( found ) continue;
  104. //if( Component->m_FlagControlMulti == 1 )
  105. // continue; /* yes */
  106. // removed because with multiple instances of one schematic
  107. // (several sheets pointing to 1 screen), this will be erroneously be toggled.
  108. Entry = FindLibPart( Component->m_ChipName.GetData(), wxEmptyString, FIND_ROOT );
  109. if( Entry == NULL )
  110. continue;
  111. /* Power symbol and other component which have the reference starting by
  112. * "#" are not included in netlist (pseudo components) */
  113. wxString str = Component->GetRef(sheet);
  114. if( str[0] == '#' )
  115. continue;
  116. /* Create the pin table for this component */
  117. int ii = sizeof(ObjetNetListStruct*) * MAXPIN;
  118. if( s_SortedComponentPinList == NULL )
  119. s_SortedComponentPinList = (ObjetNetListStruct**) MyMalloc( ii );
  120. memset( s_SortedComponentPinList, 0, ii );
  121. DEntry = Entry->m_Drawings;
  122. for( ; DEntry != NULL; DEntry = DEntry->Next() )
  123. {
  124. if( DEntry->Type() != COMPONENT_PIN_DRAW_TYPE )
  125. continue;
  126. if( DEntry->m_Unit
  127. && (DEntry->m_Unit != Component->m_Multi) )
  128. continue;
  129. if( DEntry->m_Convert
  130. && (DEntry->m_Convert != Component->m_Convert) )
  131. continue;
  132. {
  133. AddPinToComponentPinList( Component, sheet, (LibDrawPin*) DEntry );
  134. }
  135. }
  136. //Component->m_FlagControlMulti = 1;
  137. Component->m_UsedOnSheets.Add(*sheet);
  138. if( Entry->m_UnitCount > 1 )
  139. FindOthersUnits( Component, sheet);
  140. /* Tri sur le numero de Pin de TabListePin */
  141. qsort( s_SortedComponentPinList, s_SortedPinCount, sizeof(ObjetNetListStruct*),
  142. ( int( * ) ( const void*, const void* ) )SortPinsByNum );
  143. /* Elimination des Pins redondantes du s_SortedComponentPinList */
  144. EraseDuplicatePins( s_SortedComponentPinList, s_SortedPinCount );
  145. return Component;
  146. }
  147. return NULL;
  148. }
  149. /**************************************************************************************/
  150. static wxString ReturnPinNetName( ObjetNetListStruct* Pin,
  151. const wxString& DefaultFormatNetname )
  152. /**************************************************************************************/
  153. /* Return the net name for the pin Pin.
  154. * Net name is:
  155. * "?" if pin not connected
  156. * "netname" for global net (like gnd, vcc ..
  157. * "netname_sheetnumber" for the usual nets
  158. */
  159. {
  160. int netcode = Pin->GetNet();
  161. wxString NetName;
  162. if( (netcode == 0 ) || ( Pin->m_FlagOfConnection != PAD_CONNECT ) )
  163. {
  164. return NetName;
  165. }
  166. else
  167. {
  168. int jj;
  169. for( jj = 0; jj < g_NbrObjNet; jj++ )
  170. {
  171. if( g_TabObjNet[jj].GetNet() != netcode )
  172. continue;
  173. if( ( g_TabObjNet[jj].m_Type != NET_HIERLABEL)
  174. && ( g_TabObjNet[jj].m_Type != NET_LABEL)
  175. && ( g_TabObjNet[jj].m_Type != NET_PINLABEL) )
  176. continue;
  177. NetName = *g_TabObjNet[jj].m_Label;
  178. break;
  179. }
  180. if( !NetName.IsEmpty() )
  181. {
  182. if( g_TabObjNet[jj].m_Type != NET_PINLABEL ){
  183. NetName = g_TabObjNet[jj].m_SheetList.PathHumanReadable()
  184. + NetName;
  185. }
  186. //NetName << wxT("_") << g_TabObjNet[jj].m_SheetList.PathHumanReadable();
  187. }
  188. else
  189. {
  190. NetName.Printf( DefaultFormatNetname.GetData(), netcode );
  191. }
  192. }
  193. return NetName;
  194. }
  195. /***********************************************************************/
  196. void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame,
  197. const wxString& FullFileName )
  198. /***********************************************************************/
  199. /* Create a generic netlist, and call an external netlister
  200. * to change the netlist syntax and create the file
  201. * -- does this still work?
  202. */
  203. {
  204. wxString Line, FootprintName;
  205. DrawSheetPath* sheet;
  206. EDA_BaseStruct* DrawList;
  207. EDA_SchComponentStruct* Component;
  208. wxString netname;
  209. int ii;
  210. FILE* tmpfile;
  211. wxString TmpFullFileName = FullFileName;
  212. ChangeFileNameExt( TmpFullFileName, wxT( ".tmp" ) );
  213. if( ( tmpfile = wxFopen( TmpFullFileName, wxT( "wt" ) ) ) == NULL )
  214. {
  215. wxString msg = _( "Failed to create file " ) + TmpFullFileName;
  216. DisplayError( frame, msg );
  217. return;
  218. }
  219. ClearUsedFlags( frame ); /* Reset the flags FlagControlMulti in all schematic files*/
  220. fprintf( tmpfile, "$BeginNetlist\n" );
  221. /* Create netlist module section */
  222. fprintf( tmpfile, "$BeginComponentList\n" );
  223. EDA_SheetList SheetList( NULL );
  224. for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
  225. {
  226. for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Pnext )
  227. {
  228. DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet );
  229. if( Component == NULL )
  230. break; // No component left
  231. FootprintName.Empty();
  232. if( !Component->m_Field[FOOTPRINT].IsVoid() )
  233. {
  234. FootprintName = Component->m_Field[FOOTPRINT].m_Text;
  235. FootprintName.Replace( wxT( " " ), wxT( "_" ) );
  236. }
  237. fprintf( tmpfile, "\n$BeginComponent\n" );
  238. fprintf( tmpfile, "TimeStamp=%8.8lX\n", Component->m_TimeStamp );
  239. fprintf( tmpfile, "Footprint=%s\n", CONV_TO_UTF8( FootprintName ) );
  240. Line = wxT( "Reference=" ) + Component->GetPath(sheet) + wxT( "\n" );
  241. Line.Replace( wxT( " " ), wxT( "_" ) );
  242. fprintf( tmpfile, CONV_TO_UTF8( Line ) );
  243. Line = Component->m_Field[VALUE].m_Text;
  244. Line.Replace( wxT( " " ), wxT( "_" ) );
  245. fprintf( tmpfile, "Value=%s\n", CONV_TO_UTF8( Line ) );
  246. Line = Component->m_ChipName;
  247. Line.Replace( wxT( " " ), wxT( "_" ) );
  248. fprintf( tmpfile, "Libref=%s\n", CONV_TO_UTF8( Line ) );
  249. // Write pin list:
  250. fprintf( tmpfile, "$BeginPinList\n" );
  251. for( ii = 0; ii < s_SortedPinCount; ii++ )
  252. {
  253. ObjetNetListStruct* Pin = s_SortedComponentPinList[ii];
  254. if( !Pin )
  255. continue;
  256. netname = ReturnPinNetName( Pin, wxT( "$-%.6d" ) );
  257. if( netname.IsEmpty() )
  258. netname = wxT( "?" );
  259. fprintf( tmpfile, "%.4s=%s\n", (char*) &Pin->m_PinNum,
  260. CONV_TO_UTF8( netname ) );
  261. }
  262. fprintf( tmpfile, "$EndPinList\n" );
  263. fprintf( tmpfile, "$EndComponent\n" );
  264. }
  265. }
  266. MyFree( s_SortedComponentPinList );
  267. s_SortedComponentPinList = NULL;
  268. fprintf( tmpfile, "$EndComponentList\n" );
  269. fprintf( tmpfile, "\n$BeginNets\n" );
  270. WriteGENERICListOfNets( tmpfile, g_TabObjNet );
  271. fprintf( tmpfile, "$EndNets\n" );
  272. fprintf( tmpfile, "\n$EndNetlist\n" );
  273. fclose( tmpfile );
  274. // Call the external module (plug in )
  275. if( g_NetListerCommandLine.IsEmpty() )
  276. return;
  277. wxString CommandFile;
  278. if( wxIsAbsolutePath( g_NetListerCommandLine ) )
  279. CommandFile = g_NetListerCommandLine;
  280. else
  281. CommandFile = FindKicadFile( g_NetListerCommandLine );
  282. CommandFile += wxT( " " ) + TmpFullFileName;
  283. CommandFile += wxT( " " ) + FullFileName;
  284. wxExecute( CommandFile, wxEXEC_SYNC );
  285. }
  286. /********************************************************/
  287. static void ClearUsedFlags( WinEDA_SchematicFrame* frame )
  288. /********************************************************/
  289. /* Clear flag FlagControlMulti, used in netlist generation */
  290. {
  291. SCH_SCREEN* screen;
  292. EDA_BaseStruct* DrawList;
  293. EDA_ScreenList ScreenList;
  294. for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
  295. {
  296. DrawList = screen->EEDrawList;
  297. while( DrawList )
  298. {
  299. if( DrawList->Type() == DRAW_LIB_ITEM_STRUCT_TYPE )
  300. {
  301. EDA_SchComponentStruct* Component = (EDA_SchComponentStruct*) DrawList;
  302. //Component->m_FlagControlMulti = 0;
  303. Component->m_UsedOnSheets.Clear();
  304. }
  305. DrawList = DrawList->Pnext;
  306. }
  307. }
  308. }
  309. /*************************************************************/
  310. static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f,
  311. bool use_netnames )
  312. /*************************************************************/
  313. /* Routine de generation du fichier netliste ( Format PSPICE )
  314. * si use_netnames = TRUE
  315. * les nodes sont identifies par le netname
  316. * sinon les nodes sont identifies par le netnumber
  317. *
  318. * tous les textes graphiques commenant par [.-+]pspice ou [.-+]gnucap
  319. * sont considrs comme des commandes a placer dans la netliste
  320. * [.-]pspice ou gnucap sont en debut
  321. +pspice et +gnucap sont en fin de netliste
  322. */
  323. {
  324. char Line[1024];
  325. DrawSheetPath* sheet;
  326. EDA_BaseStruct* DrawList;
  327. EDA_SchComponentStruct* Component;
  328. int ii, nbitems;
  329. wxString text;
  330. wxArrayString SpiceCommandAtBeginFile, SpiceCommandAtEndFile;
  331. wxString msg;
  332. #define BUFYPOS_LEN 4
  333. wxChar bufnum[BUFYPOS_LEN + 1];
  334. DateAndTime( Line );
  335. fprintf( f, "* %s (Spice format) creation date: %s\n\n", NETLIST_HEAD_STRING, Line );
  336. /* Create text list starting by [.-]pspice , or [.-]gnucap (simulator commands) */
  337. /* and create text list starting by [+]pspice , or [+]gnucap (simulator commands) */
  338. bufnum[BUFYPOS_LEN] = 0;
  339. EDA_SheetList SheetList( NULL );
  340. for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
  341. {
  342. for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Pnext )
  343. {
  344. wxChar ident;
  345. if( DrawList->Type() != DRAW_TEXT_STRUCT_TYPE )
  346. continue;
  347. #define DRAWTEXT ( (DrawTextStruct*) DrawList )
  348. text = DRAWTEXT->m_Text; if( text.IsEmpty() )
  349. continue;
  350. ident = text.GetChar( 0 );
  351. if( ident != '.' && ident != '-' && ident != '+' )
  352. continue;
  353. text.Remove( 0, 1 ); //Remove the first char.
  354. text.Remove( 6 ); //text contains 6 char.
  355. if( ( text == wxT( "pspice" ) ) || ( text == wxT( "gnucap" ) ) )
  356. {
  357. /* Put the Y position as an ascii string, for sort by vertical position,
  358. * using usual sort string by alphabetic value */
  359. int ypos = DRAWTEXT->m_Pos.y;
  360. for( ii = 0; ii < BUFYPOS_LEN; ii++ )
  361. {
  362. bufnum[BUFYPOS_LEN - 1 - ii] = (ypos & 63) + ' '; ypos >>= 6;
  363. }
  364. text = DRAWTEXT->m_Text.AfterFirst( ' ' );
  365. msg.Printf( wxT( "%s %s" ), bufnum, text.GetData() ); // First BUFYPOS_LEN char are the Y position
  366. if( ident == '+' )
  367. SpiceCommandAtEndFile.Add( msg );
  368. else
  369. SpiceCommandAtBeginFile.Add( msg );
  370. }
  371. }
  372. }
  373. /* Print texts starting by [.-]pspice , ou [.-]gnucap (of course, without the Y position string)*/
  374. nbitems = SpiceCommandAtBeginFile.GetCount();
  375. if( nbitems )
  376. {
  377. SpiceCommandAtBeginFile.Sort();
  378. for( ii = 0; ii < nbitems; ii++ )
  379. {
  380. SpiceCommandAtBeginFile[ii].Remove( 0, BUFYPOS_LEN );
  381. SpiceCommandAtBeginFile[ii].Trim( TRUE );
  382. SpiceCommandAtBeginFile[ii].Trim( FALSE );
  383. fprintf( f, "%s\n", CONV_TO_UTF8( SpiceCommandAtBeginFile[ii] ) );
  384. }
  385. }
  386. fprintf( f, "\n" );
  387. /* Create component list */
  388. ClearUsedFlags( frame ); /* Reset the flags FlagControlMulti in all schematic files*/
  389. for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
  390. {
  391. for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Pnext )
  392. {
  393. DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet );
  394. if( Component == NULL )
  395. break;
  396. fprintf( f, "%s ", CONV_TO_UTF8( Component->GetRef( sheet ) ) );
  397. // Write pin list:
  398. for( ii = 0; ii < s_SortedPinCount; ii++ )
  399. {
  400. ObjetNetListStruct* Pin = s_SortedComponentPinList[ii];
  401. if( !Pin )
  402. continue;
  403. wxString NetName = ReturnPinNetName( Pin, wxT( "N-%.6d" ) );
  404. if( NetName.IsEmpty() )
  405. NetName = wxT( "?" );
  406. if( use_netnames )
  407. fprintf( f, " %s", CONV_TO_UTF8( NetName ) );
  408. else // Use number for net names (with net number = 0 for "GND"
  409. {
  410. // NetName = "0" is "GND" net for Spice
  411. if( NetName == wxT( "0" ) || NetName == wxT( "GND" ) )
  412. fprintf( f, " 0" );
  413. else
  414. fprintf( f, " %d", Pin->GetNet() );
  415. }
  416. }
  417. fprintf( f, " %s\n", CONV_TO_UTF8( Component->m_Field[VALUE].m_Text ) );
  418. }
  419. }
  420. MyFree( s_SortedComponentPinList );
  421. s_SortedComponentPinList = NULL;
  422. /* Print texts starting by [+]pspice , ou [+]gnucap */
  423. nbitems = SpiceCommandAtEndFile.GetCount();
  424. if( nbitems )
  425. {
  426. fprintf( f, "\n" );
  427. SpiceCommandAtEndFile.Sort();
  428. for( ii = 0; ii < nbitems; ii++ )
  429. {
  430. SpiceCommandAtEndFile[ii].Remove( 0, +BUFYPOS_LEN );
  431. SpiceCommandAtEndFile[ii].Trim( TRUE );
  432. SpiceCommandAtEndFile[ii].Trim( FALSE );
  433. fprintf( f, "%s\n", CONV_TO_UTF8( SpiceCommandAtEndFile[ii] ) );
  434. }
  435. }
  436. fprintf( f, "\n.end\n" );
  437. }
  438. /*****************************************************************************************/
  439. static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with_pcbnew )
  440. /*****************************************************************************************/
  441. /* Routine de generation du fichier netliste ( Format ORCAD PCB 2 ameliore )
  442. * si with_pcbnew = FALSE
  443. * format PCBNEW (OrcadPcb2 + commentaires et liste des nets)
  444. * si with_pcbnew = FALSE
  445. * Format ORCADPCB2 strict
  446. */
  447. {
  448. wxString Line, FootprintName;
  449. char Buf[256];
  450. DrawSheetPath* sheet;
  451. EDA_BaseStruct* DrawList;
  452. EDA_SchComponentStruct* Component;
  453. int ii;
  454. ListComponent* CmpList = NULL;
  455. int CmpListCount = 0, CmpListSize = 1000;
  456. DateAndTime( Buf );
  457. if( with_pcbnew )
  458. fprintf( f, "# %s created %s\n(\n", NETLIST_HEAD_STRING, Buf );
  459. else
  460. fprintf( f, "( { %s created %s }\n", NETLIST_HEAD_STRING, Buf );
  461. /* Create netlist module section */
  462. ClearUsedFlags( frame ); /* Reset the flags FlagControlMulti in all schematic files*/
  463. EDA_SheetList SheetList( NULL );
  464. for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
  465. {
  466. for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Pnext )
  467. {
  468. DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet);
  469. if( Component == NULL )
  470. break;
  471. /* Get the Component FootprintFilter and put the component in CmpList if filter is not void */
  472. EDA_LibComponentStruct* Entry;
  473. if( ( Entry = FindLibPart( Component->m_ChipName.GetData(), wxEmptyString,
  474. FIND_ROOT ) ) != NULL )
  475. {
  476. if( Entry->m_FootprintList.GetCount() != 0 ) /* Put in list */
  477. {
  478. if( CmpList == NULL ){
  479. CmpList = (ListComponent*)
  480. MyZMalloc( sizeof(ListComponent) * CmpListSize );
  481. }
  482. if( CmpListCount >= CmpListSize )
  483. {
  484. CmpListSize += 1000;
  485. CmpList = (ListComponent*) realloc(
  486. CmpList,
  487. sizeof(ListComponent) * CmpListSize );
  488. }
  489. CmpList[CmpListCount].m_Comp = Component;
  490. strcpy(CmpList[CmpListCount].m_Ref, Component->GetRef( sheet ).mb_str());
  491. CmpListCount++;
  492. }
  493. }
  494. if( !Component->m_Field[FOOTPRINT].IsVoid() )
  495. {
  496. FootprintName = Component->m_Field[FOOTPRINT].m_Text;
  497. FootprintName.Replace( wxT( " " ), wxT( "_" ) );
  498. }
  499. else
  500. FootprintName = wxT( "$noname" );
  501. Line = Component->GetRef(sheet);
  502. fprintf( f, " ( %s %s",
  503. CONV_TO_UTF8(Component->GetPath(sheet)),
  504. CONV_TO_UTF8( FootprintName ) );
  505. fprintf( f, " %s", CONV_TO_UTF8( Line ) );
  506. Line = Component->m_Field[VALUE].m_Text;
  507. Line.Replace( wxT( " " ), wxT( "_" ) );
  508. fprintf( f, " %s", CONV_TO_UTF8( Line ) );
  509. if( with_pcbnew ) // Add the lib name for this component
  510. {
  511. Line = Component->m_ChipName;
  512. Line.Replace( wxT( " " ), wxT( "_" ) );
  513. fprintf( f, " {Lib=%s}", CONV_TO_UTF8( Line ) );
  514. }
  515. fprintf( f, "\n" );
  516. // Write pin list:
  517. for( ii = 0; ii < s_SortedPinCount; ii++ )
  518. {
  519. ObjetNetListStruct* Pin = s_SortedComponentPinList[ii];
  520. if( !Pin )
  521. continue;
  522. wxString netname = ReturnPinNetName( Pin, wxT( "N-%.6d" ) );
  523. if( netname.IsEmpty() )
  524. netname = wxT( " ?" );
  525. fprintf( f, " ( %4.4s %s )\n", (char*) &Pin->m_PinNum,
  526. CONV_TO_UTF8( netname ) );
  527. }
  528. fprintf( f, " )\n" );
  529. }
  530. }
  531. fprintf( f, ")\n*\n" );
  532. MyFree( s_SortedComponentPinList );
  533. s_SortedComponentPinList = NULL;
  534. /* Write the allowed footprint list for each component */
  535. if( with_pcbnew && CmpList )
  536. {
  537. fprintf( f, "{ Allowed footprints by component:\n" );
  538. EDA_LibComponentStruct* Entry;
  539. for( ii = 0; ii < CmpListCount; ii++ )
  540. {
  541. Component = CmpList[ii].m_Comp;
  542. Entry = FindLibPart( Component->m_ChipName.GetData(), wxEmptyString, FIND_ROOT );
  543. //Line.Printf(_("%s"), CmpList[ii].m_Ref);
  544. //Line.Replace( wxT( " " ), wxT( "_" ) );
  545. unsigned int i;
  546. for(i=0; i<sizeof(CmpList[ii].m_Ref) && CmpList[ii].m_Ref[i]; i++){
  547. if(CmpList[ii].m_Ref[i] == ' ')
  548. CmpList[ii].m_Ref[i] = '_';
  549. }
  550. fprintf( f, "$component %s\n", CmpList[ii].m_Ref );
  551. /* Write the footprint list */
  552. for( unsigned int jj = 0; jj < Entry->m_FootprintList.GetCount(); jj++ )
  553. {
  554. fprintf( f, " %s\n", CONV_TO_UTF8( Entry->m_FootprintList[jj] ) );
  555. }
  556. fprintf( f, "$endlist\n" );
  557. }
  558. fprintf( f, "$endfootprintlist\n}\n" );
  559. }
  560. if( CmpList )
  561. free( CmpList );
  562. if( with_pcbnew )
  563. {
  564. fprintf( f, "{ Pin List by Nets\n" );
  565. WriteGENERICListOfNets( f, g_TabObjNet );
  566. fprintf( f, "}\n" );
  567. fprintf( f, "#End\n" );
  568. }
  569. }
  570. /*************************************************************************************/
  571. static void AddPinToComponentPinList( EDA_SchComponentStruct* Component,
  572. DrawSheetPath* sheetlist, LibDrawPin* Pin )
  573. /*************************************************************************************/
  574. /* Add a new pin description in the pin list s_SortedComponentPinList
  575. * a pin description is a pointer to the corresponding structure
  576. * created by BuildNetList() in the table g_TabObjNet
  577. */
  578. {
  579. int ii;
  580. /* Search the PIN description for Pin in g_TabObjNet*/
  581. for( ii = 0; ii < g_NbrObjNet; ii++ )
  582. {
  583. if( g_TabObjNet[ii].m_Type != NET_PIN )
  584. continue;
  585. if( g_TabObjNet[ii].m_Link != Component )
  586. continue;
  587. if( g_TabObjNet[ii].m_SheetList != *sheetlist )
  588. continue;
  589. if( g_TabObjNet[ii].m_PinNum != Pin->m_PinNum )
  590. continue;
  591. {
  592. s_SortedComponentPinList[s_SortedPinCount] = &g_TabObjNet[ii];
  593. s_SortedPinCount++;
  594. if( s_SortedPinCount >= MAXPIN )
  595. {
  596. /* Log message for Internal error */
  597. DisplayError( NULL, wxT( "AddPinToComponentPinList err: MAXPIN reached" ) );
  598. return;
  599. }
  600. }
  601. }
  602. }
  603. /**********************************************************************/
  604. static void EraseDuplicatePins( ObjetNetListStruct** TabPin, int NbrPin )
  605. /**********************************************************************/
  606. /*
  607. * Routine qui elimine les Pins de meme Numero de la liste des objets
  608. * (Liste des Pins d'un boitier) passee en entree
  609. * Ces pins redondantes proviennent des pins (alims... ) communes a plusieurs
  610. * elements d'un boitier a multiple parts.
  611. */
  612. {
  613. int ii, jj;
  614. for( ii = 0; ii < NbrPin - 1; ii++ )
  615. {
  616. if( TabPin[ii] == NULL )
  617. continue; /* Deja supprime */
  618. if( TabPin[ii]->m_PinNum != TabPin[ii + 1]->m_PinNum )
  619. continue;
  620. /* 2 Pins doublees */
  621. for( jj = ii + 1; jj < NbrPin; jj++ )
  622. {
  623. if( TabPin[ii]->m_PinNum != TabPin[jj]->m_PinNum )
  624. break;
  625. TabPin[jj] = NULL;
  626. }
  627. }
  628. }
  629. /**********************************************************************/
  630. static void FindOthersUnits( EDA_SchComponentStruct* Component_in, DrawSheetPath* Sheet_in)
  631. /**********************************************************************/
  632. /* Recherche les autres parts du boitier auquel appartient la part Component,
  633. * pour les boitiers a parts multiples.
  634. * Appelle AddPinToComponentPinList() pour classer les pins des parts trouvees
  635. */
  636. {
  637. EDA_BaseStruct* DrawList;
  638. EDA_SchComponentStruct* Component2;
  639. EDA_LibComponentStruct* Entry;
  640. LibEDA_BaseStruct* DEntry;
  641. DrawSheetPath* sheet;
  642. wxString str;
  643. EDA_SheetList SheetList( NULL );
  644. unsigned int i;
  645. bool found;
  646. for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
  647. {
  648. DrawList = sheet->LastDrawList();
  649. while( DrawList )
  650. {
  651. switch( DrawList->Type() )
  652. {
  653. case DRAW_LIB_ITEM_STRUCT_TYPE:
  654. Component2 = (EDA_SchComponentStruct*) DrawList;
  655. found = false;
  656. for( i =0; i<Component2->m_UsedOnSheets.GetCount(); i++){
  657. if( Component2->m_UsedOnSheets.Item(i) == *Sheet_in ){
  658. found = true;
  659. }
  660. }
  661. if( found ) break;
  662. //if( Component2->m_FlagControlMulti == 1 ) //has it been used? (on this sheet?)
  663. // break;
  664. str = Component2->GetRef(sheet);
  665. if( str.CmpNoCase( Component_in->GetRef(Sheet_in) ) != 0 )
  666. break;
  667. Entry = FindLibPart( Component2->m_ChipName.GetData(), wxEmptyString, FIND_ROOT );
  668. if( Entry == NULL )
  669. break;
  670. if( str[0] == '#' )
  671. break;
  672. if( Entry->m_Drawings != NULL )
  673. {
  674. DEntry = Entry->m_Drawings;
  675. for( ; DEntry != NULL; DEntry = DEntry->Next() )
  676. {
  677. if( DEntry->Type() != COMPONENT_PIN_DRAW_TYPE )
  678. continue;
  679. if( DEntry->m_Unit
  680. && (DEntry->m_Unit != Component2->m_Multi) )
  681. continue;
  682. if( DEntry->m_Convert
  683. && (DEntry->m_Convert != Component2->m_Convert) )
  684. continue;
  685. {
  686. AddPinToComponentPinList( Component2, sheet, (LibDrawPin*) DEntry );
  687. }
  688. }
  689. }
  690. Component2->m_UsedOnSheets.Add(*Sheet_in);
  691. //Component2->m_FlagControlMulti = 1; //mark it as used..
  692. break;
  693. default:
  694. break;
  695. }
  696. DrawList = DrawList->Pnext;
  697. }
  698. }
  699. }
  700. /**************************************************************************/
  701. static int SortPinsByNum( ObjetNetListStruct** Pin1, ObjetNetListStruct** Pin2 )
  702. /**************************************************************************/
  703. /* Routine de comparaison pour le tri des pins par numero croissant
  704. * du tableau des pins s_SortedComponentPinList par qsort()
  705. */
  706. {
  707. ObjetNetListStruct* Obj1, * Obj2;
  708. int Num1, Num2;
  709. char Line[5];
  710. Obj1 = *Pin1; Obj2 = *Pin2;
  711. Num1 = Obj1->m_PinNum; Num2 = Obj2->m_PinNum;
  712. Line[4] = 0; memcpy( Line, &Num1, 4 ); Num1 = atoi( Line );
  713. memcpy( Line, &Num2, 4 ); Num2 = atoi( Line );
  714. return Num1 - Num2;
  715. }
  716. /*************************************************************************/
  717. static void WriteGENERICListOfNets( FILE* f, ObjetNetListStruct* ObjNet )
  718. /*************************************************************************/
  719. /* Ecrit dans le fichier f la liste des nets ( classee par NetCodes ), et des
  720. * elements qui y sont connectes
  721. */
  722. {
  723. int ii, jj;
  724. int NetCode, LastNetCode = -1;
  725. int SameNetcodeCount = 0;
  726. EDA_SchComponentStruct* Cmp;
  727. wxString NetName, CmpRef;
  728. wxString NetcodeName;
  729. char FirstItemInNet[1024];
  730. for( ii = 0; ii < g_NbrObjNet; ii++ )
  731. {
  732. if( (NetCode = ObjNet[ii].GetNet()) != LastNetCode ) // New net found, write net id;
  733. {
  734. SameNetcodeCount = 0; // Items count for this net
  735. NetName.Empty();
  736. for( jj = 0; jj < g_NbrObjNet; jj++ ) // Find a label (if exists) for this net
  737. {
  738. if( ObjNet[jj].GetNet() != NetCode )
  739. continue;
  740. if( ( ObjNet[jj].m_Type != NET_HIERLABEL)
  741. && ( ObjNet[jj].m_Type != NET_LABEL)
  742. && ( ObjNet[jj].m_Type != NET_PINLABEL) )
  743. continue;
  744. NetName = *g_TabObjNet[jj].m_Label; break;
  745. }
  746. NetcodeName.Printf( wxT( "Net %d " ), NetCode );
  747. NetcodeName += wxT( "\"" );
  748. if( !NetName.IsEmpty() )
  749. {
  750. NetcodeName += NetName;
  751. if( g_TabObjNet[jj].m_Type != NET_PINLABEL ){
  752. // usual net name, add in the sheet path
  753. NetcodeName = g_TabObjNet[jj].m_SheetList.PathHumanReadable()
  754. + NetcodeName;
  755. //NetcodeName << wxT("_") <<
  756. // g_TabObjNet[jj].m_SheetList.PathHumanReadable();
  757. }
  758. }
  759. NetcodeName += wxT( "\"" );
  760. LastNetCode = NetCode;
  761. }
  762. if( ObjNet[ii].m_Type != NET_PIN )
  763. continue;
  764. Cmp = (EDA_SchComponentStruct*) ObjNet[ii].m_Link;
  765. CmpRef = Cmp->GetRef(&ObjNet[ii].m_SheetList); //is this correct?
  766. if( CmpRef.StartsWith( wxT( "#" ) ) )
  767. continue; // Pseudo component (Like Power symbol)
  768. // Print the pin list for this net, if 2 or more items are connected:
  769. SameNetcodeCount++;
  770. if( SameNetcodeCount == 1 ) /* first item for this net found,
  771. * Print this connection, when a second item will be found */
  772. {
  773. sprintf( FirstItemInNet, " %s %.4s\n", CONV_TO_UTF8( CmpRef ),
  774. (const char*) &ObjNet[ii].m_PinNum );
  775. }
  776. if( SameNetcodeCount == 2 ) // Second item for this net found, Print the Net name, and the first item
  777. {
  778. fprintf( f, "%s\n", CONV_TO_UTF8( NetcodeName ) );
  779. fputs( FirstItemInNet, f );
  780. }
  781. if( SameNetcodeCount >= 2 )
  782. fprintf( f, " %s %.4s\n", CONV_TO_UTF8( CmpRef ),
  783. (const char*) &ObjNet[ii].m_PinNum );
  784. }
  785. }
  786. /* Generation des netlistes au format CadStar */
  787. wxString StartLine( wxT( "." ) );
  788. /*********************************************************/
  789. static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f )
  790. /*********************************************************/
  791. /* Routine de generation du fichier netliste ( Format CADSTAR )
  792. * Entete:
  793. * ..HEA
  794. * ..TIM 2004 07 29 16 22 17
  795. * ..APP "Cadstar RINF Output - Version 6.0.2.3"
  796. * ..UNI INCH 1000.0 in
  797. * ..TYP FULL
  798. *
  799. * liste des composants:
  800. * ..ADD_COM X1 "CNT D41612 (48PTS MC CONTOUR)"
  801. * ..ADD_COM U2 "74HCT245D" "74HCT245D"
  802. *
  803. * Connexions:
  804. * ..ADD_TER RR2 6 "$42"
  805. * ..TER U1 100
  806. * CA 6
  807. *
  808. * ..ADD_TER U2 6 "$59"
  809. * ..TER U7 39
  810. * U6 17
  811. * U1 122
  812. *
  813. * ..ADD_TER P2 1 "$9"
  814. * ..TER T3 1
  815. * U1 14
  816. */
  817. {
  818. wxString StartCmpDesc = StartLine + wxT( "ADD_COM" );
  819. wxString msg;
  820. wxString FootprintName;
  821. char Line[1024];
  822. DrawSheetPath* sheet;
  823. EDA_BaseStruct* DrawList;
  824. EDA_SchComponentStruct* Component;
  825. wxString Title = g_Main_Title + wxT( " " ) + GetBuildVersion();
  826. fprintf( f, "%sHEA\n", CONV_TO_UTF8( StartLine ) );
  827. DateAndTime( Line );
  828. fprintf( f, "%sTIM %s\n", CONV_TO_UTF8( StartLine ), Line );
  829. fprintf( f, "%sAPP ", CONV_TO_UTF8( StartLine ) );
  830. fprintf( f, "\"%s\"\n", CONV_TO_UTF8( Title ) );
  831. fprintf( f, "\n" );
  832. /* Create netlist module section */
  833. ClearUsedFlags( frame ); /* Reset the flags FlagControlMulti in all schematic files*/
  834. EDA_SheetList SheetList( NULL );
  835. for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
  836. {
  837. for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Pnext )
  838. {
  839. DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet);
  840. if( Component == NULL )
  841. break;
  842. if( !Component->m_Field[FOOTPRINT].IsVoid() )
  843. {
  844. FootprintName = Component->m_Field[FOOTPRINT].m_Text;
  845. FootprintName.Replace( wxT( " " ), wxT( "_" ) );
  846. }
  847. else
  848. FootprintName = wxT( "$noname" );
  849. msg = Component->GetRef(sheet);
  850. fprintf( f, "%s ", CONV_TO_UTF8( StartCmpDesc ) );
  851. fprintf( f, "%s", CONV_TO_UTF8( msg ) );
  852. msg = Component->m_Field[VALUE].m_Text;
  853. msg.Replace( wxT( " " ), wxT( "_" ) );
  854. fprintf( f, " \"%s\"", CONV_TO_UTF8( msg ) );
  855. fprintf( f, "\n" );
  856. }
  857. }
  858. fprintf( f, "\n" );
  859. MyFree( s_SortedComponentPinList );
  860. s_SortedComponentPinList = NULL;
  861. WriteListOfNetsCADSTAR( f, g_TabObjNet );
  862. fprintf( f, "\n%sEND\n", CONV_TO_UTF8( StartLine ) );
  863. }
  864. /*************************************************************************/
  865. static void WriteListOfNetsCADSTAR( FILE* f, ObjetNetListStruct* ObjNet )
  866. /*************************************************************************/
  867. /* Ecrit dans le fichier f la liste des nets ( classee par NetCodes ), et des
  868. * pins qui y sont connectes
  869. * format:
  870. * .ADD_TER RR2 6 "$42"
  871. * .TER U1 100
  872. * CA 6
  873. */
  874. {
  875. wxString InitNetDesc = StartLine + wxT( "ADD_TER" );
  876. wxString StartNetDesc = StartLine + wxT( "TER" );
  877. wxString NetcodeName, InitNetDescLine;
  878. int ii, jj, print_ter = 0;
  879. int NetCode, LastNetCode = -1;
  880. EDA_SchComponentStruct* Cmp;
  881. wxString NetName;
  882. for( ii = 0; ii < g_NbrObjNet; ii++ )
  883. ObjNet[ii].m_Flag = 0;
  884. for( ii = 0; ii < g_NbrObjNet; ii++ )
  885. {
  886. // Get the NetName of the current net :
  887. if( (NetCode = ObjNet[ii].GetNet()) != LastNetCode )
  888. {
  889. NetName.Empty();
  890. for( jj = 0; jj < g_NbrObjNet; jj++ )
  891. {
  892. if( ObjNet[jj].GetNet() != NetCode )
  893. continue;
  894. if( ( ObjNet[jj].m_Type != NET_HIERLABEL)
  895. && ( ObjNet[jj].m_Type != NET_LABEL)
  896. && ( ObjNet[jj].m_Type != NET_PINLABEL) )
  897. continue;
  898. NetName = *ObjNet[jj].m_Label; break;
  899. }
  900. NetcodeName = wxT( "\"" );
  901. if( !NetName.IsEmpty() )
  902. {
  903. NetcodeName += NetName;
  904. if( g_TabObjNet[jj].m_Type != NET_PINLABEL ){
  905. NetcodeName = g_TabObjNet[jj].m_SheetList.PathHumanReadable()
  906. + NetcodeName;
  907. //NetcodeName << wxT("_") <<
  908. // g_TabObjNet[jj].m_SheetList.PathHumanReadable();
  909. }
  910. }
  911. else // this net has no name: create a default name $<net number>
  912. NetcodeName << wxT( "$" ) << NetCode;
  913. NetcodeName += wxT( "\"" );
  914. LastNetCode = NetCode;
  915. print_ter = 0;
  916. }
  917. if( ObjNet[ii].m_Type != NET_PIN )
  918. continue;
  919. if( ObjNet[ii].m_Flag != 0 )
  920. continue;
  921. Cmp = (EDA_SchComponentStruct*) ObjNet[ii].m_Link;
  922. wxString refstr = Cmp->GetRef(&(ObjNet[ii].m_SheetList));
  923. if( refstr[0] == '#' )
  924. continue; // Pseudo composant (symboles d'alims)
  925. switch( print_ter )
  926. {
  927. case 0:
  928. {
  929. char buf[5];
  930. wxString str_pinnum;
  931. strncpy( buf, (char*) &ObjNet[ii].m_PinNum, 4 ); buf[4] = 0;
  932. str_pinnum = CONV_FROM_UTF8( buf );
  933. InitNetDescLine.Printf( wxT( "\n%s %s %.4s %s" ),
  934. InitNetDesc.GetData(),
  935. refstr.GetData(),
  936. str_pinnum.GetData(), NetcodeName.GetData() );
  937. }
  938. print_ter++;
  939. break;
  940. case 1:
  941. fprintf( f, "%s\n", CONV_TO_UTF8( InitNetDescLine ) );
  942. fprintf( f, "%s %s %.4s\n",
  943. CONV_TO_UTF8( StartNetDesc ),
  944. CONV_TO_UTF8( refstr ),
  945. (char*) &ObjNet[ii].m_PinNum );
  946. print_ter++;
  947. break;
  948. default:
  949. fprintf( f, " %s %.4s\n",
  950. CONV_TO_UTF8( refstr ),
  951. (char*) &ObjNet[ii].m_PinNum );
  952. break;
  953. }
  954. ObjNet[ii].m_Flag = 1;
  955. // Recherche des pins redondantes et mise a 1 de m_Flag,
  956. // pour ne pas generer plusieurs fois la connexion
  957. for( jj = ii + 1; jj < g_NbrObjNet; jj++ )
  958. {
  959. if( ObjNet[jj].GetNet() != NetCode )
  960. break;
  961. if( ObjNet[jj].m_Type != NET_PIN )
  962. continue;
  963. EDA_SchComponentStruct* tstcmp =
  964. (EDA_SchComponentStruct*) ObjNet[jj].m_Link;
  965. wxString p = Cmp->GetPath( &( ObjNet[ii].m_SheetList ) );
  966. wxString tstp = tstcmp->GetPath( &( ObjNet[jj].m_SheetList ) );
  967. if( p.Cmp(tstp) != 0 )
  968. continue;
  969. if( ObjNet[jj].m_PinNum == ObjNet[ii].m_PinNum )
  970. ObjNet[jj].m_Flag = 1;
  971. }
  972. }
  973. }