autorout.cpp 7.67 KB
Newer Older
1 2 3 4
/**
 * @file autorout.cpp
 * @brief Autorouting command and control.
 */
5

6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
 * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
 *
 * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors.
 *
 * 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
 */

33 34 35 36
#include <fctsys.h>
#include <class_drawpanel.h>
#include <wxPcbStruct.h>
#include <gr_basic.h>
37

38 39 40
#include <pcbnew.h>
#include <cell.h>
#include <zones.h>
41

42 43 44
#include <class_board.h>
#include <class_module.h>
#include <class_track.h>
45 46 47
#include <convert_to_biu.h>

#include <autorout.h>
48

49

50
MATRIX_ROUTING_HEAD RoutingMatrix;     // routing matrix (grid) to route 2-sided boards
51 52

/* init board, route traces*/
53
void PCB_EDIT_FRAME::Autoroute( wxDC* DC, int mode )
54
{
55
    int      start, stop;
56 57 58 59 60
    MODULE*  Module = NULL;
    D_PAD*   Pad    = NULL;
    int      autoroute_net_code = -1;
    wxString msg;

61
    if( GetBoard()->GetCopperLayerCount() > 1 )
62
    {
63 64
        Route_Layer_TOP    = GetScreen()->m_Route_Layer_TOP;
        Route_Layer_BOTTOM = GetScreen()->m_Route_Layer_BOTTOM;
65 66 67
    }
    else
    {
68
        Route_Layer_TOP = Route_Layer_BOTTOM = LAYER_N_BACK;
69 70 71 72 73 74 75 76 77
    }

    switch( mode )
    {
    case ROUTE_NET:
        if( GetScreen()->GetCurItem() )
        {
            switch( GetScreen()->GetCurItem()->Type() )
            {
78
            case PCB_PAD_T:
79 80 81 82 83 84 85 86 87 88
                Pad = (D_PAD*) GetScreen()->GetCurItem();
                autoroute_net_code = Pad->GetNet();
                break;

            default:
                break;
            }
        }
        if( autoroute_net_code <= 0 )
        {
89
            wxMessageBox( _( "Net not selected" ) ); return;
90 91 92 93 94
        }
        break;

    case ROUTE_MODULE:
        Module = (MODULE*) GetScreen()->GetCurItem();
95
        if( (Module == NULL) || (Module->Type() != PCB_MODULE_T) )
96
        {
97
            wxMessageBox( _( "Module not selected" ) );
stambaughw's avatar
stambaughw committed
98
            return;
99 100 101 102 103
        }
        break;

    case ROUTE_PAD:
        Pad = (D_PAD*) GetScreen()->GetCurItem();
104

105
        if( (Pad == NULL)  || (Pad->Type() != PCB_PAD_T) )
106
        {
107
            wxMessageBox( _( "Pad not selected" ) );
stambaughw's avatar
stambaughw committed
108
            return;
109
        }
110

111 112 113
        break;
    }

114
    if( (GetBoard()->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK ) == 0 )
115
        Compile_Ratsnest( DC, true );
116

stambaughw's avatar
stambaughw committed
117
    /* Set the flag on the ratsnest to CH_ROUTE_REQ. */
118
    for( unsigned ii = 0; ii < GetBoard()->GetRatsnestsCount(); ii++ )
119
    {
stambaughw's avatar
stambaughw committed
120
        RATSNEST_ITEM* ptmp = &GetBoard()->m_FullRatsnest[ii];
121
        ptmp->m_Status &= ~CH_ROUTE_REQ;
122 123 124 125

        switch( mode )
        {
        case ROUTE_ALL:
stambaughw's avatar
stambaughw committed
126 127
            ptmp->m_Status |= CH_ROUTE_REQ;
            break;
128 129 130

        case ROUTE_NET:
            if( autoroute_net_code == ptmp->GetNet() )
131
                ptmp->m_Status |= CH_ROUTE_REQ;
132 133 134 135 136
            break;

        case ROUTE_MODULE:
        {
            D_PAD* pt_pad = (D_PAD*) Module->m_Pads;
137
            for( ; pt_pad != NULL; pt_pad = pt_pad->Next() )
138
            {
139 140
                if( ptmp->m_PadStart == pt_pad )
                    ptmp->m_Status |= CH_ROUTE_REQ;
141

142 143
                if( ptmp->m_PadEnd == pt_pad )
                    ptmp->m_Status |= CH_ROUTE_REQ;
144 145 146 147 148 149
            }

            break;
        }

        case ROUTE_PAD:
stambaughw's avatar
stambaughw committed
150
            if( ( ptmp->m_PadStart == Pad ) || ( ptmp->m_PadEnd == Pad ) )
151
                ptmp->m_Status |= CH_ROUTE_REQ;
152

153 154 155 156 157 158
            break;
        }
    }

    start = time( NULL );

stambaughw's avatar
stambaughw committed
159
    /* Calculation of no fixed routing to 5 mils and more. */
160
    RoutingMatrix.m_GridRouting = (int)GetScreen()->GetGridSize().x;
161

162 163
    if( RoutingMatrix.m_GridRouting < (5*IU_PER_MILS) )
        RoutingMatrix.m_GridRouting = 5*IU_PER_MILS;
164

165

stambaughw's avatar
stambaughw committed
166
    /* Calculated ncol and nrow, matrix size for routing. */
167
    RoutingMatrix.ComputeMatrixSize( GetBoard() );
168

169
    m_messagePanel->EraseMsgBox();
170

stambaughw's avatar
stambaughw committed
171
    /* Map the board */
172
    RoutingMatrix.m_RoutingLayersCount = 1;
173

174
    if( Route_Layer_TOP != Route_Layer_BOTTOM )
175
        RoutingMatrix.m_RoutingLayersCount = 2;
176

177
    if( RoutingMatrix.InitRoutingMatrix() < 0 )
178
    {
179
        wxMessageBox( _( "No memory for autorouting" ) );
180
        RoutingMatrix.UnInitRoutingMatrix();  /* Free memory. */
181 182 183
        return;
    }

184
    SetStatusText( _( "Place Cells" ) );
185
    PlaceCells( GetBoard(), -1, FORCE_PADS );
186

stambaughw's avatar
stambaughw committed
187
    /* Construction of the track list for router. */
188
    RoutingMatrix.m_RouteCount = Build_Work( GetBoard() );
189

190
    // DisplayRoutingMatrix( m_canvas, DC );
191

192
    Solve( DC, RoutingMatrix.m_RoutingLayersCount );
193

stambaughw's avatar
stambaughw committed
194 195 196
    /* Free memory. */
    FreeQueue();
    InitWork();             /* Free memory for the list of router connections. */
197
    RoutingMatrix.UnInitRoutingMatrix();
198
    stop = time( NULL ) - start;
199 200
    msg.Printf( wxT( "time = %d second%s" ), stop, ( stop == 1 ) ? wxT( "" ) : wxT( "s" ) );
    SetStatusText( msg );
201 202
}

203

204 205 206
/* Clear the flag CH_NOROUTABLE which is set to 1 by Solve(),
 * when a track was not routed.
 * (If this flag is 1 the corresponding track it is not rerouted)
207
 */
208
void PCB_EDIT_FRAME::Reset_Noroutable( wxDC* DC )
209
{
stambaughw's avatar
stambaughw committed
210
    if( ( GetBoard()->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK )== 0 )
211
        Compile_Ratsnest( DC, true );
212

213
    for( unsigned ii = 0; ii < GetBoard()->GetRatsnestsCount(); ii++ )
214
    {
215
        GetBoard()->m_FullRatsnest[ii].m_Status &= ~CH_UNROUTABLE;
216
    }
217 218
}

219

220
/* DEBUG Function: displays the routing matrix */
221
void DisplayRoutingMatrix( EDA_DRAW_PANEL* panel, wxDC* DC )
222
{
223 224
    int dcell0, dcell1 = 0;
    EDA_COLOR_T color;
225

226
    int maxi = 600 / RoutingMatrix.m_Ncols;
stambaughw's avatar
stambaughw committed
227
    maxi = ( maxi * 3 ) / 4;
228

229 230 231
    if( !maxi )
        maxi = 1;

232
    GRSetDrawMode( DC, GR_COPY );
233

234
    for( int col = 0; col < RoutingMatrix.m_Ncols; col++ )
235
    {
236
        for( int row = 0; row < RoutingMatrix.m_Nrows; row++ )
237
        {
238
            color  = BLACK;
239
            dcell0 = RoutingMatrix.GetCell( row, col, BOTTOM );
240

241
            if( dcell0 & HOLE )
242
                color = GREEN;
243

244
//            if( RoutingMatrix.m_RoutingLayersCount )
245
//                dcell1 = GetCell( row, col, TOP );
246

247
            if( dcell1 & HOLE )
248
                color = RED;
249

250
//            dcell0 |= dcell1;
251

stambaughw's avatar
stambaughw committed
252
            if( !color && ( dcell0 & VIA_IMPOSSIBLE ) )
253
                color = BLUE;
254

255
            if( dcell0 & CELL_is_EDGE )
256
                color = YELLOW;
257
            else if( dcell0 & CELL_is_ZONE )
258
                color = YELLOW;
259 260 261

            #define DRAW_OFFSET_X -20
            #define DRAW_OFFSET_Y 20
262
//            if( color )
263
            {
264 265
                for( int i = 0; i < maxi; i++ )
                    for( int j = 0; j < maxi; j++ )
266
                        GRPutPixel( panel->GetClipBox(), DC,
267 268
                                    ( col * maxi ) + i + DRAW_OFFSET_X,
                                    ( row * maxi ) + j + DRAW_OFFSET_Y, color );
269 270 271 272

            }
        }
    }
273
}