/* * Build net list connection table. * Initializes s_NetObjectslist */ NETLIST_OBJECT_LIST * SCH_EDIT_FRAME::BuildNetListBase() { wxBusyCursor Busy; // Creates the flattened sheet list: SCH_SHEET_LIST aSheets; // Build netlist info bool success = s_NetObjectslist.BuildNetListInfo( aSheets ); if( !success ) { SetStatusText( _("No Objects" ) ); return &s_NetObjectslist; } /* The new %zu specification is needed to properly format a size_t * value (returned by size(), here) */ wxString msg; msg.Printf( _( "Net count = %zu" ), s_NetObjectslist.size() ); SetStatusText( msg ); return &s_NetObjectslist; }
void SCH_TEXT::GetNetListItem( NETLIST_OBJECT_LIST& aNetListItems, SCH_SHEET_PATH* aSheetPath ) { if( GetLayer() == LAYER_NOTES || GetLayer() == LAYER_SHEETLABEL ) return; NETLIST_OBJECT* item = new NETLIST_OBJECT(); item->m_SheetPath = *aSheetPath; item->m_SheetPathInclude = *aSheetPath; item->m_Comp = (SCH_ITEM*) this; item->m_Type = NET_LABEL; if( GetLayer() == LAYER_GLOBLABEL ) item->m_Type = NET_GLOBLABEL; else if( GetLayer() == LAYER_HIERLABEL ) item->m_Type = NET_HIERLABEL; item->m_Label = m_Text; item->m_Start = item->m_End = GetTextPos(); aNetListItems.push_back( item ); // If a bus connects to label if( Connection( *aSheetPath )->IsBusLabel( m_Text ) ) { item->ConvertBusToNetListItems( aNetListItems ); } }
void SCH_NO_CONNECT::GetNetListItem( NETLIST_OBJECT_LIST& aNetListItems, SCH_SHEET_PATH* aSheetPath ) { NETLIST_OBJECT* item = new NETLIST_OBJECT(); item->m_SheetPath = *aSheetPath; item->m_SheetPathInclude = *aSheetPath; item->m_Comp = this; item->m_Type = NET_NOCONNECT; item->m_Start = item->m_End = m_pos; aNetListItems.push_back( item ); }
void SCH_JUNCTION::GetNetListItem( NETLIST_OBJECT_LIST& aNetListItems, SCH_SHEET_PATH* aSheetPath ) { NETLIST_OBJECT* item = new NETLIST_OBJECT(); item->m_SheetPath = *aSheetPath; item->m_SheetPathInclude = *aSheetPath; item->m_Comp = (SCH_ITEM*) this; item->m_Type = NET_JUNCTION; item->m_Start = item->m_End = m_pos; aNetListItems.push_back( item ); }
void SCH_SHEET::GetNetListItem( NETLIST_OBJECT_LIST& aNetListItems, SCH_SHEET_PATH* aSheetPath ) { SCH_SHEET_PATH sheetPath = *aSheetPath; sheetPath.push_back( this ); for( size_t i = 0; i < m_pins.size(); i++ ) { NETLIST_OBJECT* item = new NETLIST_OBJECT(); item->m_SheetPathInclude = sheetPath; item->m_SheetPath = *aSheetPath; item->m_Comp = &m_pins[i]; item->m_Link = this; item->m_Type = NET_SHEETLABEL; item->m_Label = m_pins[i].GetText(); item->m_Start = item->m_End = m_pins[i].GetPosition(); aNetListItems.push_back( item ); if( IsBusLabel( m_pins[i].GetText() ) ) item->ConvertBusToNetListItems( aNetListItems ); } }
void NETLIST_OBJECT::ConvertBusToNetListItems( NETLIST_OBJECT_LIST& aNetListItems ) { wxCHECK_RET( IsBusLabel( m_Label ), wxT( "<" ) + m_Label + wxT( "> is not a valid bus label." ) ); if( m_Type == NET_HIERLABEL ) m_Type = NET_HIERBUSLABELMEMBER; else if( m_Type == NET_GLOBLABEL ) m_Type = NET_GLOBBUSLABELMEMBER; else if( m_Type == NET_SHEETLABEL ) m_Type = NET_SHEETBUSLABELMEMBER; else if( m_Type == NET_LABEL ) m_Type = NET_BUSLABELMEMBER; else wxCHECK_RET( false, wxT( "Net list object type is not valid." ) ); unsigned i; wxString tmp, busName, busNumber; long begin, end, member; busName = busLabelRe.GetMatch( m_Label, 1 ); busNumber = busLabelRe.GetMatch( m_Label, 2 ); /* Search for '[' because a bus label is like "busname[nn..mm]" */ i = busNumber.Find( '[' ); i++; while( i < busNumber.Len() && busNumber[i] != '.' ) { tmp.Append( busNumber[i] ); i++; } tmp.ToLong( &begin ); while( i < busNumber.Len() && busNumber[i] == '.' ) i++; tmp.Empty(); while( i < busNumber.Len() && busNumber[i] != ']' ) { tmp.Append( busNumber[i] ); i++; } tmp.ToLong( &end ); if( begin < 0 ) begin = 0; if( end < 0 ) end = 0; if( begin > end ) std::swap( begin, end ); member = begin; tmp = busName; tmp << member; m_Label = tmp; m_Member = member; for( member++; member <= end; member++ ) { NETLIST_OBJECT* item = new NETLIST_OBJECT( *this ); // Conversion of bus label to the root name + the current member id. tmp = busName; tmp << member; item->m_Label = tmp; item->m_Member = member; aNetListItems.push_back( item ); } }
bool NETLIST_EXPORTER_GENERIC::writeListOfNets( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ) { int ret = 0; int netCode; int lastNetCode = -1; int sameNetcodeCount = 0; wxString netName; wxString ref; wxString netcodeName; char firstItemInNet[256]; for( unsigned ii = 0; ii < aObjectsList.size(); ii++ ) { SCH_COMPONENT* comp; NETLIST_OBJECT* nitem = aObjectsList[ii]; // New net found, write net id; if( ( netCode = nitem->GetNet() ) != lastNetCode ) { sameNetcodeCount = 0; // Items count for this net netName = nitem->GetNetName(); netcodeName.Printf( wxT( "Net %d " ), netCode ); netcodeName << wxT( "\"" ) << netName << wxT( "\"" ); // Add the netname without prefix, in cases we need only the // "short" netname netcodeName += wxT( " \"" ) + nitem->GetShortNetName() + wxT( "\"" ); lastNetCode = netCode; } if( nitem->m_Type != NET_PIN ) continue; if( nitem->m_Flag != 0 ) // Redundant pin, skip it continue; comp = nitem->GetComponentParent(); // Get the reference for the net name and the main parent component ref = comp->GetRef( &nitem->m_SheetPath ); if( ref[0] == wxChar( '#' ) ) continue; // Pseudo component (Like Power symbol) // Print the pin list for this net, use special handling if // 2 or more items are connected: // if first item for this net found, defer printing this connection // until a second item will is found if( ++sameNetcodeCount == 1 ) { snprintf( firstItemInNet, sizeof(firstItemInNet), " %s %.4s\n", TO_UTF8( ref ), (const char*) &aObjectsList[ii]->m_PinNum ); } // Second item for this net found, print the Net name, and the // first item if( sameNetcodeCount == 2 ) { ret |= fprintf( f, "%s\n", TO_UTF8( netcodeName ) ); ret |= fputs( firstItemInNet, f ); } if( sameNetcodeCount >= 2 ) ret |= fprintf( f, " %s %.4s\n", TO_UTF8( ref ), (const char*) &nitem->m_PinNum ); } return ret >= 0; }
/** * Function findBestNetNameForEachNet * fill the .m_NetNameCandidate member of each item of aNetItemBuffer * with a reference to the "best" NETLIST_OBJECT usable to give a name to the net * If no suitable object found, .m_NetNameCandidate is filled with 0. * The "best" NETLIST_OBJECT is a NETLIST_OBJECT that have the type label * and by priority order: * the label is global or local * the label is in the first sheet in a hierarchy (the root sheet has the most priority) * alphabetic order. */ void NETLIST_OBJECT_LIST::findBestNetNameForEachNet() { int netcode = 0; // current netcode for tested items unsigned idxstart = 0; // index of the first item of this net NETLIST_OBJECT* item; NETLIST_OBJECT* candidate; // Pass 1: find the best name for labelled nets: item = NULL; candidate = NULL; for( unsigned ii = 0; ii <= size(); ii++ ) { if( ii == size() ) // last item already found netcode = -2; else item = GetItem( ii ); if( netcode != item->GetNet() ) // End of net found { if( candidate ) // One or more labels exists, find the best { for (unsigned jj = idxstart; jj < ii; jj++ ) GetItem( jj )->SetNetNameCandidate( candidate ); } if( netcode == -2 ) break; netcode = item->GetNet(); candidate = NULL; idxstart = ii; } switch( item->m_Type ) { case NET_HIERLABEL: case NET_LABEL: case NET_PINLABEL: case NET_GLOBLABEL: // A candidate is found: select the better between the previous // and this one if( candidate == NULL ) candidate = item; else { if( evalLabelsPriority( item, candidate ) ) // item has a highter priority than candidate // so update the best candidate candidate = item; } break; default: break; } } // Pass 2: find the best name for not labelled nets: // The "default" net name is Net-<<Ref cmp>_Pad<num pad>> // (see NETLIST_OBJECT::GetShortNetName()) // therefore the "best" is the short net name alphabetically classed first // (to avoid net names changes when the net is not modified, // even if components are moved or deleted and undelete or replaced, as long // the reference is kept) // Build the list of items with no net names NETLIST_OBJECT_LIST list; for( unsigned ii = 0; ii < size(); ii++ ) { item = GetItem( ii ); if( !item->HasNetNameCandidate() ) list.push_back( item ); } if( list.size() == 0 ) return; idxstart = 0; candidate = NULL; netcode = list.GetItemNet( 0 ); for( unsigned ii = 0; ii <= list.size(); ii++ ) { if( ii < list.size() ) item = list.GetItem( ii ); if( netcode != item->GetNet() || ii >= list.size() ) // End of net found { if( candidate ) { for (unsigned jj = idxstart; jj < ii; jj++ ) { NETLIST_OBJECT* obj = list.GetItem( jj ); obj->SetNetNameCandidate( candidate ); } } if( ii >= list.size() ) break; netcode = item->GetNet(); candidate = NULL; idxstart = ii; } // Examine all pins of the net to find the best candidate, // i.e. the first net name candidate, by alphabetic order // the net names are names bu_ilt by GetShortNetName // (Net-<{reference}-Pad{pad number}> like Net-<U3-Pad5> // Not named nets do not have usually a lot of members. // Many have only 2 members(a pad and a non connection symbol) if( item->m_Type == NET_PIN ) { // A candidate is found, however components which are not in // netlist are not candidate because some have their reference // changed each time the netlist is built (power components) // and anyway obviously they are not a good candidate SCH_COMPONENT* link = item->GetComponentParent(); if( link && link->IsInNetlist() ) { // select the better between the previous and this one item->SetNetNameCandidate( item ); // Needed to calculate GetShortNetName if( candidate == NULL ) candidate = item; else { if( item->GetShortNetName().Cmp( candidate->GetShortNetName() ) < 0 ) candidate = item; } } } } }
/* the master function of NETLIST_OBJECT_LIST class. * Build the list of connected objects (pins, labels ...) and * all info needed to generate netlists or run ERC diags */ bool NETLIST_OBJECT_LIST::BuildNetListInfo( SCH_SHEET_LIST& aSheets ) { s_NetObjectslist.SetOwner( true ); s_NetObjectslist.FreeList(); SCH_SHEET_PATH* sheet; // Fill list with connected items from the flattened sheet list for( sheet = aSheets.GetFirst(); sheet != NULL; sheet = aSheets.GetNext() ) { for( SCH_ITEM* item = sheet->LastScreen()->GetDrawItems(); item; item = item->Next() ) { item->GetNetListItem( *this, sheet ); } } if( size() == 0 ) return false; // Sort objects by Sheet SortListbySheet(); sheet = &(GetItem( 0 )->m_SheetPath); m_lastNetCode = m_lastBusNetCode = 1; for( unsigned ii = 0, istart = 0; ii < size(); ii++ ) { NETLIST_OBJECT* net_item = GetItem( ii ); if( net_item->m_SheetPath != *sheet ) // Sheet change { sheet = &(net_item->m_SheetPath); istart = ii; } switch( net_item->m_Type ) { case NET_ITEM_UNSPECIFIED: wxMessageBox( wxT( "BuildNetListBase() error" ) ); break; case NET_PIN: case NET_PINLABEL: case NET_SHEETLABEL: case NET_NOCONNECT: if( net_item->GetNet() != 0 ) break; case NET_SEGMENT: // Test connections point to point type without bus. if( net_item->GetNet() == 0 ) { net_item->SetNet( m_lastNetCode ); m_lastNetCode++; } pointToPointConnect( net_item, IS_WIRE, istart ); break; case NET_JUNCTION: // Control of the junction outside BUS. if( net_item->GetNet() == 0 ) { net_item->SetNet( m_lastNetCode ); m_lastNetCode++; } segmentToPointConnect( net_item, IS_WIRE, istart ); /* Control of the junction, on BUS. */ if( net_item->m_BusNetCode == 0 ) { net_item->m_BusNetCode = m_lastBusNetCode; m_lastBusNetCode++; } segmentToPointConnect( net_item, IS_BUS, istart ); break; case NET_LABEL: case NET_HIERLABEL: case NET_GLOBLABEL: // Test connections type junction without bus. if( net_item->GetNet() == 0 ) { net_item->SetNet( m_lastNetCode ); m_lastNetCode++; } segmentToPointConnect( net_item, IS_WIRE, istart ); break; case NET_SHEETBUSLABELMEMBER: if( net_item->m_BusNetCode != 0 ) break; case NET_BUS: /* Control type connections point to point mode bus */ if( net_item->m_BusNetCode == 0 ) { net_item->m_BusNetCode = m_lastBusNetCode; m_lastBusNetCode++; } pointToPointConnect( net_item, IS_BUS, istart ); break; case NET_BUSLABELMEMBER: case NET_HIERBUSLABELMEMBER: case NET_GLOBBUSLABELMEMBER: /* Control connections similar has on BUS */ if( net_item->GetNet() == 0 ) { net_item->m_BusNetCode = m_lastBusNetCode; m_lastBusNetCode++; } segmentToPointConnect( net_item, IS_BUS, istart ); break; } } #if defined(NETLIST_DEBUG) && defined(DEBUG) std::cout << "\n\nafter sheet local\n\n"; DumpNetTable(); #endif /* Updating the Bus Labels Netcode connected by Bus */ connectBusLabels(); /* Group objects by label. */ for( unsigned ii = 0; ii < size(); ii++ ) { switch( GetItem( ii )->m_Type ) { case NET_PIN: case NET_SHEETLABEL: case NET_SEGMENT: case NET_JUNCTION: case NET_BUS: case NET_NOCONNECT: break; case NET_LABEL: case NET_GLOBLABEL: case NET_PINLABEL: case NET_BUSLABELMEMBER: case NET_GLOBBUSLABELMEMBER: labelConnect( GetItem( ii ) ); break; case NET_SHEETBUSLABELMEMBER: case NET_HIERLABEL: case NET_HIERBUSLABELMEMBER: break; case NET_ITEM_UNSPECIFIED: break; } } #if defined(NETLIST_DEBUG) && defined(DEBUG) std::cout << "\n\nafter sheet global\n\n"; DumpNetTable(); #endif // Connection between hierarchy sheets for( unsigned ii = 0; ii < size(); ii++ ) { if( GetItem( ii )->m_Type == NET_SHEETLABEL || GetItem( ii )->m_Type == NET_SHEETBUSLABELMEMBER ) sheetLabelConnect( GetItem( ii ) ); } // Sort objects by NetCode SortListbyNetcode(); #if defined(NETLIST_DEBUG) && defined(DEBUG) std::cout << "\n\nafter qsort()\n"; DumpNetTable(); #endif /* Compress numbers of Netcode having consecutive values. */ int NetCode = 0; m_lastNetCode = 0; for( unsigned ii = 0; ii < size(); ii++ ) { if( GetItem( ii )->GetNet() != m_lastNetCode ) { NetCode++; m_lastNetCode = GetItem( ii )->GetNet(); } GetItem( ii )->SetNet( NetCode ); } // Set the minimal connection info: setUnconnectedFlag(); // find the best label object to give the best net name to each net findBestNetNameForEachNet(); return true; }
void DIALOG_ERC::TestErc( wxArrayString* aMessagesList ) { wxFileName fn; if( !DiagErcTableInit ) { memcpy( DiagErc, DefaultDiagErc, sizeof(DefaultDiagErc) ); DiagErcTableInit = true; } m_writeErcFile = m_WriteResultOpt->GetValue(); /* Build the whole sheet list in hierarchy (sheet, not screen) */ SCH_SHEET_LIST sheets; sheets.AnnotatePowerSymbols(); if( m_parent->CheckAnnotate( aMessagesList, false ) ) { if( aMessagesList ) { wxString msg = _( "Annotation required!" ); msg += wxT( "\n" ); aMessagesList->Add( msg ); } return; } SCH_SCREENS screens; // Erase all previous DRC markers. screens.DeleteAllMarkers( MARK_ERC ); for( SCH_SCREEN* screen = screens.GetFirst(); screen != NULL; screen = screens.GetNext() ) { /* Ff wire list has changed, delete Undo Redo list to avoid pointers on deleted * data problems. */ if( screen->SchematicCleanUp( NULL ) ) screen->ClearUndoRedoList(); } /* Test duplicate sheet names inside a given sheet, one cannot have sheets with * duplicate names (file names can be duplicated). */ TestDuplicateSheetNames( true ); NETLIST_OBJECT_LIST* objectsConnectedList = m_parent->BuildNetListBase(); // Reset the connection type indicator objectsConnectedList->ResetConnectionsType(); unsigned lastNet; unsigned nextNet = lastNet = 0; int NetNbItems = 0; int MinConn = NOC; for( unsigned net = 0; net < objectsConnectedList->size(); net++ ) { if( objectsConnectedList->GetItemNet( lastNet ) != objectsConnectedList->GetItemNet( net ) ) { // New net found: MinConn = NOC; NetNbItems = 0; nextNet = net; } switch( objectsConnectedList->GetItemType( net ) ) { // These items do not create erc problems case NET_ITEM_UNSPECIFIED: case NET_SEGMENT: case NET_BUS: case NET_JUNCTION: case NET_LABEL: case NET_BUSLABELMEMBER: case NET_PINLABEL: case NET_GLOBLABEL: case NET_GLOBBUSLABELMEMBER: break; case NET_HIERLABEL: case NET_HIERBUSLABELMEMBER: case NET_SHEETLABEL: case NET_SHEETBUSLABELMEMBER: // ERC problems when pin sheets do not match hierarchical labels. // Each pin sheet must match a hierarchical label // Each hierarchical label must match a pin sheet TestLabel( objectsConnectedList, net, nextNet ); break; case NET_NOCONNECT: // ERC problems when a noconnect symbol is connected to more than one pin. MinConn = NET_NC; if( NetNbItems != 0 ) Diagnose( objectsConnectedList->GetItem( net ), NULL, MinConn, UNC ); break; case NET_PIN: // Look for ERC problems between pins: TestOthersItems( objectsConnectedList, net, nextNet, &NetNbItems, &MinConn ); break; } lastNet = net; } // Displays global results: wxString num; int markers = screens.GetMarkerCount(); int warnings = screens.GetMarkerCount( WAR ); num.Printf( wxT( "%d" ), markers ); m_TotalErrCount->SetLabel( num ); num.Printf( wxT( "%d" ), markers - warnings ); m_LastErrCount->SetLabel( num ); num.Printf( wxT( "%d" ), warnings ); m_LastWarningCount->SetLabel( num ); // Display diags: DisplayERC_MarkersList(); // Display new markers: m_parent->GetCanvas()->Refresh(); if( m_writeErcFile ) { fn = g_RootSheet->GetScreen()->GetFileName(); 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 ) ); } } }