DIRECTORY
CD, CDCells, CDDirectory, CDGenerate, CDOps, CDSequencer,
Core, CoreProperties,
CoreGeometry,
IO, PWCore, PWCoreLichen, Rope, RopeList, Sinix, --SoS,-- Sisyph, TerminalIO;
LayoutSchematics:
CEDAR
PROGRAM
IMPORTS CDCells, CDDirectory, CDGenerate, CDOps, CDSequencer, CoreProperties, IO, PWCore, PWCoreLichen, Rope, RopeList, Sinix, --SoS,-- Sisyph, TerminalIO =
BEGIN
ROPE: TYPE = Core.ROPE;
CellType: TYPE = Core.CellType;
Wire: TYPE = Core.Wire;
LayoutSelectedSchematics: CDGenerate.GeneratorProc = {
cx: Sisyph.Context ← Sisyph.Create[design];
selected: CD.Instance; multiple: BOOL;
[selected, multiple] ← CDOps.SelectedInstance[design];
IF selected=NIL THEN {TerminalIO.PutF["\n** No current selection --can't do it.\n"]; RETURN};
IF multiple THEN {TerminalIO.PutF["\n** Multiple instances selected --can't do it.\n"]; RETURN};
IF NOT CDCells.IsCell[selected.ob] THEN {TerminalIO.PutF["\n** Not a cell --can't do it.\n"]; RETURN};
IF NOT Rope.Match["*.sch", CDDirectory.Name[selected.ob]] THEN {TerminalIO.PutF["\n** Not a schematics --can't do it.\n"]; RETURN};
TerminalIO.PutF["\nGenerating layout for %g.\n", IO.rope[CDDirectory.Name[selected.ob]]];
ob ← CheckSch[design, cx, selected.ob].layout;
};
WriteBold:
PROC [before, bold, after:
ROPE ←
NIL] = {
TerminalIO.PutF["%g%l%g%l%g", IO.rope[before], IO.rope["b"], IO.rope[bold], IO.rope["B"], IO.rope[after]];
};
CheckMask:
PROC [design:
CD.Design, layout:
CD.Object]
RETURNS [ok:
BOOL ←
TRUE] = {
name: ROPE ← CDDirectory.Name[layout];
cellType: CellType ← NARROW [Sinix.Extract[layout, PWCore.extractMode! ANY => {WriteBold["Sinix extraction fails for ", name, " .\n"]; GOTO Fails}].result];
TerminalIO.PutRope["**SOS not yet available\n"];
IF SoS.CheckDesignRules [cellType, PWCore.extractMode.decoration, design, NEW [BOOL ← FALSE], FALSE, FALSE, FALSE, NIL] #0
THEN {WriteBold["DRC errors in cell ", name, " .\n"]; GOTO Fails};
EXITS Fails => RETURN [FALSE];
};
CheckSch:
PROC [design:
CD.Design, cx: Sisyph.Context, sch:
CD.Object]
RETURNS [ok:
BOOL ←
TRUE, layout:
CD.Object ←
NIL] = {
name: ROPE ← CDDirectory.Name[sch];
cellType: CellType ← Sisyph.ES[name, cx ! ANY => {WriteBold["Sisyph extraction fails for ", name, ".\n"]; GOTO Fails}];
IF CoreProperties.GetCellTypeProp[cellType, PWCore.layoutAtomProp]=
NIL
THEN {
name ← Rope.Cat[Rope.Substr[name, 0, Rope.Length[name]-4], PWCore.maskSuffix];
layout ← CDDirectory.Fetch[design, name].object;
IF layout=NIL THEN RETURN;
PWCore.DecorateValue[cellType, layout ! ANY => {WriteBold["Decoration fails for ", name, " .\n"]; GOTO Fails}];
} ELSE layout ← PWCore.Layout[cellType ! ANY => {WriteBold["Layout generation fails for ", name, " .\n"]; GOTO Fails}];
PWCoreLichen.Compare[cellType ! ANY => {WriteBold["Comparaison with schematics fails for ", name, " .\n"]; GOTO Fails}];
ok ← CheckMask[design, layout];
EXITS Fails => RETURN [FALSE, layout];
};
Cat:
PROC [list:
LIST
OF
ROPE]
RETURNS [catted:
ROPE ←
NIL] = {
WHILE list#NIL DO catted ← Rope.Cat[catted, " ", list.first]; list ← list.rest ENDLOOP;
};
Cons:
PROC [rope:
ROPE, list:
LIST
OF
ROPE]
RETURNS [
LIST
OF
ROPE] = {
RETURN [IF RopeList.Memb[list, rope] THEN list ELSE CONS [rope, list]];
};
CheckSchematics:
PROC [command: CDSequencer.Command] = {
cx: Sisyph.Context ← Sisyph.Create[command.design];
checked, notSch, notOk: LIST OF ROPE;
sel, notCells: INT ← 0;
TerminalIO.PutF["Check schematics\n"];
FOR instances:
CD.InstanceList ← CDOps.InstList[command.design], instances.rest
WHILE instances#
NIL
DO
obj: CD.Object ← instances.first.ob;
name: ROPE ← CDDirectory.Name[obj];
IF NOT instances.first.selected THEN LOOP;
sel ← sel + 1;
IF NOT CDCells.IsCell[obj] THEN {notCells ← notCells + 1; LOOP};
SELECT
TRUE
FROM
Rope.Match[Rope.Cat["*", PWCore.maskSuffix], name] => {
schName: ROPE ← Rope.Cat[Rope.Substr[name, 0, Rope.Length[name]-5], ".sch"];
sch: CD.Object ← CDDirectory.Fetch[command.design, schName].object;
IF sch#
NIL
AND CDCells.IsCell[sch]
AND ~ RopeList.Memb[checked, schName]
THEN {
checked ← Cons[name, Cons[schName, checked]];
IF NOT CheckSch[command.design, cx, sch].ok THEN notOk ← Cons[name, Cons[schName, notOk]];
} ELSE {
checked ← Cons[name, checked];
IF NOT CheckMask[command.design, obj].ok THEN notOk ← Cons[name, notOk];
};
};
Rope.Match["*.sch", name] => {
IF RopeList.Memb[checked, name] THEN LOOP;
checked ← Cons[name, checked];
IF NOT CheckSch[command.design, cx, obj].ok THEN notOk ← Cons[name, notOk];
};
ENDCASE => {
notSch ← Cons[name, notSch]; LOOP;
};
ENDLOOP;
TerminalIO.PutF["%g instances selected.", IO.int[sel]];
IF notCells#0 THEN TerminalIO.PutF[" %g instances not cells.", IO.int[notCells]];
IF notSch#NIL THEN TerminalIO.PutF["\n%gcells not schematics.\n", IO.rope[Cat[notSch]]];
TerminalIO.PutF[" %g schematics checked.\n", IO.int[RopeList.Length[checked]]];
IF notOk#NIL THEN WriteBold["", Cat[notOk], " not ok.\n"];
IF notOk=NIL AND notCells=0 THEN WriteBold["", "OK", ".\n"];
};
[] ← CDGenerate.Register[context: CDGenerate.AssertContext["PatchWork"], key: "Layout selected schematics", generator: LayoutSelectedSchematics, cache: FALSE];
[] ← CDGenerate.Register[context: CDGenerate.AssertContext["USER"], key: "Layout selected schematics", generator: LayoutSelectedSchematics, cache: FALSE];
CDMenus.ImplementEntryCommand[$ProgramMenu, "Check selected Schematics", CheckSchematics];
CDSequencer.ImplementCommand[key: $DAUserCheckSchematics, proc: CheckSchematics, queue: doQueue];
END.