<> <> <> <> DIRECTORY CD, CDBasics, CDCells, CDDirectory, CDInstances, CDMenus, CDOps, CDOrient, CDProperties, CDRects, CDSatellites, CDSequencer, CDViewer, CDViewHighlight, CedarProcess, Core, CoreClasses, CoreFlat, CoreOps, CoreGeometry, HashTable, IO, Process, Rope, Sinix, SinixOps, TerminalIO, ViewerClasses; SinixOpsImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDDirectory, CDInstances, CDMenus, CDOps, CDOrient, CDProperties, CDRects, CDSatellites, CDViewer, CDViewHighlight, CedarProcess, CoreClasses, CoreFlat, CoreOps, CoreGeometry, HashTable, IO, Process, Rope, Sinix, TerminalIO EXPORTS SinixOps SHARES CDRects = BEGIN OPEN SinixOps; extractModeAtom: ATOM _ $ExtractMode; highlightMenu: REF = CDMenus.CreateMenu["Highlight nets"]; backgroundMenu: REF = CDMenus.CreateMenu["Background Extraction"]; <> <> 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]; }; <> 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]; }; <<>> <> <> SameCDInstance: PROC [i, j: Instance] RETURNS [BOOL] ~ INLINE { RETURN [i.ob=j.ob AND i.location=j.location AND i.orientation=j.orientation] }; <> RelocateInInstance: PROC [inInst, outInst: Instance] RETURNS [Instance] ~ INLINE { RETURN [CDInstances.DeComposed[inst: inInst, cellPos: outInst.location, cellSize: outInst.ob.size, cellOrient: outInst.orientation]]; }; IsSelectedInstance: PROC [possibleInst: Instance, design: Design] RETURNS [BOOL _ FALSE] = { closed: Instance = design.actual.first.mightReplace; open: Instance = design.actual.first.dummyCell; FOR list: Instances _ NARROW [open.ob.specificRef, CD.CellPtr].contents, list.rest WHILE list#NIL DO IF list.first.selected AND SameCDInstance[RelocateInInstance[list.first, closed], possibleInst] THEN RETURN [TRUE] ENDLOOP; }; <> HighLightInst: PUBLIC PROC [instance: Instance] RETURNS [hinstance: Instance] = { hinstance _ NEW [CD.InstanceRep _ [ ob: CDRects.CreateRect[CD.InterestSize[instance.ob], CD.shadeLayer], location: CDBasics.BaseOfRect[CDOrient.MapRect[CD.InterestRect[instance.ob], instance.ob.size, instance.orientation, instance.location]], orientation: instance.orientation]]; }; HighLightListInst: PUBLIC PROC [instances: Instances] RETURNS [hinstances: Instances _ 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: Instance => bbox _ CDInstances.InstRectO[hinst]; hinstlist: Instances => bbox _ CDInstances.BoundingRectO[hinstlist]; ENDCASE => {}; <> <> <<-- hinst: Instance => CDInstances.InstRectO[hinst],>> < CDInstances.BoundingRectO[hinstlist],>> < CDBasics.empty;>> FOR viewers: LIST OF ViewerClasses.Viewer _ CDViewer.ViewersOf[design], viewers.rest WHILE viewers#NIL DO CDViewHighlight.ShowInstance[v: viewers.first, instOrList: highlight, key: highlightMenu]; IF CDBasics.NonEmpty[bbox] THEN CDViewer.ShowAndScale[viewer: viewers.first, rect: bbox]; ENDLOOP; }; HighlightNets: PUBLIC PROC [decoration: Decoration, design: CD.Design, instance: Instance, root: CellType, flatWires: LIST OF FlatWireRec] ~ { hinstances: Instances _ NIL; EachFlatWire: CoreGeometry.EachFlatWireProc = { IF SearchedOrParent[flatWires, flatWire] THEN hinstances _ CDInstances.AppendToList[HighLightListInst[geometry], 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[transf, 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]; HighlightDesign[design, CoreGeometry.TransformList[instance, hinstances]]; }; <> IsIcon: PUBLIC PROC [decoration: Decoration, cell: CellType] RETURNS [BOOL] ~ { RETURN [CoreGeometry.HasIR[decoration, cell] AND cell.class#CoreClasses.recordCellClass] }; ExtractCDInstance: PUBLIC PROC [instance: Instance, design: 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: Design, mode: Mode] RETURNS [instance: Instance _ NIL, root: CellType _ NIL] ~ { result: REF; IF design.actual.rest=NIL THEN { TerminalIO.WriteF["*** 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.changed THEN { TerminalIO.WriteF["*** 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.WriteF["*** Top cell extracts to NIL.\n"]; ISTYPE[result, Wire] => TerminalIO.WriteF["*** Top cell extracts to a Wire.\n"]; ISTYPE[result, Wires] => TerminalIO.WriteF["*** Top cell extracts to Wires.\n"]; ENDCASE => root _ NARROW [result]; }; <<>> CDStackToPath: PUBLIC PROC [design: Design, mode: Mode] RETURNS [instance: Instance, root: CellType, pushed: CellType, flatPushed: FlatCellTypeRec] = { <> TransfUnboundFlat: CoreFlat.UnboundFlatCellProc = { revStack: LIST OF CD.PushRec = NARROW [data]; possibleInst: Instance = CoreGeometry.GetTransf[mode.decoration, instance]; IF SameCDInstance[possibleInst, RelocateInInstance[revStack.rest.first.mightReplace, revStack.first.mightReplace]] THEN UnboundFlat[cell, target, flatCell, instance, parent, flatParent, revStack.rest]; }; UnboundFlat: CoreFlat.UnboundFlatCellProc = { revStack: LIST OF CD.PushRec = NARROW [data]; SELECT TRUE FROM NOT CoreGeometry.HasIR[mode.decoration, cell] => CoreFlat.NextUnboundCellType[cell, target, flatCell, instance, parent, flatParent, data, UnboundFlat]; revStack.rest=NIL => {pushed _ cell; flatPushed _ flatCell}; cell.class=CoreClasses.recordCellClass => CoreFlat.NextUnboundCellType[cell, target, flatCell, instance, parent, flatParent, data, TransfUnboundFlat]; ENDCASE => {TerminalIO.WriteF["*** 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; <> 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: Design, mode: Mode, flatCellsActuals: BOOL _ FALSE] RETURNS [instance: Instance, root: CellType, pushed: CellType, flatPushed: FlatCellTypeRec, flatCells: LIST OF FlatCellTypeRec _ NIL, flatWires: LIST OF FlatWireRec _ NIL] ~ { isIcon: BOOL; IsSelectedWire: CoreOps.EachWireProc ~ { FOR geometry: 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: Instance = CoreGeometry.GetTransf[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; }; }; <> SelectedCellType: PUBLIC PROC [design: Design, mode: Mode] RETURNS [instance: Instance, root: CellType _ NIL, cell: CellType, flatCell: FlatCellTypeRec _ [], transf: Instance] = { 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.WriteF["*** 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. transf _ CoreGeometry.Transform[design.actual.first.mightReplace, CoreGeometry.GetTransf[mode.decoration, cellInstance]]; } ELSE { multiple: BOOL; result: REF; [instance, multiple] _ CDOps.SelectedInstance[design]; IF multiple THEN {TerminalIO.WriteF["\n** Multiple instances selected. No action.\n"]; RETURN}; IF instance=NIL THEN {TerminalIO.WriteF["\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.WriteF["\n** Not a Core cell. No action.\n"]; RETURN}; cell _ root; transf _ instance; }; }; HighlightMenu: PROC [design: Design, mode: Mode] ~ { HighlightDesign[design, NIL]; SELECT CDMenus.CallMenu[highlightMenu] FROM $selected => { instance: 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.WriteF["*** No wire selected.\n"]; RETURN}; IF flatCells#NIL THEN TerminalIO.WriteF["Cell instances selected: corresponding actuals are highlighted.\n"]; TerminalIO.WriteF["The following wires have been selected:\t"]; FOR fw: LIST OF FlatWireRec _ flatWires, fw.rest WHILE fw#NIL DO TerminalIO.WriteF["\t%g", IO.rope[CoreFlat.WirePathRope[root, fw.first]]]; ENDLOOP; TerminalIO.WriteF["\n"]; HighlightNets[mode.decoration, design, instance, root, flatWires]; }; $named => { instance: 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.WriteF["*** 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]]]]; }; $wires => { HighlightWire: CoreOps.EachWireProc = { hinstances _ CDInstances.AppendToList[HighLightListInst[CoreGeometry.GetGeometry[mode.decoration, wire]], hinstances]; }; instance: Instance; root: CellType; cell: CellType; flatCell: FlatCellTypeRec; transf: Instance; hinstances: Instances _ NIL; [instance, root, cell, flatCell, transf] _ SelectedCellType[design, mode]; IF root=NIL THEN RETURN; IF cell.class#CoreClasses.recordCellClass THEN {TerminalIO.WriteF["*** Only applicable to record cells!\n"]; RETURN}; [] _ CoreOps.VisitWireSeq[NARROW [cell.data, CoreClasses.RecordCellType].internal, HighlightWire]; HighlightDesign[design, CoreGeometry.TransformList[transf, hinstances]]; }; $pins => { HighlightWire: CoreOps.EachWireProc = { hinstances _ CDInstances.AppendToList[HighLightListInst[CoreGeometry.GetPins[mode.decoration, wire]], hinstances]; }; instance: Instance; root: CellType; cell: CellType; flatCell: FlatCellTypeRec; transf: Instance; hinstances: Instances _ NIL; [instance, root, cell, flatCell, transf] _ SelectedCellType[design, mode]; IF root=NIL THEN RETURN; [] _ CoreOps.VisitWireSeq[cell.public, HighlightWire]; HighlightDesign[design, CoreGeometry.TransformList[transf, hinstances]]; }; ENDCASE => {}; }; ProcessData: TYPE = REF ProcessDataRec; ProcessDataRec: TYPE = RECORD [design: Design, key: ATOM, mode: Mode, filter: FilterProc]; <> 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: LIST OF Instance _ CDOps.InstList[processData.design], instances.rest WHILE instances#NIL DO CedarProcess.CheckAbort[]; IF CDProperties.GetDesignProp[processData.design, processData.key]=NIL THEN RETURN; -- no 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; }; <> BackgroundMenu: PROC [key: ATOM, design: Design, mode: Mode, filter: FilterProc] ~ { SELECT CDMenus.CallMenu[backgroundMenu] FROM $start => { IF CDProperties.GetDesignProp[design, key]#NIL THEN {TerminalIO.WriteF["*** 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.WriteRope["Background extraction started for this design\n"]; }; $stop => { process: CedarProcess.Process = NARROW [CDProperties.GetDesignProp[design, key]]; IF process=NIL THEN {TerminalIO.WriteF["*** Background extraction was not started for this design\n"]; RETURN}; CedarProcess.Abort[process]; CDProperties.PutDesignProp[design, key, NIL]; TerminalIO.WriteRope["Background extraction stopped for this design\n"]; }; ENDCASE => RETURN; }; HighLightWireGeometry: PROC [design: CD.Design, mode: Mode, name: ROPE, wires: LIST OF Wire] = { IF name=NIL THEN RETURN; -- no highlight done <> FOR insts: LIST OF CD.Instance _ 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: LIST OF CD.Instance _ 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, gs.first], geometry]; ENDLOOP; FOR i: NAT IN [0 .. w.size) DO AddGeometry[w[i]] ENDLOOP; }; geometry: LIST OF CD.Instance _ 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.WriteF["Highlight of the culprits done.\n"]; ENDLOOP; }; ExtractSelected: PROC [design: CD.Design, mode: Mode] = { nb: INT _ 0; HighlightDesign[design, NIL]; FOR instances: Instances _ 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.WriteF["*** Extraction failed in cell %g.\n", IO.rope[name]]; IF prop=CoreOps.nameProp THEN TerminalIO.WriteF["*** 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.WriteF["*** 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.WriteF["*** Extraction failed in cell %g.\n", IO.rope[name]]; TerminalIO.WriteF[ "*** 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.WriteF["*** Extraction failed in cell %g.\n", IO.rope[name]]; TerminalIO.WriteF[ "*** 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.WriteF["*** Extraction failed in cell %g.\n", IO.rope[name]]; TerminalIO.WriteF["*** Fusion by name problem: %g.\n", IO.rope[msg]]; HighLightWireGeometry[design, mode, name, LIST [wire]]; GOTO Failed; }; Sinix.StructuralLoop => { TerminalIO.WriteF["*** Extraction failed in cell %g.\n", IO.rope[name]]; TerminalIO.WriteF["*** 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.WriteF["*** Extraction returned NIL"] ELSE CoreOps.Print[ref: result, out: TerminalIO.TOS[], level: LAST [NAT]]; TerminalIO.WriteF["\n"]; ENDLOOP; IF nb=0 THEN TerminalIO.WriteF["*** No instance selected.\n"]; IF nb>1 THEN TerminalIO.WriteF["%g instances extracted.\n", IO.int[nb]]; EXITS Failed => RETURN; }; ExtractModeForCommand: PROC [key: REF] RETURNS [mode: Mode] ~ { mode _ GetExtractMode[key]; IF mode=NIL THEN TerminalIO.WriteF["*** Command not supported for this technology\n"]; }; HighlightCommand: PROC [command: CDSequencer.Command] ~ { mode: Mode = ExtractModeForCommand[command.key]; IF mode#NIL THEN HighlightMenu[command.design, mode]; }; HighlightLayoutCommand: PROC [command: CDSequencer.Command] ~ { mode: Mode = ExtractModeForCommand[command.design.technology]; IF mode#NIL THEN HighlightMenu[command.design, mode]; }; ExtractCommand: PROC [command: CDSequencer.Command] ~ { mode: Mode = ExtractModeForCommand[command.key]; IF mode#NIL THEN ExtractSelected[command.design, mode]; }; ExtractLayoutCommand: PROC [command: CDSequencer.Command] ~ { mode: Mode = ExtractModeForCommand[command.design.technology]; IF mode#NIL THEN ExtractSelected[command.design, mode]; }; BackgroundExtractionCommand: PROC [command: CDSequencer.Command] ~ { mode: Mode = NARROW [CDProperties.GetProp[command.key, extractModeAtom]]; 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^]; }; <> RegisterOtherProgramWithContext: PROC [technology: Technology, program: PROC [CDSequencer.Command], mode: Mode, prompt: ROPE, key: ATOM] ~ { [] _ CDProperties.RegisterProperty[key, $SinixOps]; CDProperties.PutProp[key, extractModeAtom, mode]; CDMenus.ImplementEntryCommand[menu: $OtherProgramMenu, entry: prompt, p: program, key: key, technology: technology]; }; RegisterHighlightCommand: PUBLIC PROC [technology: Technology _ NIL, mode: Mode, prompt: ROPE, key: ATOM] ~ { RegisterOtherProgramWithContext[technology, HighlightCommand, mode, prompt, key]; }; RegisterExtractCommand: PUBLIC PROC [technology: Technology _ NIL, mode: Mode, prompt: ROPE, key: ATOM] ~ { RegisterOtherProgramWithContext[technology, ExtractCommand, mode, prompt, key]; }; RegisterDefaultLayoutMode: PUBLIC PROC [technology: Technology, mode: Mode] ~ { IF technology=NIL THEN ERROR; CDProperties.PutProp[technology, extractModeAtom, mode]; CDMenus.ImplementEntryCommand[menu: $OtherProgramMenu, entry: "Extract layout", p: ExtractLayoutCommand, key: $ExtractLayout, technology: technology]; CDMenus.ImplementEntryCommand[menu: $OtherProgramMenu, entry: "Highlight net in layout", p: HighlightLayoutCommand, key: $HighlightNetInLayout, technology: technology]; }; RegisterBackgroundExtractionCommand: PUBLIC PROC [technology: Technology, mode: Mode, prompt: ROPE, key: ATOM, filter: FilterProc] = { [] _ CDProperties.RegisterProperty[key, $SinixOps]; CDProperties.PutProp[key, extractModeAtom, mode]; CDProperties.PutProp[key, $SinixBackgroundFilter, NEW [FilterProc _ filter]]; CDMenus.ImplementEntryCommand[menu: $OtherProgramMenu, entry: prompt, p: BackgroundExtractionCommand, key: key, technology: technology]; }; GetExtractMode: PUBLIC PROC [tech: REF] RETURNS [mode: Mode _ NIL] ~ { WITH tech SELECT FROM technology: Technology => mode _ NARROW [CDProperties.GetProp[technology, extractModeAtom]]; key: ATOM => { technology: Technology = CD.FetchTechnology[key]; mode _ NARROW [CDProperties.GetProp[ IF technology#NIL THEN technology ELSE key, extractModeAtom]]; }; ENDCASE => {}; }; <> [] _ CDProperties.RegisterProperty[extractModeAtom, $SinixOps]; [] _ CDProperties.RegisterProperty[$ExtractLayout, $SinixOps]; [] _ CDProperties.RegisterProperty[$HighlightNetInLayout, $SinixOps]; [] _ CDProperties.RegisterProperty[$SinixBackgroundFilter, $SinixOps]; CDMenus.CreateEntry[highlightMenu, "Highlight selected nets", $selected]; CDMenus.CreateEntry[highlightMenu, "Highlight named wire in selected cell", $named]; CDMenus.CreateEntry[highlightMenu, "Highlight all wires of selected cell", $wires]; CDMenus.CreateEntry[highlightMenu, "Highlight all pins of selected cell", $pins]; CDMenus.CreateEntry[backgroundMenu, "Start", $start]; CDMenus.CreateEntry[backgroundMenu, "Stop", $stop]; END.