Merge branch 'master' into magic-8.2
This commit is contained in:
commit
c77dd1fb49
|
|
@ -3182,7 +3182,6 @@ CmdDrc(w, cmd)
|
||||||
bool doforall = FALSE;
|
bool doforall = FALSE;
|
||||||
bool dolist = FALSE;
|
bool dolist = FALSE;
|
||||||
int count_total;
|
int count_total;
|
||||||
DRCCountList *dcl, *dclsrch;
|
|
||||||
int argc = cmd->tx_argc;
|
int argc = cmd->tx_argc;
|
||||||
char **argv = cmd->tx_argv;
|
char **argv = cmd->tx_argv;
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
|
|
@ -3199,7 +3198,7 @@ CmdDrc(w, cmd)
|
||||||
"check recheck area under box in all cells",
|
"check recheck area under box in all cells",
|
||||||
"count count error tiles in each cell under box",
|
"count count error tiles in each cell under box",
|
||||||
"euclidean on|off enable/disable Euclidean geometry checking",
|
"euclidean on|off enable/disable Euclidean geometry checking",
|
||||||
"find [nth] locate next (or nth) error in the layout",
|
"find [nth] locate next (or nth) error in the layout",
|
||||||
"help print this help information",
|
"help print this help information",
|
||||||
"off turn off background checker",
|
"off turn off background checker",
|
||||||
"on reenable background checker",
|
"on reenable background checker",
|
||||||
|
|
@ -3305,15 +3304,6 @@ CmdDrc(w, cmd)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COUNT:
|
case COUNT:
|
||||||
count_total = -1;
|
|
||||||
if (argc == 3)
|
|
||||||
if (!strncmp(argv[2], "total", 5))
|
|
||||||
count_total = 0;
|
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
|
||||||
if (count_total == -1) lobj = Tcl_NewListObj(0, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((window = w) == NULL)
|
if ((window = w) == NULL)
|
||||||
{
|
{
|
||||||
window = ToolGetBoxWindow(&rootArea, (int *) NULL);
|
window = ToolGetBoxWindow(&rootArea, (int *) NULL);
|
||||||
|
|
@ -3323,61 +3313,44 @@ CmdDrc(w, cmd)
|
||||||
rootArea = w->w_surfaceArea;
|
rootArea = w->w_surfaceArea;
|
||||||
|
|
||||||
rootUse = (CellUse *) window->w_surfaceID;
|
rootUse = (CellUse *) window->w_surfaceID;
|
||||||
dcl = DRCCount(rootUse, &rootArea);
|
count_total = DRCCount(rootUse, &rootArea);
|
||||||
while (dcl != NULL)
|
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
if (dolist)
|
||||||
{
|
{
|
||||||
if (count_total >= 0)
|
lobj = Tcl_NewListObj(0, NULL);
|
||||||
count_total += dcl->dcl_count;
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
else
|
Tcl_NewStringObj(rootUse->cu_def->cd_name, -1));
|
||||||
{
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
#ifdef MAGIC_WRAPPER
|
Tcl_NewIntObj(count_total));
|
||||||
if (dolist)
|
|
||||||
{
|
|
||||||
Tcl_Obj *pobj = Tcl_NewListObj(0, NULL);
|
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
|
||||||
Tcl_NewStringObj(dcl->dcl_def->cd_name, -1));
|
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
|
||||||
Tcl_NewIntObj(dcl->dcl_count));
|
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (dcl->dcl_count > 1)
|
|
||||||
TxPrintf("Cell %s has %d error tiles.\n",
|
|
||||||
dcl->dcl_def->cd_name, dcl->dcl_count);
|
|
||||||
else if (dcl->dcl_count == 1)
|
|
||||||
TxPrintf("Cell %s has just one error tile.\n",
|
|
||||||
dcl->dcl_def->cd_name);
|
|
||||||
#ifdef MAGIC_WRAPPER
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
freeMagic((char *)dcl);
|
|
||||||
dcl = dcl->dcl_next;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (count_total > 1)
|
||||||
|
TxPrintf("Cell %s has %d error tiles.\n",
|
||||||
|
rootUse->cu_def->cd_name, count_total);
|
||||||
|
else if (count_total == 1)
|
||||||
|
TxPrintf("Cell %s has just one error tile.\n",
|
||||||
|
rootUse->cu_def->cd_name);
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
if (count_total >= 0)
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
if (doforall)
|
||||||
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
|
else if (count_total >= 0)
|
||||||
{
|
{
|
||||||
if (dolist)
|
if (dolist)
|
||||||
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(count_total));
|
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(count_total));
|
||||||
else
|
else
|
||||||
{
|
TxPrintf("Total DRC errors found: %d\n", count_total);
|
||||||
if ((DRCBackGround != DRC_SET_OFF) && (count_total == -1))
|
|
||||||
count_total = 0;
|
|
||||||
if (count_total >= 0)
|
|
||||||
TxPrintf("Total DRC errors found: %d\n", count_total);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (dolist)
|
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
|
||||||
#else
|
#else
|
||||||
if ((DRCBackGround != DRC_SET_OFF) && (count_total == -1))
|
TxPrintf("Total DRC errors found: %d\n", count_total);
|
||||||
count_total = 0;
|
|
||||||
if (count_total >= 0)
|
|
||||||
TxPrintf("Total DRC errors found: %d\n", count_total);
|
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -343,7 +343,7 @@ drcListallError (celldef, rect, cptr, scx)
|
||||||
area = &scx->scx_area;
|
area = &scx->scx_area;
|
||||||
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
||||||
DRCErrorCount += 1;
|
DRCErrorCount += 1;
|
||||||
h = HashFind(&DRCErrorTable, cptr->drcc_why);
|
h = HashFind(&DRCErrorTable, drcSubstitute(cptr));
|
||||||
lobj = (Tcl_Obj *) HashGetValue(h);
|
lobj = (Tcl_Obj *) HashGetValue(h);
|
||||||
if (lobj == NULL)
|
if (lobj == NULL)
|
||||||
lobj = Tcl_NewListObj(0, NULL);
|
lobj = Tcl_NewListObj(0, NULL);
|
||||||
|
|
@ -747,111 +747,42 @@ drcCheckFunc(scx, cdarg)
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DRCCountList *
|
int
|
||||||
DRCCount(use, area)
|
DRCCount(use, area)
|
||||||
CellUse *use; /* Top-level use of hierarchy. */
|
CellUse *use; /* Top-level use of hierarchy. */
|
||||||
Rect *area; /* Area in which violations are counted. */
|
Rect *area; /* Area in which violations are counted. */
|
||||||
{
|
{
|
||||||
DRCCountList *dcl, *newdcl;
|
|
||||||
HashTable dupTable;
|
|
||||||
HashEntry *he;
|
|
||||||
HashSearch hs;
|
|
||||||
int count;
|
int count;
|
||||||
SearchContext scx;
|
SearchContext scx;
|
||||||
extern int drcCountFunc(); /* Forward reference. */
|
CellDef *def;
|
||||||
|
extern int drcCountFunc2();
|
||||||
/* Use a hash table to make sure that we don't output information
|
|
||||||
* for any cell more than once.
|
|
||||||
*/
|
|
||||||
|
|
||||||
HashInit(&dupTable, 16, HT_WORDKEYS);
|
|
||||||
|
|
||||||
scx.scx_use = use;
|
scx.scx_use = use;
|
||||||
scx.scx_x = use->cu_xlo;
|
scx.scx_x = use->cu_xlo;
|
||||||
scx.scx_y = use->cu_ylo;
|
scx.scx_y = use->cu_ylo;
|
||||||
scx.scx_area = *area;
|
scx.scx_area = *area;
|
||||||
scx.scx_trans = GeoIdentityTransform;
|
scx.scx_trans = GeoIdentityTransform;
|
||||||
(void) drcCountFunc(&scx, &dupTable);
|
|
||||||
|
|
||||||
/* Create the list from the hash table */
|
def = use->cu_def;
|
||||||
|
|
||||||
dcl = NULL;
|
|
||||||
if (dupTable.ht_table != (HashEntry **) NULL)
|
|
||||||
{
|
|
||||||
HashStartSearch(&hs);
|
|
||||||
while ((he = HashNext(&dupTable, &hs)) != (HashEntry *)NULL)
|
|
||||||
{
|
|
||||||
count = (spointertype)HashGetValue(he);
|
|
||||||
if (count > 1)
|
|
||||||
{
|
|
||||||
newdcl = (DRCCountList *)mallocMagic(sizeof(DRCCountList));
|
|
||||||
newdcl->dcl_count = count - 1;
|
|
||||||
newdcl->dcl_def = (CellDef *)he->h_key.h_ptr;
|
|
||||||
newdcl->dcl_next = dcl;
|
|
||||||
dcl = newdcl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
HashKill(&dupTable);
|
|
||||||
return dcl;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
drcCountFunc(scx, dupTable)
|
|
||||||
SearchContext *scx;
|
|
||||||
HashTable *dupTable; /* Passed as client data, used to
|
|
||||||
* avoid searching any cell twice.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
int count;
|
|
||||||
HashEntry *h;
|
|
||||||
CellDef *def;
|
|
||||||
extern int drcCountFunc2();
|
|
||||||
|
|
||||||
/* If we've already seen this cell definition before, then skip it
|
|
||||||
* now.
|
|
||||||
*/
|
|
||||||
|
|
||||||
def = scx->scx_use->cu_def;
|
|
||||||
h = HashFind(dupTable, (char *)def);
|
|
||||||
if (HashGetValue(h) != 0) goto done;
|
|
||||||
HashSetValue(h, 1);
|
|
||||||
|
|
||||||
/* Count errors in this cell definition by scanning the error plane. */
|
/* Count errors in this cell definition by scanning the error plane. */
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
(void) DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR],
|
(void) DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR],
|
||||||
&def->cd_bbox, &DBAllButSpaceBits, drcCountFunc2, (ClientData) &count);
|
&def->cd_bbox, &DBAllButSpaceBits, drcCountFunc2, (ClientData)(&count));
|
||||||
HashSetValue(h, (spointertype)count + 1);
|
|
||||||
|
|
||||||
/* Ignore children that have not been loaded---we will only report */
|
return count;
|
||||||
/* errors that can be seen. This avoids immediately loading and */
|
|
||||||
/* drc processing large layouts simply because we asked for an */
|
|
||||||
/* error count. When the cell is loaded, drc will be checked */
|
|
||||||
/* anyway, and the count can be updated in response to that check. */
|
|
||||||
|
|
||||||
if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) return 0;
|
|
||||||
|
|
||||||
/* New behavior: Don't search children, instead propagate errors up. */
|
|
||||||
/* (void) DBCellSrArea(scx, drcCountFunc, (ClientData) dupTable); */
|
|
||||||
|
|
||||||
/* As a special performance hack, if the complete cell area is
|
|
||||||
* handled here, don't bother to look at any more array elements.
|
|
||||||
*/
|
|
||||||
|
|
||||||
done: if (GEO_SURROUND(&scx->scx_area, &def->cd_bbox)) return 2;
|
|
||||||
else return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
drcCountFunc2(tile, pCount)
|
drcCountFunc2(tile, countptr)
|
||||||
Tile *tile; /* Tile found in error plane. */
|
Tile *tile; /* Tile found in error plane. */
|
||||||
int *pCount; /* Address of count word. */
|
int *countptr; /* Address of count word. */
|
||||||
{
|
{
|
||||||
if (TiGetType(tile) != (TileType) TT_SPACE) *pCount += 1;
|
if (TiGetType(tile) != (TileType) TT_SPACE) (*countptr)++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
|
||||||
11
drc/drc.h
11
drc/drc.h
|
|
@ -125,15 +125,6 @@ typedef struct drcpendingcookie
|
||||||
struct drcpendingcookie *dpc_next;
|
struct drcpendingcookie *dpc_next;
|
||||||
} DRCPendingCookie;
|
} DRCPendingCookie;
|
||||||
|
|
||||||
/* Structure used to pass back lists of cell definitions and error tile counts */
|
|
||||||
|
|
||||||
typedef struct drccountlist
|
|
||||||
{
|
|
||||||
CellDef *dcl_def;
|
|
||||||
int dcl_count;
|
|
||||||
struct drccountlist *dcl_next;
|
|
||||||
} DRCCountList;
|
|
||||||
|
|
||||||
/* Structure used to keep information about the current DRC style */
|
/* Structure used to keep information about the current DRC style */
|
||||||
|
|
||||||
typedef struct drckeep
|
typedef struct drckeep
|
||||||
|
|
@ -267,7 +258,7 @@ extern void DRCPrintRulesTable();
|
||||||
extern void DRCWhy();
|
extern void DRCWhy();
|
||||||
extern void DRCPrintStats();
|
extern void DRCPrintStats();
|
||||||
extern void DRCCheck();
|
extern void DRCCheck();
|
||||||
extern DRCCountList *DRCCount();
|
extern int DRCCount();
|
||||||
extern int DRCFind();
|
extern int DRCFind();
|
||||||
extern void DRCCatchUp();
|
extern void DRCCatchUp();
|
||||||
extern bool DRCFindInteractions();
|
extern bool DRCFindInteractions();
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ TCL_FILES = \
|
||||||
console.tcl \
|
console.tcl \
|
||||||
techbuilder.tcl \
|
techbuilder.tcl \
|
||||||
cellmgr.tcl \
|
cellmgr.tcl \
|
||||||
|
drcmgr.tcl \
|
||||||
libmgr.tcl \
|
libmgr.tcl \
|
||||||
texthelper.tcl \
|
texthelper.tcl \
|
||||||
tools.tcl \
|
tools.tcl \
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,195 @@
|
||||||
|
#------------------------------------------------------
|
||||||
|
# Script for generating the "DRC manager" window.
|
||||||
|
#
|
||||||
|
# Written by Tim Edwards, November 2019
|
||||||
|
#------------------------------------------------------
|
||||||
|
|
||||||
|
global Opts
|
||||||
|
|
||||||
|
if {$::tk_version >= 8.5} {
|
||||||
|
|
||||||
|
set Opts(drcmgr) 0
|
||||||
|
|
||||||
|
magic::tag addpath "magic::drcmanager"
|
||||||
|
magic::tag path "magic::drcmanager"
|
||||||
|
|
||||||
|
# Callback to the DRC manager
|
||||||
|
|
||||||
|
proc magic::drccallback {command} {
|
||||||
|
global Opts
|
||||||
|
|
||||||
|
set fid [.drcmgr.box.view selection]
|
||||||
|
if {[.drcmgr.box.view parent $fid] == {}} {
|
||||||
|
set value {}
|
||||||
|
} else {
|
||||||
|
set value [.drcmgr.box.view item $fid -text]
|
||||||
|
}
|
||||||
|
|
||||||
|
if { $Opts(target) == "default" } {
|
||||||
|
set winlist [magic::windownames layout]
|
||||||
|
set winname [lindex $winlist 0]
|
||||||
|
} else {
|
||||||
|
set winname $Opts(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch $command {
|
||||||
|
update {
|
||||||
|
magic::drcmanager update
|
||||||
|
}
|
||||||
|
last {
|
||||||
|
.drcmgr.box.view selection set [.drcmgr.box.view prev $fid]
|
||||||
|
magic::drccallback zoom
|
||||||
|
}
|
||||||
|
next {
|
||||||
|
.drcmgr.box.view selection set [.drcmgr.box.view next $fid]
|
||||||
|
magic::drccallback zoom
|
||||||
|
}
|
||||||
|
zoom {
|
||||||
|
if {$value != {}} {
|
||||||
|
set snaptype [snap]
|
||||||
|
snap internal
|
||||||
|
box values {*}$value
|
||||||
|
magic::suspendall
|
||||||
|
magic::findbox zoom
|
||||||
|
magic::zoom 2
|
||||||
|
magic::resumeall
|
||||||
|
snap $snaptype
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#----------------------------------------------
|
||||||
|
# Create the DRC manager window
|
||||||
|
#----------------------------------------------
|
||||||
|
|
||||||
|
proc magic::makedrcmanager { mgrpath } {
|
||||||
|
global filtered
|
||||||
|
|
||||||
|
set filtered 1
|
||||||
|
toplevel ${mgrpath}
|
||||||
|
wm withdraw ${mgrpath}
|
||||||
|
frame ${mgrpath}.actionbar
|
||||||
|
frame ${mgrpath}.box
|
||||||
|
frame ${mgrpath}.target
|
||||||
|
|
||||||
|
ttk::treeview ${mgrpath}.box.view -selectmode browse \
|
||||||
|
-yscrollcommand "${mgrpath}.box.vert set" \
|
||||||
|
-xscrollcommand "${mgrpath}.box.vert set" \
|
||||||
|
-columns 0
|
||||||
|
scrollbar ${mgrpath}.box.vert -orient vertical -command "${mgrpath}.box.view yview"
|
||||||
|
${mgrpath}.box.view heading #0 -text "DRC Rule"
|
||||||
|
${mgrpath}.box.view heading 0 -text "Error Number"
|
||||||
|
${mgrpath}.box.view column #0 -stretch true -anchor w -minwidth 350
|
||||||
|
${mgrpath}.box.view column 0 -stretch false -anchor center -minwidth 50
|
||||||
|
|
||||||
|
grid columnconfigure ${mgrpath}.box 0 -weight 1 -minsize 500
|
||||||
|
grid columnconfigure ${mgrpath}.box 1 -weight 0
|
||||||
|
grid rowconfigure ${mgrpath}.box 0 -weight 1
|
||||||
|
grid ${mgrpath}.box.view -row 0 -column 0 -sticky news
|
||||||
|
grid ${mgrpath}.box.vert -row 0 -column 1 -sticky news
|
||||||
|
|
||||||
|
grid rowconfigure ${mgrpath} 0 -weight 0
|
||||||
|
grid rowconfigure ${mgrpath} 1 -weight 1
|
||||||
|
grid rowconfigure ${mgrpath} 2 -weight 0
|
||||||
|
grid columnconfigure ${mgrpath} 0 -weight 1
|
||||||
|
grid ${mgrpath}.actionbar -row 0 -column 0 -sticky news
|
||||||
|
grid ${mgrpath}.box -row 1 -column 0 -sticky news
|
||||||
|
grid ${mgrpath}.target -row 2 -column 0 -sticky news
|
||||||
|
|
||||||
|
button ${mgrpath}.actionbar.update -text "Update" \
|
||||||
|
-command {magic::drccallback update}
|
||||||
|
button ${mgrpath}.actionbar.last -text "Last" -command {magic::drccallback last}
|
||||||
|
button ${mgrpath}.actionbar.next -text "Next" -command {magic::drccallback next}
|
||||||
|
button ${mgrpath}.actionbar.zoom -text "Zoom" -command {magic::drccallback zoom}
|
||||||
|
|
||||||
|
pack ${mgrpath}.actionbar.update -side left
|
||||||
|
pack ${mgrpath}.actionbar.last -side left
|
||||||
|
pack ${mgrpath}.actionbar.next -side left
|
||||||
|
pack ${mgrpath}.actionbar.zoom -side right
|
||||||
|
|
||||||
|
label ${mgrpath}.target.name -text "Target window:"
|
||||||
|
menubutton ${mgrpath}.target.list -text "default" \
|
||||||
|
-menu ${mgrpath}.target.list.winmenu
|
||||||
|
|
||||||
|
pack ${mgrpath}.target.name -side left -padx 2
|
||||||
|
pack ${mgrpath}.target.list -side left
|
||||||
|
|
||||||
|
#Withdraw the window when the close button is pressed
|
||||||
|
wm protocol ${mgrpath} WM_DELETE_WINDOW "set Opts(drcmgr) 0 ; \
|
||||||
|
wm withdraw ${mgrpath}"
|
||||||
|
|
||||||
|
#-------------------------------------------------
|
||||||
|
# Callback when a treeview item is opened
|
||||||
|
#-------------------------------------------------
|
||||||
|
|
||||||
|
bind .drcmgr <<TreeviewOpen>> {
|
||||||
|
set s [.drcmgr.box.view selection]
|
||||||
|
foreach i [.drcmgr.box.view children $s] {
|
||||||
|
# NOTE: not hierarchical
|
||||||
|
.drcmgr.box.view item $i -open false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bind .drcmgr <<TreeviewClose>> {
|
||||||
|
set s [.drcmgr.box.view selection]
|
||||||
|
foreach i [.drcmgr.box.view children $s] {
|
||||||
|
foreach j [.drcmgr.box.view children $i] {
|
||||||
|
.drcmgr.box.view delete $j
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proc magic::adddrcentry {key valuelist} {
|
||||||
|
set id [.drcmgr.box.view insert {} end -text ${key}]
|
||||||
|
set i 0
|
||||||
|
foreach value $valuelist {
|
||||||
|
.drcmgr.box.view insert $id end -text "$value"
|
||||||
|
incr i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#--------------------------------------------------------------
|
||||||
|
# The cell manager window main callback function
|
||||||
|
#--------------------------------------------------------------
|
||||||
|
|
||||||
|
proc magic::drcmanager {{option "update"}} {
|
||||||
|
global editstack
|
||||||
|
global CAD_ROOT
|
||||||
|
|
||||||
|
# Check for existence of the manager widget
|
||||||
|
if {[catch {wm state .drcmgr}]} {
|
||||||
|
if {$option == "create"} {
|
||||||
|
magic::makedrcmanager .drcmgr
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} elseif { $option == "create"} {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
magic::suspendall
|
||||||
|
|
||||||
|
# Get existing list of error classes and remove them
|
||||||
|
set currules [.drcmgr.box.view children {}]
|
||||||
|
foreach rule $currules {
|
||||||
|
.drcmgr.box.view delete ${rule}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run DRC
|
||||||
|
select top cell
|
||||||
|
set drcdict [dict create {*}[drc listall why]]
|
||||||
|
|
||||||
|
# set first true
|
||||||
|
dict for {key value} $drcdict {
|
||||||
|
magic::adddrcentry ${key} ${value}
|
||||||
|
# .drcmgr.box.view item ${key} -open $first
|
||||||
|
# set first false
|
||||||
|
}
|
||||||
|
magic::resumeall
|
||||||
|
}
|
||||||
|
|
||||||
|
} ;# (if Tk version 8.5)
|
||||||
|
|
||||||
|
|
@ -367,6 +367,10 @@ catch {source ${CAD_ROOT}/magic/tcl/cellmgr.tcl}
|
||||||
|
|
||||||
catch {source ${CAD_ROOT}/magic/tcl/libmgr.tcl}
|
catch {source ${CAD_ROOT}/magic/tcl/libmgr.tcl}
|
||||||
|
|
||||||
|
# Generate the DRC manager
|
||||||
|
|
||||||
|
catch {source ${CAD_ROOT}/magic/tcl/drcmgr.tcl}
|
||||||
|
|
||||||
# Generate the text helper
|
# Generate the text helper
|
||||||
|
|
||||||
catch {source ${CAD_ROOT}/magic/tcl/texthelper.tcl}
|
catch {source ${CAD_ROOT}/magic/tcl/texthelper.tcl}
|
||||||
|
|
@ -1404,6 +1408,13 @@ proc magic::openwrapper {{cell ""} {framename ""}} {
|
||||||
} else { \
|
} else { \
|
||||||
wm withdraw .techmgr } }]
|
wm withdraw .techmgr } }]
|
||||||
|
|
||||||
|
$m add check -label "DRC Manager" -variable Opts(drcmgr) \
|
||||||
|
-command [subst { magic::drcmanager create; \
|
||||||
|
if { \$Opts(drcmgr) } { \
|
||||||
|
wm deiconify .drcmgr ; raise .drcmgr \
|
||||||
|
} else { \
|
||||||
|
wm withdraw .drcmgr } }]
|
||||||
|
|
||||||
$m add check -label "Netlist Window" -variable Opts(netlist) \
|
$m add check -label "Netlist Window" -variable Opts(netlist) \
|
||||||
-command [subst { if { \[windownames netlist\] != {}} { \
|
-command [subst { if { \[windownames netlist\] != {}} { \
|
||||||
set Opts(netlist) 0 ; closewindow \[windownames netlist\] \
|
set Opts(netlist) 0 ; closewindow \[windownames netlist\] \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue