2671 lines
57 KiB
C
2671 lines
57 KiB
C
/*
|
|
* irCommand.c --
|
|
*
|
|
* Command interface for interactive router. This file processes command
|
|
* lines beginning with the `iroute' command.
|
|
*
|
|
* (The "wizard" command, `*iroute', for testing, debugging, etc.,
|
|
* is processed in irTestCmd.c.)
|
|
*
|
|
* *********************************************************************
|
|
* * Copyright (C) 1987, 1990 Michael H. Arnold, Walter S. Scott, and *
|
|
* * the Regents of the University of California. *
|
|
* * Permission to use, copy, modify, and distribute this *
|
|
* * software and its documentation for any purpose and without *
|
|
* * fee is hereby granted, provided that the above copyright *
|
|
* * notice appear in all copies. The University of California *
|
|
* * makes no representations about the suitability of this *
|
|
* * software for any purpose. It is provided "as is" without *
|
|
* * express or implied warranty. Export of this software outside *
|
|
* * of the United States of America may require an export license. *
|
|
* *********************************************************************
|
|
*
|
|
*/
|
|
|
|
#ifndef lint
|
|
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/irouter/irCommand.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
|
|
#endif /* not lint */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "tcltk/tclmagic.h"
|
|
#include "utils/magic.h"
|
|
#include "utils/geometry.h"
|
|
#include "utils/hash.h"
|
|
#include "tiles/tile.h"
|
|
#include "database/database.h"
|
|
#include "utils/signals.h"
|
|
#include "textio/textio.h"
|
|
#include "graphics/graphics.h"
|
|
#include "windows/windows.h"
|
|
#include "dbwind/dbwind.h"
|
|
#include "dbwind/dbwtech.h"
|
|
#include "textio/txcommands.h"
|
|
#include "utils/main.h"
|
|
#include "utils/utils.h"
|
|
#include "commands/commands.h"
|
|
#include "utils/styles.h"
|
|
#include "utils/malloc.h"
|
|
#include "utils/list.h"
|
|
#include "mzrouter/mzrouter.h"
|
|
#include "irouter/irouter.h"
|
|
#include "irouter/irInternal.h"
|
|
|
|
/* window command issued to */
|
|
static MagWindow *irWindow;
|
|
|
|
/* Subcommand table - declared here since its referenced before defined */
|
|
typedef struct
|
|
{
|
|
char *sC_name; /* name of iroute subcommand */
|
|
void (*sC_proc)(); /* Procedure implementing this subcommand */
|
|
char *sC_commentString; /* describes subcommand */
|
|
char *sC_usage; /* command syntax */
|
|
|
|
} SubCmdTableE;
|
|
extern SubCmdTableE irSubcommands[];
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* irSetNoisyAutoInt
|
|
*
|
|
* Set integer parameter, interpeting the string "AUTOMATIC" (or prefix)
|
|
* as -1.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* If valueS is a nonnull string, interpret and set parm
|
|
* accordingly.
|
|
*
|
|
* If valueS is null, the parameter value is left unaltered.
|
|
*
|
|
* If file is nonnull parameter value is written to file.
|
|
*
|
|
* If file is null, parameter value is written to magic text window via
|
|
* TxPrintf
|
|
*
|
|
* If file is (FILE *)1, parameter value is returned as a Tcl object
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
irSetNoisyAutoInt(parm, valueS, file)
|
|
int *parm;
|
|
char *valueS;
|
|
FILE *file;
|
|
{
|
|
int which;
|
|
|
|
/* special value Table */
|
|
#define V_AUTOMATIC -1
|
|
static struct
|
|
{
|
|
char *sv_name; /* name */
|
|
int sv_type;
|
|
} specialValues[] = {
|
|
{"automatic", V_AUTOMATIC},
|
|
{0}
|
|
};
|
|
|
|
/* If value non-null set parm */
|
|
if(valueS!=NULL)
|
|
{
|
|
int i;
|
|
|
|
/* check if special value */
|
|
which = LookupStruct(
|
|
valueS,
|
|
(char **) specialValues,
|
|
sizeof specialValues[0]);
|
|
|
|
if(which == -1)
|
|
{
|
|
TxError("Ambiguous value: '%s'\n",valueS);
|
|
TxError("Value must be 'AUTOMATIC', or a nonnegative integer\n");
|
|
return;
|
|
}
|
|
else if (which >= 0 )
|
|
{
|
|
/* special value */
|
|
int type = specialValues[which].sv_type;
|
|
|
|
if(type == V_AUTOMATIC)
|
|
{
|
|
*parm = -1;
|
|
}
|
|
else
|
|
{
|
|
/* should not ever get here */
|
|
ASSERT(FALSE,"irSetNoisyAutoInt");
|
|
}
|
|
}
|
|
else if(StrIsInt(valueS) && (i=atoi(valueS))>=0)
|
|
{
|
|
*parm = i;
|
|
}
|
|
else
|
|
{
|
|
TxError("Bad value: \"%s\"\n", valueS);
|
|
TxError("Value must be 'AUTOMATIC', or a nonnegative integer\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Print parm value */
|
|
if(file)
|
|
{
|
|
if(*parm == -1)
|
|
{
|
|
fprintf(file,"AUTOMATIC");
|
|
}
|
|
else
|
|
{
|
|
fprintf(file, "%8d ",*parm);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(*parm == -1)
|
|
{
|
|
TxPrintf("AUTOMATIC");
|
|
}
|
|
else
|
|
{
|
|
TxPrintf("%8d ",*parm);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* irLSet<parm> --
|
|
*
|
|
* Set and display Route Layer parameter <parm>.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Call low level routine of appropriate type to set/display parameter.
|
|
* Value of parm can be displayed either in Magic text window (file is
|
|
* NULL) or to a file.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
/* irLSetActive -- */
|
|
Tcl_Obj *
|
|
irLSetActive(rL,s,file)
|
|
RouteLayer *rL;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
if (file == (FILE *)1)
|
|
return Tcl_NewBooleanObj(rL->rl_routeType.rt_active);
|
|
SetNoisyBool(&(rL->rl_routeType.rt_active), s, file);
|
|
return NULL;
|
|
}
|
|
|
|
/* irLSetWidth -- */
|
|
Tcl_Obj *
|
|
irLSetWidth(rL,s,file)
|
|
RouteLayer *rL;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
if (file == (FILE *)1)
|
|
return Tcl_NewIntObj(rL->rl_routeType.rt_width);
|
|
SetNoisyInt(&(rL->rl_routeType.rt_width),s,file);
|
|
return NULL;
|
|
}
|
|
|
|
/* irLSetLength -- */
|
|
Tcl_Obj *
|
|
irLSetLength(rL,s,file)
|
|
RouteLayer *rL;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
if (file == (FILE *)1)
|
|
return Tcl_NewIntObj(rL->rl_routeType.rt_length);
|
|
SetNoisyInt(&(rL->rl_routeType.rt_length),s,file);
|
|
return NULL;
|
|
}
|
|
|
|
/* irLSetHCost -- */
|
|
Tcl_Obj *
|
|
irLSetHCost(rL,s,file)
|
|
RouteLayer *rL;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
if (file == (FILE *)1)
|
|
return Tcl_NewIntObj(rL->rl_hCost);
|
|
SetNoisyInt(&(rL->rl_hCost),s,file);
|
|
return NULL;
|
|
}
|
|
|
|
/* irLSetVCost -- */
|
|
Tcl_Obj *
|
|
irLSetVCost(rL,s,file)
|
|
RouteLayer *rL;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
if (file == (FILE *)1)
|
|
return Tcl_NewIntObj(rL->rl_vCost);
|
|
SetNoisyInt(&(rL->rl_vCost),s,file);
|
|
return NULL;
|
|
}
|
|
|
|
/* irLSetJogCost -- */
|
|
Tcl_Obj *
|
|
irLSetJogCost(rL,s,file)
|
|
RouteLayer *rL;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
if (file == (FILE *)1)
|
|
return Tcl_NewIntObj(rL->rl_jogCost);
|
|
SetNoisyInt(&(rL->rl_jogCost),s,file);
|
|
return NULL;
|
|
}
|
|
|
|
/* irLSetHintCost -- */
|
|
Tcl_Obj *
|
|
irLSetHintCost(rL,s,file)
|
|
RouteLayer *rL;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
if (file == (FILE *)1)
|
|
return Tcl_NewIntObj(rL->rl_hintCost);
|
|
SetNoisyInt(&(rL->rl_hintCost),s,file);
|
|
return NULL;
|
|
}
|
|
|
|
/* irLSetOverCost -- */
|
|
Tcl_Obj *
|
|
irLSetOverCost(rL,s,file)
|
|
RouteLayer *rL;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
if (file == (FILE *)1)
|
|
return Tcl_NewIntObj(rL->rl_overCost);
|
|
SetNoisyInt(&(rL->rl_overCost),s,file);
|
|
return NULL;
|
|
}
|
|
|
|
#else
|
|
|
|
/* irLSetActive -- */
|
|
void
|
|
irLSetActive(rL,s,file)
|
|
RouteLayer *rL;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyBool(&(rL->rl_routeType.rt_active),s,file);
|
|
}
|
|
|
|
/* irLSetWidth -- */
|
|
void
|
|
irLSetWidth(rL,s,file)
|
|
RouteLayer *rL;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyInt(&(rL->rl_routeType.rt_width),s,file);
|
|
}
|
|
|
|
/* irLSetLength -- */
|
|
void
|
|
irLSetLength(rL,s,file)
|
|
RouteLayer *rL;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyInt(&(rL->rl_routeType.rt_length),s,file);
|
|
}
|
|
|
|
/* irLSetHCost -- */
|
|
void
|
|
irLSetHCost(rL,s,file)
|
|
RouteLayer *rL;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyInt(&(rL->rl_hCost),s,file);
|
|
}
|
|
|
|
/* irLSetVCost -- */
|
|
void
|
|
irLSetVCost(rL,s,file)
|
|
RouteLayer *rL;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyInt(&(rL->rl_vCost),s,file);
|
|
}
|
|
|
|
/* irLSetJogCost -- */
|
|
void
|
|
irLSetJogCost(rL,s,file)
|
|
RouteLayer *rL;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyInt(&(rL->rl_jogCost),s,file);
|
|
}
|
|
|
|
|
|
/* irLSetHintCost -- */
|
|
void
|
|
irLSetHintCost(rL,s,file)
|
|
RouteLayer *rL;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyInt(&(rL->rl_hintCost),s,file);
|
|
}
|
|
|
|
/* irLSetOverCost -- */
|
|
void
|
|
irLSetOverCost(rL,s,file)
|
|
RouteLayer *rL;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyInt(&(rL->rl_overCost),s,file);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* irCSet<parm> --
|
|
*
|
|
* Set and display contact parameter <parm>.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Call low level routine of appropriate type to set/display parameter.
|
|
* Value of parm can be displayed either in Magic text window (file is
|
|
* NULL) or to a file.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
|
|
/* irCSetActive -- */
|
|
Tcl_Obj *
|
|
irCSetActive(rC,s, file)
|
|
RouteContact *rC;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
if (file == (FILE *)1)
|
|
return Tcl_NewBooleanObj(rC->rc_routeType.rt_active);
|
|
SetNoisyBool(&(rC->rc_routeType.rt_active),s,file);
|
|
return NULL;
|
|
}
|
|
|
|
/* irCSetWidth -- */
|
|
Tcl_Obj *
|
|
irCSetWidth(rC,s,file)
|
|
RouteContact *rC;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
if (file == (FILE *)1)
|
|
return Tcl_NewIntObj(rC->rc_routeType.rt_width);
|
|
SetNoisyInt(&(rC->rc_routeType.rt_width),s,file);
|
|
return NULL;
|
|
}
|
|
|
|
/* irCSetLength-- */
|
|
Tcl_Obj *
|
|
irCSetLength(rC,s,file)
|
|
RouteContact *rC;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
if (file == (FILE *)1)
|
|
return Tcl_NewIntObj(rC->rc_routeType.rt_length);
|
|
SetNoisyInt(&(rC->rc_routeType.rt_length),s,file);
|
|
return NULL;
|
|
}
|
|
|
|
/* irCSetCost -- */
|
|
Tcl_Obj *
|
|
irCSetCost(rC,s,file)
|
|
RouteContact *rC;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
if (file == (FILE *)1)
|
|
return Tcl_NewIntObj(rC->rc_cost);
|
|
SetNoisyInt(&(rC->rc_cost),s,file);
|
|
return NULL;
|
|
}
|
|
|
|
#else
|
|
|
|
/* irCSetActive -- */
|
|
void
|
|
irCSetActive(rC,s, file)
|
|
RouteContact *rC;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyBool(&(rC->rc_routeType.rt_active),s,file);
|
|
}
|
|
|
|
/* irCSetWidth -- */
|
|
void
|
|
irCSetWidth(rC,s,file)
|
|
RouteContact *rC;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyInt(&(rC->rc_routeType.rt_width),s,file);
|
|
}
|
|
|
|
/* irCSetLength -- */
|
|
void
|
|
irCSetLength(rC,s,file)
|
|
RouteContact *rC;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyInt(&(rC->rc_routeType.rt_length),s,file);
|
|
}
|
|
|
|
/* irCSetCost -- */
|
|
void
|
|
irCSetCost(rC,s,file)
|
|
RouteContact *rC;
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyInt(&(rC->rc_cost),s,file);
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* irSrSet<parm> --
|
|
*
|
|
* Set and display search parameter <parm>.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Call low level routine of appropriate type to set/display parameter.
|
|
* Value of parm can be displayed either in Magic text window (file is
|
|
* NULL) or to a file.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
|
|
/* irSrSetRate -- */
|
|
void
|
|
irSrSetRate(s,file)
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyDI(&irMazeParms->mp_wRate,s,file);
|
|
}
|
|
|
|
/* irSrSetWidth -- */
|
|
void
|
|
irSrSetWidth(s,file)
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyDI(&(irMazeParms->mp_wWidth),s,file);
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* irWzdSet<parm> --
|
|
*
|
|
* Set and display wizard parameter <parm>.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Call low level routine of appropriate type to set/display parameter.
|
|
* Value of parm can be displayed either in Magic text window (file is
|
|
* NULL) or to a file.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
/* irWzdSetBloomCost -- */
|
|
void
|
|
irWzdSetBloomCost(s,file)
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyDI(&(irMazeParms->mp_bloomDeltaCost),s,file);
|
|
}
|
|
|
|
/* irWzdSetBloomLimit -- */
|
|
void
|
|
irWzdSetBloomLimit(s,file)
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyDI(&(irMazeParms->mp_bloomLimit),s,file);
|
|
}
|
|
|
|
/* irWzdSetBoundsIncrement -- */
|
|
void
|
|
irWzdSetBoundsIncrement(s,file)
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
irSetNoisyAutoInt(&(irMazeParms->mp_boundsIncrement),s,file);
|
|
}
|
|
|
|
/* irWzdSetEstimate -- */
|
|
void
|
|
irWzdSetEstimate(s,file)
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyBool(&(irMazeParms->mp_estimate),s,file);
|
|
}
|
|
|
|
/* irWzdSetExpandEndpoints-- */
|
|
void
|
|
irWzdSetExpandEndpoints(s, file)
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
SetNoisyBool(&(irMazeParms->mp_expandEndpoints),s,file);
|
|
}
|
|
|
|
/* irWzdSetPenalty -- */
|
|
void
|
|
irWzdSetPenalty(s, file)
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
if(s)
|
|
{
|
|
/* arg given, set penalty to it */
|
|
float value;
|
|
if(sscanf(s,"%f",&value)==1)
|
|
{
|
|
irMazeParms->mp_penalty.rf_mantissa =
|
|
(int) (value * (1<<irMazeParms->mp_penalty.rf_nExponent));
|
|
}
|
|
else
|
|
{
|
|
TxError("Bad penalty value: %s\n",s);
|
|
}
|
|
}
|
|
|
|
/* print the current penalty factor. */
|
|
if(file)
|
|
{
|
|
fprintf(file,"%f",
|
|
(double)irMazeParms->mp_penalty.rf_mantissa /
|
|
(double)(1<<irMazeParms->mp_penalty.rf_nExponent));
|
|
}
|
|
else
|
|
{
|
|
TxPrintf("%f",
|
|
(double)irMazeParms->mp_penalty.rf_mantissa /
|
|
(double)(1<<irMazeParms->mp_penalty.rf_nExponent));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* irWzdSetPenetration-- */
|
|
void
|
|
irWzdSetPenetration(s, file)
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
irSetNoisyAutoInt(&(irMazeParms->mp_maxWalkLength),s,file);
|
|
}
|
|
|
|
/* irWzdSetWindow -- */
|
|
void
|
|
irWzdSetWindow(s, file)
|
|
char *s;
|
|
FILE *file;
|
|
{
|
|
int which;
|
|
int i, type;
|
|
|
|
/* special arg Table */
|
|
#define SP_COMMAND -1
|
|
#define SP_DOT -2
|
|
static struct
|
|
{
|
|
char *sp_name; /* name */
|
|
int sp_type;
|
|
} specialArgs[] = {
|
|
{"command", SP_COMMAND},
|
|
{".", SP_DOT},
|
|
{0}
|
|
};
|
|
|
|
if(s!=NULL)
|
|
/* set parameter */
|
|
{
|
|
/* check if special arg */
|
|
which = LookupStruct(
|
|
s,
|
|
(char **) specialArgs,
|
|
sizeof specialArgs[0]);
|
|
|
|
if(which == -1)
|
|
{
|
|
TxError("Ambiguous argument: '%s'\n",s);
|
|
TxError("Argument must 'COMMAND', '.', or a nonneg. integer\n");
|
|
return;
|
|
}
|
|
else if (which >= 0 )
|
|
{
|
|
/* special argument */
|
|
type = specialArgs[which].sp_type;
|
|
if(type == SP_COMMAND)
|
|
{
|
|
irRouteWid = -1;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(type==SP_DOT,"wzdSetWindow");
|
|
if(irWindow==NULL)
|
|
{
|
|
TxError("Point to a layout window first!\n");
|
|
return;
|
|
}
|
|
else
|
|
irRouteWid = irWindow->w_wid;
|
|
}
|
|
}
|
|
else if(StrIsInt(s) && (i=atoi(s))>=0)
|
|
{
|
|
irRouteWid = i;
|
|
}
|
|
else
|
|
{
|
|
TxError("Bad argument: \"%s\"\n", s);
|
|
TxError("Argument must be 'COMMAND', '.', or a nonneg. integer\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Print current value of parm */
|
|
if(file)
|
|
{
|
|
if(irRouteWid == -1)
|
|
{
|
|
fprintf(file,"COMMAND");
|
|
}
|
|
else
|
|
{
|
|
fprintf(file,"%d",irRouteWid);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(irRouteWid == -1)
|
|
{
|
|
TxPrintf("COMMAND");
|
|
}
|
|
else
|
|
{
|
|
TxPrintf("%d",irRouteWid);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* irContactsCmd --
|
|
*
|
|
* Irouter subcommand to set and display parameters on contacts.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Modify contact parameters and display them.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
/* Contact Parameter Table */
|
|
static struct
|
|
{
|
|
char *cP_name; /* name of parameter */
|
|
#ifdef MAGIC_WRAPPER
|
|
Tcl_Obj *(*cP_proc)(); /* Procedure processing this parameter */
|
|
#else
|
|
void (*cP_proc)(); /* Procedure processing this parameter */
|
|
#endif
|
|
} cParms[] = {
|
|
{"active", irCSetActive},
|
|
{"width", irCSetWidth},
|
|
{"length", irCSetLength},
|
|
{"cost", irCSetCost},
|
|
{0}
|
|
};
|
|
|
|
/* NEXTVALUE - returns pointer to next value arg (string). */
|
|
#define NEXTVALUE \
|
|
( \
|
|
(argc <= 4) ? NULL : \
|
|
(nV_i >= argc-1) ? cmd->tx_argv[nV_i=4] : cmd->tx_argv[++nV_i] \
|
|
)
|
|
|
|
void
|
|
irContactsCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
TileType tileType;
|
|
RouteContact *rC;
|
|
|
|
int argc = cmd->tx_argc;
|
|
int which, n;
|
|
int nV_i; /* Used by NEXTVALUE, must be initialized */
|
|
bool doList = FALSE;
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
/* Check for "-list" option */
|
|
if (!strncmp(cmd->tx_argv[argc - 1], "-list", 5))
|
|
{
|
|
doList = TRUE;
|
|
argc--;
|
|
}
|
|
#endif
|
|
|
|
nV_i = argc - 1;
|
|
|
|
/* Process by case */
|
|
if(argc == 2 ||
|
|
(argc == 3 && (strcmp(cmd->tx_argv[2],"*")==0)) ||
|
|
(argc >= 4 &&
|
|
(strcmp(cmd->tx_argv[2],"*")==0) &&
|
|
(strcmp(cmd->tx_argv[3],"*")==0)))
|
|
{
|
|
/* PROCESS ALL PARMS FOR ALL CONTACT TYPES */
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
if (doList)
|
|
{
|
|
Tcl_Obj *alllist, *rlist, *rname, *robj;
|
|
alllist = Tcl_NewListObj(0, NULL);
|
|
|
|
/* Process contact parms */
|
|
for (rC = irRouteContacts; rC != NULL; rC = rC->rc_next)
|
|
{
|
|
rlist = Tcl_NewListObj(0, NULL);
|
|
rname = Tcl_NewStringObj(
|
|
DBTypeLongNameTbl[rC->rc_routeType.rt_tileType], -1);
|
|
Tcl_ListObjAppendElement(magicinterp, rlist, rname);
|
|
for (n = 0; cParms[n].cP_name; n++)
|
|
{
|
|
robj = (*cParms[n].cP_proc)(rC, NEXTVALUE, (FILE *)1);
|
|
Tcl_ListObjAppendElement(magicinterp, rlist, robj);
|
|
}
|
|
Tcl_ListObjAppendElement(magicinterp, alllist, rlist);
|
|
}
|
|
Tcl_SetObjResult(magicinterp, alllist);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
/* Print Contact Heading */
|
|
TxPrintf("%-12.12s ", "contact");
|
|
for(n=0; cParms[n].cP_name; n++)
|
|
{
|
|
TxPrintf("%8.8s ",cParms[n].cP_name);
|
|
}
|
|
TxPrintf("\n");
|
|
|
|
TxPrintf("%-12.12s ", irRepeatChar(strlen("contact"),'-'));
|
|
for(n=0; cParms[n].cP_name; n++)
|
|
{
|
|
TxPrintf("%8.8s ",irRepeatChar(strlen(cParms[n].cP_name),'-'));
|
|
}
|
|
TxPrintf("\n");
|
|
|
|
/* Process contact parms */
|
|
for (rC=irRouteContacts; rC!= NULL; rC=rC->rc_next)
|
|
{
|
|
TxPrintf("%-12.12s ",
|
|
DBTypeLongNameTbl[rC->rc_routeType.rt_tileType]);
|
|
for(n=0; cParms[n].cP_name; n++)
|
|
{
|
|
(*cParms[n].cP_proc)(rC,NEXTVALUE,NULL);
|
|
}
|
|
TxPrintf("\n");
|
|
}
|
|
}
|
|
}
|
|
else if(argc==3 ||
|
|
(argc >= 4 && (strcmp(cmd->tx_argv[3],"*")==0)))
|
|
{
|
|
/* PROCESS ALL PARMS ASSOCIATED WITH CONTACT */
|
|
/* convert layer string to tileType */
|
|
tileType = DBTechNameType(cmd->tx_argv[2]);
|
|
if(tileType<0)
|
|
{
|
|
TxError("Unrecognized layer (type): \"%.20s\"\n",
|
|
cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
|
|
if(rC=irFindRouteContact(tileType))
|
|
{
|
|
/* Print Contact Heading */
|
|
TxPrintf("%-12.12s ", "contact");
|
|
for(n=0; cParms[n].cP_name; n++)
|
|
{
|
|
TxPrintf("%8.8s ",cParms[n].cP_name);
|
|
}
|
|
TxPrintf("\n");
|
|
|
|
TxPrintf("%-12.12s ", irRepeatChar(strlen("contact"),'-'));
|
|
for(n=0; cParms[n].cP_name; n++)
|
|
{
|
|
TxPrintf("%8.8s ",irRepeatChar(strlen(cParms[n].cP_name),'-'));
|
|
}
|
|
TxPrintf("\n");
|
|
|
|
/* Process contact parms */
|
|
TxPrintf("%-12.12s ",
|
|
DBTypeLongNameTbl[rC->rc_routeType.rt_tileType]);
|
|
for(n=0; cParms[n].cP_name; n++)
|
|
{
|
|
(*cParms[n].cP_proc)(rC,NEXTVALUE,NULL);
|
|
}
|
|
TxPrintf("\n");
|
|
}
|
|
else
|
|
{
|
|
TxError("Unrecognized route-contact: \"%.20s\"\n",
|
|
cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
}
|
|
else if(argc>=4 && strcmp(cmd->tx_argv[2],"*")==0)
|
|
{
|
|
/* PROCESS A COLUMN (THE VALUES OF A PARAMETER FOR ALL CONTACTS) */
|
|
|
|
/* Lookup parameter name in contact parm table */
|
|
which = LookupStruct(
|
|
cmd->tx_argv[3],
|
|
(char **) cParms,
|
|
sizeof cParms[0]);
|
|
|
|
/* Process table lookup */
|
|
if (which == -1)
|
|
{
|
|
/* AMBIGUOUS PARAMETER */
|
|
TxError("Ambiguous parameter: \"%s\"\n",
|
|
cmd->tx_argv[3]);
|
|
return;
|
|
}
|
|
else if (which<0)
|
|
{
|
|
/* PARAMETER NOT FOUND */
|
|
TxError("Unrecognized parameter: %s\n", cmd->tx_argv[3]);
|
|
TxError("Valid contact parameters are: ");
|
|
for (n = 0; cParms[n].cP_name; n++)
|
|
TxError(" %s", cParms[n].cP_name);
|
|
TxError("\n");
|
|
return;
|
|
}
|
|
|
|
else
|
|
{
|
|
/* CONTACT PARAMETER FOUND */
|
|
|
|
/* Print Heading */
|
|
TxPrintf("%-12.12s ", "contact");
|
|
TxPrintf("%8.8s ",cParms[which].cP_name);
|
|
TxPrintf("\n");
|
|
|
|
TxPrintf("%-12.12s ", irRepeatChar(strlen("contact"),'-'));
|
|
TxPrintf("%8.8s ",
|
|
irRepeatChar(strlen(cParms[which].cP_name),'-'));
|
|
TxPrintf("\n");
|
|
|
|
/* Process contact parm */
|
|
for (rC=irRouteContacts; rC!= NULL; rC=rC->rc_next)
|
|
{
|
|
TxPrintf("%-12.12s ",
|
|
DBTypeLongNameTbl[rC->rc_routeType.rt_tileType]);
|
|
(*cParms[which].cP_proc)(rC,NEXTVALUE,NULL);
|
|
TxPrintf("\n");
|
|
}
|
|
}
|
|
}
|
|
else if(argc>=4)
|
|
{
|
|
/* PROCESS PARAMETER ASSOCIATED WITH CONTACT */
|
|
/* convert layer string to tileType */
|
|
tileType = DBTechNameType(cmd->tx_argv[2]);
|
|
if(tileType<0)
|
|
{
|
|
TxError("Unrecognized layer (type): \"%.20s\"\n",
|
|
cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
|
|
if(rC=irFindRouteContact(tileType))
|
|
{
|
|
/* Lookup contact parameter name in table */
|
|
which = LookupStruct(
|
|
cmd->tx_argv[3],
|
|
(char **) cParms,
|
|
sizeof cParms[0]);
|
|
|
|
/* Process result of lookup */
|
|
if (which >= 0)
|
|
{
|
|
/* parameter found - call proc that processes it
|
|
* NULL second arg means display only
|
|
*/
|
|
(*cParms[which].cP_proc)(rC,NEXTVALUE,NULL);
|
|
TxPrintf("\n");
|
|
}
|
|
else if (which == -1)
|
|
{
|
|
/* ambiguous parameter - complain */
|
|
TxError("Ambiguous parameter: \"%s\"\n",
|
|
cmd->tx_argv[3]);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
/* unrecognized parameter - complain */
|
|
TxError("Unrecognized parameter: %s\n", cmd->tx_argv[3]);
|
|
TxError("Valid contact parameters are: ");
|
|
for (n = 0; cParms[n].cP_name; n++)
|
|
TxError(" %s", cParms[n].cP_name);
|
|
TxError("\n");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TxError("Unrecognized route-contact: \"%.20s\"\n",
|
|
cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
/* Give warning if number of parm values didn't come out even */
|
|
if (nV_i != argc-1)
|
|
{
|
|
TxError("Warning: Number of parameter values didn't match number of parameters.\n");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* irHelpCmd --
|
|
*
|
|
* Irouter subcommand to describe available commands. (Driven by command
|
|
* table, defined above IRCommand()).
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Display requested help info.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
/*ARGSUSED*/
|
|
void
|
|
irHelpCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
int n;
|
|
int which;
|
|
|
|
if(cmd->tx_argc == 2)
|
|
{
|
|
/* No arg, so print summary of commands */
|
|
TxPrintf("\niroute - route from cursor to box\n\n");
|
|
for(n=0; irSubcommands[n].sC_name!=NULL; n++)
|
|
{
|
|
TxPrintf("iroute %s - %s\n",
|
|
irSubcommands[n].sC_name,
|
|
irSubcommands[n].sC_commentString);
|
|
}
|
|
TxPrintf("\niroute help <subcmd>");
|
|
TxPrintf(" - print usage info for subcommand.\n\n");
|
|
}
|
|
else
|
|
{
|
|
/* Lookup subcommand in table, and printed associated help info */
|
|
which = LookupStruct(
|
|
cmd->tx_argv[2],
|
|
(char **) irSubcommands,
|
|
sizeof irSubcommands[0]);
|
|
|
|
/* Process result of lookup */
|
|
if (which >= 0)
|
|
{
|
|
/* subcommand found - call print out its comment string and usage */
|
|
TxPrintf("\niroute %s - %s\n",
|
|
irSubcommands[which].sC_name,
|
|
irSubcommands[which].sC_commentString);
|
|
TxPrintf("\nusage:\niroute %s\n",
|
|
irSubcommands[which].sC_usage);
|
|
}
|
|
else if (which == -1)
|
|
{
|
|
/* ambiguous subcommand - complain */
|
|
TxError("Ambiguous iroute subcommand: \"%s\"\n", cmd->tx_argv[2]);
|
|
}
|
|
else
|
|
{
|
|
/* unrecognized subcommand - complain */
|
|
TxError("Unrecognized iroute subcommand: \"%s\"\n",
|
|
cmd->tx_argv[2]);
|
|
TxError("Valid iroute irSubcommands are: ");
|
|
for (n = 0; irSubcommands[n].sC_name; n++)
|
|
TxError(" %s", irSubcommands[n].sC_name);
|
|
TxError("\n");
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* irLayersCmd --
|
|
*
|
|
* Irouter subcommand to set and display parameters on route layers.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Modify contact parameters and display them.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
/* Layer Parameter Table */
|
|
static struct
|
|
{
|
|
char *lP_name; /* name of parameter */
|
|
#ifdef MAGIC_WRAPPER
|
|
Tcl_Obj *(*lP_proc)(); /* procedure processing this parameter */
|
|
#else
|
|
void (*lP_proc)(); /* procedure processing this parameter */
|
|
#endif
|
|
} lParms[] = {
|
|
{"active", irLSetActive},
|
|
{"width", irLSetWidth},
|
|
{"length", irLSetLength},
|
|
{"hCost", irLSetHCost},
|
|
{"vCost", irLSetVCost},
|
|
{"jogCost", irLSetJogCost},
|
|
{"hintCost", irLSetHintCost},
|
|
{"overCost", irLSetOverCost},
|
|
{0}
|
|
};
|
|
|
|
/* NEXTVALUE - returns pointer to next value arg (string). */
|
|
#define NEXTVALUE \
|
|
( \
|
|
(argc <= 4) ? NULL : \
|
|
(nV_i >= argc-1) ? cmd->tx_argv[nV_i=4] : cmd->tx_argv[++nV_i] \
|
|
)
|
|
|
|
/*ARGSUSED*/
|
|
void
|
|
irLayersCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
TileType tileType;
|
|
RouteLayer *rL;
|
|
bool doList = FALSE;
|
|
|
|
int argc = cmd->tx_argc;
|
|
int which, n;
|
|
int nV_i; /* Used by NEXTVALUE, must be initialized */
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
/* Check for "-list" option */
|
|
if (!strncmp(cmd->tx_argv[argc - 1], "-list", 5))
|
|
{
|
|
doList = TRUE;
|
|
argc--;
|
|
}
|
|
#endif
|
|
|
|
nV_i = argc - 1;
|
|
|
|
/* Process by case */
|
|
if(argc == 2 ||
|
|
(argc == 3 && (strcmp(cmd->tx_argv[2],"*")==0)) ||
|
|
(argc >= 4 &&
|
|
(strcmp(cmd->tx_argv[2],"*")==0) &&
|
|
(strcmp(cmd->tx_argv[3],"*")==0)))
|
|
{
|
|
/* PROCESS ALL PARMS FOR ALL ROUTE LAYERS */
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
if (doList)
|
|
{
|
|
Tcl_Obj *alllist, *rlist, *robj, *rname;
|
|
alllist = Tcl_NewListObj(0, NULL);
|
|
|
|
/* Process parms for each route layer */
|
|
for (rL = irRouteLayers; rL != NULL; rL = rL->rl_next)
|
|
{
|
|
rlist = Tcl_NewListObj(0, NULL);
|
|
rname = Tcl_NewStringObj(
|
|
DBTypeLongNameTbl[rL->rl_routeType.rt_tileType], -1);
|
|
Tcl_ListObjAppendElement(magicinterp, rlist, rname);
|
|
for (n = 0; lParms[n].lP_name; n++)
|
|
{
|
|
robj = (*lParms[n].lP_proc)(rL, NEXTVALUE, (FILE *)1);
|
|
Tcl_ListObjAppendElement(magicinterp, rlist, robj);
|
|
}
|
|
Tcl_ListObjAppendElement(magicinterp, alllist, rlist);
|
|
}
|
|
Tcl_SetObjResult(magicinterp, alllist);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
/* Print Route Layer Heading */
|
|
TxPrintf("%-12.12s ", "layer");
|
|
for(n=0; lParms[n].lP_name; n++)
|
|
{
|
|
TxPrintf("%8.8s ",lParms[n].lP_name);
|
|
}
|
|
TxPrintf("\n");
|
|
|
|
TxPrintf("%-12.12s ", irRepeatChar(strlen("layer"),'-'));
|
|
for(n=0; lParms[n].lP_name; n++)
|
|
{
|
|
TxPrintf("%8.8s ", irRepeatChar(strlen(lParms[n].lP_name),'-'));
|
|
}
|
|
TxPrintf("\n");
|
|
|
|
/* Process parms for each route layer */
|
|
for (rL=irRouteLayers; rL!= NULL; rL=rL->rl_next)
|
|
{
|
|
TxPrintf("%-12.12s ",
|
|
DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]);
|
|
for(n=0; lParms[n].lP_name; n++)
|
|
{
|
|
(*lParms[n].lP_proc)(rL,NEXTVALUE,NULL);
|
|
}
|
|
TxPrintf("\n");
|
|
}
|
|
}
|
|
}
|
|
else if(argc==3 ||
|
|
(argc >= 4 && (strcmp(cmd->tx_argv[3],"*")==0)))
|
|
{
|
|
/* PROCESS ALL PARMS ASSOCIATED WITH ROUTE LAYER */
|
|
/* convert layer string to tileType */
|
|
tileType = DBTechNameType(cmd->tx_argv[2]);
|
|
if(tileType<0)
|
|
{
|
|
TxError("Unrecognized layer (type): \"%.20s\"\n",
|
|
cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
|
|
if (rL=irFindRouteLayer(tileType))
|
|
{
|
|
/* Print Route Layer Heading */
|
|
TxPrintf("%-12.12s ", "layer");
|
|
for(n=0; lParms[n].lP_name; n++)
|
|
{
|
|
TxPrintf("%8.8s ",lParms[n].lP_name);
|
|
}
|
|
TxPrintf("\n");
|
|
|
|
TxPrintf("%-12.12s ", irRepeatChar(strlen("layer"),'-'));
|
|
for(n=0; lParms[n].lP_name; n++)
|
|
{
|
|
TxPrintf("%8.8s ", irRepeatChar(strlen(lParms[n].lP_name),'-'));
|
|
}
|
|
TxPrintf("\n");
|
|
|
|
/* Process parms for route layer */
|
|
TxPrintf("%-12.12s ",
|
|
DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]);
|
|
for(n=0; lParms[n].lP_name; n++)
|
|
{
|
|
(*lParms[n].lP_proc)(rL,NEXTVALUE,NULL);
|
|
}
|
|
TxPrintf("\n");
|
|
}
|
|
else
|
|
{
|
|
TxError("Unrecognized route layer or contact: \"%.20s\"\n",
|
|
cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
}
|
|
else if(argc>=4 && strcmp(cmd->tx_argv[2],"*")==0)
|
|
{
|
|
/* PROCESS A COLUMN (THE VALUES OF A PARAMETER FOR ALL LAYERS) */
|
|
|
|
/* Lookup parameter name in layer parm table */
|
|
which = LookupStruct(
|
|
cmd->tx_argv[3],
|
|
(char **) lParms,
|
|
sizeof lParms[0]);
|
|
|
|
/* Process table lookup */
|
|
if (which == -1)
|
|
{
|
|
/* AMBIGUOUS PARAMETER */
|
|
TxError("Ambiguous parameter: \"%s\"\n",
|
|
cmd->tx_argv[3]);
|
|
return;
|
|
}
|
|
|
|
else if (which<0)
|
|
{
|
|
/* PARAMETER NOT FOUND */
|
|
TxError("Unrecognized parameter: %s\n", cmd->tx_argv[3]);
|
|
TxError("Valid layer parameters are: ");
|
|
for (n = 0; lParms[n].lP_name; n++)
|
|
TxError(" %s", lParms[n].lP_name);
|
|
TxError("\n");
|
|
return;
|
|
}
|
|
|
|
else
|
|
{
|
|
/* LAYER PARAMETER FOUND */
|
|
|
|
/* Print Heading */
|
|
TxPrintf("%-12.12s ", "layer");
|
|
TxPrintf("%8.8s ",lParms[which].lP_name);
|
|
TxPrintf("\n");
|
|
|
|
TxPrintf("%-12.12s ", irRepeatChar(strlen("layer"),'-'));
|
|
TxPrintf("%8.8s ",
|
|
irRepeatChar(strlen(lParms[which].lP_name),'-'));
|
|
TxPrintf("\n");
|
|
|
|
/* Process parm for each route layer */
|
|
for (rL=irRouteLayers; rL!= NULL; rL=rL->rl_next)
|
|
{
|
|
TxPrintf("%-12.12s ",
|
|
DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]);
|
|
(*lParms[which].lP_proc)(rL,NEXTVALUE,NULL);
|
|
TxPrintf("\n");
|
|
}
|
|
|
|
}
|
|
}
|
|
else if(argc>=4)
|
|
{
|
|
/* PROCESS PARAMETER ASSOCIATED WITH ROUTE LAYER */
|
|
/* convert layer string to tileType */
|
|
tileType = DBTechNameType(cmd->tx_argv[2]);
|
|
if(tileType<0)
|
|
{
|
|
TxError("Unrecognized layer (type): \"%.20s\"\n",
|
|
cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
|
|
if (rL=irFindRouteLayer(tileType))
|
|
{
|
|
/* Lookup route layer parameter name in table */
|
|
which = LookupStruct(
|
|
cmd->tx_argv[3],
|
|
(char **) lParms,
|
|
sizeof lParms[0]);
|
|
|
|
/* Process result of lookup */
|
|
if (which >= 0)
|
|
{
|
|
/* parameter found - call proc that processes it
|
|
* NULL second arg means display only
|
|
*/
|
|
(*lParms[which].lP_proc)(rL,NEXTVALUE,NULL);
|
|
TxPrintf("\n");
|
|
}
|
|
else if (which == -1)
|
|
{
|
|
/* ambiguous parameter - complain */
|
|
TxError("Ambiguous parameter: \"%s\"\n",
|
|
cmd->tx_argv[3]);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
/* unrecognized parameter - complain */
|
|
TxError("Unrecognized parameter: %s\n", cmd->tx_argv[3]);
|
|
TxError("Valid route layer parameters are: ");
|
|
for (n = 0; lParms[n].lP_name; n++)
|
|
TxError(" %s", lParms[n].lP_name);
|
|
TxError("\n");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TxError("Unrecognized layer: \"%.20s\"\n",
|
|
cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Give warning if number of parm values didn't come out even */
|
|
if (nV_i != argc-1)
|
|
{
|
|
TxError("Warning: Number of parameter values didn't match number of parameters.\n");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* irRouteCmd --
|
|
*
|
|
* Irouter subcommand to actually do a route.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Compute a route and paint it into edit cell.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
/* Route options Table */
|
|
static char* rOptions[] = {
|
|
"-dbox", /* 0 */
|
|
"-dlabel", /* 1 */
|
|
"-dlayers", /* 2 */
|
|
"-drect", /* 3 */
|
|
"-dselection",/* 4 */
|
|
"-scursor", /* 5 */
|
|
"-slabel", /* 6 */
|
|
"-slayers", /* 7 */
|
|
"-spoint", /* 8 */
|
|
#ifdef MAGIC_WRAPPER
|
|
"-timeout", /* 9 */
|
|
#endif
|
|
NULL
|
|
};
|
|
|
|
void
|
|
irRouteCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
Point *startPtArg = NULL; /* pts to start point, if given on command */
|
|
Rect *destRectArg = NULL; /* pts to dest rect, if given on command */
|
|
char *startLabel = NULL; /* pts to labelname, if given on command */
|
|
char *destLabel = NULL; /* pts to labelname, if given on command */
|
|
List *startLayers = NULL;
|
|
List *destLayers = NULL;
|
|
int startType; /* type of start specifier */
|
|
int destType; /* type of destination specifier */
|
|
Point startPt;
|
|
Rect destRect;
|
|
int irResult = MZ_NO_ACTION;
|
|
int i; /* index of arg being processed */
|
|
int argc = cmd->tx_argc;
|
|
char **argv = cmd->tx_argv;
|
|
|
|
TileTypeBitMask layerMask;
|
|
RouteLayer *rL;
|
|
|
|
/* set startType and destType to defaults */
|
|
startType = ST_CURSOR;
|
|
destType = DT_BOX;
|
|
|
|
/* skip over cmd name args */
|
|
i = 2;
|
|
|
|
/* process options */
|
|
while(i<argc)
|
|
{
|
|
int which = Lookup(argv[i],&(rOptions[0]));
|
|
switch (which)
|
|
{
|
|
case -2:
|
|
/* not found */
|
|
TxError("Bad option to 'iroute route': '%s'\n",argv[i]);
|
|
goto leaveClean;
|
|
case -1:
|
|
/* ambiguous */
|
|
TxError("Ambiguous option to 'iroute route': '%s'\n",argv[i]);
|
|
goto leaveClean;
|
|
case 0:
|
|
/* dBox */
|
|
destType = DT_BOX;
|
|
break;
|
|
case 1:
|
|
/* dLabel */
|
|
destType = DT_LABEL;
|
|
if(++i>=argc)
|
|
{
|
|
TxError("Missing label.\n");
|
|
goto leaveClean;
|
|
}
|
|
destLabel = argv[i];
|
|
break;
|
|
case 2:
|
|
/* dLayers */
|
|
if(++i>=argc)
|
|
{
|
|
TxError("Missing layer list.\n");
|
|
goto leaveClean;
|
|
}
|
|
(void) CmdParseLayers(argv[i],&layerMask);
|
|
for(rL=irRouteLayers; rL!=NULL; rL=rL->rl_next)
|
|
{
|
|
if(TTMaskHasType(&layerMask,rL->rl_routeType.rt_tileType) &&
|
|
rL->rl_routeType.rt_active)
|
|
{
|
|
LIST_ADD(rL, destLayers);
|
|
}
|
|
}
|
|
if(destLayers==NULL)
|
|
{
|
|
TxError("No active route layers in destination list!\n");
|
|
goto leaveClean;
|
|
}
|
|
break;
|
|
case 3:
|
|
/* dRect */
|
|
destType = DT_RECT;
|
|
if(++i>=argc)
|
|
{
|
|
TxError("Incomplete coordinates.\n");
|
|
goto leaveClean;
|
|
}
|
|
if(!StrIsNumeric(argv[i]))
|
|
{
|
|
TxError("Non coordinate: %s\n",argv[i]);
|
|
goto leaveClean;
|
|
}
|
|
destRect.r_xbot = cmdParseCoord(w, argv[i], FALSE, TRUE);
|
|
|
|
if(++i>=argc)
|
|
{
|
|
TxError("Incomplete coordinates.\n");
|
|
goto leaveClean;
|
|
}
|
|
if(!StrIsNumeric(argv[i]))
|
|
{
|
|
TxError("Nonnumeric coordinate: %s\n",argv[i]);
|
|
goto leaveClean;
|
|
}
|
|
destRect.r_ybot = cmdParseCoord(w, argv[i], FALSE, FALSE);
|
|
|
|
if(++i>=argc)
|
|
{
|
|
TxError("Incomplete coordinates.\n");
|
|
goto leaveClean;
|
|
}
|
|
if(!StrIsNumeric(argv[i]))
|
|
{
|
|
TxError("Nonnumeric coordinate: %s\n",argv[i]);
|
|
goto leaveClean;
|
|
}
|
|
destRect.r_xtop = cmdParseCoord(w, argv[i], FALSE, TRUE);
|
|
|
|
if(++i>=argc)
|
|
{
|
|
TxError("Incomplete coordinates.\n");
|
|
goto leaveClean;
|
|
}
|
|
if(!StrIsNumeric(argv[i]))
|
|
{
|
|
TxError("Nonnumeric coordinate: %s\n",argv[i]);
|
|
goto leaveClean;
|
|
}
|
|
destRect.r_ytop = cmdParseCoord(w, argv[i], FALSE, FALSE);
|
|
|
|
destRectArg = &destRect;
|
|
break;
|
|
case 4:
|
|
/* dSelection */
|
|
destType = DT_SELECTION;
|
|
break;
|
|
case 5:
|
|
/* sCursor */
|
|
startType = ST_CURSOR;
|
|
break;
|
|
case 6:
|
|
/* sLabel */
|
|
startType = ST_LABEL;
|
|
if(++i>=argc)
|
|
{
|
|
TxError("Missing label.\n");
|
|
goto leaveClean;
|
|
}
|
|
startLabel = argv[i];
|
|
break;
|
|
case 7:
|
|
/* sLayers */
|
|
if(++i>=argc)
|
|
{
|
|
TxError("Missing layer list.\n");
|
|
goto leaveClean;
|
|
}
|
|
(void) CmdParseLayers(argv[i],&layerMask);
|
|
for(rL=irRouteLayers; rL!=NULL; rL=rL->rl_next)
|
|
{
|
|
if(TTMaskHasType(&layerMask,
|
|
rL->rl_routeType.rt_tileType) &&
|
|
rL->rl_routeType.rt_active)
|
|
{
|
|
LIST_ADD(rL, startLayers);
|
|
}
|
|
}
|
|
if(startLayers==NULL)
|
|
{
|
|
TxError("No active route layers in start list!\n");
|
|
goto leaveClean;
|
|
}
|
|
break;
|
|
case 8:
|
|
/* sPoint */
|
|
startType = ST_POINT;
|
|
if(++i>=argc)
|
|
{
|
|
TxError("Incomplete coordinates.\n");
|
|
goto leaveClean;
|
|
}
|
|
if(!StrIsNumeric(argv[i]))
|
|
{
|
|
TxError("Nonnumeric coordinate: %s\n",argv[i]);
|
|
goto leaveClean;
|
|
}
|
|
startPt.p_x = cmdParseCoord(w, argv[i], FALSE, TRUE);
|
|
if(++i>=argc)
|
|
{
|
|
TxError("Incomplete coordinates.\n");
|
|
goto leaveClean;
|
|
}
|
|
if(!StrIsNumeric(argv[i]))
|
|
{
|
|
TxError("Nonnumeric coordinate: %s\n",argv[i]);
|
|
goto leaveClean;
|
|
}
|
|
startPt.p_y = cmdParseCoord(w, argv[i], FALSE, FALSE);
|
|
|
|
startPtArg = &startPt;
|
|
break;
|
|
#ifdef MAGIC_WRAPPER
|
|
case 9:
|
|
if(++i>=argc)
|
|
{
|
|
TxError("No timeout value given.\n");
|
|
goto leaveClean;
|
|
}
|
|
if(!StrIsInt(argv[i]))
|
|
{
|
|
TxError("Noninteger timeout value: %s\n",argv[i]);
|
|
goto leaveClean;
|
|
}
|
|
SigRemoveTimer();
|
|
SigTimerInterrupts();
|
|
SigSetTimer(atoi(argv[i]));
|
|
break;
|
|
#endif
|
|
default:
|
|
/* shouldn't happen */
|
|
ASSERT(FALSE,"irRouteCmd");
|
|
break;
|
|
}
|
|
|
|
/* advance to next option */
|
|
++i;
|
|
}
|
|
|
|
/* We're done parsing the command, call irRoute to do the real work */
|
|
irResult = irRoute(w, startType, startPtArg, startLabel, startLayers,
|
|
destType, destRectArg, destLabel, destLayers);
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
SigTimerDisplay();
|
|
|
|
/* Set Tcl Result to irResult */
|
|
switch (irResult)
|
|
{
|
|
case MZ_SUCCESS:
|
|
Tcl_SetResult(magicinterp, "Route success", 0);
|
|
break;
|
|
case MZ_CURRENT_BEST:
|
|
Tcl_SetResult(magicinterp, "Route best before interrupt", 0);
|
|
break;
|
|
case MZ_FAILURE:
|
|
Tcl_SetResult(magicinterp, "Route failure", 0);
|
|
break;
|
|
case MZ_UNROUTABLE:
|
|
Tcl_SetResult(magicinterp, "Route unroutable", 0);
|
|
break;
|
|
case MZ_INTERRUPTED:
|
|
Tcl_SetResult(magicinterp, "Route interrupted", 0);
|
|
break;
|
|
case MZ_ALREADY_ROUTED:
|
|
Tcl_SetResult(magicinterp, "Route already routed", 0);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
leaveClean:
|
|
ListDealloc(startLayers);
|
|
ListDealloc(destLayers);
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* irSearchCmd --
|
|
*
|
|
* Irouter subcommand to set and display search parameters.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Modify search parameters and display them.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
/* Search Parameter Table */
|
|
static struct
|
|
{
|
|
char *srP_name; /* name of parameter */
|
|
void (*srP_proc)(); /* Procedure processing this parameter */
|
|
} srParms[] = {
|
|
{"rate", irSrSetRate},
|
|
{"width", irSrSetWidth},
|
|
{0}
|
|
};
|
|
|
|
void
|
|
irSearchCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
|
|
/* Process by case */
|
|
if(cmd->tx_argc == 2)
|
|
/* print values of all parms */
|
|
{
|
|
int n;
|
|
|
|
for(n=0; srParms[n].srP_name; n++)
|
|
{
|
|
TxPrintf(" %s=", srParms[n].srP_name);
|
|
(*srParms[n].srP_proc)(NULL,NULL);
|
|
}
|
|
TxPrintf("\n");
|
|
}
|
|
else if(cmd->tx_argc == 3 || cmd->tx_argc == 4)
|
|
/* process single parameter */
|
|
{
|
|
int which;
|
|
|
|
/* Lookup parameter name in contact parm table */
|
|
which = LookupStruct(
|
|
cmd->tx_argv[2],
|
|
(char **) srParms,
|
|
sizeof srParms[0]);
|
|
|
|
/* Process table lookup */
|
|
if (which == -1)
|
|
/* parameter ambiguous */
|
|
{
|
|
TxError("Ambiguous parameter: \"%s\"\n",
|
|
cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
else if (which<0)
|
|
/* parameter not found */
|
|
{
|
|
int n;
|
|
|
|
TxError("Unrecognized parameter: %s\n", cmd->tx_argv[2]);
|
|
TxError("Valid search parameters are: ");
|
|
for (n = 0; srParms[n].srP_name; n++)
|
|
TxError(" %s", srParms[n].srP_name);
|
|
TxError("\n");
|
|
return;
|
|
}
|
|
else
|
|
/* parameter found - process it */
|
|
{
|
|
char *arg;
|
|
|
|
if(cmd->tx_argc == 3)
|
|
/* just want current value - use null argument */
|
|
{
|
|
arg = NULL;
|
|
}
|
|
else
|
|
/* setting parameter, arg = value string */
|
|
{
|
|
arg = cmd->tx_argv[3];
|
|
}
|
|
|
|
TxPrintf(" %s=", srParms[which].srP_name);
|
|
(*srParms[which].srP_proc)(arg,NULL);
|
|
TxPrintf("\n");
|
|
}
|
|
|
|
}
|
|
else
|
|
/* Too many arguments */
|
|
{
|
|
TxError("Too many args on 'iroute search'\n");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* irSpacingsCmd --
|
|
*
|
|
* Irouter subcommand to set and display minimum spacings between
|
|
* routetypes.
|
|
*
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Modify and display spacing parameters.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
irSpacingsCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
TileType tileType;
|
|
RouteType *rT;
|
|
char *s;
|
|
int which, value, argI, i, n;
|
|
|
|
/* Special Value Table */
|
|
static struct
|
|
{
|
|
char *sV_name; /* name of value */
|
|
int sV_value; /* corresponding interger value */
|
|
} sValue[] = {
|
|
{"n", -1},
|
|
{"nil", -1},
|
|
{"none", -1},
|
|
{"null", -1},
|
|
{0}
|
|
};
|
|
|
|
/* Subcell Table */
|
|
static struct
|
|
{
|
|
char *sT_name; /* name of value */
|
|
int sT_value; /* corresponding interger value */
|
|
} subcellTable[] = {
|
|
{"subcell", TT_SUBCELL},
|
|
{0}
|
|
};
|
|
|
|
/* Process by case */
|
|
if(cmd->tx_argc == 2)
|
|
{
|
|
/* NO ARGS TO SPACING REQUEST - DISPLAY ALL SPACINGS */
|
|
|
|
/* Print spacings for each route type */
|
|
for (rT=irRouteTypes; rT!= NULL; rT=rT->rt_next)
|
|
{
|
|
TxPrintf("%s: ",
|
|
DBTypeLongNameTbl[rT->rt_tileType]);
|
|
for (i=0;i<TT_MAXTYPES;i++)
|
|
if(rT->rt_spacing[i]>=0)
|
|
TxPrintf("%s=%d ",DBTypeLongNameTbl[i],rT->rt_spacing[i]);
|
|
if(rT->rt_spacing[TT_SUBCELL]>=0)
|
|
TxPrintf("%s=%d ","SUBCELL",rT->rt_spacing[TT_SUBCELL]);
|
|
TxPrintf("\n\n");
|
|
}
|
|
}
|
|
else if(cmd->tx_argc==3)
|
|
{
|
|
/* ONE ARG TO SPACING REQUEST */
|
|
|
|
if (strcmp(cmd->tx_argv[2],"CLEAR")==0)
|
|
{
|
|
/* CLEAR ALL SPACINGS */
|
|
for (rT=irRouteTypes; rT!= NULL; rT=rT->rt_next)
|
|
/* <=TT_MAXTYPES below includes TT_SUBCELL */
|
|
for (i=0;i<=TT_MAXTYPES;i++)
|
|
rT->rt_spacing[i]= -1;
|
|
}
|
|
else
|
|
{
|
|
/* PRINT SPACINGS FOR GIVEN ROUTE LAYER */
|
|
|
|
/* convert layer string to tileType */
|
|
tileType = DBTechNameType(cmd->tx_argv[2]);
|
|
if(tileType<0)
|
|
{
|
|
TxError("Unrecognized layer (type): \"%.20s\"\n",
|
|
cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
|
|
if (rT=irFindRouteType(tileType))
|
|
{
|
|
|
|
TxPrintf("%s: ",
|
|
DBTypeLongNameTbl[rT->rt_tileType]);
|
|
for (i=0;i<TT_MAXTYPES;i++)
|
|
if(rT->rt_spacing[i]>=0)
|
|
TxPrintf("%s=%d ",
|
|
DBTypeLongNameTbl[i],rT->rt_spacing[i]);
|
|
if(rT->rt_spacing[TT_SUBCELL]>=0)
|
|
TxPrintf("%s=%d ","SUBCELL",rT->rt_spacing[TT_SUBCELL]);
|
|
TxPrintf("\n\n");
|
|
}
|
|
else
|
|
{
|
|
TxError("Unrecognized route layer or contact: \"%.20s\"\n",
|
|
cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else if(cmd->tx_argc==4)
|
|
{
|
|
/* PRINT VALUE OF GIVEN SPACING */
|
|
|
|
/* convert layer string to tileType */
|
|
tileType = DBTechNameType(cmd->tx_argv[2]);
|
|
if(tileType<0)
|
|
{
|
|
TxError("Unrecognized layer (type): \"%.20s\"\n",
|
|
cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
|
|
if ((rT=irFindRouteType(tileType))==NULL)
|
|
{
|
|
TxError("Unrecognized route layer or contact: \"%.20s\"\n",
|
|
cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
|
|
/* convert type-string spacing is "to" to tiletype */
|
|
tileType = DBTechNameType(cmd->tx_argv[3]);
|
|
if(tileType<0)
|
|
{
|
|
/* if not a real type, check to see if "SUBCELL" */
|
|
which = LookupStruct(
|
|
cmd->tx_argv[3],
|
|
(char **) subcellTable,
|
|
sizeof subcellTable[0]);
|
|
if ( which>= 0)
|
|
tileType = TT_SUBCELL;
|
|
}
|
|
if(tileType<0)
|
|
{
|
|
TxError("Unrecognized layer (type): \"%.20s\"\n",
|
|
cmd->tx_argv[3]);
|
|
return;
|
|
}
|
|
|
|
/* Print current value of spacing */
|
|
if(rT->rt_spacing[tileType] >= 0)
|
|
TxPrintf("\t%d\n",rT->rt_spacing[tileType]);
|
|
else
|
|
TxPrintf("\tNIL\n");
|
|
}
|
|
else if(EVEN(cmd->tx_argc))
|
|
{
|
|
/* TYPE PARMS DON'T PAIR EVENLY WITH VALUE PARMS */
|
|
TxError("Type and value args don't pair evenly.\n");
|
|
TxError("Usage: *iroute spacing [routeType] [type1] [value1] [type2 value2] ... [typen valuen]\n");
|
|
}
|
|
else
|
|
{
|
|
/* SET SPACINGS */
|
|
|
|
/* convert layer string to tileType */
|
|
tileType = DBTechNameType(cmd->tx_argv[2]);
|
|
if(tileType<0)
|
|
{
|
|
TxError("Unrecognized layer (type): \"%.20s\"\n",
|
|
cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
|
|
if ((rT=irFindRouteType(tileType))==NULL)
|
|
{
|
|
TxError("Unrecognized route layer or contact: \"%.20s\"\n",
|
|
cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
|
|
/* Prepend tab to echo of new values */
|
|
TxPrintf("\t");
|
|
|
|
/* process type/value pairs */
|
|
for (argI=3; argI<cmd->tx_argc; argI +=2)
|
|
{
|
|
/* convert type-string spacing is "to" to tiletype */
|
|
tileType = DBTechNameType(cmd->tx_argv[argI]);
|
|
if(tileType<0)
|
|
{
|
|
/* if not a real type, check to see if "SUBCELL" */
|
|
which = LookupStruct(
|
|
cmd->tx_argv[argI],
|
|
(char **) subcellTable,
|
|
sizeof subcellTable[0]);
|
|
if ( which>= 0)
|
|
tileType = TT_SUBCELL;
|
|
}
|
|
if(tileType<0)
|
|
{
|
|
TxError("\nUnrecognized layer (type): \"%.20s\"\n",
|
|
cmd->tx_argv[argI]);
|
|
continue;
|
|
}
|
|
|
|
/* convert value-string to integer */
|
|
s = cmd->tx_argv[argI+1];
|
|
if (StrIsNumeric(s))
|
|
{
|
|
value = cmdParseCoord(w, s, TRUE, FALSE);
|
|
if (value < -1)
|
|
{
|
|
TxError("\nBad spacing value: %d\n",value);
|
|
TxError("Valid spacing values are: ");
|
|
TxError("<a nonnegative integer> -1");
|
|
for (n = 0; sValue[n].sV_name; n++)
|
|
TxError(" %s", sValue[n].sV_name);
|
|
TxError("\n");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Lookup in special value table */
|
|
which = LookupStruct(
|
|
s,
|
|
(char **) sValue,
|
|
sizeof sValue[0]);
|
|
|
|
/* Process result of lookup */
|
|
if (which >= 0)
|
|
{
|
|
/* special value found, set string accordingly */
|
|
value = sValue[which].sV_value;
|
|
}
|
|
else if (which == -1)
|
|
{
|
|
/* ambiguous value - complain */
|
|
TxError("\nAmbiguous value: \"%s\"\n",s);
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
/* unrecognized value - complain */
|
|
TxError("Bad spacing value: %s\n",s);
|
|
TxError("Valid spacing values are: ");
|
|
TxError("<a nonnegative integer> -1");
|
|
for (n = 0; sValue[n].sV_name; n++)
|
|
TxError(" %s", sValue[n].sV_name);
|
|
TxError("\n");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* Set value in route type */
|
|
rT->rt_spacing[tileType]=value;
|
|
|
|
/* Print new value */
|
|
if(rT->rt_spacing[tileType] != -1)
|
|
TxPrintf(" %s=%d",
|
|
(tileType == TT_SUBCELL ?
|
|
"SUBCELL" : DBTypeLongNameTbl[tileType]),
|
|
rT->rt_spacing[tileType]);
|
|
else
|
|
TxPrintf(" %s=NIL",
|
|
(tileType==TT_SUBCELL ?
|
|
"SUBCELL" : DBTypeLongNameTbl[tileType]));
|
|
}
|
|
TxPrintf("\n");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* irVerbosityCmd --
|
|
*
|
|
* Irouter subcommand to set amount of messages given by irouter and mzrouter.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Sets verbosity parameter
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
irVerbosityCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
if(cmd->tx_argc >3)
|
|
{
|
|
TxError("'iroute verbosity' only takes one arg!\n");
|
|
return;
|
|
}
|
|
|
|
if(cmd->tx_argc == 3)
|
|
{
|
|
int i;
|
|
|
|
/* ONE ARG */
|
|
if(StrIsInt(cmd->tx_argv[2]) && (i=atoi(cmd->tx_argv[2]))>=0)
|
|
{
|
|
irMazeParms->mp_verbosity = i;
|
|
}
|
|
else
|
|
{
|
|
TxError("Bad argument: \"%s\"\n", cmd->tx_argv[2]);
|
|
TxError("Argument must be a nonnegative integer\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Print current value of verbosity */
|
|
switch (irMazeParms->mp_verbosity)
|
|
{
|
|
case 0:
|
|
/* shhhhh! we're in silent mode */
|
|
break;
|
|
|
|
case 1:
|
|
TxPrintf("\t1 (Brief messages)\n");
|
|
break;
|
|
|
|
default:
|
|
ASSERT(irMazeParms->mp_verbosity>=2,"irVerbosityCmd");
|
|
TxPrintf("\t%d (Lots of statistics)\n",
|
|
irMazeParms->mp_verbosity);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* irVersionCmd --
|
|
*
|
|
* Irouter subcommand to display irouter version string.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Displays version string.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
irVersionCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
|
|
if(cmd->tx_argc == 2)
|
|
{
|
|
/* Print out version string */
|
|
TxPrintf("\tIrouter version %s\n", IROUTER_VERSION);
|
|
}
|
|
else
|
|
{
|
|
TxError("Too many args on 'iroute version'\n");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* irWizardCmd --
|
|
*
|
|
* Irouter subcommand to set and display less frequently modified parameters.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* See above.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
/* Wizard Parameter Table */
|
|
static struct
|
|
{
|
|
char *wzdP_name; /* name of parameter */
|
|
void (*wzdP_proc)(); /* Procedure processing this parameter */
|
|
} wzdParms[] = {
|
|
{"bloom", irWzdSetBloomCost},
|
|
{"bloomLimit", irWzdSetBloomLimit},
|
|
{"boundsIncrement", irWzdSetBoundsIncrement},
|
|
{"estimate", irWzdSetEstimate},
|
|
{"expandEndpoints", irWzdSetExpandEndpoints},
|
|
{"penalty", irWzdSetPenalty},
|
|
{"penetration", irWzdSetPenetration},
|
|
{"window", irWzdSetWindow},
|
|
{0}
|
|
};
|
|
|
|
void
|
|
irWizardCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
|
|
/* Process by case */
|
|
if(cmd->tx_argc == 2)
|
|
/* print values of all parms */
|
|
{
|
|
int n;
|
|
|
|
for(n=0; wzdParms[n].wzdP_name; n++)
|
|
{
|
|
TxPrintf(" %s=", wzdParms[n].wzdP_name);
|
|
(*wzdParms[n].wzdP_proc)(NULL,NULL);
|
|
TxPrintf("\n");
|
|
}
|
|
}
|
|
else if(cmd->tx_argc == 3 || cmd->tx_argc == 4)
|
|
/* process single parameter */
|
|
{
|
|
int which;
|
|
|
|
/* Lookup parameter name in contact parm table */
|
|
which = LookupStruct(
|
|
cmd->tx_argv[2],
|
|
(char **) wzdParms,
|
|
sizeof wzdParms[0]);
|
|
|
|
/* Process table lookup */
|
|
if (which == -1)
|
|
/* parameter ambiguous */
|
|
{
|
|
TxError("Ambiguous parameter: \"%s\"\n",
|
|
cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
else if (which<0)
|
|
/* parameter not found */
|
|
{
|
|
int n;
|
|
|
|
TxError("Unrecognized parameter: %s\n", cmd->tx_argv[2]);
|
|
TxError("Valid wizard parameters are: ");
|
|
for (n = 0; wzdParms[n].wzdP_name; n++)
|
|
TxError(" %s", wzdParms[n].wzdP_name);
|
|
TxError("\n");
|
|
return;
|
|
}
|
|
else
|
|
/* parameter found - process it */
|
|
{
|
|
char *arg;
|
|
|
|
if(cmd->tx_argc == 3)
|
|
/* just want current value - use null argument */
|
|
{
|
|
arg = NULL;
|
|
}
|
|
else
|
|
/* setting parameter, arg = value string */
|
|
{
|
|
arg = cmd->tx_argv[3];
|
|
}
|
|
|
|
TxPrintf(" %s=", wzdParms[which].wzdP_name);
|
|
(*wzdParms[which].wzdP_proc)(arg,NULL);
|
|
TxPrintf("\n");
|
|
}
|
|
|
|
}
|
|
else
|
|
/* Too many arguments */
|
|
{
|
|
TxError("Too many args on 'iroute wizard'\n");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* irSaveParametersCmd --
|
|
*
|
|
* Irouter subcommand to create "source" file setting all irouter parameters
|
|
* (except ref. window) to current value - to reset to these values just
|
|
* source the file with `:source'.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Write file of Magic commands to set parms. to current values.
|
|
*
|
|
* NOTE:
|
|
* Note defined after all other commands, so it can make use of
|
|
* datastructures defined just in front of other commands,
|
|
* such as the search parameter table.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
irSaveParametersCmd(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
FILE *saveFile;
|
|
RouteContact *rC;
|
|
RouteLayer *rL;
|
|
|
|
/* make sure exactly one arg given */
|
|
if(cmd->tx_argc !=3)
|
|
{
|
|
if(cmd->tx_argc == 2)
|
|
TxError("Must specify save file!\n");
|
|
else
|
|
TxError("Too many args on ':iroute saveParameter'\n");
|
|
return;
|
|
}
|
|
|
|
/* open save file */
|
|
saveFile = fopen(cmd->tx_argv[2], "w");
|
|
if (saveFile == NULL)
|
|
{
|
|
TxError("Could not open file '%s' for writing.\n", cmd->tx_argv[2]);
|
|
return;
|
|
}
|
|
|
|
/* write header comment */
|
|
fprintf(saveFile,"# Irouter version %s\n", IROUTER_VERSION);
|
|
fprintf(saveFile,"#\n");
|
|
fprintf(saveFile,
|
|
"# This is a Magic command file generated by the Magic command\n");
|
|
fprintf(saveFile,"#\t:iroute saveParameters\n");
|
|
fprintf(saveFile,"# To restore these parameter settings,");
|
|
fprintf(saveFile," use the Magic `:source' command.\n\n");
|
|
|
|
/* turn verbosity down to errors and warnings, to avoid lots of
|
|
* gibberish when the file is sourced.
|
|
*/
|
|
fprintf(saveFile,":iroute verbosity 0\n");
|
|
|
|
/* save CONTACT parameters */
|
|
for (rC=irRouteContacts; rC!= NULL; rC=rC->rc_next)
|
|
{
|
|
int n;
|
|
|
|
fprintf(saveFile,":iroute contact %s * ",
|
|
DBTypeLongNameTbl[rC->rc_routeType.rt_tileType]);
|
|
for(n=0; cParms[n].cP_name; n++)
|
|
{
|
|
(*cParms[n].cP_proc)(rC,NULL,saveFile);
|
|
}
|
|
fprintf(saveFile,"\n");
|
|
}
|
|
|
|
/* save LAYER parameters */
|
|
for (rL=irRouteLayers; rL!= NULL; rL=rL->rl_next)
|
|
{
|
|
int n;
|
|
|
|
fprintf(saveFile,":iroute layer %s * ",
|
|
DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]);
|
|
for(n=0; lParms[n].lP_name; n++)
|
|
{
|
|
(*lParms[n].lP_proc)(rL,NULL,saveFile);
|
|
}
|
|
fprintf(saveFile,"\n");
|
|
}
|
|
|
|
/* save SEARCH parameters */
|
|
{
|
|
int n;
|
|
|
|
for(n=0; srParms[n].srP_name; n++)
|
|
{
|
|
fprintf(saveFile,":iroute search %s ",
|
|
srParms[n].srP_name);
|
|
(*srParms[n].srP_proc)(NULL,saveFile);
|
|
fprintf(saveFile,"\n");
|
|
}
|
|
}
|
|
|
|
/* save SPACINGS */
|
|
{
|
|
RouteType *rT;
|
|
int i;
|
|
|
|
fprintf(saveFile,":iroute spacings CLEAR\n");
|
|
for (rT=irRouteTypes; rT!= NULL; rT=rT->rt_next)
|
|
{
|
|
for (i=0;i<TT_MAXTYPES;i++)
|
|
if(rT->rt_spacing[i]>=0)
|
|
fprintf(saveFile,":iroute spacings %s %s %d\n",
|
|
DBTypeLongNameTbl[rT->rt_tileType],
|
|
DBTypeLongNameTbl[i],
|
|
rT->rt_spacing[i]);
|
|
if(rT->rt_spacing[TT_SUBCELL]>=0)
|
|
fprintf(saveFile,":iroute spacings %s %s %d\n",
|
|
DBTypeLongNameTbl[rT->rt_tileType],
|
|
"SUBCELL",
|
|
rT->rt_spacing[TT_SUBCELL]);
|
|
}
|
|
}
|
|
|
|
/* save WIZARD parameters */
|
|
{
|
|
int n;
|
|
|
|
for(n=0; wzdParms[n].wzdP_name; n++)
|
|
{
|
|
fprintf(saveFile,":iroute wizard %s ",
|
|
wzdParms[n].wzdP_name);
|
|
(*wzdParms[n].wzdP_proc)(NULL,saveFile);
|
|
fprintf(saveFile,"\n");
|
|
}
|
|
}
|
|
|
|
/* save VERBOSITY parameter (done last so :source is silent) */
|
|
fprintf(saveFile,":iroute verbosity %d\n",
|
|
irMazeParms->mp_verbosity);
|
|
|
|
(void) fclose(saveFile);
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* IRCommand --
|
|
*
|
|
* Command interface for interactive router. Processes `:iroute' command
|
|
* lines.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Depends on the command; see below.
|
|
*
|
|
* Organization:
|
|
* We select a procedure based on the first keyword (argv[0])
|
|
* and call it to do the work of implementing the subcommand. Each
|
|
* such procedure is of the following form:
|
|
*
|
|
* int
|
|
* proc(argc, argv)
|
|
* int argc;
|
|
* char *argv[];
|
|
* {
|
|
* }
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
/*--- Subcommand Table ---*/
|
|
|
|
SubCmdTableE irSubcommands[] = {
|
|
{"contacts", irContactsCmd,
|
|
"set route-contact parameters",
|
|
"contacts [type] [parameter] [value1] ... [valuen]\n\
|
|
\t(can use '*' for type or parameter)"},
|
|
|
|
{"help", irHelpCmd,
|
|
"summarize iroute subcommands",
|
|
"help [subcommand]"},
|
|
|
|
{"layers", irLayersCmd,
|
|
"set route-layer parameters",
|
|
"layers [type] [parameter] [value1] ... [valuen]\n\
|
|
\t(can use '*' for type or parameter)"},
|
|
|
|
{"route", irRouteCmd,
|
|
"connect point to node(s)",
|
|
"route [options]\n\
|
|
\t-sLayers layers = layers route may start on.\n\
|
|
\t-sCursor = start route at cursor (DEFAULT)\n\
|
|
\t-sLabel name = start route at label of given name\n\
|
|
\t-sPoint x y = start route at given coordinates\n\
|
|
\t-dLayers layers = layers route may end on.\n\
|
|
\t-dBox = route to box (DEFAULT)\n\
|
|
\t-dLabel name = route to label of given name\n\
|
|
\t-dRect xbot ybot xtop ytop = route to rectangle of given coordinates\n\
|
|
\t-dSelection = route to selection"},
|
|
|
|
{"saveParameters", irSaveParametersCmd,
|
|
"write out all irouter parameters\n\
|
|
\t(can be read back with :source)",
|
|
"saveParameters <filename>"},
|
|
|
|
{"search", irSearchCmd,
|
|
"set parameters controlling the internal search for routes",
|
|
"search [searchParameter] [value]"},
|
|
|
|
{"spacings", irSpacingsCmd,
|
|
"set minimum spacing between route-type and arbitrary type",
|
|
"spacings [route-type] [type] [spacing] ... [typen spacingn]\n\
|
|
\t(types can be 'SUBCELL', spacing can be 'nil')\n\
|
|
iroute spacings CLEAR\n\
|
|
\t(sets all spacings to nil)"},
|
|
|
|
{"verbosity", irVerbosityCmd,
|
|
"control the amount of messages printed",
|
|
"verbosity [level]\n\
|
|
\t(0 = errors and warnings only, 1 = brief, 2 = lots of statistics)"},
|
|
|
|
{"version", irVersionCmd,
|
|
"identify irouter version",
|
|
"version"},
|
|
|
|
{"wizard", irWizardCmd,
|
|
"set miscellaneous parameters",
|
|
"wizard [wizardParameter] [value]"},
|
|
|
|
{0}
|
|
}, *subCmdP;
|
|
|
|
void
|
|
IRCommand(w, cmd)
|
|
MagWindow *w;
|
|
TxCommand *cmd;
|
|
{
|
|
int n;
|
|
int which;
|
|
|
|
/* make sure we have maze parameters */
|
|
if(irMazeParms==NULL)
|
|
{
|
|
TxError("Need irouter style in mzrouter section of technology file");
|
|
TxError(" to use irouter.\n");
|
|
return;
|
|
}
|
|
|
|
/* make window available to all subroutines */
|
|
irWindow = w;
|
|
|
|
/* If in silent mode, turn printing off */
|
|
if(irMazeParms->mp_verbosity==0)
|
|
{
|
|
TxPrintOff();
|
|
}
|
|
|
|
if(cmd->tx_argc == 1)
|
|
{
|
|
int irResult;
|
|
|
|
/* No subcommand specified - so just route from cursor to box
|
|
* No endpts or layers explicitly given on cmd, so args are
|
|
* NULL below.
|
|
*/
|
|
irResult = irRoute(w, ST_CURSOR,
|
|
(Point*)NULL, (char*)NULL, (List*)NULL,
|
|
DT_BOX, (Point*)NULL, (char*)NULL, (List*)NULL);
|
|
|
|
#ifdef MAGIC_WRAPPER
|
|
/* Set Tcl Result to irResult */
|
|
switch (irResult)
|
|
{
|
|
case MZ_SUCCESS:
|
|
Tcl_SetResult(magicinterp, "Route success", 0);
|
|
break;
|
|
case MZ_CURRENT_BEST:
|
|
Tcl_SetResult(magicinterp, "Route best before interrupt", 0);
|
|
break;
|
|
case MZ_FAILURE:
|
|
Tcl_SetResult(magicinterp, "Route failure", 0);
|
|
break;
|
|
case MZ_UNROUTABLE:
|
|
Tcl_SetResult(magicinterp, "Route unroutable", 0);
|
|
break;
|
|
case MZ_INTERRUPTED:
|
|
Tcl_SetResult(magicinterp, "Route interrupted", 0);
|
|
break;
|
|
case MZ_ALREADY_ROUTED:
|
|
Tcl_SetResult(magicinterp, "Route already routed", 0);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
}
|
|
else
|
|
{
|
|
/* Lookup subcommand in table */
|
|
which = LookupStruct(
|
|
cmd->tx_argv[1],
|
|
(char **) irSubcommands,
|
|
sizeof irSubcommands[0]);
|
|
|
|
/* Process result of lookup */
|
|
if (which >= 0)
|
|
{
|
|
/* subcommand found - call proc that implements it */
|
|
subCmdP = &irSubcommands[which];
|
|
(*subCmdP->sC_proc)(w,cmd);
|
|
}
|
|
else if (which == -1)
|
|
{
|
|
/* ambiguous subcommand - complain */
|
|
TxError("Ambiguous iroute subcommand: \"%s\"\n", cmd->tx_argv[1]);
|
|
}
|
|
else
|
|
{
|
|
/* unrecognized subcommand - complain */
|
|
TxError("Unrecognized iroute subcommand: \"%s\"\n",
|
|
cmd->tx_argv[1]);
|
|
TxError("Valid iroute irSubcommands are: ");
|
|
for (n = 0; irSubcommands[n].sC_name; n++)
|
|
TxError(" %s", irSubcommands[n].sC_name);
|
|
TxError("\n");
|
|
}
|
|
}
|
|
|
|
/* turn printing back on, and return */
|
|
TxPrintOn();
|
|
return;
|
|
}
|