diff options
Diffstat (limited to 'tclqrouter.c')
-rw-r--r-- | tclqrouter.c | 371 |
1 files changed, 369 insertions, 2 deletions
diff --git a/tclqrouter.c b/tclqrouter.c index d06dcbb..d37cba3 100644 --- a/tclqrouter.c +++ b/tclqrouter.c @@ -11,6 +11,7 @@ #include <sys/types.h> #include <sys/stat.h> #include <errno.h> +#include <math.h> /* for round() */ #include <tk.h> @@ -123,6 +124,9 @@ static int qrouter_layers( static int qrouter_drc( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +static int qrouter_query( + ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); static int qrouter_passes( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); @@ -141,6 +145,15 @@ static int qrouter_print( static int qrouter_quit( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +static int qrouter_pitchx( + ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int qrouter_pitchy( + ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int qrouter_unblock( + ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); static cmdstruct qrouter_commands[] = { @@ -161,12 +174,16 @@ static cmdstruct qrouter_commands[] = {"obstruction", qrouter_obs}, {"ignore", qrouter_ignore}, {"priority", qrouter_priority}, + {"pitchx", qrouter_pitchx}, + {"pitchy", qrouter_pitchy}, + {"unblock", qrouter_unblock}, {"via", qrouter_via}, {"resolution", qrouter_resolution}, {"congested", qrouter_congested}, {"layers", qrouter_layers}, {"drc", qrouter_drc}, {"passes", qrouter_passes}, + {"query", qrouter_query}, {"vdd", qrouter_vdd}, {"gnd", qrouter_gnd}, {"failing", qrouter_failing}, @@ -314,7 +331,7 @@ void tcl_stdflush(FILE *f) char *stdptr = stdstr + 11; Tcl_SaveResult(qrouterinterp, &state); - strcpy(stdptr, (f == stderr) ? "err" : "out"); + strncpy(stdptr, (f == stderr) ? "err" : "out", 3); Tcl_Eval(qrouterinterp, stdstr); Tcl_RestoreResult(qrouterinterp, &state); } @@ -620,6 +637,7 @@ qrouter_start(ClientData clientData, Tcl_Interp *interp, argv[argc++] = strdup(Tcl_GetString(objv[i])); } + init_config(); result = runqrouter(argc, argv); if ((result == 0) && (batchmode == 0)) GUI_init(interp); @@ -1602,7 +1620,7 @@ qrouter_readlef(ClientData clientData, Tcl_Interp *interp, LEFfile = Tcl_GetString(objv[1]); mscale = LefRead(LEFfile); - if (Scales.mscale < mscale) Scales.mscale = mscale; + update_mscale(mscale); for (i = 0; i < Num_layers; i++) { @@ -2409,6 +2427,231 @@ qrouter_resolution(ClientData clientData, Tcl_Interp *interp, } /*------------------------------------------------------*/ +/* Command "query" */ +/* */ +/* Print information about a specific grid point, */ +/* instance, node, or net. Option "watch" indicates to */ +/* monitor the position during DEF read-in and print */ +/* information when the node information changes, */ +/* especially if the grid position is disabled. */ +/* */ +/* Options: */ +/* */ +/* query grid <ix> <iy> <layer> [watch] */ +/* query position <dx> <dy> <layer> [watch] */ +/* query instance <instance> */ +/* query node <instance>/<pin> */ +/* query net <name> */ +/* */ +/* <layer> may be either a layer name or integer index. */ +/* <dx> and <dy> should be given in microns. <ix> and */ +/* <iy> are integer indexes. All other arguments are */ +/* strings. */ +/*------------------------------------------------------*/ + +static int +qrouter_query(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + char *layername, *instname, *netname, *pinname; + int idx, result, layer; + int gridx, gridy; + double dx, dy; + unsigned char is_index, do_watch, do_unwatch; + + static char *subCmds[] = { + "grid", "position", "instance", "node", "net", NULL + }; + enum SubIdx { + GridIdx, PosIdx, InstIdx, NodeIdx, NetIdx + }; + + if (objc < 2) { + Fprintf(stderr, "Usage:\n"); + Fprintf(stderr, " query position <x_microns> <y_microns> <layer> [watch]\n"); + Fprintf(stderr, " query grid <gridx> <gridy> <layer> [watch]\n"); + Fprintf(stderr, " query instance <inst_name>\n"); + Fprintf(stderr, " query node <inst_name>/<pin_name>\n"); + Fprintf(stderr, " query net <net_name>\n"); + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?"); + return TCL_ERROR; + } + else if ((result = Tcl_GetIndexFromObj(interp, objv[1], + (CONST84 char **)subCmds, "option", 0, &idx)) != TCL_OK) + return result; + + do_watch = do_unwatch = FALSE; + switch (idx) { + case GridIdx: + case PosIdx: + if (objc == 6) { + if (!strcmp(Tcl_GetString(objv[5]), "watch")) { + do_watch = TRUE; + objc--; + } + else if (!strcmp(Tcl_GetString(objv[5]), "unwatch")) { + do_unwatch = TRUE; + objc--; + } + } + if (objc != 5) { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?"); + return TCL_ERROR; + } + is_index = (idx == GridIdx) ? TRUE : FALSE; + + layername = Tcl_GetString(objv[4]); + layer = LefFindLayerNum(layername); + if (layer < 0) { + result = Tcl_GetIntFromObj(interp, objv[4], &layer); + if (result != TCL_OK) { + Tcl_SetResult(interp, "No such layer name.\n", NULL); + return result; + } + } + if (layer >= Num_layers) { + Tcl_SetResult(interp, "Bad layer number.\n", NULL); + return result; + } + if (is_index) { + result = Tcl_GetIntFromObj(interp, objv[2], &gridx); + if (result != TCL_OK) { + Tcl_SetResult(interp, "Cannot parse grid X index\n", NULL); + return result; + } + result = Tcl_GetIntFromObj(interp, objv[3], &gridy); + if (result != TCL_OK) { + Tcl_SetResult(interp, "Cannot parse grid Y index\n", NULL); + return result; + } + /* Translate gridx, gridy into dx, dy */ + dx = (gridx * PitchX) + Xlowerbound; + dy = (gridy * PitchY) + Ylowerbound; + } + else { + result = Tcl_GetDoubleFromObj(interp, objv[2], &dx); + if (result != TCL_OK) { + Tcl_SetResult(interp, "Cannot parse grid X position\n", NULL); + return result; + } + result = Tcl_GetDoubleFromObj(interp, objv[3], &dy); + if (result != TCL_OK) { + Tcl_SetResult(interp, "Cannot parse grid Y position\n", NULL); + return result; + } + /* Translate dx, dy into nearest gridx, gridy */ + gridx = (int)(round((dx - Xlowerbound) / PitchX)); + gridy = (int)(round((dy - Ylowerbound) / PitchY)); + + Fprintf(stdout, "Grid position index is (%d %d)\n", gridx, gridy); + } + if (gridx < 0) { + Tcl_SetResult(interp, "Grid X position must not be negative.\n", + NULL); + return result; + } + if (gridy < 0) { + Tcl_SetResult(interp, "Grid Y position must not be negative.\n", + NULL); + return result; + } + if (do_watch) { + DPOINT newtest; + newtest = (DPOINT)malloc(sizeof(struct dpoint_)); + newtest->layer = layer; + newtest->next = testpoint; + if (idx == GridIdx) { + newtest->gridx = gridx; + newtest->gridy = gridy; + newtest->x = 0; + newtest->y = 0; + Fprintf(stdout, "Watching grid position index (%d %d)" + " layer %d.\n", gridx, gridy, layer); + } + else { + newtest->x = dx; + newtest->y = dy; + newtest->gridx = -1; + newtest->gridy = -1; + Fprintf(stdout, "Watching grid position (%g %g)um" + " layer %d.\n", dx, dy, layer); + } + testpoint = newtest; + } + else if (do_unwatch) { + DPOINT ptest, ltest; + ltest = NULL; + for (ptest = testpoint; ptest; ptest = ptest->next) { + if (ptest->x == dx && ptest->y == dy && ptest->layer == layer) { + if (ltest == NULL) { + testpoint = testpoint->next; + free(ptest); + } + else { + ltest->next = ptest->next; + free(ptest); + } + Fprintf(stdout, "No longer watching grid position (%g %g)um" + " index (%d %d) layer %d.\n", + dx, dy, gridx, gridy, layer); + break; + } + ltest = ptest; + } + if (ptest == NULL) { + Fprintf(stdout, "Grid position (%g %g)um index (%d %d)" + " layer %d is not on the watch list.\n", + dx, dy, gridx, gridy, layer); + } + } + else if (gridx >= NumChannelsX) { + Tcl_SetResult(interp, "Grid X position is larger than the number" + " of horizontal route tracks.\n", NULL); + return result; + } + else if (gridy >= NumChannelsY) { + Tcl_SetResult(interp, "Grid Y position is larger than the number" + " of vertical route tracks.\n", NULL); + return result; + } + else { + Fprintf(stdout, "Querying grid position (%g %g)um index (%d %d)" + " layer %d:\n", dx, dy, gridx, gridy, layer); + print_grid_information(gridx, gridy, layer); + } + break; + + case InstIdx: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?"); + return TCL_ERROR; + } + instname = Tcl_GetString(objv[2]); + print_instance_information(instname); + break; + + case NodeIdx: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?"); + return TCL_ERROR; + } + instname = Tcl_GetString(objv[2]); + print_node_information(instname); + break; + + case NetIdx: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?"); + return TCL_ERROR; + } + netname = Tcl_GetString(objv[2]); + print_net_information(netname); + break; + } + return QrouterTagCallback(interp, objc, objv); +} + +/*------------------------------------------------------*/ /* Command "drc" */ /* */ /* Set qrouter options related to handling of DRC */ @@ -2988,3 +3231,127 @@ qrouter_print(ClientData clientData, Tcl_Interp *interp, } /*------------------------------------------------------*/ +/* Command "pitchx" */ +/* */ +/* Set the base pitch for vertical routing layers. */ +/* Values larger than current value will be ignored. */ +/* Without an argument, current value is returned. */ +/* */ +/* Options: */ +/* */ +/* pitchx [<value>] */ +/*------------------------------------------------------*/ + +static int +qrouter_pitchx(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + int result; + double value; + + if (objc == 1) { + Tcl_SetObjResult(interp, Tcl_NewDoubleObj(PitchX)); + } + else if (objc == 2) { + result = Tcl_GetDoubleFromObj(interp, objv[1], &value); + if (result != TCL_OK) return result; + if (value <= 0.0) { + Tcl_SetResult(interp, "PitchX value has to be a positive value" + "; ignored", NULL); + return TCL_ERROR; + } + else if ((PitchX > 0.0) && (value > PitchX)) { + Tcl_SetResult(interp, "PitchX is larger than current value" + "; ignored", NULL); + } + else { + PitchX = value; + } + } + else { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?"); + return TCL_ERROR; + } + return QrouterTagCallback(interp, objc, objv); +} + +/*------------------------------------------------------*/ +/* Command "pitchy" */ +/* */ +/* Set the base pitch for horizontal routing layers. */ +/* Values larger than current value will be ignored. */ +/* Without an argument, current value is returned. */ +/* */ +/* Options: */ +/* */ +/* pitchy [<value>] */ +/*------------------------------------------------------*/ + +static int +qrouter_pitchy(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + int result; + double value; + + if (objc == 1) { + Tcl_SetObjResult(interp, Tcl_NewDoubleObj(PitchY)); + } + else if (objc == 2) { + result = Tcl_GetDoubleFromObj(interp, objv[1], &value); + if (result != TCL_OK) return result; + if (value <= 0.0) { + Tcl_SetResult(interp, "PitchY value has to be a positive value" + "; ignored", NULL); + return TCL_ERROR; + } + else if ((PitchY > 0.0) && (value > PitchY)) { + Tcl_SetResult(interp, "PitchY is larger than current value" + "; ignored", NULL); + } + else { + PitchY = value; + } + } + else { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?"); + return TCL_ERROR; + } + return QrouterTagCallback(interp, objc, objv); +} + +/*------------------------------------------------------*/ +/* Command "unblock" */ +/* */ +/* Set the unblocking flag, which indicates to qrouter */ +/* that all grid points that lie cleanly inside pin */ +/* geometry should be marked routable. This command */ +/* must be issued before read_def to be effective. */ +/* */ +/* Options: */ +/* */ +/* unblock [true|false] */ +/*------------------------------------------------------*/ + +static int +qrouter_unblock(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + int result, value; + + if (objc == 1) { + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(unblockAll)); + } + else if (objc == 2) { + result = Tcl_GetBooleanFromObj(interp, objv[1], &value); + if (result != TCL_OK) return result; + unblockAll = (value == 0) ? FALSE : TRUE; + } + else { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?"); + return TCL_ERROR; + } + return QrouterTagCallback(interp, objc, objv); +} + +/*------------------------------------------------------*/ |