Files
magic/irouter/irCommand.c
T
Patrick Kurth ea03883829 Fixed unused-parameters/unused-variables warnings
Added a ARG_UNUSED macro in utils/magic.h, which
produces a simple cast to void to silence the warnings.
The reasons this is used as opposed to an attribute is
that most compilers should support this.
Besides this, the macro can be easily searched for in
the future to potentially remove (where possible) the
unused parameters.
2025-10-10 22:12:19 +02:00

2679 lines
58 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
{
const char *sC_name; /* name of iroute subcommand */
void (*sC_proc)(); /* Procedure implementing this subcommand */
const char *sC_commentString; /* describes subcommand */
const char *sC_usage; /* command syntax */
} SubCmdTableE;
extern const 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 const struct
{
const 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,
(const LookupTable *) 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;
{
SetNoisyInt(&(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 const struct
{
const 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,
(const LookupTable *) 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 const struct
{
const 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;
{
ARG_UNUSED(w);
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],
(const LookupTable *) 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],
(const LookupTable *) 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;
{
ARG_UNUSED(w);
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],
(const LookupTable *) 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 const struct
{
const 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;
{
ARG_UNUSED(w);
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],
(const LookupTable *) 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],
(const LookupTable *) 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 const char* const 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 const struct
{
const 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;
{
ARG_UNUSED(w);
/* 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],
(const LookupTable *) 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 const struct
{
const 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 const struct
{
const 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],
(const LookupTable *) 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],
(const LookupTable *) 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,
(const LookupTable *) 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;
{
ARG_UNUSED(w);
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;
{
ARG_UNUSED(w);
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 const struct
{
const 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;
{
ARG_UNUSED(w);
/* 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],
(const LookupTable *) 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;
{
ARG_UNUSED(w);
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 ---*/
const 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],
(const LookupTable *) 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;
}