DAUserCmdsImpl.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Last Edited by: Louis Monier April 28, 1988 6:02:27 pm PDT
Last Edited by: Christian Jacobi, January 7, 1987 11:41:28 am PST
Jean-Marc Frailong May 1, 1988 4:36:06 pm PDT
Barth, October 15, 1987 11:35:03 am PDT
Bertrand Serlet April 17, 1988 5:25:49 pm PDT
DIRECTORY
CD, CDSequencer, CDSequencerExtras, CDViewer,
Core, CoreCDUser, CoreFlat, CoreGeometry, CoreOps, CoreProperties,
DAUser,
ExtractOps,
IO, MessageWindow,
Ports,
PW, PWCore, RefTab, Rope, Rosemary, RosemaryUser, Sisyph, Static, TerminalIO;
DAUserCmdsImpl:
CEDAR
PROGRAM
IMPORTS CD, CDSequencerExtras, CDViewer, CoreCDUser, CoreFlat, CoreGeometry, CoreOps, CoreProperties, ExtractOps, IO, MessageWindow, Ports, PW, PWCore, RefTab, Rope, Rosemary, RosemaryUser, Sisyph, Static, TerminalIO
EXPORTS DAUser
= BEGIN
Decorations
layoutDecoration: CoreGeometry.Decoration = PWCore.extractMode.decoration;
schematicDecoration: CoreGeometry.Decoration = Sisyph.mode.decoration;
Layout
GenerateLayout:
PROC [comm: CDSequencer.Command] = {
LayoutOne: CoreCDUser.EachRootCellTypeProc ~ {
layout: CD.Object = PWCore.Layout[root];
design: CD.Design;
TerminalIO.PutF["Generating layout for %g.\n", IO.rope[CoreOps.GetCellTypeName[root]]];
design ← PW.Draw[layout];
design.name ← CD.Describe[layout];
};
[] ← CoreCDUser.EnumerateSelectedCellTypes[comm.design, LayoutOne];
};
shellWithTexts: BOOL ← TRUE; -- this may be modified using the interpreter to have raw shells
ShowShell:
PROC [comm: CDSequencer.Command] = {
OneShell: CoreCDUser.EachRootCellTypeProc ~ {
HasLayoutPins: CoreOps.EachWireProc ~ {
Force enumeration to return TRUE iff some public has layout geometry
quit ← CoreGeometry.HasPins[layoutDecoration, wire];
};
rootName: Rope.ROPE = CoreOps.GetCellTypeName[root];
IF CoreCDUser.GetRootCellTypeDecoration[root]=schematicDecoration THEN [] ← PWCore.Layout[root];
IF CoreOps.VisitWire[root.public, HasLayoutPins]
THEN {
[] ← PW.Draw[CoreGeometry.CreateShell[layoutDecoration, root, shellWithTexts]];
TerminalIO.PutF["Created layout shell for %g.\n", IO.rope[rootName]];
}
ELSE TerminalIO.PutF["%g has no layout pins...\n", IO.rope[rootName]];
};
[] ← CoreCDUser.EnumerateSelectedCellTypes[comm.design, OneShell];
};
ForgetLayout:
PROC [comm: CDSequencer.Command] = {
Warning: This command is extremely unsafe:
- it does not reach for parent celltypes that might be using the same layout
- it removes layout only one level deep
- it will break StdCellsCMosB if applied to a standard cell
- it uses PWCoreLichen properties by name in order to reduce loading dependencies...
ForgetOne: CoreCDUser.EachRootCellTypeProc ~ {
RemoveLayoutPins: CoreOps.EachWireProc ~ {
CoreGeometry.PutGeometry[layoutDecoration, wire, NIL];
};
IF NOT CoreGeometry.HasObject[layoutDecoration, root] THEN RETURN;
TerminalIO.PutF["Removing layout for %g.\n", IO.rope[CoreOps.GetCellTypeName[root]]];
CoreGeometry.PutObject[layoutDecoration, root, NIL]; -- ct -> layout
[] ← CoreOps.VisitWireSeq[root.public, RemoveLayoutPins];
CoreProperties.PutCellTypeProp[root, $PWCoreLichenCompareResults, NIL];
CoreProperties.PutCellTypeProp[root, $PWCoreLichenImplDone, NIL];
};
[] ← CoreCDUser.EnumerateSelectedCellTypes[comm.design, ForgetOne];
};
Static
RootedErrorWires: TYPE = LIST OF RootedErrorWire;
RootedErrorWire:
TYPE =
RECORD[root: Core.CellType, flatWire: CoreFlat.FlatWireRec, count:
INT];
DoStaticCheck:
PROC [command: CDSequencer.Command] = {
CheckOne: CoreCDUser.EachRootCellTypeProc = {
CheckCount: Static.ConnectionCheckProc = {
IF (
NOT unconnectedOK)
AND ((flatWire.wireRoot=public
AND count<1)
OR (
NOT flatWire.wireRoot=public
AND count<2))
THEN {
errors ← CONS[[root, flatWire, count], errors];
TerminalIO.PutF["DAUser: %g has %g connection.\n",
IO.rope[CoreFlat.WirePathRope[root, flatWire]],
IO.rope[IF count=0 THEN "no" ELSE "only one"]];
};
};
name: IO.ROPE = CoreOps.GetCellTypeName[root];
cutSet: CoreFlat.CutSet ←
IF CoreProperties.GetCellTypeProp[root, Static.staticCutSetProp]=
NIL
THEN CoreFlat.CreateCutSet[labels: LIST ["Logic", "LogicMacro"]]
ELSE NIL;
errors: RootedErrorWires ← NIL;
TerminalIO.PutF["DAUser: %g static checking %g.\n", IO.rope[IF flat THEN "Flat" ELSE "Hierarchical"], IO.rope[name]];
quit ← (IF flat THEN Static.CountFlatConnections ELSE Static.CountHierarchicalConnections)[root, CheckCount, cutSet];
FOR errs: RootedErrorWires ← errors, errs.rest
UNTIL errs=
NIL
DO
root: Core.CellType ← errs.first.root;
flatWire: CoreFlat.FlatWireRec ← errs.first.flatWire;
{
CoreCDUser.HighlightFlatWire[root, flatWire, command.design ! CoreCDUser.CoreCDUserError => {TerminalIO.PutF["%g\n", IO.rope[msg]]; GOTO oops}];
IF NOT flat THEN CoreCDUser.SelectFlatWire[root, flatWire, command.design ! CoreCDUser.CoreCDUserError => {TerminalIO.PutF["%g\n", IO.rope[msg]]; GOTO oops}];
EXITS oops => NULL;
};
TerminalIO.PutF["DAUser: %g has %g connection.\n",
IO.rope[CoreFlat.WirePathRope[root, flatWire]],
IO.rope[IF errs.first.count=0 THEN "no" ELSE "only one"]];
quit ← MessageWindow.Confirm["Static: Error highlighted, quit?"];
ENDLOOP;
TerminalIO.PutF["DAUser: Finished static checking %g.\n", IO.rope[name]];
};
flat: BOOL ← command.key=$StaticFlatCheck;
[] ← CoreCDUser.EnumerateSelectedCellTypes[command.design, CheckOne];
};
Rosemary
GetBool:
PROC [ct: Core.CellType, prop:
ATOM, default:
BOOL]
RETURNS [
BOOL] ~ {
Read a boolean property from a CT with the specified default
rb: REF BOOL ← NARROW [CoreProperties.GetCellTypeProp[ct, prop]];
RETURN [IF rb=NIL THEN default ELSE rb^];
};
RunRosemary:
PUBLIC
PROC [cellType: Core.CellType, design:
CD.Design]
RETURNS [tester: RosemaryUser.Tester ←
NIL] = {
IF cellType#
NIL
THEN {
-- something to do
public: Core.Wire ← cellType.public;
Vdd: Core.Wire ← CoreOps.FindWire[public, "Vdd"];
Gnd: Core.Wire ← CoreOps.FindWire[public, "Gnd"];
testButtons: LIST OF Rope.ROPE ← NIL;
IF Vdd=NIL THEN TerminalIO.PutRope["DAUser: Couldn't find Vdd\n"]
ELSE [] ← Rosemary.SetFixedWire[Vdd, H];
IF Gnd=NIL THEN TerminalIO.PutRope["DAUser: Couldn't find Gnd\n"]
ELSE [] ← Rosemary.SetFixedWire[Gnd, L];
FOR tbl:
LIST
OF
REF
ANY ←
NARROW[CoreProperties.GetCellTypeProp[cellType, $Tests]], tbl.rest
UNTIL tbl=
NIL
DO
testButtons ← CONS[CoreOps.FixStupidRef[tbl.first], testButtons];
ENDLOOP;
IF testButtons=NIL THEN testButtons ← LIST["Logic Test"];
CoreCDUser.SetDesignRootCellType[design, cellType];
CoreCDUser.SetRootCellTypeDecoration[cellType, Sisyph.mode.decoration];
tester ← RosemaryUser.TestProcedureViewer[
cellType: cellType,
testButtons: testButtons,
name: Rope.Cat[CoreOps.GetCellTypeName[cellType], " Test"],
displayWires: RosemaryUser.DisplayPortLeafWires[cellType],
recordDeltas: GetBool[cellType, $RecordDeltas, TRUE],
cutSet: NARROW[CoreProperties.GetCellTypeProp[cellType, $CutSet]]];
tester.display.recordSteps ← tester.display.recordDeltas AND GetBool[cellType, $RecordSteps, TRUE];
};
RosemaryCreate:
PROC [command: CDSequencer.Command] = {
ct: Core.CellType ← NIL;
SeeOne: CoreCDUser.EachRootCellTypeProc ~ {
IF ct=NIL THEN ct ← root ELSE {quit ← TRUE; ct ← NIL};
};
IF CoreCDUser.EnumerateSelectedCellTypes[command.design, SeeOne] THEN TerminalIO.PutF["\n*** Only a single cell may be simulated at a time ***\n"]
ELSE IF ct=NIL THEN TerminalIO.PutF["\n*** No cell selected for simulation ***\n"]
ELSE [] ← RunRosemary[ct, command.design];
RosemaryPrintSelectedWires:
PROC [command: CDSequencer.Command] = {
PrintAValue: CoreCDUser.SelectedFlatWireActionProc = {
TerminalIO.PutF[
"Value[%g] = %g\n",
IO.rope[CoreFlat.WirePathRope[cellType, selectedFlatWire^]],
IO.rope[Ports.LSToRope[
Rosemary.WireValue[display.simulation, selectedFlatWire]]]];
};
cellType: Core.CellType ← NIL;
display: RosemaryUser.RoseDisplay ← NIL;
[cellType, display] ← GetRoseDisplay[command];
IF display#NIL THEN CoreCDUser.DoForSelectedFlatWires[cellType, PrintAValue, display.cutSet, command.design];
};
RosemaryPlotSelectedWires:
PROC [command: CDSequencer.Command] = {
AddAWire: CoreCDUser.SelectedFlatWireActionProc = {
errorMsg: Rope.ROPE ← RosemaryUser.AddWireToPlot[display, selectedFlatWire];
IF errorMsg#NIL THEN ERROR CoreCDUser.CoreCDUserError[errorMsg];
};
cellType: Core.CellType ← NIL;
display: RosemaryUser.RoseDisplay ← NIL;
[cellType, display] ← GetRoseDisplay[command];
IF display#NIL THEN CoreCDUser.DoForSelectedFlatWires[cellType, AddAWire, display.cutSet, command.design];
};
RosemaryPlotSelectedCellTypes:
PROC [command: CDSequencer.Command] = {
AddACellType: CoreCDUser.SelectedFlatCellActionProc = {
errorMsg: Rope.ROPE ← RosemaryUser.AddStateToPlot[display, selectedFlatCell];
IF errorMsg#NIL THEN ERROR CoreCDUser.CoreCDUserError[errorMsg];
};
cellType: Core.CellType ← NIL;
display: RosemaryUser.RoseDisplay ← NIL;
[cellType, display] ← GetRoseDisplay[command];
IF display#NIL THEN CoreCDUser.DoForSelectedFlatCells[cellType, AddACellType, display.cutSet, command.design];
};
GetRoseDisplay:
PROC [command: CDSequencer.Command]
RETURNS [cellType: Core.CellType ←
NIL, display: RosemaryUser.RoseDisplay ←
NIL] = {
cellType ← CoreCDUser.GetDesignRootCellType[command.design];
IF cellType=NIL THEN TerminalIO.PutRope["DAUser: No root cell type"]
ELSE {
display ← RosemaryUser.RoseDisplayFor[cellType];
IF display=NIL THEN TerminalIO.PutRope["DAUser: No Rosemary simulation"]
};
};
RosemaryCheckCoverage:
PROC [command: CDSequencer.Command] ~ {
cellType: Core.CellType ← NIL;
display: RosemaryUser.RoseDisplay ← NIL;
[cellType, display] ← GetRoseDisplay[command];
SELECT
TRUE
FROM
display=NIL => NULL; -- error message already printed
RosemaryUser.CheckCoverage[display] => TerminalIO.PutF["The test forces all wires at least once to the H and L states.\n"];
ENDCASE => TerminalIO.PutF["Some wires do not reach the H or L states. Check details in the Rosemary typescript.\n"];
};
Highlight Layout <-> Sch
HighlightCorrespondingLayout:
PROC [command: CDSequencer.Command] = {
decoration: CoreGeometry.Decoration = PWCore.extractMode.decoration;
geom: CoreGeometry.Instances ← NIL;
ConsGeom: CoreGeometry.EachInstanceProc = {geom ← CONS [instance, geom]};
EachWire: CoreCDUser.SelectedFlatWireActionProc = {
flatWire: CoreFlat.FlatWireRec ← CoreFlat.CanonizeWire[root, selectedFlatWire^];
EachPair: RefTab.EachPairAction = {
ew: Core.Wire = NARROW [key];
sw: Core.Wire = NARROW [val];
IF NOT CoreOps.RecursiveMember[flatWire.wire, sw] THEN RETURN;
[] ← CoreGeometry.EnumerateAllGeometry[layoutDecoration, layoutCT, ew, ConsGeom];
};
layoutRoot2: CoreGeometry.Object; layoutCT: Core.CellType; extractedToSource: RefTab.Ref;
[layoutRoot2, layoutCT, extractedToSource] ← PWCore.LayoutInfo[root];
IF layoutRoot2#layoutRoot THEN ERROR;
[] ← RefTab.Pairs[extractedToSource, EachPair];
};
root: Core.CellType ← CoreCDUser.GetDesignRootCellType[command.design];
layoutRoot: CoreGeometry.Object;
layoutDesign: CD.Design;
IF root=NIL THEN {TerminalIO.PutF["*** No registered cellType for HighlightCorrespondingLayout!\n"]; RETURN};
layoutRoot ← CoreGeometry.GetObject[layoutDecoration, root];
IF layoutRoot=NIL THEN {TerminalIO.PutF["*** No layout for cellType!\n"]; RETURN};
layoutDesign ← CDViewer.FindDesign[CD.Describe[layoutRoot]];
IF layoutDesign=NIL THEN {TerminalIO.PutF["*** No layout design for cellType!\n"]; RETURN};
ExtractOps.HighlightDesign[command.design];
CoreCDUser.DoForSelectedFlatWires[root, EachWire, NIL, command.design];
geom ← CoreGeometry.TransformList[layoutDesign.actual.first.specific.contents.first.trans, geom];
ExtractOps.HighlightDesignList[layoutDesign, ExtractOps.HighlightInstanceList[geom]];
};
Initialization
CDSequencerExtras.RegisterCommand[key: $StaticFlatCheck, proc: DoStaticCheck, queue: doQueue];
CDSequencerExtras.RegisterCommand[key: $StaticHierCheck, proc: DoStaticCheck, queue: doQueue];
CDSequencerExtras.RegisterCommand[key: $RosemaryCreate, proc: RosemaryCreate, queue: doQueue];
CDSequencerExtras.RegisterCommand[key: $RosemaryPrintSelectedWires, proc: RosemaryPrintSelectedWires, queue: doQueue];
CDSequencerExtras.RegisterCommand[key: $RosemaryPlotSelectedWires, proc: RosemaryPlotSelectedWires, queue: doQueue];
CDSequencerExtras.RegisterCommand[key: $RosemaryPlotSelectedCellTypes, proc: RosemaryPlotSelectedCellTypes, queue: doQueue];
CDSequencerExtras.RegisterCommand[key: $RosemaryCheckCoverage, proc: RosemaryCheckCoverage, queue: doQueue];
CDSequencerExtras.RegisterCommand[key: $LayoutGenerate, proc: GenerateLayout, queue: doQueue];
CDSequencerExtras.RegisterCommand[key: $LayoutUndo, proc: ForgetLayout, queue: doQueue];
CDSequencerExtras.RegisterCommand[key: $LayoutShell, proc: ShowShell, queue: doQueue];
CDSequencerExtras.RegisterCommand[key: $HighlightCorrespondingLayout, proc: HighlightCorrespondingLayout, queue: doQueue];
END.