748 lines
26 KiB
C++
748 lines
26 KiB
C++
/**************************************************/
|
|
/* Module de tst "ERC" ( Electrical Rules Check ) */
|
|
/**************************************************/
|
|
|
|
#include "fctsys.h"
|
|
#include "common.h"
|
|
#include "class_drawpanel.h"
|
|
#include "kicad_string.h"
|
|
#include "gestfich.h"
|
|
#include "appl_wxstruct.h"
|
|
#include "bitmaps.h"
|
|
|
|
#include "program.h"
|
|
#include "general.h"
|
|
#include "netlist.h"
|
|
#include "class_marker_sch.h"
|
|
#include "protos.h"
|
|
#include "erc.h"
|
|
|
|
#include "dialog_erc.h"
|
|
|
|
|
|
/* ERC tests :
|
|
* 1 - conflicts between connected pins ( example: 2 connected outputs )
|
|
* 2 - minimal connections requirements ( 1 input *must* be connected to an output, or a passive pin )
|
|
*/
|
|
|
|
|
|
/* fonctions locales */
|
|
static bool WriteDiagnosticERC( const wxString& FullFileName );
|
|
static void Diagnose( WinEDA_DrawPanel* panel,
|
|
NETLIST_OBJECT* NetItemRef,
|
|
NETLIST_OBJECT* NetItemTst, int MinConnexion, int Diag );
|
|
static void TestOthersItems( WinEDA_DrawPanel* panel,
|
|
unsigned NetItemRef,
|
|
unsigned NetStart,
|
|
int* NetNbItems, int* MinConnexion );
|
|
static void TestLabel( WinEDA_DrawPanel* panel,
|
|
unsigned NetItemRef,
|
|
unsigned StartNet );
|
|
|
|
/* Local variables */
|
|
int WriteFichierERC = FALSE;
|
|
|
|
/*
|
|
* Electrical type of pins:
|
|
* PIN_INPUT = usual pin input: must be connected
|
|
* PIN_OUTPUT = usual output
|
|
* PIN_BIDI = input or output (like port for a microprocessor)
|
|
* PIN_TRISTATE = tris state bus pin
|
|
* PIN_PASSIVE = pin for passive components: must be connected, and can be connected to any pin
|
|
* PIN_UNSPECIFIED = unkown electrical properties: creates alway a warning when connected
|
|
* PIN_POWER_IN = power input (GND, VCC for ICs). Must be connected to a power output.
|
|
* PIN_POWER_OUT = output of a regulator: intended to be connected to power input pins
|
|
* PIN_OPENCOLLECTOR = pin type open collector
|
|
* PIN_OPENEMITTER = pin type open emitter
|
|
* PIN_NC = not connected (must be left open)
|
|
*
|
|
* Minimal requirements:
|
|
* All pins *must* be connected (except PIN_NC).
|
|
* When a pin is not connected in schematic, the user must place a "non connected" symbol to this pin.
|
|
* This ensures a forgotten connection will be detected.
|
|
*/
|
|
|
|
/* Messages for conflicts :
|
|
* PIN_INPUT, PIN_OUTPUT, PIN_BIDI, PIN_TRISTATE, PIN_PASSIVE,
|
|
* PIN_UNSPECIFIED, PIN_POWER_IN, PIN_POWER_OUT, PIN_OPENCOLLECTOR,
|
|
* PIN_OPENEMITTER, PIN_NC
|
|
* These messages are used to show the ERC matrix in ERC dialog
|
|
*/
|
|
|
|
// Messages for matrix rows:
|
|
const wxChar* CommentERC_H[] =
|
|
{
|
|
wxT( "Input Pin...." ),
|
|
wxT( "Output Pin..." ),
|
|
wxT( "BiDi Pin....." ),
|
|
wxT( "3 State Pin.." ),
|
|
wxT( "Passive Pin.." ),
|
|
wxT( "Unspec Pin..." ),
|
|
wxT( "Power IN Pin." ),
|
|
wxT( "PowerOUT Pin." ),
|
|
wxT( "Open Coll...." ),
|
|
wxT( "Open Emit...." ),
|
|
wxT( "No Conn......" ),
|
|
NULL
|
|
};
|
|
|
|
// Messages for matrix columns
|
|
const wxChar* CommentERC_V[] =
|
|
{
|
|
wxT( "Input Pin" ),
|
|
wxT( "Output Pin" ),
|
|
wxT( "BiDi Pin" ),
|
|
wxT( "3 State Pin" ),
|
|
wxT( "Passive Pin" ),
|
|
wxT( "Unspec Pin" ),
|
|
wxT( "Power IN Pin" ),
|
|
wxT( "PowerOUT Pin" ),
|
|
wxT( "Open Coll" ),
|
|
wxT( "Open Emit" ),
|
|
wxT( "No Conn" ),
|
|
NULL
|
|
};
|
|
|
|
|
|
/* Look up table which gives the diag for a pair of connected pins
|
|
* Can be modified by ERC options.
|
|
* at start up: must be loaded by DefaultDiagErc
|
|
*/
|
|
int DiagErc[PIN_NMAX][PIN_NMAX];
|
|
bool DiagErcTableInit; // go to TRUE after DiagErc init
|
|
|
|
/* Default Look up table which gives the diag for a pair of connected pins
|
|
* Same as DiagErc, but cannot be modified
|
|
* Used to init or reset DiagErc
|
|
*/
|
|
int DefaultDiagErc[PIN_NMAX][PIN_NMAX] =
|
|
{
|
|
/* I, O, Bi, 3S, Pas, UnS,PwrI,PwrO, OC, OE, NC */
|
|
/* I */ { OK, OK, OK, OK, OK, WAR, OK, OK, OK, OK, WAR },
|
|
/* O */ { OK, ERR, OK, WAR, OK, WAR, OK, ERR, ERR, ERR, WAR },
|
|
/* Bi*/ { OK, OK, OK, OK, OK, WAR, OK, WAR, OK, WAR, WAR },
|
|
/* 3S*/ { OK, WAR, OK, OK, OK, WAR, WAR, ERR, WAR, WAR, WAR },
|
|
/*Pas*/ { OK, OK, OK, OK, OK, WAR, OK, OK, OK, OK, WAR },
|
|
/*UnS */ { WAR, WAR, WAR, WAR, WAR, WAR, WAR, WAR, WAR, WAR, WAR },
|
|
/*PwrI*/ { OK, OK, OK, WAR, OK, WAR, OK, OK, OK, OK, ERR },
|
|
/*PwrO*/ { OK, ERR, WAR, ERR, OK, WAR, OK, ERR, ERR, ERR, WAR },
|
|
/* OC */ { OK, ERR, OK, WAR, OK, WAR, OK, ERR, OK, OK, WAR },
|
|
/* OE */ { OK, ERR, WAR, WAR, OK, WAR, OK, ERR, OK, OK, WAR },
|
|
/* NC */ { WAR, WAR, WAR, WAR, WAR, WAR, WAR, WAR, WAR, WAR, WAR }
|
|
};
|
|
|
|
|
|
/* Minimal connection table */
|
|
#define DRV 3 /* Net driven by a signal (a pin output for instance) */
|
|
#define NET_NC 2 /* Net "connected" to a "NoConnect symbol" */
|
|
#define NOD 1 /* Net not driven ( Such as 2 or more connected inputs )*/
|
|
#define NOC 0 /* Pin isolee, non connectee */
|
|
|
|
/* Look up table which gives the minimal drive for a pair of connected pins on a net
|
|
* Initial state of a net is NOC (No Connection)
|
|
* Can be updated to NET_NC, or NOD (Not Driven) or DRV (DRIven)
|
|
*
|
|
* Can be updated to NET_NC only if the previous state is NOC
|
|
*
|
|
* Nets are OK when their final state is NET_NC or DRV
|
|
* Nets with the state NOD have no source signal
|
|
*/
|
|
static int MinimalReq[PIN_NMAX][PIN_NMAX] =
|
|
{
|
|
/* In, Out, Bi, 3S, Pas, UnS,PwrI,PwrO, OC, OE, NC */
|
|
/* In*/ { NOD, DRV, DRV, DRV, DRV, DRV, NOD, DRV, DRV, DRV, NOC },
|
|
/*Out*/ { DRV, DRV, DRV, DRV, DRV, DRV, DRV, DRV, DRV, DRV, NOC },
|
|
/* Bi*/ { DRV, DRV, DRV, DRV, DRV, DRV, NOD, DRV, DRV, DRV, NOC },
|
|
/* 3S*/ { DRV, DRV, DRV, DRV, DRV, DRV, NOD, DRV, DRV, DRV, NOC },
|
|
/*Pas*/ { DRV, DRV, DRV, DRV, DRV, DRV, NOD, DRV, DRV, DRV, NOC },
|
|
/*UnS*/ { DRV, DRV, DRV, DRV, DRV, DRV, NOD, DRV, DRV, DRV, NOC },
|
|
/*PwrI*/ { NOD, DRV, NOD, NOD, NOD, NOD, NOD, DRV, NOD, NOD, NOC },
|
|
/*PwrO*/ { DRV, DRV, DRV, DRV, DRV, DRV, DRV, DRV, DRV, DRV, NOC },
|
|
/* OC*/ { DRV, DRV, DRV, DRV, DRV, DRV, NOD, DRV, DRV, DRV, NOC },
|
|
/* OE*/ { DRV, DRV, DRV, DRV, DRV, DRV, NOD, DRV, DRV, DRV, NOC },
|
|
/* NC*/ { NOC, NOC, NOC, NOC, NOC, NOC, NOC, NOC, NOC, NOC, NOC }
|
|
};
|
|
|
|
|
|
|
|
/** Function TestDuplicateSheetNames( )
|
|
* inside a given sheet, one cannot have sheets with duplicate names (file names can be duplicated).
|
|
*/
|
|
int TestDuplicateSheetNames( )
|
|
{
|
|
int err_count = 0;
|
|
EDA_ScreenList ScreenList; // Created the list of screen
|
|
for( SCH_SCREEN* Screen = ScreenList.GetFirst(); Screen != NULL; Screen = ScreenList.GetNext() )
|
|
{
|
|
for( SCH_ITEM* ref_item = Screen->EEDrawList; ref_item != NULL; ref_item = ref_item->Next() )
|
|
{
|
|
// search for a scheet;
|
|
if( ref_item->Type() != DRAW_SHEET_STRUCT_TYPE )
|
|
continue;
|
|
for( SCH_ITEM* item_to_test = ref_item->Next();
|
|
item_to_test != NULL;
|
|
item_to_test = item_to_test->Next() )
|
|
{
|
|
if( item_to_test->Type() != DRAW_SHEET_STRUCT_TYPE )
|
|
continue;
|
|
|
|
// We have found a second sheet: compare names
|
|
if( ( (DrawSheetStruct*) ref_item )->m_SheetName.CmpNoCase( ( (DrawSheetStruct*)
|
|
item_to_test )->
|
|
m_SheetName ) == 0 )
|
|
{
|
|
/* Create a new marker type ERC error*/
|
|
MARKER_SCH* Marker = new MARKER_SCH();
|
|
Marker->m_TimeStamp = GetTimeStamp();
|
|
Marker->SetData( ERCE_DUPLICATE_SHEET_NAME,
|
|
( (DrawSheetStruct*) item_to_test )->m_Pos,
|
|
_( "Duplicate Sheet name" ),
|
|
( (DrawSheetStruct*) item_to_test )->m_Pos );
|
|
Marker->SetMarkerType( MARK_ERC );
|
|
Marker->SetErrorLevel( ERR );
|
|
Marker->SetNext( Screen->EEDrawList );
|
|
Screen->EEDrawList = Marker;
|
|
err_count++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return err_count;
|
|
}
|
|
|
|
/**************************************************/
|
|
void DIALOG_ERC::TestErc( wxArrayString* aMessagesList )
|
|
/**************************************************/
|
|
{
|
|
wxFileName fn;
|
|
unsigned NetItemRef;
|
|
unsigned OldItem;
|
|
unsigned StartNet;
|
|
|
|
int NetNbItems, MinConn;
|
|
|
|
if( !DiagErcTableInit )
|
|
{
|
|
memcpy( DiagErc, DefaultDiagErc, sizeof(DefaultDiagErc) );
|
|
DiagErcTableInit = TRUE;
|
|
}
|
|
|
|
WriteFichierERC = m_WriteResultOpt->GetValue();
|
|
|
|
ReAnnotatePowerSymbolsOnly();
|
|
if( m_Parent->CheckAnnotate( aMessagesList, false ) )
|
|
{
|
|
if( aMessagesList )
|
|
{
|
|
wxString msg = _( "Annotation Required!" );
|
|
msg += wxT( "\n" );
|
|
aMessagesList->Add( msg );
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* Erase all DRC markers */
|
|
DeleteAllMarkers( MARK_ERC );
|
|
|
|
g_EESchemaVar.NbErrorErc = 0;
|
|
g_EESchemaVar.NbWarningErc = 0;
|
|
|
|
/* Cleanup the entire hierarchy */
|
|
EDA_ScreenList ScreenList;
|
|
|
|
for( SCH_SCREEN* Screen = ScreenList.GetFirst(); Screen != NULL; Screen = ScreenList.GetNext() )
|
|
{
|
|
bool ModifyWires;
|
|
ModifyWires = Screen->SchematicCleanUp( NULL );
|
|
|
|
/* if wire list has changed, delete Undo Redo list to avoid
|
|
* pointers on deleted data problems */
|
|
if( ModifyWires )
|
|
Screen->ClearUndoRedoList();
|
|
}
|
|
|
|
/* Test duplicate sheet names
|
|
* inside a given sheet, one cannot have sheets with duplicate names (file names can be duplicated).
|
|
*/
|
|
int errcnt = TestDuplicateSheetNames( );
|
|
g_EESchemaVar.NbErrorErc += errcnt;
|
|
g_EESchemaVar.NbWarningErc += errcnt;
|
|
|
|
m_Parent->BuildNetListBase();
|
|
|
|
/* Reset the flag m_FlagOfConnection, that will be used next, in calculations */
|
|
for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ )
|
|
g_NetObjectslist[ii]->m_FlagOfConnection = UNCONNECTED;
|
|
|
|
|
|
StartNet = OldItem = 0;
|
|
NetNbItems = 0;
|
|
MinConn = NOC;
|
|
|
|
for( NetItemRef = 0; NetItemRef < g_NetObjectslist.size(); NetItemRef++ )
|
|
{
|
|
/* Tst changement de net */
|
|
if( g_NetObjectslist[OldItem]->GetNet() != g_NetObjectslist[NetItemRef]->GetNet() )
|
|
{
|
|
MinConn = NOC;
|
|
NetNbItems = 0;
|
|
StartNet = NetItemRef;
|
|
}
|
|
|
|
switch( g_NetObjectslist[NetItemRef]->m_Type )
|
|
{
|
|
case NET_ITEM_UNSPECIFIED:
|
|
case NET_SEGMENT:
|
|
case NET_BUS:
|
|
case NET_JONCTION:
|
|
case NET_LABEL:
|
|
case NET_BUSLABELMEMBER:
|
|
case NET_PINLABEL:
|
|
case NET_GLOBLABEL:
|
|
case NET_GLOBBUSLABELMEMBER:
|
|
|
|
// These items do not create erc problems
|
|
break;
|
|
|
|
case NET_HIERLABEL:
|
|
case NET_HIERBUSLABELMEMBER:
|
|
case NET_SHEETLABEL:
|
|
case NET_SHEETBUSLABELMEMBER:
|
|
|
|
// ERC problems when pin sheets do not match hierachical labels.
|
|
// Each pin sheet must match a hierachical label
|
|
// Each hierachicallabel must match a pin sheet
|
|
TestLabel( m_Parent->DrawPanel, NetItemRef, StartNet );
|
|
break;
|
|
|
|
case NET_NOCONNECT:
|
|
|
|
// ERC problems when a noconnect symbol is connected to more than one pin.
|
|
MinConn = NET_NC;
|
|
if( NetNbItems != 0 )
|
|
Diagnose( m_Parent->DrawPanel,
|
|
g_NetObjectslist[NetItemRef], NULL, MinConn, UNC );
|
|
break;
|
|
|
|
case NET_PIN:
|
|
|
|
// Look for ERC problems between pins:
|
|
TestOthersItems( m_Parent->DrawPanel,
|
|
NetItemRef, StartNet, &NetNbItems, &MinConn );
|
|
break;
|
|
}
|
|
|
|
OldItem = NetItemRef;
|
|
}
|
|
|
|
// Displays global results:
|
|
wxString num;
|
|
num.Printf( wxT( "%d" ), g_EESchemaVar.NbErrorErc );
|
|
m_TotalErrCount->SetLabel( num );
|
|
|
|
num.Printf( wxT( "%d" ), g_EESchemaVar.NbErrorErc - g_EESchemaVar.NbWarningErc );
|
|
m_LastErrCount->SetLabel( num );
|
|
|
|
num.Printf( wxT( "%d" ), g_EESchemaVar.NbWarningErc );
|
|
m_LastWarningCount->SetLabel( num );
|
|
|
|
// Display diags:
|
|
DisplayERC_MarkersList();
|
|
|
|
// Display new markers:
|
|
m_Parent->DrawPanel->Refresh();
|
|
|
|
/* Generation ouverture fichier diag */
|
|
if( WriteFichierERC == TRUE )
|
|
{
|
|
fn = g_RootSheet->m_AssociatedScreen->m_FileName;
|
|
fn.SetExt( wxT( "erc" ) );
|
|
|
|
wxFileDialog dlg( this, _( "ERC File" ), fn.GetPath(), fn.GetFullName(),
|
|
_( "Electronic rule check file (.erc)|*.erc" ),
|
|
wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
|
|
|
|
if( dlg.ShowModal() == wxID_CANCEL )
|
|
return;
|
|
|
|
if( WriteDiagnosticERC( dlg.GetPath() ) )
|
|
{
|
|
Close( TRUE );
|
|
ExecuteFile( this, wxGetApp().GetEditorName(),
|
|
QuoteFullPath( fn ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/********************************************************/
|
|
static void Diagnose( WinEDA_DrawPanel* aPanel,
|
|
NETLIST_OBJECT* aNetItemRef,
|
|
NETLIST_OBJECT* aNetItemTst,
|
|
int aMinConn, int aDiag )
|
|
/********************************************************/
|
|
|
|
/* Creates an ERC marker to show the ERC problem about aNetItemRef
|
|
* or between aNetItemRef and aNetItemTst
|
|
* if MinConn < 0: this is an error on labels
|
|
*/
|
|
{
|
|
MARKER_SCH* Marker = NULL;
|
|
SCH_SCREEN* screen;
|
|
int ii, jj;
|
|
|
|
if( aDiag == OK )
|
|
return;
|
|
|
|
/* Creation du nouveau marqueur type Erreur ERC */
|
|
Marker = new MARKER_SCH();
|
|
Marker->m_TimeStamp = GetTimeStamp();
|
|
|
|
Marker->SetMarkerType( MARK_ERC );
|
|
Marker->SetErrorLevel( WAR );
|
|
screen = aNetItemRef->m_SheetList.LastScreen();
|
|
Marker->SetNext( screen->EEDrawList );
|
|
screen->EEDrawList = Marker;
|
|
g_EESchemaVar.NbErrorErc++;
|
|
g_EESchemaVar.NbWarningErc++;
|
|
|
|
wxString msg;
|
|
if( aMinConn < 0 ) // Traitement des erreurs sur labels
|
|
{
|
|
if( (aNetItemRef->m_Type == NET_HIERLABEL)
|
|
|| (aNetItemRef->m_Type == NET_HIERBUSLABELMEMBER) )
|
|
{
|
|
msg.Printf( _( "HLabel %s not connected to SheetLabel" ),
|
|
aNetItemRef->m_Label->GetData() );
|
|
}
|
|
else
|
|
msg.Printf( _( "SheetLabel %s not connected to HLabel" ),
|
|
aNetItemRef->m_Label->GetData() );
|
|
|
|
Marker->SetData( ERCE_HIERACHICAL_LABEL, aNetItemRef->m_Start, msg, aNetItemRef->m_Start );
|
|
return;
|
|
}
|
|
|
|
ii = aNetItemRef->m_ElectricalType;
|
|
|
|
wxString string_pinnum, cmp_ref;
|
|
char ascii_buf[5];
|
|
ascii_buf[4] = 0;
|
|
memcpy( ascii_buf, &aNetItemRef->m_PinNum, 4 );
|
|
string_pinnum = CONV_FROM_UTF8( ascii_buf );
|
|
cmp_ref = wxT( "?" );
|
|
if( aNetItemRef->m_Type == NET_PIN && aNetItemRef->m_Link )
|
|
cmp_ref = ( (SCH_COMPONENT*) aNetItemRef->m_Link )->GetRef( &aNetItemRef->m_SheetList );
|
|
|
|
if( aNetItemTst == NULL )
|
|
{
|
|
if( aMinConn == NOC ) /* 1 seul element dans le net */
|
|
{
|
|
msg.Printf( _( "Cmp %s, Pin %s (%s) Unconnected" ),
|
|
cmp_ref.GetData(), string_pinnum.GetData(),
|
|
MsgPinElectricType[ii] );
|
|
Marker->SetData( ERCE_PIN_NOT_CONNECTED,
|
|
aNetItemRef->m_Start,
|
|
msg,
|
|
aNetItemRef->m_Start );
|
|
return;
|
|
}
|
|
|
|
if( aMinConn == NOD ) /* pas de pilotage du net */
|
|
{
|
|
if( aNetItemRef->m_Type == NET_PIN && aNetItemRef->m_Link )
|
|
cmp_ref = ( (SCH_COMPONENT*) aNetItemRef->m_Link )->GetRef(
|
|
&aNetItemRef->m_SheetList );
|
|
msg.Printf(
|
|
_( "Cmp %s, Pin %s (%s) not driven (Net %d)" ),
|
|
cmp_ref.GetData(), string_pinnum.GetData(),
|
|
MsgPinElectricType[ii], aNetItemRef->GetNet() );
|
|
Marker->SetData( ERCE_PIN_NOT_DRIVEN,
|
|
aNetItemRef->m_Start,
|
|
msg,
|
|
aNetItemRef->m_Start );
|
|
return;
|
|
}
|
|
|
|
if( aDiag == UNC )
|
|
{
|
|
msg.Printf(
|
|
_( "More than 1 Pin connected to UnConnect symbol" ) );
|
|
Marker->SetData( ERCE_NOCONNECT_CONNECTED,
|
|
aNetItemRef->m_Start,
|
|
msg,
|
|
aNetItemRef->m_Start );
|
|
return;
|
|
}
|
|
}
|
|
|
|
if( aNetItemTst ) /* Erreur entre 2 pins */
|
|
{
|
|
jj = aNetItemTst->m_ElectricalType;
|
|
int errortype = ERCE_PIN_TO_PIN_WARNING;
|
|
if( aDiag == ERR )
|
|
{
|
|
Marker->SetErrorLevel( ERR );
|
|
g_EESchemaVar.NbWarningErc--;
|
|
errortype = ERCE_PIN_TO_PIN_ERROR;
|
|
}
|
|
|
|
wxString alt_string_pinnum, alt_cmp;
|
|
memcpy( ascii_buf, &aNetItemTst->m_PinNum, 4 );
|
|
alt_string_pinnum = CONV_FROM_UTF8( ascii_buf );
|
|
alt_cmp = wxT( "?" );
|
|
if( aNetItemTst->m_Type == NET_PIN && aNetItemTst->m_Link )
|
|
alt_cmp = ( (SCH_COMPONENT*) aNetItemTst->m_Link )->GetRef( &aNetItemTst->m_SheetList );
|
|
msg.Printf( _("Cmp %s, Pin %s (%s) connected to " ),
|
|
cmp_ref.GetData(), string_pinnum.GetData(), MsgPinElectricType[ii] );
|
|
Marker->SetData( errortype,
|
|
aNetItemRef->m_Start,
|
|
msg,
|
|
aNetItemRef->m_Start );
|
|
msg.Printf( _("Cmp %s, Pin %s (%s) (net %d)" ),
|
|
alt_cmp.GetData(), alt_string_pinnum.GetData(), MsgPinElectricType[jj],
|
|
aNetItemRef->GetNet() );
|
|
Marker->SetAuxiliaryData( msg, aNetItemTst->m_Start );
|
|
}
|
|
}
|
|
|
|
|
|
/********************************************************************/
|
|
static void TestOthersItems( WinEDA_DrawPanel* panel,
|
|
unsigned NetItemRef,
|
|
unsigned netstart,
|
|
int* NetNbItems, int* MinConnexion )
|
|
/********************************************************************/
|
|
|
|
/* Routine testant les conflits electriques entre
|
|
* NetItemRef
|
|
* et les autres items du meme net
|
|
*/
|
|
{
|
|
unsigned NetItemTst;
|
|
|
|
int ref_elect_type, jj, erc = OK, local_minconn;
|
|
|
|
/* Analyse de la table des connexions : */
|
|
|
|
ref_elect_type = g_NetObjectslist[NetItemRef]->m_ElectricalType;
|
|
|
|
NetItemTst = netstart;
|
|
local_minconn = NOC;
|
|
|
|
/* Test pins Pins connected to NetItemRef */
|
|
for( ; ; NetItemTst++ )
|
|
{
|
|
if( NetItemRef == NetItemTst )
|
|
continue;
|
|
|
|
/* We examine only a given net. We stop the search if the net changes */
|
|
if( (NetItemTst >= g_NetObjectslist.size()) // End of list
|
|
|| ( g_NetObjectslist[NetItemRef]->GetNet() != g_NetObjectslist[NetItemTst]->GetNet() ) ) // End of net
|
|
{
|
|
/* Fin de netcode trouve: Tst connexion minimum */
|
|
if( (*MinConnexion < NET_NC ) && (local_minconn < NET_NC ) ) /* Not connected or not driven pin */
|
|
{
|
|
bool seterr = true;
|
|
if( local_minconn == NOC && g_NetObjectslist[NetItemRef]->m_Type == NET_PIN)
|
|
{
|
|
/* This pin is not connected: for multiple part per package, and duplicated pin,
|
|
* search for an other instance of this pin
|
|
* this will be flagged only is all instances of this pin are not connected
|
|
* TODO test also if instances connected are connected to the same net
|
|
*/
|
|
for ( unsigned duppin = 0; duppin < g_NetObjectslist.size(); duppin ++ )
|
|
{
|
|
if ( g_NetObjectslist[duppin]->m_Type != NET_PIN )
|
|
continue;
|
|
if( duppin == NetItemRef )
|
|
continue;
|
|
if ( g_NetObjectslist[NetItemRef]->m_PinNum != g_NetObjectslist[duppin]->m_PinNum )
|
|
continue;
|
|
|
|
if( ( (SCH_COMPONENT*) g_NetObjectslist[NetItemRef]->m_Link )->GetRef(&g_NetObjectslist[NetItemRef]->m_SheetList) !=
|
|
((SCH_COMPONENT*) g_NetObjectslist[duppin]->m_Link )->GetRef(&g_NetObjectslist[duppin]->m_SheetList) )
|
|
continue;
|
|
// Same component and same pin. Do dot create error for this pin
|
|
// if the other pin is connected (i.e. if duppin net has an other item)
|
|
if ( (duppin > 0) && (g_NetObjectslist[duppin]->GetNet() == g_NetObjectslist[duppin-1]->GetNet()))
|
|
seterr = false;
|
|
if ( (duppin < g_NetObjectslist.size()-1) && (g_NetObjectslist[duppin]->GetNet() == g_NetObjectslist[duppin+1]->GetNet()) )
|
|
seterr = false;
|
|
}
|
|
}
|
|
if ( seterr )
|
|
Diagnose( panel, g_NetObjectslist[NetItemRef], NULL, local_minconn, WAR );
|
|
*MinConnexion = DRV; // inhibition autres messages de ce type pour ce net
|
|
}
|
|
return;
|
|
}
|
|
|
|
switch( g_NetObjectslist[NetItemTst]->m_Type )
|
|
{
|
|
case NET_ITEM_UNSPECIFIED:
|
|
case NET_SEGMENT:
|
|
case NET_BUS:
|
|
case NET_JONCTION:
|
|
case NET_LABEL:
|
|
case NET_HIERLABEL:
|
|
case NET_BUSLABELMEMBER:
|
|
case NET_HIERBUSLABELMEMBER:
|
|
case NET_SHEETBUSLABELMEMBER:
|
|
case NET_SHEETLABEL:
|
|
case NET_GLOBLABEL:
|
|
case NET_GLOBBUSLABELMEMBER:
|
|
case NET_PINLABEL:
|
|
break;
|
|
|
|
case NET_NOCONNECT:
|
|
local_minconn = MAX( NET_NC, local_minconn );
|
|
break;
|
|
|
|
case NET_PIN:
|
|
jj = g_NetObjectslist[NetItemTst]->m_ElectricalType;
|
|
local_minconn = MAX( MinimalReq[ref_elect_type][jj], local_minconn );
|
|
|
|
if( NetItemTst <= NetItemRef )
|
|
break;
|
|
|
|
*NetNbItems += 1;
|
|
if( erc == OK ) // 1 marqueur par pin maxi
|
|
{
|
|
erc = DiagErc[ref_elect_type][jj];
|
|
if( erc != OK )
|
|
{
|
|
if( g_NetObjectslist[NetItemTst]->m_FlagOfConnection == 0 )
|
|
{
|
|
Diagnose( panel, g_NetObjectslist[NetItemRef], g_NetObjectslist[NetItemTst], 0, erc );
|
|
g_NetObjectslist[NetItemTst]->m_FlagOfConnection = NOCONNECT_SYMBOL_PRESENT;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/********************************************************/
|
|
static bool WriteDiagnosticERC( const wxString& FullFileName )
|
|
/*********************************************************/
|
|
|
|
/* Create the Diagnostic file (<xxx>.erc file)
|
|
*/
|
|
{
|
|
SCH_ITEM* DrawStruct;
|
|
MARKER_SCH* Marker;
|
|
char Line[1024];
|
|
static FILE* OutErc;
|
|
DrawSheetPath* Sheet;
|
|
wxString msg;
|
|
|
|
if( ( OutErc = wxFopen( FullFileName, wxT( "wt" ) ) ) == NULL )
|
|
return FALSE;
|
|
|
|
DateAndTime( Line );
|
|
msg = _( "ERC report" );
|
|
|
|
fprintf( OutErc, "%s (%s)\n", CONV_TO_UTF8( msg ), Line );
|
|
|
|
EDA_SheetList SheetList;
|
|
|
|
for( Sheet = SheetList.GetFirst(); Sheet != NULL; Sheet = SheetList.GetNext() )
|
|
{
|
|
if( Sheet->Last() == g_RootSheet )
|
|
{
|
|
msg.Printf( _( "\n***** Sheet / (Root) \n" ) );
|
|
}
|
|
else
|
|
{
|
|
wxString str = Sheet->PathHumanReadable();
|
|
msg.Printf( _( "\n***** Sheet %s\n" ), str.GetData() );
|
|
}
|
|
|
|
fprintf( OutErc, "%s", CONV_TO_UTF8( msg ) );
|
|
|
|
DrawStruct = Sheet->LastDrawList();
|
|
for( ; DrawStruct != NULL; DrawStruct = DrawStruct->Next() )
|
|
{
|
|
if( DrawStruct->Type() != TYPE_MARKER_SCH )
|
|
continue;
|
|
|
|
Marker = (MARKER_SCH*) DrawStruct;
|
|
if( Marker->GetMarkerType() != MARK_ERC )
|
|
continue;
|
|
msg = Marker->GetReporter().ShowReport();
|
|
fprintf( OutErc, "%s", CONV_TO_UTF8( msg ) );
|
|
}
|
|
}
|
|
|
|
msg.Printf( _( "\n >> Errors ERC: %d\n" ), g_EESchemaVar.NbErrorErc );
|
|
fprintf( OutErc, "%s", CONV_TO_UTF8( msg ) );
|
|
fclose( OutErc );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static bool IsLabelsConnected( NETLIST_OBJECT* a, NETLIST_OBJECT* b )
|
|
{
|
|
int at = a->m_Type;
|
|
int bt = b->m_Type;
|
|
|
|
if( (at == NET_HIERLABEL || at == NET_HIERBUSLABELMEMBER)
|
|
&&(bt == NET_SHEETLABEL || bt == NET_SHEETBUSLABELMEMBER) )
|
|
{
|
|
if( a->m_SheetList == b->m_SheetListInclude )
|
|
{
|
|
return true; //connected!
|
|
}
|
|
}
|
|
return false; //these two are unconnected
|
|
}
|
|
|
|
|
|
/***********************************************************************/
|
|
void TestLabel( WinEDA_DrawPanel* panel,
|
|
unsigned NetItemRef,
|
|
unsigned StartNet )
|
|
/***********************************************************************/
|
|
|
|
/* Routine controlant qu'un sheetLabel est bien connecte a un Glabel de la
|
|
* sous-feuille correspondante
|
|
*/
|
|
{
|
|
unsigned NetItemTst;
|
|
int erc = 1;
|
|
|
|
|
|
NetItemTst = StartNet;
|
|
|
|
/* Examen de la liste des Labels connectees a NetItemRef */
|
|
for( ; ; NetItemTst++ )
|
|
{
|
|
if( NetItemTst == NetItemRef )
|
|
continue;
|
|
|
|
/* Est - on toujours dans le meme net ? */
|
|
if( ( NetItemTst == g_NetObjectslist.size() )
|
|
|| ( g_NetObjectslist[NetItemRef]->GetNet() != g_NetObjectslist[NetItemTst]->GetNet() ) )
|
|
{
|
|
/* Fin de netcode trouve */
|
|
if( erc )
|
|
{
|
|
/* GLabel ou SheetLabel orphelin */
|
|
Diagnose( panel, g_NetObjectslist[NetItemRef], NULL, -1, WAR );
|
|
}
|
|
return;
|
|
}
|
|
if( IsLabelsConnected( g_NetObjectslist[NetItemRef], g_NetObjectslist[NetItemTst] ) )
|
|
erc = 0;
|
|
|
|
//same thing, different order.
|
|
if( IsLabelsConnected( g_NetObjectslist[NetItemTst], g_NetObjectslist[NetItemRef] ) )
|
|
erc = 0;
|
|
}
|
|
}
|