Compare commits

..

No commits in common. "master" and "8.3.635" have entirely different histories.

10 changed files with 42 additions and 281 deletions

View File

@ -1 +1 @@
8.3.637 8.3.635

View File

@ -131,11 +131,8 @@ DBWAddButtonHandler(
for (i = 0; i < MAXBUTTONHANDLERS; i++) for (i = 0; i < MAXBUTTONHANDLERS; i++)
{ {
if (dbwButtonHandlers[i] != NULL) continue; if (dbwButtonHandlers[i] != NULL) continue;
StrDup(&dbwButtonHandlers[i], name); (void) StrDup(&dbwButtonHandlers[i], name);
if (doc != NULL) (void) StrDup(&dbwButtonDoc[i], doc);
StrDup(&dbwButtonDoc[i], doc);
else
dbwButtonDoc[i] = (char *)NULL;
dbwButtonProcs[i] = proc; dbwButtonProcs[i] = proc;
dbwButtonCursors[i] = cursor; dbwButtonCursors[i] = cursor;
return; return;
@ -276,37 +273,6 @@ DBWGetButtonHandler()
return dbwButtonHandlers[dbwButtonCurrentIndex]; return dbwButtonHandlers[dbwButtonCurrentIndex];
} }
/*
* ----------------------------------------------------------------------------
*
* DBWButtonHandlerIndex()
*
* Given a string, return the index of the button handler. If the
* string does not correspond to any button handler name, then
* return -1.
*
* Results:
* Index of button handler, if it exists; -1 otherwise.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
int
DBWButtonHandlerIndex(char *toolName)
{
int i;
for (i = 0; i < MAXBUTTONHANDLERS; i++)
{
if (dbwButtonHandlers[i] == NULL) return -1;
else if (!strcmp(toolName, dbwButtonHandlers[i])) return i;
}
return -1;
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -328,10 +294,7 @@ DBWButtonHandlerIndex(char *toolName)
void void
DBWPrintButtonDoc() DBWPrintButtonDoc()
{ {
if (dbwButtonDoc[dbwButtonCurrentIndex])
TxPrintf("%s", dbwButtonDoc[dbwButtonCurrentIndex]); TxPrintf("%s", dbwButtonDoc[dbwButtonCurrentIndex]);
else
TxPrintf("(no usage information)\n");
} }

View File

@ -152,7 +152,6 @@ extern void DBWAddButtonHandler(const char *name, const cb_database_buttonhandle
int cursor, const char *doc); int cursor, const char *doc);
extern char *DBWGetButtonHandler(); extern char *DBWGetButtonHandler();
extern char *DBWChangeButtonHandler(); extern char *DBWChangeButtonHandler();
extern int DBWButtonHandlerIndex();
extern void DBWPrintButtonDoc(); extern void DBWPrintButtonDoc();
extern void DBWBoxHandler(); extern void DBWBoxHandler();

View File

@ -20,64 +20,22 @@
<H2>macro</H2> <H2>macro</H2>
<HR> <HR>
Define or print a key or button macro binding. Define or print a macro called char
<HR> <HR>
<H3>Usage:</H3> <H3>Usage:</H3>
<BLOCKQUOTE> <BLOCKQUOTE>
<B>macro</B> [<I>window_type</I>] [<I>option</I>] [<I>key</I> [<I>value</I>]] <B>macro</B> [<I>window_type</I>] [<I>key</I> [<I>value</I>]] <BR><BR>
<BR><BR>
<BLOCKQUOTE> <BLOCKQUOTE>
where <I>key</I> is the name of a valid key (see below), and where <I>key</I> is the name of a valid key (see below), and
<I>value</I> is a <B>magic</B> command-line command. If <I>value</I> is a <B>magic</B> command-line command. If
present, <I>window_type</I> must be one of the known valid window present, <I>window_type</I> must be one of the four window
types accepted by the <B>specialopen</B> command (<B>color</B>, types accepted by the <B>specialopen</B> command: <B>layout</B>,
<B>netlist</B>, and <B>wind3d</B>), or a known layout tool <B>color</B>, <B>netlist</B>, and <B>wind3d</B>. If omitted,
(<B>box</B>, <B>wiring</B>, <B>nettool</B>, or <B>pick</B>). If the layout window is assumed by default, unless the command has
omitted, the layout window is assumed by default, unless the command been called from inside a window (using the colon or semicolon
has been called from inside a window (using the colon or semicolon
escape to the command-line), in which case that window type is escape to the command-line), in which case that window type is
assumed. <P> assumed.
In the non-Tcl version of magic, the <I>window_type</I> must be
one of the three valid window types listed above, or <B>layout</B>.
Tool button bindings are hard-coded, fixed, and unknown to the
macro handler. <P>
In the Tcl version of magic, tool types are generated by
procedure and can be modified or overridden. The four tools
listed above are the default tools known to magic. If no window
or tool type is given, then the current tool in the current
active layout window is assumed.<P>
<I>option</I> may be one of the following:
<DL>
<DT> <B>list</B> [<B>-reverse</B>]
<DD> The key bindings are returned in the form of a Tcl list
(Tcl version of magic only). The returned value is a
single list with alternating entries of the macro key and
the macro binding. In Tcl, this list can be treated as a
dictionary type of key:value pairs. With the <B>-reverse</B>
option, the keys and values are reversed, resulting in a
dictionary that can be searched or listed by function.
<DT> <B>help</B>
<DD> Curently, <B>macro help</B> is equivalent to <B>macro</B>
without arguments, and returns a full list of macro names
and their bindings.
<DT> <B>search</B> <I>text</I>
<DD> Return only results which match (all or in part) the string
<I>text</I>. For example, <B>macro search grid</B> will
return all key bindings that include the command <B>grid</B>.
<DT> <B>copy</B> <I>tool_name</I>
<DD> This is a method introduced to allow the interactive creation
of new tools, in the Tcl version of magic. Each tool is defined
specifically by its unique button and key bindings. Because
tools generally keep most of the same default bindings, the
<B>copy</B> option will copy all the existing bindings to the
new tool from the current tool. This can be followed by
switching to the new tool and replacing macros with ones
unique to the tool.
</DL>
</BLOCKQUOTE> </BLOCKQUOTE>
</BLOCKQUOTE> </BLOCKQUOTE>
@ -114,6 +72,7 @@ Define or print a key or button macro binding.
etc., the <B>macro</B> command accepts the abbreviated etc., the <B>macro</B> command accepts the abbreviated
forms <B>Button1</B>, and so forth. <P> forms <B>Button1</B>, and so forth. <P>
Finally, key modifiers may be prepended to the key name. Finally, key modifiers may be prepended to the key name.
Valid key modifiers are <B>Shift_</B>, <B>Control_</B>, Valid key modifiers are <B>Shift_</B>, <B>Control_</B>,
<B>Alt_</B>, and <B>Meta_</B>, and may be coupled in any <B>Alt_</B>, and <B>Meta_</B>, and may be coupled in any
@ -130,7 +89,6 @@ Define or print a key or button macro binding.
<H3>See Also:</H3> <H3>See Also:</H3>
<BLOCKQUOTE> <BLOCKQUOTE>
<A HREF=imacro.html><B>imacro</B></A> <BR> <A HREF=imacro.html><B>imacro</B></A> <BR>
<A HREF=toolchange.html><B>tool</B></A> (Tcl version) <BR>
</BLOCKQUOTE> </BLOCKQUOTE>
<P><IMG SRC=graphics/line1.gif><P> <P><IMG SRC=graphics/line1.gif><P>

View File

@ -524,13 +524,6 @@ DRCBasicCheck (celldef, checkRect, clipRect, function, cdata)
return (errors); return (errors);
} }
/* Expect that keeping around 3 MaxRectsData records should be sufficient
* to avoid recomputing drcCanonicalMaxwidth() multiple times. Note that
* if a PDK sets up multiple rules on an edge which all require running
* drcCanonicalMaxwidth(), then this cache size may need to be revisited.
*/
#define MAXRECTSCACHE 3
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -568,19 +561,6 @@ drcTile (tile, dinfo, arg)
int triggered; int triggered;
int cdist, dist, ccdist, result; int cdist, dist, ccdist, result;
/* Keep up to three MaxRectsData records to avoid doing the same
* expensive computation more than once.
*
* mrdcache[0] will be used for the tpleft tile, since it will never
* be reused. mrdcache[1] and mrdcache[2] will be used for the tile
* itself. Note that if more than 2 DRCCookie entries for the same
* edge require drcCanonicalMaxwidth(), then mrdcache[2] will be
* re-used so that at least mrdcache[1] is always a cache hit.
*/
static MaxRectsData *mrdcache[MAXRECTSCACHE] = {NULL, NULL, NULL};
DRCCookie *cptrcache;
arg->dCD_constraint = &errRect; arg->dCD_constraint = &errRect;
/* /*
@ -722,8 +702,6 @@ drcTile (tile, dinfo, arg)
DRCstatEdges++; DRCstatEdges++;
} }
cptrcache = NULL;
/* /*
* Check design rules along a vertical boundary between two tiles. * Check design rules along a vertical boundary between two tiles.
* *
@ -879,23 +857,12 @@ drcTile (tile, dinfo, arg)
if (cptr->drcc_flags & DRC_REVERSE) if (cptr->drcc_flags & DRC_REVERSE)
{ {
mrd = drcCanonicalMaxwidth(tpleft, GEO_WEST, arg, cptr, mrd = drcCanonicalMaxwidth(tpleft, GEO_WEST, arg, cptr);
&mrdcache[0]);
triggered = 0; triggered = 0;
} }
else else if (firsttile)
{ {
if (cptrcache == NULL) mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr);
{
mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr,
&mrdcache[1]);
cptrcache = cptr;
}
else if (cptrcache != cptr)
mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr,
&mrdcache[2]);
else
mrd = mrdcache[1];
triggered = 0; triggered = 0;
} }
if (!trigpending || (DRCCurStyle->DRCFlags if (!trigpending || (DRCCurStyle->DRCFlags
@ -1186,8 +1153,6 @@ drcTile (tile, dinfo, arg)
} }
} }
cptrcache = NULL;
/* /*
* Check design rules along a horizontal boundary between two tiles. * Check design rules along a horizontal boundary between two tiles.
* *
@ -1334,23 +1299,12 @@ drcTile (tile, dinfo, arg)
if (cptr->drcc_flags & DRC_REVERSE) if (cptr->drcc_flags & DRC_REVERSE)
{ {
mrd = drcCanonicalMaxwidth(tpbot, GEO_SOUTH, arg, cptr, mrd = drcCanonicalMaxwidth(tpbot, GEO_SOUTH, arg, cptr);
&mrdcache[0]);
triggered = 0; triggered = 0;
} }
else else if (firsttile)
{ {
if (cptrcache == NULL) mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr);
{
mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr,
&mrdcache[1]);
cptrcache = cptr;
}
else if (cptrcache != cptr)
mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr,
&mrdcache[2]);
else
mrd = mrdcache[1];
triggered = 0; triggered = 0;
} }
if (!trigpending || (DRCCurStyle->DRCFlags if (!trigpending || (DRCCurStyle->DRCFlags

View File

@ -510,17 +510,16 @@ MaxRectsExclude(
*/ */
MaxRectsData * MaxRectsData *
drcCanonicalMaxwidth(starttile, dir, arg, cptr, mrdptr) drcCanonicalMaxwidth(starttile, dir, arg, cptr)
Tile *starttile; Tile *starttile;
int dir; /* direction of rule */ int dir; /* direction of rule */
struct drcClientData *arg; struct drcClientData *arg;
DRCCookie *cptr; DRCCookie *cptr;
MaxRectsData **mrdptr;
{ {
int s, edgelimit; int s, edgelimit;
Tile *tile,*tp; Tile *tile,*tp;
TileTypeBitMask wrongtypes; TileTypeBitMask wrongtypes;
MaxRectsData *mrd = *mrdptr; static MaxRectsData *mrd = (MaxRectsData *)NULL;
Rect *boundrect, boundorig; Rect *boundrect, boundorig;
/* Generate an initial array size of 8 for rlist and swap. */ /* Generate an initial array size of 8 for rlist and swap. */
@ -530,7 +529,6 @@ drcCanonicalMaxwidth(starttile, dir, arg, cptr, mrdptr)
mrd->rlist = (Rect *)mallocMagic(8 * sizeof(Rect)); mrd->rlist = (Rect *)mallocMagic(8 * sizeof(Rect));
mrd->swap = (Rect *)mallocMagic(8 * sizeof(Rect)); mrd->swap = (Rect *)mallocMagic(8 * sizeof(Rect));
mrd->listdepth = 8; mrd->listdepth = 8;
*mrdptr = mrd;
} }
if (starttile == NULL) return mrd; if (starttile == NULL) return mrd;

View File

@ -2755,56 +2755,6 @@ extOutputDevices(def, transList, outFile)
/* get corrected by extComputeEffectiveLW(). */ /* get corrected by extComputeEffectiveLW(). */
length = (extTransRec.tr_gatelen - width) / 2; length = (extTransRec.tr_gatelen - width) / 2;
} }
if ((n == 1) && (length == 0) && (extTransRec.tr_gatelen == 0))
{
/* If a one-terminal device has not recorded any
* gate length, then get W and L from the bounding
* box of the device. This routine could be much
* better optimized but it is probably not worth
* the effort. Just reusing the code from above
* for creating extSpecialDevice, a list of device
* tiles. Note that W and L are not distinguishable
* and hopefully the PDK defines the device by area
* and perimeter.
*/
LinkedTile *lt;
Rect devbbox, ltbox;
extSpecialDevice = (LinkedTile *)NULL;
arg.fra_uninit = (ClientData)extTransRec.tr_gatenode;
arg.fra_region = (ExtRegion *)reg;
arg.fra_each = extSDTileFunc;
ExtFindNeighbors(reg->treg_tile, reg->treg_dinfo,
arg.fra_pNum, &arg);
arg.fra_uninit = (ClientData) reg;
arg.fra_region = (ExtRegion *) extTransRec.tr_gatenode;
arg.fra_each = (int (*)()) NULL;
ExtFindNeighbors(reg->treg_tile, reg->treg_dinfo,
arg.fra_pNum, &arg);
lt = extSpecialDevice;
if (lt)
{
TiToRect(lt->t, &devbbox);
for (; lt; lt = lt->t_next)
{
TiToRect(lt->t, &ltbox);
GeoInclude(&ltbox, &devbbox);
}
free_magic1_t mm1 = freeMagic1_init();
for (lt = extSpecialDevice; lt; lt = lt->t_next)
freeMagic1(&mm1, (char *)lt);
freeMagic1_end(&mm1);
}
length = devbbox.r_xtop - devbbox.r_xbot;
/* Width was likely a perimeter value and will
* be recalculated as the actual device width.
*/
width = devbbox.r_ytop - devbbox.r_ybot;
}
} }
/*------------------------------------------------------*/ /*------------------------------------------------------*/

View File

@ -1299,11 +1299,6 @@ proc magic::add_check_callbacks {gencell_type library} {
# A final default dependency will be added to all entries # A final default dependency will be added to all entries
# to run the "check" procedure for the device. Dependencies # to run the "check" procedure for the device. Dependencies
# that are more targeted get run first. # that are more targeted get run first.
#
# NOTE: The "check" procedure must be the first in the
# list, as otherwise, any invalid entry that is corrected
# by the check callback will have been used to evaluate
# dependent values.
#---------------------------------------------------------- #----------------------------------------------------------
proc magic::add_dependency {callback gencell_type library args} { proc magic::add_dependency {callback gencell_type library args} {
@ -1360,13 +1355,13 @@ proc magic::update_dialog {callback pname gencell_type library} {
set parameters [dict merge $pdefaults [magic::gencell_getparams]] set parameters [dict merge $pdefaults [magic::gencell_getparams]]
} }
if {$callback != {}} {
set parameters [$callback $pname $parameters]
}
if {[catch {set parameters [${library}::${gencell_type}_check $parameters]} \ if {[catch {set parameters [${library}::${gencell_type}_check $parameters]} \
checkerr]} { checkerr]} {
puts stderr $checkerr puts stderr $checkerr
} }
if {$callback != {}} {
set parameters [$callback $pname $parameters]
}
magic::gencell_setparams $parameters magic::gencell_setparams $parameters
} }

View File

@ -534,11 +534,8 @@ proc magic::enable_tools {} {
# The user can change these bindings at will by using the # The user can change these bindings at will by using the
# "macro" command when the tool is active. # "macro" command when the tool is active.
# NOTE: Do not name a tool "netlist" because it will get
# confused with the "netlist" window.
magic::macro copy wiring magic::macro copy wiring
magic::macro copy nettool magic::macro copy netlist
magic::macro copy pick magic::macro copy pick
magic::tool wiring magic::tool wiring
@ -552,7 +549,7 @@ proc magic::enable_tools {} {
macro Button4 "wire incr width ; wire show" macro Button4 "wire incr width ; wire show"
macro Button5 "wire decr width ; wire show" macro Button5 "wire decr width ; wire show"
magic::tool nettool magic::tool netlist
macro Button1 "netlist select" macro Button1 "netlist select"
macro Button2 "netlist join" macro Button2 "netlist join"
macro Button3 "netlist terminal" macro Button3 "netlist terminal"
@ -707,8 +704,8 @@ proc magic::tool {{type next}} {
if {$type == "next"} { if {$type == "next"} {
switch $Opts(tool) { switch $Opts(tool) {
box { set type wiring } box { set type wiring }
wiring { set type nettool } wiring { set type netlist }
nettool { set type pick } netlist { set type pick }
pick { set type box } pick { set type box }
} }
} }
@ -764,9 +761,9 @@ proc magic::tool {{type next}} {
set Opts(tool) wiring set Opts(tool) wiring
cursor 19 ;# sets the cursor cursor 19 ;# sets the cursor
} }
nettool { netlist {
puts stdout {Switching to NETLIST tool.} puts stdout {Switching to NETLIST tool.}
set Opts(tool) nettool set Opts(tool) netlist
cursor 18 ;# sets the cursor cursor 18 ;# sets the cursor
} }
pick { pick {

View File

@ -1056,7 +1056,6 @@ windDoMacro(w, cmd, interactive)
bool do_help = FALSE; bool do_help = FALSE;
bool do_reverse = FALSE; bool do_reverse = FALSE;
char *searchterm = NULL; char *searchterm = NULL;
char *clientName = NULL;
macrodef *cMacro; macrodef *cMacro;
HashTable *clienttable; HashTable *clienttable;
HashEntry *h; HashEntry *h;
@ -1074,25 +1073,9 @@ windDoMacro(w, cmd, interactive)
argstart = 1; argstart = 1;
if (cmd->tx_argc == 1) if (cmd->tx_argc == 1)
wc = DBWclientID; /* Default client */ wc = DBWclientID; /* Added by NP 11/15/04 */
else if (cmd->tx_argc > 1) else if (cmd->tx_argc > 1)
{
wc = WindGetClient(cmd->tx_argv[1], TRUE); wc = WindGetClient(cmd->tx_argv[1], TRUE);
if (wc != NULL)
{
clientName = cmd->tx_argv[1];
argstart++;
}
else
{
/* Check if argument is a known layout button handler */
if (DBWButtonHandlerIndex(cmd->tx_argv[1]) != -1)
{
clientName = cmd->tx_argv[1];
argstart++;
}
}
}
while (cmd->tx_argc > argstart) while (cmd->tx_argc > argstart)
{ {
@ -1133,15 +1116,6 @@ windDoMacro(w, cmd, interactive)
wc = DBWclientID; wc = DBWclientID;
} }
MacroCopy(wc, cmd->tx_argv[argstart]); MacroCopy(wc, cmd->tx_argv[argstart]);
/* If tool name did not previously exist, then add
* it to the list of known tool names, so that it
* can be found later by the "macro" command.
*/
if (DBWButtonHandlerIndex(cmd->tx_argv[argstart]) == -1)
DBWAddButtonHandler(cmd->tx_argv[argstart],
(const cb_database_buttonhandler_t)NULL,
0, (const char *)NULL);
} }
return; return;
} }
@ -1173,53 +1147,26 @@ windDoMacro(w, cmd, interactive)
if (MacroKey(cmd->tx_argv[argstart], &verbose) == 0) if (MacroKey(cmd->tx_argv[argstart], &verbose) == 0)
if (MacroKey(cmd->tx_argv[argstart + 1], &verbose) != 0) if (MacroKey(cmd->tx_argv[argstart + 1], &verbose) != 0)
{
wc = 0;
argstart++;
return; return;
} }
} }
}
/* If a clientName wasn't given, but wc is DBWclientID, then get else
* the clientName from the default button handler. argstart++;
*/
if ((clientName == NULL) && (wc == DBWclientID))
clientName = DBWGetButtonHandler();
if (cmd->tx_argc == argstart) if (cmd->tx_argc == argstart)
{ {
if (clientName == NULL) if (wc == (WindClient)0)
h = NULL;
else
h = HashLookOnly(&MacroClients, (char *)clientName);
if (h == NULL)
{ {
#ifdef MAGIC_WRAPPER TxError("No such client.\n");
Tcl_Obj *lobj;
lobj = Tcl_NewListObj(0, NULL);
#endif
TxError("Cannot get macro list from current window.\n");
#ifndef MAGIC_WRAPPER
TxError("List of known macro clients:\n");
#endif
/* If clientName was not in MacroClients, then what is? */
HashStartSearch(&hs);
while ((h = HashNext(&MacroClients, &hs)) != NULL)
{
char *clientName = h->h_key.h_name;
#ifdef MAGIC_WRAPPER
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewStringObj(clientName, -1));
#else
TxError("%s ", clientName);
#endif
}
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, lobj);
#else
TxError("\n");
#endif
return; return;
} }
h = HashLookOnly(&MacroClients, (char *)wc);
if (h == NULL)
return;
else else
{ {
clienttable = (HashTable *)HashGetValue(h); clienttable = (HashTable *)HashGetValue(h);