/* * RouteCmd.c -- * * Commands for the route modules only. * * ********************************************************************* * * Copyright (C) 1985, 1990 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/router/rtrCmd.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/styles.h" #include "utils/geometry.h" #include "tiles/tile.h" #include "utils/hash.h" #include "utils/utils.h" #include "database/database.h" #include "windows/windows.h" #include "dbwind/dbwind.h" #include "utils/main.h" #include "textio/txcommands.h" #include "select/select.h" #include "commands/commands.h" #include "utils/heap.h" #include "router/router.h" #include "utils/netlist.h" #include "netmenu/netmenu.h" #include "gcr/gcr.h" #include "grouter/grouter.h" /* C99 compat */ #include "textio/textio.h" #include "irouter/irouter.h" #include "mzrouter/mzrouter.h" #include "garouter/garouter.h" #include "router/routerInt.h" /* Global variable initialization */ bool RtrMazeStems = FALSE; /* Set by default to original behavior */ /* * ---------------------------------------------------------------------------- * * CmdGARouterTest -- * * Debugging of gate-array router. * * Usage: * *garoute cmd [args] * * Results: * None. * * Side effects: * See comments in GATest() in garouter/gaTest.c for details. * * ---------------------------------------------------------------------------- */ void CmdGARouterTest(w, cmd) MagWindow *w; TxCommand *cmd; { GATest(w, cmd); } /* * ---------------------------------------------------------------------------- * * CmdGRouterTest -- * * Debugging of global router. * * Usage: * *groute cmd [args] * * Results: * None. * * Side effects: * See comments in GlTest() in grouter/glTest.c for details. * * ---------------------------------------------------------------------------- */ void CmdGRouterTest(w, cmd) MagWindow *w; TxCommand *cmd; { GlTest(w, cmd); } /* * ---------------------------------------------------------------------------- * * CmdIRouterTest -- * * Debugging of interactive router. * * Usage: * *iroute [subcmd] [args] * * Results: * None. * * Side effects: * See comments in IRTest() in irouter/irTestCmd.c for details. * * ---------------------------------------------------------------------------- */ void CmdIRouterTest(w, cmd) MagWindow *w; TxCommand *cmd; { IRTest(w, cmd); } /* * ---------------------------------------------------------------------------- * * CmdMZRouterTest -- * * Debugging of maze router. * * Usage: * *mzroute [subcmd] [args] * * Results: * None. * * Side effects: * See comments in MZTest() in mzrouter/mzTestCmd.c for details. * * ---------------------------------------------------------------------------- */ void CmdMZRouterTest(w, cmd) MagWindow *w; TxCommand *cmd; { MZTest(w, cmd); } /* * ---------------------------------------------------------------------------- * * CmdChannel -- * * Implement the "channel" command. Generate a cell __CHANNEL__ showing * the channel structure for the edit cell, within the area of the box. * * Useage: * :channel [netlist] * :channel [-] * * Results: * None. * * Side effects: * Creates a __CHANNEL__ def if it does not already exist. Paints * on the error layer of that def. Uses the feedback layer to display * the channels that result. * * ---------------------------------------------------------------------------- */ void CmdChannel(w, cmd) MagWindow *w; TxCommand *cmd; { Rect newBox; CellDef *def, *RtrDecomposeName(); char *name; extern int cmdChannelFunc(); /* Forward declaration. */ if (cmd->tx_argc > 3) { TxError("Usage: %s [netlist | -]\n", cmd->tx_argv[0]); return; } if (!ToolGetEditBox(&newBox)) return; name = (char *) NULL; if (cmd->tx_argc == 2) name = cmd->tx_argv[1]; if (RtrDecomposeName(EditCellUse, &newBox, name) == (CellDef *) NULL) { TxError("\nRouting area (box) is too small to hold useful channels.\n"); return; } TxPrintf("\n"); /* Display the channels using feedback. */ def = DBCellLookDef("__CHANNEL__"); if (def == NULL) return; (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR], &newBox, &DBSpaceBits, cmdChannelFunc, (ClientData) NULL); } int cmdChannelFunc(tile) Tile *tile; { Rect area, rootArea; TiToRect(tile, &area); GeoTransRect(&EditToRootTransform, &area, &rootArea); DBWFeedbackAdd(&area, "Channel area", EditRootDef, 1, STYLE_OUTLINEHIGHLIGHTS); return 0; } /* * ---------------------------------------------------------------------------- * * CmdGaRoute -- * * Command interface for gate-array routing. * * Results: * None. * * Side effects: * Depends on the command; see below. * * ---------------------------------------------------------------------------- */ void CmdGaRoute(w, cmd) MagWindow *w; TxCommand *cmd; { typedef enum { CHANNEL, GEN, HELP, NOWARN, RESET, ROUTE, WARN } cmdType; static char *chanTypeName[] = { "NORMAL", "HRIVER", "VRIVER" }; extern bool GAStemWarn; char *name, *channame; int n, chanType; Rect editArea; FILE *f; static const struct { const char *cmd_name; cmdType cmd_val; } cmds[] = { {"channel xl yl xh yh [type]\n\ channel [type] define a channel", CHANNEL}, {"generate type [file] generate channel definition commands", GEN}, {"help print this message", HELP}, {"nowarn only warn if all locations of a terminal\n\ are unreachable", NOWARN}, {"route [netlist] route the current cell",ROUTE}, {"reset clear all channel definitions", RESET}, {"warn leave feedback for each location of a\n\ terminal that is unreachable", WARN}, {0} }; GAInit(); if (cmd->tx_argc == 1) goto doRoute; n = LookupStruct(cmd->tx_argv[1], (const LookupTable *) cmds, sizeof cmds[0]); if (n < 0) { if (n == -1) TxError("Ambiguous option: \"%s\"\n", cmd->tx_argv[1]); else TxError("Unrecognized routing command: %s\n", cmd->tx_argv[1]); TxError(" Type \"garoute help\" for help.\n"); return; } switch (cmds[n].cmd_val) { case HELP: TxPrintf("Gate-array router commands have the form:\n"); TxPrintf("\"garoute option\", where option is one of:\n\n"); for (n = 0; cmds[n].cmd_name; n++) TxPrintf("%s\n", cmds[n].cmd_name); TxPrintf("\n"); break; case WARN: if (cmd->tx_argc != 2) goto badWarn; GAStemWarn = TRUE; TxPrintf( "Will leave feedback for each unusable terminal loc.\n"); break; case NOWARN: if (cmd->tx_argc != 2) { badWarn: TxError("Usage: \"garoute warn\" or \"garoute nowarn\"\n"); return; } GAStemWarn = FALSE; TxPrintf( "Will only leave feedback if all locs for a terminal are unusable.\n"); break; case RESET: TxPrintf("Clearing all channel information.\n"); GAClearChannels(); break; case GEN: if (cmd->tx_argc < 3 || cmd->tx_argc > 4) { TxError("Usage: garoute generate type [file]\n"); return; } if (!ToolGetEditBox(&editArea)) return; channame = cmd->tx_argv[2]; { bool need_close; FILE *f; if (cmd->tx_argc == 4) { f = fopen(cmd->tx_argv[3], "w"); if (f == NULL) { perror(cmd->tx_argv[3]); return; } need_close = TRUE; } else { f = stdout; need_close = FALSE; } if (channame[0] == 'h') GAGenChans(CHAN_HRIVER, &editArea, f); else if (channame[0] == 'v') GAGenChans(CHAN_VRIVER, &editArea, f); else { TxError("Unrecognized channel type: %s\n", channame); TxError("Legal types are \"h\" or \"v\"\n"); } if (need_close) (void) fclose(f); } break; case CHANNEL: channame = (char *) NULL; if (cmd->tx_argc == 2 || cmd->tx_argc == 3) { if (!ToolGetEditBox(&editArea)) return; if (cmd->tx_argc == 3) channame = cmd->tx_argv[2]; else chanType = CHAN_NORMAL; /* default */ } else if (cmd->tx_argc == 6 || cmd->tx_argc == 7) { editArea.r_xbot = cmdParseCoord(w, cmd->tx_argv[2], FALSE, TRUE); editArea.r_ybot = cmdParseCoord(w, cmd->tx_argv[3], FALSE, FALSE); editArea.r_xtop = cmdParseCoord(w, cmd->tx_argv[4], FALSE, TRUE); editArea.r_ytop = cmdParseCoord(w, cmd->tx_argv[5], FALSE, FALSE); chanType = CHAN_NORMAL; if (cmd->tx_argc == 7) channame = cmd->tx_argv[6]; } else goto badChanCmd; if (channame) { if (channame[0] == 'h') chanType = CHAN_HRIVER; else if (channame[0] == 'v') chanType = CHAN_VRIVER; else { TxError("Unrecognized channel type: %s\n", channame); goto badChanCmd; } } TxPrintf("Channel [%s] %d %d %d %d\n", chanTypeName[chanType], editArea.r_xbot, editArea.r_ybot, editArea.r_xtop, editArea.r_ytop); if (!GADefineChannel(chanType, &editArea)) { TxError("Channel definition failed.\n"); break; } break; case ROUTE: doRoute: if (cmd->tx_argc > 3) { TxError("Usage: garoute route [netlist]\n"); break; } name = (char *) NULL; if (cmd->tx_argc == 3) name = cmd->tx_argv[2]; n = GARouteCmd(EditCellUse, name); if (n < 0) TxError("Couldn't route at all.\n"); else if (n > 0) TxPrintf("%d routing error%s.\n", n, n == 1 ? "" : "s"); else TxPrintf("No routing errors.\n"); break; } return; badChanCmd: TxError("Usage: garoute channel xlo ylo xhi yhi [type]\n"); } /* * ---------------------------------------------------------------------------- * * CmdIRoute -- * * Interactive route command. * Calls command entry point in irouter/irCommand.c * * Usage: * iroute [subcmd [args]] * (See irCommand.c for details.) * * Results: * None. * * Side effects: * Depends on subcommand, see irCommand.c * * ---------------------------------------------------------------------------- */ void CmdIRoute(w, cmd) MagWindow *w; TxCommand *cmd; { IRCommand(w,cmd); return; } /* * ---------------------------------------------------------------------------- * * CmdRoute -- * * Route the nets in the current netlist. * * Results: * None. * * Side effects: * Modifies the edit cell. * * ---------------------------------------------------------------------------- */ #define ROUTERCHECKS 0 #define ROUTERDEBUG 1 #define ROUTERFILE 2 #define ROUTERSHOWMAP 3 #define ROUTERSHOWRES 4 #define ROUTERSHOWEND 5 #define ROUTEREND 6 #define ROUTERHELP 7 #define ROUTERJOG 8 #define ROUTERMMAX 9 #define ROUTERNETLIST 10 #define ROUTEROBST 11 #define ROUTERORIGIN 12 #define ROUTERSTATS 13 #define ROUTERSETTINGS 14 #define ROUTERSTEADY 15 #define ROUTERTECHINFO 16 #define ROUTERVIAS 17 #define ROUTERVIAMIN 18 #define ROUTERMAZESTEMS 19 void CmdRoute(w, cmd) MagWindow *w; TxCommand *cmd; { int option; GCRChannel *ch; Rect area; NLNetList netList; char *netListName; static const char * const cmdRouteOption[] = { "*checks toggle column checking", "*debug toggle router trace messages", "*file route from a channel data file", "*map toggle channel obstacle map display", "*showcolumns toggle channel column text display", "*showfinal toggle text display of final channels", "end set channel router end constant", "help print this help information", "jog int set minimum jog length (grid units)", "metal toggle metal maximization", "netlist set current netlist", "obstacle set obstacle constant", "origin [x y] print or set routing grid origin", "stats print and clear previous route statistics", "settings show router parameters", "steady set steady net constant", "tech show router technology information", "vias set metal maximization via limit (grid units)", "viamin via minimization", "mazestems use maze router to route channel stems to pins", NULL }; if (cmd->tx_argc == 1) { if (!ToolGetEditBox(&area)) return; Route(EditCellUse, &area); return; } option = Lookup(cmd->tx_argv[1], cmdRouteOption); if (option == -1) { TxError("Ambiguous routing option: \"%s\"\n", cmd->tx_argv[1]); goto usage2; } if (option < 0) goto usage; switch (option) { /* These first few options are for wizards only. */ case ROUTERDEBUG: GcrDebug= !GcrDebug; TxPrintf("Router debug tracing: %s\n", GcrDebug ? "on" : "off"); break; case ROUTERCHECKS: GcrNoCheck= !GcrNoCheck; TxPrintf("Router column checking: %s\n", GcrNoCheck ? "on" : "off"); break; case ROUTERFILE: /* Display routing problems from file directly on the screen. */ if(cmd->tx_argc!=3) goto wrongNumArgs; if((ch = GCRRouteFromFile(cmd->tx_argv[2])) == (GCRChannel *) NULL) TxError("Bad channel from file %s\n", cmd->tx_argv[2]); else { RtrPaintBack(ch, EditCellUse->cu_def); GCRFreeChannel(ch); } break; case ROUTERSHOWRES: GcrShowResult= !GcrShowResult; TxPrintf("Show channel columns: %s\n", GcrShowResult ? "on":"off"); break; case ROUTERSHOWEND: GcrShowEnd= !GcrShowEnd; TxPrintf("Show finished channels: %s\n", GcrShowEnd ? "on" : "off"); break; case ROUTERSHOWMAP: GcrShowMap= !GcrShowMap; TxPrintf("Show channel maps: %s\n", GcrShowMap ? "on" : "off"); break; case ROUTERHELP: TxPrintf("Router commands have the form \"route option\",\n"); TxPrintf("where option is one of:\n\n"); if(cmd->tx_argc==2) for (option=ROUTEREND; option<= ROUTERMAZESTEMS; option++) TxPrintf(" %s\n", cmdRouteOption[option]); else if((cmd->tx_argc==3) && !strcmp(cmd->tx_argv[2], "*wizard")) for (option=0; option !=ROUTEREND; option++) TxPrintf(" %s\n", cmdRouteOption[option]); TxPrintf("\n"); break; case ROUTERSTATS: RtrPaintStats(TT_SPACE, 0); break; case ROUTERSETTINGS: TxPrintf("Router parameter settings:\n"); TxPrintf(" Channel end constant... %f\n", RtrEndConst); TxPrintf(" Metal maximization..... %s\n", RtrDoMMax ? "on":"off"); TxPrintf(" Minimum jog length..... %d\n", GCRMinJog); TxPrintf(" Net list............... \"%s\"\n", NMNetlistName()); TxPrintf(" Obstacle constant...... %f\n", GCRObstDist); TxPrintf(" Steady net constant.... %d\n", GCRSteadyNet); TxPrintf(" Via limit.............. %d\n", RtrViaLimit); TxPrintf(" Maze route stems....... %s\n", RtrMazeStems ? "yes" : "no"); if((cmd->tx_argc!=3) || strcmp(cmd->tx_argv[2], "*wizard")) break; TxPrintf("\n"); TxPrintf(" Debug tracing.......... %s\n", GcrDebug ? "on":"off"); TxPrintf(" Column checking........ %s\n", GcrNoCheck?"on":"off"); TxPrintf(" Show channel columns... %s\n", GcrShowResult ? "on" : "off"); TxPrintf(" Show finished channels %s\n", GcrShowEnd?"on":"off"); TxPrintf(" Show channel maps...... %s\n", GcrShowMap?"on":"off"); break; case ROUTERTECHINFO: TxPrintf("Router Technology Information:\n"); TxPrintf(" Preferred layer..... %s; width %d\n", DBTypeLongName(RtrMetalType), RtrMetalWidth); TxPrintf(" Alternate layer..... %s; width %d\n", DBTypeLongName(RtrPolyType), RtrPolyWidth); TxPrintf(" Contacts............ %s; ", DBTypeLongName(RtrContactType)); TxPrintf("width %d; offset %d; surrounds %d, %d\n", RtrContactWidth, RtrContactOffset, RtrMetalSurround, RtrPolySurround); TxPrintf(" Subcell separations: %d up; %d down\n", RtrSubcellSepUp, RtrSubcellSepDown); TxPrintf(" Router grid spacing: %d\n", RtrGridSpacing); break; case ROUTERMMAX: RtrDoMMax= !RtrDoMMax; TxPrintf("Metal maximization: %s\n", RtrDoMMax ? "on" : "off"); break; case ROUTERVIAS: if(cmd->tx_argc!=2) { if(cmd->tx_argc!=3) goto wrongNumArgs; if(sscanf(cmd->tx_argv[2], "%d", &RtrViaLimit) != 1) TxError("Bad value for via limit\n"); } TxPrintf("Via limit is %d\n", RtrViaLimit); break; case ROUTEREND: if(cmd->tx_argc!=2) { if(cmd->tx_argc!=3) goto wrongNumArgs; if(sscanf(cmd->tx_argv[2], "%f", &RtrEndConst) != 1) TxError("Bad value for channel end distance\n"); } TxPrintf("Channel end constant is %f\n", RtrEndConst); break; case ROUTERJOG: if(cmd->tx_argc!=2) { if(cmd->tx_argc!=3) goto wrongNumArgs; if(sscanf(cmd->tx_argv[2], "%d", &GCRMinJog) != 1) TxError("Bad value for minimum jog length\n"); } TxPrintf("Minimum jog length is %d\n", GCRMinJog); break; case ROUTEROBST: if(cmd->tx_argc!=2) { if(cmd->tx_argc!=3) goto wrongNumArgs; if(sscanf(cmd->tx_argv[2], "%f", &GCRObstDist) != 1) TxError("Bad value for obstacle constant\n"); } TxPrintf("Obstacle constant is %f\n", GCRObstDist); break; case ROUTERSTEADY: if(cmd->tx_argc!=2) { if(cmd->tx_argc!=3) goto wrongNumArgs; if(sscanf(cmd->tx_argv[2], "%d", &GCRSteadyNet) != 1) TxError("Bad value for steady net constant\n"); } TxPrintf("Steady net constant is %d\n", GCRSteadyNet); break; case ROUTERNETLIST: if(cmd->tx_argc!=2) { if(cmd->tx_argc!=3) goto wrongNumArgs; NMNewNetlist(cmd->tx_argv[2]); } TxPrintf("Current list is \"%s\"\n", NMNetlistName()); break; case ROUTERORIGIN: if (cmd->tx_argc != 2) { if (cmd->tx_argc != 4) goto wrongNumArgs; RtrOrigin.p_x = cmdParseCoord(w, cmd->tx_argv[2], FALSE, TRUE); RtrOrigin.p_y = cmdParseCoord(w, cmd->tx_argv[3], FALSE, FALSE); break; } TxPrintf("Routing grid origin = (%d,%d)\n", RtrOrigin.p_x, RtrOrigin.p_y); break; case ROUTERVIAMIN: if (!ToolGetEditBox(&area)) return; if (!NMHasList()) { netListName = EditCellUse->cu_def->cd_name; TxPrintf("No netlist selected yet; using \"%s\".\n", netListName); NMNewNetlist(netListName); } else netListName = NMNetlistName(); if ( NLBuild(EditCellUse, &netList)) { int nvia; nvia = RtrViaMinimize(EditCellUse->cu_def); DBWAreaChanged(EditCellUse->cu_def, &area, DBW_ALLWINDOWS, &DBAllButSpaceBits); WindUpdate(); TxPrintf("\n%d vias removed\n",nvia); NLFree(&netList); } break; case ROUTERMAZESTEMS: RtrMazeStems = !RtrMazeStems; TxPrintf("Maze route channel stems: %s\n", RtrMazeStems ? "yes" : "no"); break; } /* switch*/ return; wrongNumArgs: TxError("Wrong number of arguments to %s option.\n", cmd->tx_argv[1]); TxError("Type \":route help\" for help.\n"); return; usage: TxError("\"%s\" isn't a valid router option.", cmd->tx_argv[1]); usage2: TxError(" Type \"route help\" for help.\n"); return; } /* * ---------------------------------------------------------------------------- * CmdSeeFlags -- * * Display router-generated flags on the highlight layer. User points * to a channel and invokes the command with an argument naming the * flag to be displayed. * * Results: * None. * * Side effects: * Paints highlights on the screen. Allocates a special cell def and * initializes a hash table glTileToChannel the first time it is called. * ---------------------------------------------------------------------------- */ void CmdSeeFlags(w, cmd) MagWindow * w; TxCommand *cmd; { Rect rootRect; Point point; MagWindow * window; window = CmdGetRootPoint(&point, &rootRect); if (window == (MagWindow *) NULL) return; if(cmd->tx_argc > 2) { TxError("Useage: %s [flag name]\n", cmd->tx_argv[0]); return; } if(cmd->tx_argc == 2) { GCRShow(&point, cmd->tx_argv[1]); TxError("%s: flag highlights turned on.\n", cmd->tx_argv[0]); } else { NMUnsetCell(); TxError("%s: flag highlights turned off.\n", cmd->tx_argv[0]); } }