netlist.h 16 KB
Newer Older
1
/*
2
 * This program source code file is part of KiCad, a free EDA CAD application.
3 4 5
 *
 * Copyright (C) 1992-2011 jean-pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
 * Copyright (C) 1992-2011 Wayne Stambaugh <stambaughw@verizon.net>
6
 * Copyright (C) 1992-2011 KiCad Developers, see change_log.txt for contributors.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */


27 28 29 30
/**
 * @file netlist.h
 */

31 32 33
#ifndef _NETLIST_H_
#define _NETLIST_H_

34

35
#include <macros.h>
36

37 38 39
#include <class_libentry.h>
#include <sch_sheet_path.h>
#include <sch_component.h>
40
#include <sch_text.h>
41 42


43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
/// netlist types
enum  NETLIST_TYPE_ID {
    NET_TYPE_UNINIT = 0,
    NET_TYPE_PCBNEW,
    NET_TYPE_ORCADPCB2,
    NET_TYPE_CADSTAR,
    NET_TYPE_SPICE,
    NET_TYPE_CUSTOM1,   /* NET_TYPE_CUSTOM1
                         * is the first id for user netlist format
                         * NET_TYPE_CUSTOM1+CUSTOMPANEL_COUNTMAX-1
                         * is the last id for user netlist format
                         */
    //NET_TYPE_CUSTOM_MAX = NET_TYPE_CUSTOM1 + CUSTOMPANEL_COUNTMAX - 1
};


/// Options for Spice netlist generation (OR'ed bits
enum netlistOptions {
61 62 63
    NET_PCBNEW_USE_NEW_FORMAT = 1,      // For Pcbnew use the new format (S expression and SWEET)
    NET_USE_X_PREFIX = 2,               // for Spice netlist : change "U" and "IC" reference prefix to "X"
    NET_USE_NETCODES_AS_NETNAMES = 4    // for Spice netlist : use netcode numbers as netnames
64 65 66
};


67 68 69
class SCH_COMPONENT;


70 71
#define NETLIST_HEAD_STRING "EESchema Netlist Version 1.1"

72
// Max pin number per component and footprint
73
#define MAXPIN      5000
74

75

76 77 78 79 80 81 82
/**
 * Class SCH_REFERENCE
 * is used as a helper to define a component's reference designator in a schematic.  This
 * helper is required in a complex hierarchy because a component can be used more than
 * once and its reference depends on the sheet path.  This class is used to flatten the
 * schematic hierarchy for annotation, net list generation, and bill of material
 * generation.
83
 */
84
class SCH_REFERENCE
85
{
Dick Hollenbeck's avatar
Dick Hollenbeck committed
86
    /// Component reference prefix, without number (for IC1, this is IC) )
87
    UTF8           m_Ref;               // it's private, use the accessors please
88
    SCH_COMPONENT* m_RootCmp;           ///< The component associated the reference object.
89
    LIB_PART*      m_Entry;             ///< The source component from a library.
90 91
    wxPoint        m_CmpPos;            ///< The physical position of the component in schematic
                                        ///< used to annotate by X or Y position
92 93
    int            m_Unit;              ///< The unit number for components with multiple parts
                                        ///< per package.
94
    SCH_SHEET_PATH m_SheetPath;         ///< The sheet path for this reference.
95 96
    bool           m_IsNew;             ///< True if not yet annotated.
    int            m_SheetNum;          ///< The sheet number for the reference.
97
    time_t         m_TimeStamp;         ///< The time stamp for the reference.
98
    EDA_TEXT*      m_Value;             ///< The component value of the refernce.  It is the
99 100 101
                                        ///< same for all instances.
    int            m_NumRef;            ///< The numeric part of the reference designator.
    int            m_Flag;
Dick Hollenbeck's avatar
Dick Hollenbeck committed
102

103
    friend class SCH_REFERENCE_LIST;
Dick Hollenbeck's avatar
Dick Hollenbeck committed
104

105

106
public:
107

108 109
    SCH_REFERENCE() :
        m_SheetPath()
110
    {
111 112 113 114 115 116 117 118
        m_RootCmp      = NULL;
        m_Entry        = NULL;
        m_Unit         = 0;
        m_TimeStamp    = 0;
        m_IsNew        = false;
        m_Value        = NULL;
        m_NumRef       = 0;
        m_Flag         = 0;
119
        m_SheetNum     = 0;
120 121
    }

122
    SCH_REFERENCE( SCH_COMPONENT* aComponent, LIB_PART*      aLibComponent,
123 124
                   SCH_SHEET_PATH& aSheetPath );

125
    SCH_COMPONENT* GetComp() const          { return m_RootCmp; }
126

127
    LIB_PART*      GetLibComponent() const  { return m_Entry; }
128

129
    SCH_SHEET_PATH GetSheetPath() const     { return m_SheetPath; }
130

131
    int GetUnit() const                     { return m_Unit; }
132 133 134

    void SetSheetNumber( int aSheetNumber ) { m_SheetNum = aSheetNumber; }

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
    /**
     * Function Annotate
     * updates the annotation of the component according the the current object state.
     */
    void Annotate();

    /**
     * Function Split
     * attempts to split the reference designator into a name (U) and number (1).  If the
     * last character is '?' or not a digit, the reference is tagged as not annotated.
     * For components with multiple parts per package that are not already annotated, set
     * m_Unit to a max value (0x7FFFFFFF).
     */
    void Split();

Dick Hollenbeck's avatar
Dick Hollenbeck committed
150 151 152 153 154 155
    /*  Some accessors which hide the strategy of how the reference is stored,
        thereby making it easy to change that strategy.
    */

    void SetRef( const wxString& aReference )
    {
156
        m_Ref = aReference;
Dick Hollenbeck's avatar
Dick Hollenbeck committed
157
    }
158

Dick Hollenbeck's avatar
Dick Hollenbeck committed
159 160
    wxString GetRef() const
    {
161
        return m_Ref;
Dick Hollenbeck's avatar
Dick Hollenbeck committed
162 163 164 165 166 167 168 169 170 171
    }
    void SetRefStr( const std::string& aReference )
    {
        m_Ref = aReference;
    }
    const char* GetRefStr() const
    {
        return m_Ref.c_str();
    }

172
    int CompareValue( const SCH_REFERENCE& item ) const
173
    {
174
        return Cmp_KEEPCASE( m_Value->GetText(), item.m_Value->GetText() );
175 176
    }

177
    int CompareRef( const SCH_REFERENCE& item ) const
178
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
179
        return m_Ref.compare( item.m_Ref );
180 181
    }

182 183
    int CompareLibName( const SCH_REFERENCE& item ) const
    {
184
        return Cmp_KEEPCASE( m_RootCmp->GetPartName(), item.m_RootCmp->GetPartName() );
185 186
    }

187
    bool IsUnitsLocked()
188
    {
189
        return m_Entry->UnitsLocked();
190
    }
191 192
};

193

194 195
/**
 * Class SCH_REFERENCE_LIST
196
 * is used to create a flattened list of components because in a complex hierarchy, a component
197 198 199
 * can be used more than once and its reference designator is dependent on the sheet path for
 * the same component.  This flattened list is used for netlist generation, BOM generation,
 * and schematic annotation.
200
 */
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
class SCH_REFERENCE_LIST
{
private:
    std::vector <SCH_REFERENCE> componentFlatList;

public:
    /** Constructor
     */
    SCH_REFERENCE_LIST()
    {
    }

    SCH_REFERENCE& operator[]( int aIndex )
    {
        return componentFlatList[ aIndex ];
    }

    /**
     * Function GetCount
     * @return the number of items in the list
     */
    unsigned GetCount()
    {
        return componentFlatList.size();
    }

    /**
     * Function GetItem
     * @return the aIdx item
     */
231
    SCH_REFERENCE& GetItem( int aIdx )
232 233 234 235 236 237
    {
        return componentFlatList[aIdx];
    }

    /**
     * Function AddItem
238
     * adds a SCH_REFERENCE object to the list of references.
239 240 241 242
     * @param aItem - a SCH_REFERENCE item to add
     */
    void AddItem( SCH_REFERENCE& aItem )
    {
243
        componentFlatList.push_back( aItem );
244 245
    }

246 247 248 249 250 251 252
    /**
     * Function RemoveItem
     * removes an item from the list of references.
     *
     * @param aIndex is the index of the item to be removed.
     */
    void RemoveItem( unsigned int aIndex );
253

254 255 256 257 258 259
    /**
     * Function RemoveSubComponentsFromList
     * Remove sub components from the list, when multiples parts per package are
     * found in this list.
     * Useful to create BOM, when a component must appear only once
     */
260
    void RemoveSubComponentsFromList();
261 262

    /* Sort functions:
263
     * Sort functions are used to sort components for annotation or BOM generation.
264 265 266
     * Because sorting depend on we want to do, there are many sort functions.
     * Note:
     *    When creating BOM, components are fully annotated.
267
     *    references are something like U3, U5 or R4, R8
268 269 270
     *    When annotating,  some or all components are not annotated,
     *    i.e. ref is only U or R, with no number.
     */
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287

    /**
     * Function SplitReferences
     * attempts to split all reference designators into a name (U) and number (1).  If the
     * last character is '?' or not a digit, the reference is tagged as not annotated.
     * For components with multiple parts per package that are not already annotated, set
     * m_Unit to a max value (0x7FFFFFFF).
     * @see SCH_REFERENCE::Split()
     */
    void SplitReferences()
    {
        for( unsigned ii = 0; ii < GetCount(); ii++ )
            componentFlatList[ii].Split();
    }

    /**
     * function UpdateAnnotation
288 289 290
     * Updates the reference components for the schematic project (or the current sheet)
     * Note: this function does not calculate the reference numbers stored in m_NumRef
     * So, it must be called after calculation of new reference numbers
291 292 293 294 295 296 297 298 299 300 301
     * @see SCH_REFERENCE::Annotate()
     */
    void UpdateAnnotation()
    {
        /* update the reference numbers */
        for( unsigned ii = 0; ii < GetCount(); ii++ )
        {
            componentFlatList[ii].Annotate();
        }
    }

302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
    /**
     * Function Annotate
     * set the reference designators in the list that have not been annotated.
     * @param aUseSheetNum Set to true to start annotation for each sheet at the sheet number
     *                     times \a aSheetIntervalId.  Otherwise annotate incrementally.
     * @param aSheetIntervalId The per sheet reference designator multiplier.
     * <p>
     * If a the sheet number is 2 and \a aSheetIntervalId is 100, then the first reference
     * designator would be 201 and the last reference designator would be 299 when no overlap
     * occurs with sheet number 3.  If there are 150 items in sheet number 2, then items are
     * referenced U201 to U351, and items in sheet 3 start from U352
     * </p>
     */
    void Annotate( bool aUseSheetNum, int aSheetIntervalId );

    /**
     * Function CheckAnnotation
     * check for annotations errors.
     * <p>
     * The following annotation error conditions are tested:
     * <ul>
     * <li>Components not annotated.</li>
     * <li>Components having the same reference designator (duplicates).</li>
     * <li>Components with multiple parts per package having different reference designators.</li>
     * <li>Components with multiple parts per package with invalid part count.</li>
     * </ul>
     * </p>
     * @param aMessageList A wxArrayString to store error messages.
     * @return The number of errors found.
     */
    int CheckAnnotation( wxArrayString* aMessageList );

334
    /**
335 336 337 338 339 340 341 342 343 344 345 346
     * Function sortByXCoordinate
     * sorts the list of references by X position.
     * <p>
     * Components are sorted as follows:
     * <ul>
     * <li>Numeric value of reference designator.</li>
     * <li>Sheet number.</li>
     * <li>X coordinate position.</li>
     * <li>Y coordinate position.</li>
     * <li>Time stamp.</li>
     * </ul>
     * </p>
347
     */
348
    void SortByXCoordinate()
349
    {
350
        sort( componentFlatList.begin(), componentFlatList.end(), sortByXPosition );
351 352 353
    }

    /**
354 355 356 357 358 359 360 361 362 363 364 365
     * Function sortByYCoordinate
     * sorts the list of references by Y position.
     * <p>
     * Components are sorted as follows:
     * <ul>
     * <li>Numeric value of reference designator.</li>
     * <li>Sheet number.</li>
     * <li>Y coordinate position.</li>
     * <li>X coordinate position.</li>
     * <li>Time stamp.</li>
     * </ul>
     * </p>
366
     */
367
    void SortByYCoordinate()
368
    {
369
        sort( componentFlatList.begin(), componentFlatList.end(), sortByYPosition );
370 371 372 373 374 375 376
    }

    /**
     * Function SortComponentsByTimeStamp
     * sort the flat list by Time Stamp.
     * Useful to detect duplicate Time Stamps
     */
377
    void SortByTimeStamp()
378 379 380 381 382
    {
        sort( componentFlatList.begin(), componentFlatList.end(), sortByTimeStamp );
    }

    /**
383 384 385 386 387 388 389 390 391 392 393 394 395
     * Function SortByRefAndValue
     * sorts the list of references by value.
     * <p>
     * Components are sorted in the following order:
     * <ul>
     * <li>Numeric value of reference designator.</li>
     * <li>Value of component.</li>
     * <li>Unit number when component has multiple parts.</li>
     * <li>Sheet number.</li>
     * <li>X coordinate position.</li>
     * <li>Y coordinate position.</li>
     * </ul>
     * </p>
396
     */
397
    void SortByRefAndValue()
398 399 400 401 402
    {
        sort( componentFlatList.begin(), componentFlatList.end(), sortByRefAndValue );
    }

    /**
403 404 405 406 407 408 409 410 411
     * Function SortByReferenceOnly
     * sorts the list of references by reference.
     * <p>
     * Components are sorted in the following order:
     * <ul>
     * <li>Numeric value of reference designator.</li>
     * <li>Unit number when component has multiple parts.</li>
     * </ul>
     * </p>
412
     */
413
    void SortByReferenceOnly()
414
    {
415
        sort( componentFlatList.begin(), componentFlatList.end(), sortByReferenceOnly );
416 417
    }

418 419 420 421 422 423 424 425 426 427
    /**
     * Function GetUnit
     * searches the sorted list of components for a another component with the same
     * reference and a given part unit.  Use this method to manage components with
     * multiple parts per package.
     * @param aIndex = index in aComponentsList for of given SCH_REFERENCE item to test.
     * @param aUnit = the given unit number to search
     * @return index in aComponentsList if found or -1 if not found
     */
    int FindUnit( size_t aIndex, int aUnit );
428 429

    /**
430 431 432
     * Function ResetHiddenReferences
     * clears the annotation for all references that have an invisible reference designator.
     * Invisible reference designators always have # as the first letter.
433
     */
434 435
    void ResetHiddenReferences();

436
    /**
437 438 439 440 441 442
     * Function GetRefsInUse
     * adds all the reference designator numbers greater than \a aMinRefId to \a aIdList
     * skipping the reference at \a aIndex.
     * @param aIndex = the current component index to use for reference prefix filtering.
     * @param aIdList = the buffer to fill
     * @param aMinRefId = the min id value to store. all values < aMinRefId are ignored
443
     */
444
    void GetRefsInUse( int aIndex, std::vector< int >& aIdList, int aMinRefId );
445 446

    /**
447 448 449 450 451 452 453
     * Function GetLastReference
     * returns the last used (greatest) reference number in the reference list
     * for the prefix reference given by \a aIndex.  The component list must be
     * sorted.
     *
     * @param aIndex The index of the reference item used for the search pattern.
     * @param aMinValue The minimum value for the current search.
454
     */
455 456 457 458 459 460 461 462 463 464 465
    int GetLastReference( int aIndex, int aMinValue );

private:
    /* sort functions used to sort componentFlatList
    */

    static bool sortByRefAndValue( const SCH_REFERENCE& item1, const SCH_REFERENCE& item2 );

    static bool sortByXPosition( const SCH_REFERENCE& item1, const SCH_REFERENCE& item2 );

    static bool sortByYPosition( const SCH_REFERENCE& item1, const SCH_REFERENCE& item2 );
466 467 468

    static bool sortByTimeStamp( const SCH_REFERENCE& item1, const SCH_REFERENCE& item2 );

469
    static bool sortByReferenceOnly( const SCH_REFERENCE& item1, const SCH_REFERENCE& item2 );
470 471 472 473 474 475 476 477 478 479 480 481 482

    /**
     * Function CreateFirstFreeRefId
     * searches for the first free reference number in \a aListId of reference numbers in use.
     * This function just searches for a hole in a list of incremented numbers, this list must
     * be sorted by increasing values and each value can be stored only once.  The new value
     * is added to the list.
     * @see BuildRefIdInUseList to prepare this list
     * @param aIdList The buffer that contains the reference numbers in use.
     * @param aFirstValue The first expected free value
     * @return The first free (not yet used) value.
     */
    int CreateFirstFreeRefId( std::vector<int>& aIdList, int aFirstValue );
483 484
};

485
#endif    // _NETLIST_H_