SinixOpsImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Jean-Marc Frailong July 25, 1986 8:26:35 pm PDT
Bertrand Serlet March 13, 1987 10:10:31 pm PST
Barth, February 18, 1987 8:20:55 pm PST
DIRECTORY
CD, CDBasics, CDCells, CDDirectory, CDInstances, CDOps, CDPopUpMenus, CDProperties, CDRects, CDSatellites, CDSequencer, CDViewer, CDViewHighlight,
CedarProcess, Convert,
Core, CoreClasses, CoreFlat, CoreOps,
CoreGeometry,
HashTable,
IO,
PopUpMenus, PopUpSelection, Process, Rope, Sinix, SinixOps,
TerminalIO, ViewerClasses;
SinixOpsImpl:
CEDAR
PROGRAM
IMPORTS CD, CDBasics, CDCells, CDDirectory, CDInstances, CDOps, CDPopUpMenus, CDProperties, CDRects, CDSatellites, CDSequencer, CDViewer, CDViewHighlight, CedarProcess, Convert, CoreClasses, CoreFlat, CoreOps, CoreGeometry, HashTable, IO, PopUpMenus, PopUpSelection, Process, Rope, Sinix, TerminalIO
EXPORTS SinixOps
SHARES CDRects, CoreGeometry =
BEGIN OPEN SinixOps;
Wire utilities
All arguments are canonized
SearchedOrParent:
PROC [flatWires:
LIST
OF FlatWireRec, candidate: FlatWireRec]
RETURNS [
BOOL] = {
FOR fw:
LIST
OF FlatWireRec ← flatWires, fw.rest
WHILE fw#
NIL
DO
IF CoreFlat.FlatWireEqualRec[fw.first, candidate] THEN RETURN [TRUE];
ENDLOOP;
FOR i:
NAT
IN [0 .. candidate.wire.size)
DO
IF SearchedOrParent[flatWires, [flatCell: candidate.flatCell, wireRoot: candidate.wireRoot, wire: candidate.wire[i]]] THEN RETURN [TRUE];
ENDLOOP;
RETURN [FALSE];
};
Adds a flat wire to a set of flat wires.
AddFlatWire:
PROC [root: CellType, flatCell: FlatCellTypeRec, wire: Wire, wireRoot: CoreFlat.WireRoot, flatWires:
LIST
OF FlatWireRec]
RETURNS [
LIST
OF FlatWireRec] ={
flatWire: FlatWireRec = CoreFlat.CanonizeWire[root, [flatCell: flatCell, wireRoot: wireRoot, wire: wire]];
FOR fw:
LIST
OF FlatWireRec ← flatWires, fw.rest
WHILE fw#
NIL
DO
IF CoreFlat.FlatWireEqualRec[fw.first, flatWire] THEN RETURN [flatWires];
ENDLOOP;
flatWires ← CONS [flatWire, flatWires];
FOR i:
NAT
IN [0 .. wire.size)
DO
flatWires ← AddFlatWire[root, flatCell, wire[i], wireRoot, flatWires];
ENDLOOP;
RETURN [flatWires];
};
CD Utilities
Check that two CD instances are logically the same. We need that because instances that are highlighted are equivalent to, but not equal to, instances in non pushed in cells.
Given inInst and outInst in world coordinates, return instance of inInst if it were in outInst. The basics code for this is found in CDInstances.DeComposed. This function is necessary because cells pushed in are flattened to world coordinates, so we have to build them back.
SameCDInstance:
PROC [cdinst:
CD.Instance, trans:
CD.Transformation, instance: CoreGeometry.Instance]
RETURNS [
BOOL] ~
INLINE {
RETURN [
cdinst.ob=instance.obj AND
CDBasics.DeMapPoint[cdinst.trans.off, trans]=instance.trans.off AND
CDBasics.DecomposeOrient[itemInWorld: cdinst.trans.orient, cellInWorld: trans.orient]=instance.trans.orient
];
};
IsSelectedInstance:
PROC [possibleInst: CoreGeometry.Instance, design:
CD.Design]
RETURNS [
BOOL ←
FALSE] = {
closed: CD.Instance = design.actual.first.mightReplace;
open: CD.Instance = design.actual.first.dummyCell;
IsSameInstance: CDCells.InstEnumerator = {
quit ← inst.selected AND SameCDInstance[inst, closed.trans, possibleInst];
};
RETURN [CDCells.EnumerateInstances[open.ob, IsSameInstance]];
};
Highlight
HighLightInst:
PUBLIC
PROC [instance: CoreGeometry.Instance]
RETURNS [hinstance:
CD.Instance] = {
hinstance ← CDInstances.NewInst[
CDRects.CreateRect[CD.InterestSize[instance.obj], CD.shadeLayer],
[CDBasics.MapPoint[CD.InterestBase[instance.obj], instance.trans], instance.trans.orient]
];
};
HighLightListInst:
PUBLIC
PROC [instances: CoreGeometry.Instances]
RETURNS [hinstances:
CD.InstanceList ←
NIL] = {
WHILE instances#
NIL
DO
hinstances ← CONS [HighLightInst[instances.first], hinstances]; instances ← instances.rest;
ENDLOOP;
};
HighlightDesign:
PUBLIC
PROC [design:
CD.Design, highlight:
REF] = {
bbox: CD.Rect ← CDBasics.empty;
WITH highlight
SELECT
FROM
hinst: CD.Instance => bbox ← CDInstances.InstRectO[hinst];
hinstlist: CD.InstanceList => bbox ← CDInstances.BoundingRectO[hinstlist];
ENDCASE => {};
-- Compiler bug???
bbox: CD.Rect ← CDBasics.empty;
bbox ← WITH highlight SELECT FROM
-- hinst: CD.Instance => CDInstances.InstRectO[hinst],
hinstlist: CD.InstanceList => CDInstances.BoundingRectO[hinstlist],
ENDCASE => CDBasics.empty;
FOR viewers:
LIST
OF ViewerClasses.Viewer ← CDViewer.ViewersOf[design], viewers.rest
WHILE viewers#
NIL
DO
CDViewHighlight.ShowInstance[v: viewers.first, instOrList: highlight];
IF CDBasics.NonEmpty[bbox] THEN CDViewer.ShowAndScale[viewer: viewers.first, rect: bbox];
ENDLOOP;
};
HighlightNets:
PUBLIC
PROC [decoration: Decoration, design:
CD.Design, instance:
CD.Instance, root: CellType, flatWires:
LIST
OF FlatWireRec] ~ {
hinstances: CD.InstanceList ← NIL;
EachFlatWire: CoreGeometry.EachFlatWireProc = {
IF SearchedOrParent[flatWires, flatWire]
THEN hinstances ← CDInstances.AppendToList[HighLightListInst[CoreGeometry.TransformList[trans, CoreGeometry.GetGeometry[decoration, wire]]], hinstances];
};
EachFlatCell: CoreGeometry.EachFlatCellProc = {
EachPublic: CoreOps.EachWireProc = {
flatWire: FlatWireRec =
IF bindings=
NIL
THEN [flatCell: [], wireRoot: public, wire: wire]
ELSE NARROW [HashTable.Fetch[bindings, wire].value, FlatWire]^;
IF SearchedOrParent[flatWires, flatWire]
THEN hinstances ← CDInstances.AppendToList[HighLightListInst[CoreGeometry.TransformList[trans, CoreGeometry.GetPins[decoration, wire]]], hinstances];
};
[] ← CoreOps.VisitWireSeq[cell.public, EachPublic];
};
Leaf: CoreGeometry.LeafProc = {RETURN [IsIcon[decoration, cellType]]};
CoreGeometry.EnumerateFlatGeometry[decoration: decoration, root: root, leafProc: Leaf, eachFlatWire: EachFlatWire, eachFlatCell: EachFlatCell];
IF hinstances=NIL THEN TerminalIO.PutF["*** Nothing to highlight!\n"];
HighlightDesign[design, CDInstances.ComposedList[hinstances, instance.trans]];
};
Links between Core and ChipNDale
IsIcon:
PUBLIC
PROC [decoration: Decoration, cell: CellType]
RETURNS [
BOOL] ~ {
RETURN [CoreGeometry.HasObject[decoration, cell] AND cell.class#CoreClasses.recordCellClass]
};
ExtractCDInstance:
PUBLIC
PROC [instance:
CD.Instance, design:
CD.Design, mode: Mode]
RETURNS [result:
REF, props: Properties] ~ {
userData: REF = IF mode.userData#NIL THEN mode.userData[design] ELSE NIL;
[] ← CDSatellites.GetSatellites[design]; -- enforces the strong invariant in object, one level deep
CDProperties.PutInstanceProp[instance, Sinix.satellitesProp, CDSatellites.GetSatelliteRopes[instance]];
[result, props] ← Sinix.Extract[
obj: instance.ob, mode: mode, properties: instance.properties, userData: userData
];
};
ExtractCDStack:
PUBLIC
PROC [design:
CD.Design, mode: Mode]
RETURNS [instance:
CD.Instance ←
NIL, root: CellType ←
NIL] ~ {
result: REF;
IF design.actual.rest=
NIL
THEN {
TerminalIO.PutF["*** No currently pushed-in cell.\n"];
RETURN;
};
FOR stack:
LIST
OF
CD.PushRec ← design.actual, stack.rest
WHILE stack.rest#
NIL
DO
IF stack.first.specific.changed
THEN {
TerminalIO.PutF["*** Impossible to extract stack, cell %g has been changed and not saved.\n", IO.rope[CDDirectory.Name[stack.first.mightReplace.ob]]];
RETURN;
};
instance ← stack.first.mightReplace;
ENDLOOP;
result ← ExtractCDInstance[instance: instance, design: design, mode: mode].result;
SELECT
TRUE
FROM
result=NIL => TerminalIO.PutF["*** Top cell extracts to NIL.\n"];
ISTYPE[result, Wire] => TerminalIO.PutF["*** Top cell extracts to a Wire.\n"];
ISTYPE[result, Wires] => TerminalIO.PutF["*** Top cell extracts to Wires.\n"];
ENDCASE => root ← NARROW [result];
};
CDStackToPath:
PUBLIC
PROC [design:
CD.Design, mode: Mode]
RETURNS [instance:
CD.Instance, root: CellType, pushed: CellType, flatPushed: FlatCellTypeRec] = {
We came from that one from a RecordCell [vertical move]
TransfUnboundFlat: CoreFlat.UnboundFlatCellProc = {
revStack: LIST OF CD.PushRec = NARROW [data];
possibleInst: CoreGeometry.Instance = [CoreGeometry.GetObject[mode.decoration, instance.type], CoreGeometry.GetTrans[mode.decoration, instance]];
IF SameCDInstance[revStack.rest.first.mightReplace, revStack.first.mightReplace.trans, possibleInst]
THEN UnboundFlat[cell, target, flatCell, instance, index, parent, flatParent, revStack.rest];
};
UnboundFlat:
CoreFlat.UnboundFlatCellProc = {
revStack: LIST OF CD.PushRec = NARROW [data];
SELECT
TRUE
FROM
NOT CoreGeometry.HasObject[mode.decoration, cell] => CoreFlat.NextUnboundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, UnboundFlat];
revStack.rest=NIL => {pushed ← cell; flatPushed ← flatCell};
cell.class=CoreClasses.recordCellClass => CoreFlat.NextUnboundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, TransfUnboundFlat];
ENDCASE =>
{TerminalIO.PutF["*** Pushed-in cell is deep inside an icon.\n"]; root ← NIL};
};
revStack: LIST OF CD.PushRec ← NIL;
[instance, root] ← ExtractCDStack[design, mode];
IF root=NIL THEN RETURN;
We want to deal with deeper last
FOR stack:
LIST
OF
CD.PushRec ← design.actual, stack.rest
WHILE stack#
NIL
DO
revStack ← CONS [stack.first, revStack];
ENDLOOP;
revStack ← revStack.rest; -- we do not care about the top level dummy
UnboundFlat[cell: root, data: revStack];
IF root=NIL THEN RETURN; -- error already recognized
IF pushed=NIL THEN ERROR; -- somehow hierarchies differ
};
SelectedCoreObjects:
PUBLIC
PROC [design:
CD.Design, mode: Mode, flatCellsActuals:
BOOL ←
FALSE]
RETURNS [instance:
CD.Instance, root: CellType, pushed: CellType, flatPushed: FlatCellTypeRec, flatCells:
LIST
OF FlatCellTypeRec ←
NIL, flatWires:
LIST
OF FlatWireRec ←
NIL] ~ {
isIcon: BOOL;
IsSelectedWire: CoreOps.EachWireProc ~ {
FOR geometry: CoreGeometry.Instances ←
IF isIcon
THEN CoreGeometry.GetPins[mode.decoration, wire]
ELSE CoreGeometry.GetGeometry[mode.decoration, wire], geometry.rest
WHILE geometry#
NIL
DO
IF IsSelectedInstance[geometry.first, design]
THEN flatWires ← AddFlatWire[root, flatPushed, wire, IF isIcon THEN public ELSE internal, flatWires];
ENDLOOP;
};
[instance, root, pushed, flatPushed] ← CDStackToPath[design, mode];
IF root=NIL THEN RETURN;
isIcon ← IsIcon[mode.decoration, pushed];
IF isIcon
THEN [] ← CoreOps.VisitWireSeq[pushed.public, IsSelectedWire]
ELSE {
rct: CoreClasses.RecordCellType = NARROW [pushed.data];
[] ← CoreOps.VisitWireSeq[rct.internal, IsSelectedWire];
FOR i:
NAT
IN [0 .. rct.size)
DO
possibleInst: CoreGeometry.Instance = [CoreGeometry.GetObject[mode.decoration, rct[i].type], CoreGeometry.GetTrans[mode.decoration, rct[i]]];
IF NOT IsSelectedInstance[possibleInst, design] THEN LOOP;
flatCells ← CONS [[path: CoreFlat.AddInstance[flatPushed.path, rct[i], pushed]], flatCells];
IF flatCellsActuals
THEN
FOR j:
NAT
IN [0 .. rct[i].actual.size)
DO
flatWires ← AddFlatWire[root, flatPushed, rct[i].actual.elements[j], internal, flatWires];
ENDLOOP;
ENDLOOP;
};
};
Implementation of ChipNDale commands
SelectedCellType:
PUBLIC
PROC [design:
CD.Design, mode: Mode]
RETURNS [instance:
CD.Instance, root: CellType ←
NIL, cell: CellType, flatCell: FlatCellTypeRec ← [], trans: CoreGeometry.Transformation] = {
IF design.actual.rest#
NIL
THEN {
pushed: CellType; flatPushed: FlatCellTypeRec;
flatCells: LIST OF FlatCellTypeRec; flatWires: LIST OF FlatWireRec;
cellInstance: CellInstance;
[instance, root, pushed, flatPushed, flatCells, flatWires] ← SelectedCoreObjects[design, mode, FALSE];
IF root=NIL THEN RETURN;
IF flatWires#NIL OR flatCells=NIL OR flatCells.rest#NIL THEN {TerminalIO.PutF["*** Select one instance only.\n"]; root ← NIL; RETURN};
flatCell ← flatCells.first;
[instance: cellInstance, cellType: cell] ← CoreFlat.ResolveFlatCellType[root, flatCell]; -- we could optimize and do better here.
trans ← CDBasics.ComposeTransform[itemInCell: CoreGeometry.GetTrans[mode.decoration, cellInstance], cellInWorld: design.actual.first.mightReplace.trans];
} ELSE {
multiple: BOOL;
result: REF;
[instance, multiple] ← CDOps.SelectedInstance[design];
IF multiple
THEN {TerminalIO.PutF["\n** Multiple instances selected. No action.\n"]; RETURN};
IF instance=
NIL
THEN {TerminalIO.PutF["\n** No instance selected. No action.\n"]; RETURN};
IF instance=NIL THEN RETURN;
result ← ExtractCDInstance[instance, design, mode].result;
IF result=NIL THEN RETURN;
WITH result
SELECT
FROM
ct: CellType => root ← ct;
ENDCASE => {TerminalIO.PutF["\n** Not a Core cell. No action.\n"]; RETURN};
cell ← root; trans ← instance.trans;
};
};
HighLightWireGeometry:
PROC [design:
CD.Design, mode: Mode, name:
ROPE, wires:
LIST
OF Wire] = {
IF name=NIL THEN RETURN; -- no highlight done
to be replaced by a PushByName one day
FOR insts:
CD.InstanceList ← CDOps.InstList[design], insts.rest
WHILE insts#
NIL
DO
AddGeometry:
PROC [w: Wire] = {
IF CoreOps.Member[ws, w] THEN RETURN; -- to avoid infinite recursion, for example
ws ← CONS [w, ws];
FOR gs: CoreGeometry.Instances ← CoreGeometry.GetGeometry[mode.decoration, w], gs.rest
WHILE gs#
NIL
DO
IF NOT CoreGeometry.Intersect[CD.InterestRect[insts.first.ob], gs.first] THEN LOOP;
geometry ← CONS [CoreGeometry.Transform[insts.first.trans, gs.first], geometry];
ENDLOOP;
FOR i: NAT IN [0 .. w.size) DO AddGeometry[w[i]] ENDLOOP;
};
geometry: CoreGeometry.Instances ← NIL;
ws: LIST OF Wire ← NIL;
IF NOT Rope.Equal[CDDirectory.Name[insts.first.ob], name] THEN LOOP;
WHILE wires#NIL DO AddGeometry[wires.first]; wires ← wires.rest ENDLOOP;
IF geometry=NIL THEN RETURN;
HighlightDesign[design, HighLightListInst[geometry]];
TerminalIO.PutF["Highlight of the culprits done.\n"];
ENDLOOP;
};
ExtractSelected:
PROC [design:
CD.Design, mode: Mode] = {
nb: INT ← 0;
HighlightDesign[design, NIL];
FOR instances:
CD.InstanceList ← CDOps.InstList[design], instances.rest
WHILE instances#
NIL
DO
result: REF;
IF NOT instances.first.selected THEN LOOP;
nb ← nb + 1;
result ← ExtractCDInstance[instance: instances.first, design: design, mode: mode !
Sinix.FusionPropMismatch => {
TerminalIO.PutF["*** Extraction failed in cell %g.\n", IO.rope[name]];
IF prop=CoreOps.nameProp
THEN TerminalIO.PutF["*** Two wires that do not have the same name are fused: %g and %g.\n", IO.rope[NARROW [value1]], IO.rope[NARROW [value2]]]
ELSE TerminalIO.PutF["*** Two wires that do not have the same %g property value are fused: %g and %g.\n", IO.atom[prop], IO.refAny[value1], IO.refAny[value2]];
GOTO Failed;
};
Sinix.FusionStructureMismatch => {
TerminalIO.PutF["*** Extraction failed in cell %g.\n", IO.rope[name]];
TerminalIO.PutF[
"*** Two wires with mismatching structures are fused: %g and %g.\n",
IO.rope[CoreOps.GetShortWireName[wire1]],
IO.rope[CoreOps.GetShortWireName[wire2]]
];
HighLightWireGeometry[design, mode, name, LIST [wire1, wire2]];
GOTO Failed;
};
Sinix.StructureMismatch => {
TerminalIO.PutF["*** Extraction failed in cell %g.\n", IO.rope[name]];
TerminalIO.PutF[
"*** Actual %g and subPublic %g have mismatching structures.\n",
IO.rope[CoreOps.GetShortWireName[actual]],
IO.rope[CoreOps.GetShortWireName[subPublic]]
];
HighLightWireGeometry[design, mode, name, LIST [actual]];
GOTO Failed;
};
Sinix.FusionByNameMismatch => {
TerminalIO.PutF["*** Extraction failed in cell %g.\n", IO.rope[name]];
TerminalIO.PutF["*** Fusion by name problem: %g.\n", IO.rope[msg]];
HighLightWireGeometry[design, mode, name, LIST [wire]];
GOTO Failed;
};
Sinix.StructuralLoop => {
TerminalIO.PutF["*** Extraction failed in cell %g.\n", IO.rope[name]];
TerminalIO.PutF["*** Probably a structural loop in wire: %g.\n", IO.rope[CoreOps.GetShortWireName[wire]]];
HighLightWireGeometry[design, mode, name, LIST [wire]]; -- be careful not to be recursive!
GOTO Failed;
};
].result;
IF result=
NIL
THEN TerminalIO.PutF["*** Extraction returned NIL"]
ELSE CoreOps.Print[ref: result, out: TerminalIO.CreateStream[], level: LAST [NAT]];
TerminalIO.PutF["\n"];
ENDLOOP;
IF nb=0 THEN TerminalIO.PutF["*** No instance selected.\n"];
IF nb>1 THEN TerminalIO.PutF["%g instances extracted.\n", IO.int[nb]];
EXITS Failed => RETURN;
};
HighlightMenu:
PROC [design:
CD.Design, mode: Mode] ~ {
HighlightDesign[design, NIL];
SELECT PopUpSelection.Request["Highlight nets",
LIST ["Highlight selected nets", "Highlight named wire in selected cell", "Highlight all wires of selected cell", "Highlight all pins of selected cell"], "Controls highlight",
LIST ["corresponding to selected instance", "asks for a CoreFlat name"]]
FROM
1 => {
instance: CD.Instance; root: CellType; pushed: CellType; flatPushed: FlatCellTypeRec;
flatCells: LIST OF FlatCellTypeRec; flatWires: LIST OF FlatWireRec;
[instance, root, pushed, flatPushed, flatCells, flatWires] ← SelectedCoreObjects[design, mode, TRUE];
IF root=NIL THEN RETURN;
IF flatWires=NIL THEN {TerminalIO.PutF["*** No wire selected.\n"]; RETURN};
IF flatCells#NIL THEN TerminalIO.PutF["Cell instances selected: corresponding actuals are highlighted.\n"];
TerminalIO.PutF["The following wires have been selected:\t"];
FOR fw:
LIST
OF FlatWireRec ← flatWires, fw.rest
WHILE fw#
NIL
DO
TerminalIO.PutF["\t%g", IO.rope[CoreFlat.WirePathRope[root, fw.first]]];
ENDLOOP;
TerminalIO.PutF["\n"];
HighlightNets[mode.decoration, design, instance, root, flatWires];
};
2 => {
instance: CD.Instance; root: CellType; cell: CellType; flatCell: FlatCellTypeRec;
name: ROPE; quit: BOOL ← FALSE;
flatWire: FlatWireRec;
[instance, root, cell, flatCell] ← SelectedCellType[design, mode];
IF root=NIL THEN RETURN;
name ← TerminalIO.RequestRope["enter wire name relative to selected cell: " ! TerminalIO.UserAbort => {quit ← TRUE}];
IF quit THEN RETURN;
flatWire ← CoreFlat.ParseWirePath[root, Rope.Cat[CoreFlat.CellTypePathRope[root, flatCell], name] ! CoreFlat.PathError => {TerminalIO.PutF["*** Could not find wire `%g' : %g.\n", IO.rope[name], IO.rope[msg]]; quit ← TRUE; CONTINUE}];
IF quit THEN RETURN;
HighlightNets[mode.decoration, design, instance, root, LIST [CoreFlat.ParseWirePath[root, Rope.Cat[CoreFlat.CellTypePathRope[root, flatCell], name]]]];
};
3 => {
HighlightWire: CoreOps.EachWireProc = {
hinstances ← CDInstances.AppendToList[HighLightListInst[CoreGeometry.GetGeometry[mode.decoration, wire]], hinstances];
};
instance: CD.Instance; root: CellType; cell: CellType; flatCell: FlatCellTypeRec; trans: CoreGeometry.Transformation;
hinstances: CD.InstanceList ← NIL;
[instance, root, cell, flatCell, trans] ← SelectedCellType[design, mode];
IF root=NIL THEN RETURN;
IF cell.class#CoreClasses.recordCellClass THEN {TerminalIO.PutF["*** Only applicable to record cells!\n"]; RETURN};
[] ← CoreOps.VisitWireSeq[NARROW [cell.data, CoreClasses.RecordCellType].internal, HighlightWire];
HighlightDesign[design, CDInstances.ComposedList[hinstances, trans]];
};
4 => {
HighlightWire: CoreOps.EachWireProc = {
hinstances ← CDInstances.AppendToList[HighLightListInst[CoreGeometry.GetPins[mode.decoration, wire]], hinstances];
};
instance: CD.Instance; root: CellType; cell: CellType; flatCell: FlatCellTypeRec; trans: CoreGeometry.Transformation;
hinstances: CD.InstanceList ← NIL;
[instance, root, cell, flatCell, trans] ← SelectedCellType[design, mode];
IF root=NIL THEN RETURN;
[] ← CoreOps.VisitWireSeq[cell.public, HighlightWire];
HighlightDesign[design, CDInstances.ComposedList[hinstances, trans]];
};
ENDCASE => {};
};
CDSequencer commands
ExtractLayoutCommand:
PROC [command: CDSequencer.Command] ~ {
technology: CD.Technology = command.design.technology;
mode: Mode = NARROW [CDProperties.GetProp[technology, $ExtractMode]];
IF mode#
NIL
THEN ExtractSelected[command.design, mode]
ELSE TerminalIO.PutF["No extraction mode for technology %g.\n", IO.atom[technology.key]];
};
HighlightLayoutCommand:
PROC [command: CDSequencer.Command] ~ {
technology: CD.Technology = command.design.technology;
mode: Mode = NARROW [CDProperties.GetProp[technology, $ExtractMode]];
IF mode#
NIL
THEN HighlightMenu[command.design, mode]
ELSE TerminalIO.PutF["No extraction mode for technology %g.\n", IO.atom[technology.key]];
};
ExtractCommand:
PROC [command: CDSequencer.Command] ~ {
mode: Mode = NARROW [CDProperties.GetProp[command.key, $ExtractMode]];
IF mode#NIL THEN ExtractSelected[command.design, mode] ELSE ERROR;
};
HighlightCommand:
PROC [command: CDSequencer.Command] ~ {
mode: Mode = NARROW [CDProperties.GetProp[command.key, $ExtractMode]];
IF mode#NIL THEN HighlightMenu[command.design, mode] ELSE ERROR;
};
Registration of extract modes
RegisterDefaultLayoutMode:
PUBLIC
PROC [mode: Mode, technology:
CD.Technology] ~ {
IF technology=NIL THEN ERROR;
CDProperties.PutProp[technology, $ExtractMode, mode];
};
GetExtractMode:
PUBLIC
PROC [tech:
REF]
RETURNS [mode: Mode ←
NIL] ~ {
WITH tech
SELECT
FROM
technology: CD.Technology => mode ← NARROW [CDProperties.GetProp[technology, $ExtractMode]];
key:
ATOM => {
technology: CD.Technology = CD.FetchTechnology[key];
mode ←
NARROW [CDProperties.GetProp[
IF technology#NIL THEN technology ELSE key,
$ExtractMode]];
};
ENDCASE => {};
};
RegisterModeCommands:
PUBLIC
PROC [mode: Mode, technology:
CD.Technology ←
NIL] ~ {
name: ROPE = mode.decoration.name;
menu: PopUpMenus.Menu = CDPopUpMenus.GetMenu[$OtherProgramMenu, TRUE];
extractKey: ATOM = Convert.AtomFromRope[Rope.Cat[name, "ExtractCommand"]];
highlightKey: ATOM = Convert.AtomFromRope[Rope.Cat[name, "HighlightCommand"]];
[] ← CDProperties.RegisterProperty[extractKey, $SinixOps];
[] ← CDProperties.RegisterProperty[highlightKey, $SinixOps];
CDProperties.PutProp[extractKey, $ExtractMode, mode];
CDProperties.PutProp[highlightKey, $ExtractMode, mode];
[] ← PopUpMenus.Entry[menu, Rope.Cat[name, ": extract"], NIL, extractKey, "calls extractor"];
[] ← PopUpMenus.Entry[menu, Rope.Cat[name, ": highlight"], NIL, highlightKey, "highlight submenu"];
CDSequencer.ImplementCommand[key: extractKey, technology: technology, proc: ExtractCommand, queue: doQueue];
CDSequencer.ImplementCommand[key: highlightKey, technology: technology, proc: HighlightCommand, queue: doQueue];
};
Background Extraction [Out of order]
CDSequencer.ImplementCommand[key: $BackgroundLayoutExtraction, proc: BackgroundLayoutCommand, queue: doQueue];
RegisterBackgroundExtractionCommand: PUBLIC PROC [technology: CD.Technology, mode: Mode, prompt: ROPE, key: ATOM, filter: FilterProc] = {
[] ← CDProperties.RegisterProperty[key, $SinixOps];
CDProperties.PutProp[key, $ExtractMode, mode];
CDProperties.PutProp[key, $SinixBackgroundFilter, NEW [FilterProc ← filter]];
CDMenus.ImplementEntryCommand[menu: $OtherProgramMenu, entry: prompt, p: BackgroundExtractionCommand, key: key, technology: technology];
};
BackgroundLayoutCommand: PROC [command: CDSequencer.Command] ~ {
mode: Mode = NARROW [CDProperties.GetProp[command.design.technology, $ExtractMode];
IF mode#NIL THEN HighlightMenu[command.design, mode];
};
BackgroundExtractionCommand: PROC [command: CDSequencer.Command] ~ {
mode: Mode = NARROW [CDProperties.GetProp[command.key, $ExtractMode]];
refFilter: REF FilterProc ← NARROW [CDProperties.GetProp[command.key, $SinixBackgroundFilter]];
IF mode#NIL THEN BackgroundMenu[command.key, command.design, mode, IF refFilter=NIL THEN NIL ELSE refFilter^];
};
A property is stored on the design: the key is the key parameter (name of the command), and the value is the process doing background extraction.
BackgroundMenu: PROC [key: ATOM, design: CD.Design, mode: Mode, filter: FilterProc] ~ {
SELECT TerminalIO.RequestSelection["Background Extraction", LIST ["Start", "Stop"], "Controls Background Extraction", LIST ["Starts Background Extraction", "Stops Background Extraction"]] FROM
1 => {
IF CDProperties.GetDesignProp[design, key]#NIL THEN {TerminalIO.PutF["*** Background extraction already started for this design\n"]; RETURN};
CDProperties.PutDesignProp[design, key, CedarProcess.Fork[action: ExtractProcess, data: NEW [ProcessDataRec ← [design: design, key: key, mode: mode, filter: filter]], options: [priority: background, usePriority: TRUE]]];
TerminalIO.PutF["Background extraction started for this design\n"];
};
2 => {
process: CedarProcess.Process = NARROW [CDProperties.GetDesignProp[design, key]];
IF process=NIL THEN {TerminalIO.PutF["*** Background extraction was not started for this design\n"]; RETURN};
CedarProcess.Abort[process];
CDProperties.PutDesignProp[design, key, NIL];
TerminalIO.PutF["Background extraction stopped for this design\n"];
};
ENDCASE => RETURN;
};
ProcessData: TYPE = REF ProcessDataRec;
ProcessDataRec: TYPE = RECORD [design: CD.Design, key: ATOM, mode: Mode, filter: FilterProc];
This process tries to extract all instances in the design
ExtractProcess: CedarProcess.ForkableProc = {
processData: ProcessData ← NARROW [data];
DO
-- forever
CedarProcess.CheckAbort[];
IF CDProperties.GetDesignProp[processData.design, processData.key]=NIL THEN RETURN; -- no necessary, logically. Just for safety!
FOR instances:
CD.InstanceList ← CDOps.InstList[processData.design], instances.rest
WHILE instances#
NIL
DO
CedarProcess.CheckAbort[];
IF CDProperties.GetDesignProp[processData.design, processData.key]=NIL THEN RETURN; -- not necessary, logically. Just for safety!
IF NOT CDCells.IsCell[instances.first.ob] OR NOT processData.filter[processData.design, CDDirectory.Name[instances.first.ob], instances.first.ob] THEN LOOP;
[] ← ExtractCDInstance[instances.first, processData.design, processData.mode ! ABORTED => GOTO Aborted; ANY => CONTINUE];
Process.Yield[];
Process.Pause[Process.MsecToTicks[100]];
ENDLOOP;
Process.Pause[Process.MsecToTicks[500]];
ENDLOOP;
EXITS Aborted => RETURN;
};
FilterProc: TYPE = PROC [design: CD.Design, name: ROPE, object: CD.Object] RETURNS [extract: BOOL];
RegisterBackgroundExtractionCommand: PROC [technology: CD.Technology, mode: Mode, key: ATOM, filter: FilterProc];
Create a menu entry for starting/stopping background extraction of filtered objects. If technology is NIL, the entry will be valid for ALL technologies.
Initialization
CDSequencer.ImplementCommand[key: $ExtractLayout, proc: ExtractLayoutCommand, queue: doQueue];
CDSequencer.ImplementCommand[key: $HighlightNetInLayout, proc: HighlightLayoutCommand, queue: doQueue];
[] ← CDProperties.RegisterProperty[$ExtractMode, $SinixOps];
[] ← CDProperties.RegisterProperty[$ExtractLayout, $SinixOps];
[] ← CDProperties.RegisterProperty[$HighlightNetInLayout, $SinixOps];
[] ← CDProperties.RegisterProperty[$SinixBackgroundFilter, $SinixOps];
END.