/* * 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 #include #include #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 -- * * Set and display Route Layer parameter . * * 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 -- * * Set and display contact parameter . * * 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 -- * * Set and display search parameter . * * 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 -- * * Set and display wizard parameter . * * 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<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<mp_penalty.rf_nExponent)); } else { TxPrintf("%f", (double)irMazeParms->mp_penalty.rf_mantissa / (double)(1<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 "); 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) { 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;irt_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;irt_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; argItx_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(" -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(" -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;irt_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 "}, {"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; }