InitHandle:
PROC[cmd: Commander.Handle]
RETURNS[h: Handle] = {
list: LIST OF IO.ROPE ← CommandTool.ParseToList[cmd].list;
schNm: IO.ROPE ← NIL;
designNm: IO.ROPE ← NIL;
h ← NEW[HandleRec ← []];
FOR list ← list, list.rest
WHILE list#
NIL
DO
SELECT list.first.Fetch[]
FROM
'- =>
SELECT list.first.Fetch[1]
FROM
'f, 'F => {h.lichen ← FALSE; h.rose ← FALSE; h.fromFile ← TRUE};
'l, 'L => h.lichen ← FALSE;
's, 'S => h.static ← FALSE;
'm,'M => h.mint ← FALSE;
'r, 'R => h.rose ← FALSE;
'c, 'C => h.conn ← FALSE;
'd, 'D => h.drc ← FALSE;
ENDCASE => {cmd.out.PutRope["\nUnknown switch\n"]; RETURN[NIL]};
ENDCASE => {
IF h.designNm=
NIL
THEN h.designNm ← list.first
ELSE
IF schNm=
NIL
THEN schNm ← list.first
ELSE {cmd.out.PutRope["\nMore than 2 arguments\n"]; RETURN[NIL]}};
ENDLOOP;
IF h.fromFile THEN {h.schNm ← h.designNm; h.designNm ← NIL; RETURN[h]};
h.schDesign ← GetDesign[h.designNm];
IF h.schDesign=
NIL
THEN
{cmd.out.PutF["\nCan't find design %g\n", IO.rope[h.designNm]]; RETURN[NIL]};
CDCellsInteractions.PopToTopLevel[h.schDesign];
IF schNm#
NIL
THEN {
h.schNm ← schNm;
IF CDDirectory.Fetch[h.schDesign, h.schNm]#NIL THEN RETURN[h];
h.schNm ← schNm.Cat[".icon"];
IF CDDirectory.Fetch[h.schDesign, h.schNm]#NIL THEN RETURN[h];
h.schNm ← schNm.Cat[".sch"];
IF CDDirectory.Fetch[h.schDesign, h.schNm]#NIL THEN RETURN[h];
cmd.out.PutF["\nCan't find cell %g\n", IO.rope[schNm]]; RETURN[NIL]}};
MintCheck:
PROC[cell: Core.CellType, useLayoutIfPresent:
BOOL ←
TRUE] = {
GetNode:
PROC[name:
IO.
ROPE]
RETURNS[node: Mint.Node ←
NIL] = {
IF CoreOps.FindWire[ct.public, name]#
NIL
THEN
node ← Mint.NodeFromRope[Rope.Cat["public.", name], circuit]};
GenClkNodeList:
PROC[names:
LIST
OF
IO.
ROPE]
RETURNS[list: Mint.NodeList] = {
IF names=
NIL
THEN
RETURN[
NIL]
ELSE {
hiNm: IO.ROPE ← names.first;
loNm: IO.ROPE ← Rope.Cat["n", names.first];
node: Mint.Node;
list ← GenClkNodeList[names.rest];
IF (node ← GetNode[hiNm])#
NIL
THEN {
Mint.SetNode[node, TRUE];
log.PutF["Mint Clock: %g\n", IO.rope[hiNm]]; list ← CONS[node, list]};
IF (node ← GetNode[loNm])#
NIL
THEN {
Mint.SetNode[node, FALSE];
log.PutF["Mint Clock: %g\n", IO.rope[loNm]]; list ← CONS[node, list]} }};
InitCT:
PROC
RETURNS[Core.CellType] = {
ct: Core.CellType ← IF layout THEN PWCore.LayoutInfo[cell].extractedCT ELSE cell;
IF layout
THEN {
MarkMintOneWayTransistors[ct]; this doen't work
The transistor celltype (and therefore the name) gets shared
WriteCapa.WriteWireCapa[ct, $cmosB]};
RETURN[ct]};
name: IO.ROPE ← CoreOps.GetCellTypeName[cell];
layout: BOOL ← useLayoutIfPresent AND HasLayout[cell];
ct: Core.CellType ← InitCT[];
defaultCapa: REAL ← IF layout THEN 0.0 ELSE mintSchNodeCapa;
circuit: Mint.Circuit ← Mint.CreateCircuit[ct, layout, defaultCapa];
clockNames: LIST OF IO.ROPE ← LIST["Clock","Clk","Ck","CK","PhA","PhB","phA","phB"];
clocks: Mint.NodeList ← GenClkNodeList[clockNames];
vddNode: Mint.Node ← GetNode["Vdd"];
gndNode: Mint.Node ← GetNode["Gnd"];
slowNodes: Mint.PathArray;
lastTime: Mint.ps;
veryLastTime: Mint.ps;
log.PutF["\nMint Check of %g %g.\n",
IO.rope[CoreOps.GetCellTypeName[cell]],
IO.rope[IF layout THEN "layout" ELSE "source"]];
IF vddNode=
NIL
THEN
{log.PutF["*** Cell: %g does not have a Vdd connection.\n", IO.rope[name]]; RETURN};
IF gndNode=
NIL
THEN
{log.PutF["*** Cell: %g does not have a Gnd connection.\n", IO.rope[name]]; RETURN};
Mint.SetNode[vddNode, TRUE];
Mint.SetNode[gndNode, FALSE];
Mint.InputData[circuit, LIST[gndNode, vddNode], layout, defaultCapa];
Mint.CheckLibrary[circuit];
Mint.OutputResults[circuit];
lastTime ← Mint.RecordPaths[circuit, clocks];
log.PutF["Longest time: %4.1fns\n", IO.real[lastTime/1000.0]];
[veryLastTime, slowNodes] ← Mint.FindSlowestPaths[circuit, 8, TRUE];
Mint.PrintPathArray[slowNodes, circuit];
Mint.KillCircuit[circuit]};
StaticCheck:
PROC[ref: Core.CellType, useLayoutIfPresent:
BOOL ←
TRUE] = {
layout: BOOL ← useLayoutIfPresent AND HasLayout[ref];
cell: Core.CellType ←
IF layout
THEN PWCore.LayoutInfo[ref].extractedCT
ELSE ref;
log.PutF["\nStatic Check of %g %g.\n",
IO.rope[CoreOps.GetCellTypeName[ref]],
IO.rope[IF layout THEN "layout" ELSE "source"]];
Static.CountLeafConnections[cell, Static.CheckCount]};
DRCDesign:
PROC[h: Handle] = {
rules: IO.ROPE ← "VTI";
inst: CD.Instance;
reportMsg: IO.ROPE ← NIL;
hasErrors: BOOL ← TRUE;
IF ~enableDRC THEN RETURN;
[h.layDesign, inst] ← MakeDRCTestObject[h];
IF h.layDesign=NIL THEN {log.PutRope["No layout to DRC\n"]; RETURN};
[reportMsg, hasErrors] ← DraculaOps.DRCInstance[inst, h.layDesign, rules];
IF hasErrors
THEN log.PutF["*** DRC Errors\n %g\n", IO.rope[reportMsg]]
ELSE log.PutF["No DRC Errors\n %g\n", IO.rope[reportMsg]]};
DRCDesignFile:
PROC[file:
IO.
ROPE] = {
design: CD.Design ← GetDesign[file];
inst: CD.Instance ← CDOps.InstList[design].first;
rules: IO.ROPE ← "VTI";
reportMsg: IO.ROPE ← NIL;
hasErrors: BOOL ← TRUE;
[reportMsg, hasErrors] ← DraculaOps.DRCInstance[inst, design, rules];
IF hasErrors
THEN log.PutF["*** DRC Errors\n %g\n", IO.rope[reportMsg]]
ELSE log.PutF["No DRC Errors\n %g\n", IO.rope[reportMsg]]};
MakeDRCTestObject:
PROC[h: Handle]
RETURNS[design:
CD.Design, inst:
CD.Instance] = {
TwoObjects: TYPE = RECORD[o0, o1: CD.Object, b: BOOL];
viewer: ViewerClasses.Viewer;
area: REAL ← 0.0;
tech: CD.Technology ← CMosB.cmosB;
sep: INT ← tech.lambda*16;
maxX: INT ← 0;
pos: CD.Position ← [0, 0];
height: INT;
insts: CD.InstanceList;
object: CD.Object;
objs: LIST OF CD.Object;
design ← CDOps.CreateDesign[tech];
CDOps.SetMutability[design];
viewer ← CDViewer.CreateViewer[design, FALSE];
FOR list: Cells ← h.cells, list.rest
WHILE list #
NIL
DO
IF ~HasLayout[list.first] THEN LOOP;
objs ← CONS[PWCore.LayoutInfo[list.first].layout, objs] ENDLOOP;
IF objs=NIL THEN RETURN[NIL, NIL];
DO
chngd: BOOL ← FALSE;
FOR list:
LIST
OF
CD.Object ← objs, list.rest
WHILE list.rest#
NIL
DO
size1: CD.Position ← CD.InterestSize[list.first];
size2: CD.Position ← CD.InterestSize[list.rest.first];
SELECT Basics.CompareInt[ size1.x, size2.x]
FROM
less => LOOP;
greater => [list.first, list.rest.first, chngd] ← TwoObjects[list.rest.first, list.first, TRUE];
ENDCASE =>
SELECT Basics.CompareInt[ size1.y, size2.y]
FROM
less => LOOP;
greater => [list.first, list.rest.first, chngd]←TwoObjects[list.rest.first, list.first, TRUE];
ENDCASE ENDLOOP;
IF ~chngd THEN EXIT ENDLOOP;
FOR list:
LIST
OF
CD.Object ← objs, list.rest
WHILE list#
NIL
DO
size1: CD.Position ← CD.InterestSize[list.first];
area ← area + (size1.x+sep) * (size1.y+sep) ENDLOOP;
height ← Real.Fix[RealFns.SqRt[area]];
FOR list:
LIST
OF
CD.Object ← objs, list.rest
WHILE list#
NIL
DO
size: CD.Position ← CD.InterestSize[list.first];
off: CD.Position ← CDBasics.SubPoints[pos, CDBasics.BaseOfRect[CD.InterestRect[list.first]]];
insts ← CONS[NEW[CD.InstanceRep ← [list.first, [off]]], insts];
pos ← [pos.x, pos.y+size.y+sep];
maxX ← MAX[maxX, size.x];
IF pos.y>height THEN {pos.x ← pos.x + maxX + sep; pos.y ← 0; maxX ← 0};
ENDLOOP;
object ← PW.CreateCell[insts, , "DRCCheck"];
IF ~CDDirectory.Include[design, object, "DRCCheck"] THEN ERROR;
inst ← CDOps.IncludeObject[design, object];
inst.selected ← TRUE};