← Back to team overview

kicad-developers team mailing list archive

ERC exceptions

 

This patch adds a mechanism to suppress ERC errors and warnings that
are caused by pin incompatibilities. It works by loading a file with
ERC exceptions each time an ERC is performed and then looking for a
matching entry before issuing a warning or error.

The file has the same path and name as the .sch file, but ends in .erx
(Electric Rule eXceptions). Each line contains the following four
whitespace-separated fields:

- component reference of the first component 
- pin number of the first component 
- component reference of the second component 
- pin number of the second component

# is used as a comment character.

Example:
http://svn.openmoko.org/trunk/gta02-core/gta02-core.erx

Note that the file is reloaded each time ERC is invoked, so one can
edit it in parallel to running eeschema.

Known bug: ERC dialog window needs reformatting for displaying the
exception count.

The patch depends on the TestOthersItems streamlining patch I sent
before.

- Werner

---

Index: kicad/eeschema/erc.cpp
===================================================================
--- kicad.orig/eeschema/erc.cpp	2009-07-03 10:05:43.000000000 -0300
+++ kicad/eeschema/erc.cpp	2009-07-03 10:19:15.000000000 -0300
@@ -267,6 +267,188 @@
}


+static struct exception
+{
+ char* a_ref;
+ char* a_pin;
+ char* b_ref;
+ char* b_pin;
+ char* line; /* pointer to the memory object we've allocated */
+ struct exception* next;
+}* exceptions;
+
+
+
+/********************************************************************/
+static void FreeExceptions( void )
+/********************************************************************/
+{
+ struct exception* next;
+
+ while( exceptions )
+ {
+	next = exceptions->next;
+	MyFree( exceptions->line );
+	MyFree( exceptions );
+	exceptions = next;
+ }
+}
+
+
+/********************************************************************/
+static bool ParseField( char **s, char **field )
+/********************************************************************/
+{
+ *field = *s;
+ if( ! **s )
+	return FALSE;
+ while( **s && ! isspace( **s ) )
+	(*s)++;
+ if( ! **s )
+	return TRUE;
+ *(*s)++ = 0;
+ while( **s && isspace( **s ) )
+	(*s)++;
+ return TRUE;
+}
+
+
+/********************************************************************/
+static bool ParseException( char *s )
+/********************************************************************/
+{
+ struct exception tmp;
+ struct exception* e;
+
+ tmp.line = s;
+
+ if( ! ParseField( &s, &tmp.a_ref))
+	return FALSE;
+ if( ! ParseField( &s, &tmp.a_pin ))
+	return FALSE;
+ if( ! ParseField( &s, &tmp.b_ref))
+	return FALSE;
+ if( ! ParseField( &s, &tmp.b_pin ))
+	return FALSE;
+
+ e = (struct exception*) MyMalloc( sizeof( *e ));
+ *e = tmp;
+ e->next = exceptions;
+ exceptions = e;
+
+ return TRUE;
+}
+
+
+/********************************************************************/
+static bool LoadExceptionsByName( const wxString &file_name )
+/********************************************************************/
+{
+ FILE* file;
+ char buf[200]; /* enough room for chatty comments */
+ char* s;
+ char* tmp;
+ char* hash;
+ int n = 0;
+
+ FreeExceptions();
+ file = wxFopen( file_name, wxT( "r" ) );
+ if( ! file )
+	return FALSE;
+
+ while( 1 )
+ {
+	s = fgets( buf, sizeof( buf ), file );
+	if( ! s )
+	break;
+
+	n++;
+
+	// remove comments
+	hash = strchr( s, '#' );
+	if( hash )
+	*hash = 0;
+
+	// skip leading whitespace
+	while( *s && isspace( *s ) )
+	s++;
+	if( ! *s )
+	continue;
+
+	tmp = (char*) MyMalloc( strlen( s ) + 1 );
+	strcpy( tmp, s );
+
+	if( ! ParseException( tmp ) )
+	{
+	wxString msg;
+
+	msg.Printf( wxT( "Parse error at %s:%d" ),
+	CONV_TO_UTF8( file_name ), n );
+	DisplayError( NULL, msg );
+	MyFree( tmp );
+	break;
+	}
+ }
+
+ fclose( file );
+
+ return TRUE;
+}
+
+
+/********************************************************************/
+static void LoadExceptions( void )
+/********************************************************************/
+{
+ wxFileName fn;
+
+ fn = g_RootSheet->m_AssociatedScreen->m_FileName;
+ fn.SetExt( wxT( "erx" ) );
+ if ( LoadExceptionsByName( fn.GetFullPath() ) )
+	g_EESchemaVar.NbExceptionErc = 0;
+}
+
+
+/********************************************************************/
+static bool FindException( ObjetNetListStruct* a, ObjetNetListStruct* b )
+/********************************************************************/
+{
+ SCH_COMPONENT* a_comp = (SCH_COMPONENT*) a->m_Link;
+ SCH_COMPONENT* b_comp = (SCH_COMPONENT*) b->m_Link;
+ const char* a_ref = CONV_TO_UTF8( a_comp->GetRef( &a->m_SheetList ) );
+ const char* b_ref = CONV_TO_UTF8( b_comp->GetRef( &b->m_SheetList ) );
+ const char* a_pin = (char *) &a->m_PinNum;
+ const char* b_pin = (char *) &b->m_PinNum;
+ struct exception* e = exceptions;
+
+ for( e = exceptions; e; e = e->next )
+ {
+#if 0
+fprintf(stderr, "a) %s %4.4s =? %s %4.4s\n", e->a_ref, e->a_pin, a_ref, a_pin);
+fprintf(stderr, "b) %s %4.4s =? %s %4.4s\n", e->b_ref, e->b_pin, b_ref, b_pin);
+#endif
+	if( strcmp( e->a_ref, a_ref ) )
+	continue;
+	if( strncmp( e->a_pin, a_pin, 4 ) )
+	continue;
+	if( strcmp( e->b_ref, b_ref ) )
+	continue;
+	if( strncmp( e->b_pin, b_pin, 4 ) )
+	continue;
+	return TRUE;
+ }
+ return FALSE;
+}
+
+
+/********************************************************************/
+static bool IsException( ObjetNetListStruct* a, ObjetNetListStruct* b )
+/********************************************************************/
+{
+ return FindException( a, b ) || FindException( b, a);
+}
+
+
/**************************************************/
void WinEDA_ErcFrame::TestErc( wxCommandEvent& event )
/**************************************************/
@@ -303,6 +485,7 @@

g_EESchemaVar.NbErrorErc = 0;
g_EESchemaVar.NbWarningErc = 0;
+ g_EESchemaVar.NbExceptionErc = -1; /* -1 means "no file" */

/* Cleanup the entire hierarchy */
EDA_ScreenList ScreenList;
@@ -320,6 +503,8 @@

m_Parent->BuildNetListBase();

+ LoadExceptions();
+
/* Analyse de la table des connexions : */
Lim = g_TabObjNet + g_NbrObjNet;

@@ -379,7 +564,13 @@
FreeTabNetList( g_TabObjNet, g_NbrObjNet );

wxString num;
- num.Printf( wxT( "%d" ), g_EESchemaVar.NbErrorErc );
+
+ if( g_EESchemaVar.NbExceptionErc >= 0)
+	num.Printf( wxT( "%d (%d exception%s)" ), g_EESchemaVar.NbErrorErc,
+	g_EESchemaVar.NbExceptionErc,
+	g_EESchemaVar.NbExceptionErc == 1 ? "" : "s" );
+ else
+	num.Printf( wxT( "%d" ), g_EESchemaVar.NbErrorErc );
m_TotalErrCount->SetLabel( num );

num.Printf( wxT( "%d" ), g_EESchemaVar.NbErrorErc - g_EESchemaVar.NbWarningErc );
@@ -693,6 +884,12 @@
if( NetItemTst->m_FlagOfConnection > 0 )
break;

+	if( IsException( NetItemRef, NetItemTst ) )
+	{
+	g_EESchemaVar.NbExceptionErc++;
+	break;
+	}
+
Diagnose( panel, DC, NetItemRef, NetItemTst, 0, erc );
NetItemTst->m_FlagOfConnection = NOCONNECT;
break;
Index: kicad/eeschema/general.h
===================================================================
--- kicad.orig/eeschema/general.h	2009-07-03 10:04:40.000000000 -0300
+++ kicad/eeschema/general.h	2009-07-03 10:05:43.000000000 -0300
@@ -123,6 +123,7 @@
{
int NbErrorErc;
int NbWarningErc;
+ int NbExceptionErc;
};

extern struct EESchemaVariables g_EESchemaVar;

 




Follow ups