DIRECTORY CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDInstances, CDOps, CDPopUpMenus, CDProperties, CDRects, CDSatellites, CDSequencer, CDViewer, CDViewHighlight, CedarProcess, Convert, Core, CoreClasses, CoreFlat, CoreOps, CoreGeometry, IO, PopUpMenus, PopUpSelection, Process, PW, RefTab, Rope, Sinix, SinixOps, TerminalIO, ViewerClasses; SinixOpsImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDInstances, CDOps, CDPopUpMenus, CDProperties, CDRects, CDSatellites, CDSequencer, CDViewer, CDViewHighlight, CedarProcess, Convert, CoreClasses, CoreFlat, CoreOps, CoreGeometry, IO, PopUpMenus, PopUpSelection, Process, PW, RefTab, Rope, Sinix, TerminalIO EXPORTS SinixOps SHARES CoreGeometry = BEGIN OPEN SinixOps; 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 [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 ]; }; SearchCoreGeometryInstance: PROC [possibleInst: CoreGeometry.Instance, instances: CD.InstanceList, design: CD.Design] RETURNS [BOOL] = { closed: CD.Instance = design.actual.first.mightReplace; WHILE instances#NIL DO IF SameCDInstance[instances.first, closed.trans, possibleInst] THEN RETURN [TRUE]; -- OK instances _ instances.rest; ENDLOOP; RETURN [FALSE]; -- not found }; 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 => {}; 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 [RefTab.Fetch[bindings, wire].val, 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]]; }; 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, design]]]; 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] = { 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; 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; selected: CD.InstanceList _ CDInstances.OnlySelected[CDOps.InstList[design]]; 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 SearchCoreGeometryInstance[geometry.first, selected, 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 SearchCoreGeometryInstance[possibleInst, selected, 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: 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; }; }; SelectedCellTypes: PUBLIC PROC [design: CD.Design, mode: Mode] RETURNS [cells: LIST OF CellType _ NIL] = { IF design.actual.rest#NIL THEN { root, cellType: CellType; IF CDOps.SelectedInstance[design].multiple THEN { TerminalIO.PutF["Can't handle multiple selections in pushed in cell.\n"]; RETURN[NIL]}; [root: root, cell: cellType] _ SelectedCellType[design, mode]; IF root=NIL THEN RETURN [NIL]; -- Extraction ended in error, message already printed cells _ LIST [cellType]; } ELSE FOR insts: CD.InstanceList _ CDOps.InstList[design], insts.rest WHILE insts#NIL DO result: REF; IF NOT insts.first.selected THEN LOOP; result _ ExtractCDInstance[insts.first, design, mode].result; IF result=NIL OR NOT ISTYPE [result, Core.CellType] THEN { TerminalIO.PutF["*** %g does not extract as a cell.\n", IO.rope[CDDirectory.Name[insts.first.ob, design]]]; RETURN[NIL]; }; cells _ CONS [NARROW [result, CellType], cells]; ENDLOOP; }; HighLightWireGeometry: PROC [design: CD.Design, mode: Mode, name: ROPE, wires: LIST OF Wire] = { IF name=NIL THEN RETURN; -- no highlight done 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[PW.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 *** Two wires with mismatching structures are fused: ", IO.rope[name]]; CoreOps.Print[wire1, TerminalIO.TOS[]]; TerminalIO.PutF["\nand: "]; CoreOps.Print[wire2, TerminalIO.TOS[]]; TerminalIO.PutF["\n.\n"]; HighLightWireGeometry[design, mode, name, LIST [wire1, wire2]]; GOTO Failed; }; Sinix.StructureMismatch => { TerminalIO.PutF["*** Extraction failed in cell %g.\n *** Actual: ", IO.rope[name]]; CoreOps.Print[actual, TerminalIO.TOS[]]; TerminalIO.PutF["\nand subPublic: "]; CoreOps.Print[subPublic, TerminalIO.TOS[]]; TerminalIO.PutF["\nhave mismatching structures for the index %g.\n", IO.int[index]]; 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.TOS[], 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 => {}; }; ExtractLayoutCommand: PROC [command: CDSequencer.Command] ~ { inner: PROC = { 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]]; }; CDEnvironment.DoWithWDir[CDEnvironment.GetWorkingDirectory[command.design], inner]; }; HighlightLayoutCommand: PROC [command: CDSequencer.Command] ~ { inner: PROC = { 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]]; }; CDEnvironment.DoWithWDir[CDEnvironment.GetWorkingDirectory[command.design], inner]; }; ExtractCommand: PROC [command: CDSequencer.Command] ~ { inner: PROC = { mode: Mode = NARROW [CDProperties.GetProp[command.key, $ExtractMode]]; IF mode#NIL THEN ExtractSelected[command.design, mode] ELSE ERROR; }; CDEnvironment.DoWithWDir[CDEnvironment.GetWorkingDirectory[command.design], inner]; }; HighlightCommand: PROC [command: CDSequencer.Command] ~ { inner: PROC = { mode: Mode = NARROW [CDProperties.GetProp[command.key, $ExtractMode]]; IF mode#NIL THEN HighlightMenu[command.design, mode] ELSE ERROR; }; CDEnvironment.DoWithWDir[CDEnvironment.GetWorkingDirectory[command.design], inner]; }; 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]; }; ProcessData: TYPE = REF ProcessDataRec; ProcessDataRec: TYPE = RECORD [design: CD.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: 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, processData.design], 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]; 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. SinixOpsImpl.mesa Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved. Jean-Marc Frailong September 4, 1987 2:35:20 pm PDT Bertrand Serlet September 15, 1987 7:42:46 pm PDT Barth, February 18, 1987 8:20:55 pm PST Wire utilities All arguments are canonized Adds a flat wire to a set of flat wires. 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. Answer if possibleInst is one of the instances passed. The instances must be from the currently pushed-in cell. Highlight -- 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; Links between Core and ChipNDale We came from that one from a RecordCell [vertical move] We want to deal with deeper last Implementation of ChipNDale commands to be replaced by a PushByName one day CDSequencer commands Silly line, just because CD does not do the right thing! Silly line, just because CD does not do the right thing! Silly line, just because CD does not do the right thing! Silly line, just because CD does not do the right thing! Registration of extract modes 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; }; This process tries to extract all instances in the design 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 ʘ– "Cedar" stylešœ™Icode– "Cedar" stylešœB™BKšœ3™3Kšœ1™1Kšœ$Ïk™'—J˜š œ˜ Jšœ ˜¢J˜Jšœ%˜%J˜ Jšœ˜Jšœ%œ ˜GJšœ˜—J˜šÏn œœœ˜Jšœœæœ'œ!˜¼Jšœ ˜Jšœ˜Jšœœ ˜—head™Kšœ™š žœœ œœ&œœ˜bš œœœ"œœ˜@Kšœ0œœœ˜EKšœ˜—šœœœ˜+Kšœtœœœ˜‰Kšœ˜—Kšœœ˜K˜K˜—K™(šž œœaœœœœœ˜§Kšœj˜jš œœœ"œœ˜@Kšœ/œœ ˜IKšœ˜—Kšœ œ˜'šœœœœ˜"KšœF˜FKšœ˜—Kšœ ˜K˜—K™—šœ ™ Kšœœ™®Kšœ“™“šžœœ œœ2œœœ˜šœ˜Kšœœ˜Kšœ@œ˜DKšœk˜kKšœ˜—K˜K˜—š žœœ2œœ œœ˜ˆJšœo™oKšœœ-˜7šœ œ˜Kš œ=œœœÏc˜XK˜Kšœ˜—KšœœŸ ˜J˜——™ š ž œœœ#œ œ˜ašœ ˜ Jšœœœ˜BJšœœD˜YJšœ˜—J˜J˜—š žœœœ%œœœ˜ršœ œœ˜Jšœ œK˜\Jšœ˜—J˜K˜—š žœœœ œœ˜DKšœœ˜šœ œ˜Kšœœ1˜:Kšœ œ=˜JKšœ˜—KšŸ™Kšœœ™šœœ œ™!KšŸ6™6Kšœ œ6™CKšœ™—š œ œœAœ œ˜iJšœF˜FKšœœ:˜YKšœ˜—K˜K˜—šž œœœ"œœ&œœ˜‘Jšœ œœ˜"šž œ#˜/šœ'˜)Jšœ•˜™—J˜—šž œ#˜/šž œ˜$šœœ œ˜(Jšœ.˜2Jšœœ/˜:—šœ'˜)Jšœ‘˜•—J˜—Jšœ3˜3J˜—Kšžœœ!˜FKšœ”˜”Kšœ œœ0˜FKšœN˜NK˜K˜——™ š žœœœ*œœ˜OKšœ+œ(˜\K˜K˜—šžœœœ œœœ œ˜‚Kš œ œœœœœœ˜IKšœ)Ÿ:˜cKšœg˜gšœ ˜ KšœQ˜QKšœ˜—K˜K˜—šžœœœ œœ œ œœ˜{Kšœœ˜ šœœœ˜ Kšœ6˜6Kšœ˜Kšœ˜—š œœœœ%œ œ˜Qšœœ˜&Kšœ_œ>˜ŸKšœ˜Kšœ˜—Jšœ$˜$Kšœ˜—KšœR˜Ršœœ˜Kšœœ8˜BKšœH˜NKšœH˜NKšœ œ ˜#—Kšœ˜K™—š ž œœœ œœ œM˜K˜Kšœ7™7šžœ"˜3Jš œ œœœ œ˜-Jšœ‘˜‘šœc˜eJšœY˜]—K˜—šž œÏbœ ˜-Kš œ œœœ œ˜-šœœ˜KšœŸ˜¢Kšœœ+˜˜@Kšœ1œœœ˜e—Kšœ˜—K˜—K˜KšœC˜CKšœœœœ˜Kšœ)˜)šœ˜ Kšœ9˜=Kšœ˜Kšœ"œ˜7Kšœ8˜8šœœœ˜ Kšœ˜Kšœœ<œœ˜LKšœ œL˜\š œœœœœ˜CKšœZ˜ZKšœ˜—Kšœ˜—K˜—K˜——™$šžœœœ œœ œœY˜Ëšœœ˜šœ˜Kšœ.˜.Kš œ œœœœ ˜CK˜Kšœ_œ˜fKšœœœœ˜Kšœ œœ œœœœ>œœ˜‡Kšœ˜KšœYŸ(˜Kšœ™˜™—šœœ˜Kšœ œ˜Kšœœ˜ Jšœ6˜6šœ ˜ JšœFœ˜R—šœ œ˜Kšœ?œ˜K—Kšœ œœœ˜Kšœ:˜:Jšœœœœ˜šœœœ˜Jšœ˜Jšœ=œ˜L—Kšœ$˜$—K˜—K˜K˜—šžœœœ œœ œœ œ˜jšœ˜šœ˜Jšœ˜šœ)œ˜1JšœI˜IJšœœ˜ —Jšœ>˜>Jš œœœœœŸ5˜TJšœœ ˜Jšœ˜—š œœœ3œœ˜WJšœœ˜ Jšœœœœ˜&Jšœ=˜=š œœœœœœ˜:šœ7˜7Jšœ1˜3—Jšœœ˜ Jšœ˜—Jšœœœ˜1Jš˜——Jšœ˜J˜—š žœœ œœ œœ ˜`Jš œœœœŸ˜-Jšœ&™&š œœ3œœ˜Ršž œœ˜JšœœœŸ+˜QJšœœ ˜šœTœœ˜fJš œœœ)œœ˜SJšœ œB˜QJšœ˜—Jš œœœœœ˜9J˜—Jšœ#œ˜'Jšœœœœ˜Jš œœ œœœ˜;Jšœœœ.œ˜HJšœ œœœ˜Kšœ5˜5Jšœ5˜5Jšœ˜—J˜J˜—šžœœ œ˜9Jšœœ˜ Kšœœ˜š œ œ7œ œ˜^Jšœœ˜ Jšœœœœ˜+J˜ šœS˜Sšœ˜Jšœ7œ ˜Fšœ˜Jš œYœœ œœ ˜Jšœfœ œœ˜Ÿ—Jšœ˜ J˜—šœ"˜"Jšœmœ ˜|Jšœ œ˜'Jšœ˜Jšœ œ˜'Jšœ˜Jšœ*œ˜?Jšœ˜ J˜—šœ˜JšœDœ ˜SJšœ!œ˜(Jšœ%˜%Jšœ$œ˜+JšœEœ ˜TJšœ*œ ˜9Jšœ˜ J˜—šœ˜Jšœ7œ ˜FJšœ5œ ˜CJšœ*œ ˜7Jšœ˜ J˜—šœ˜Jšœ7œ ˜FJšœAœ'˜jJšœ*œ Ÿ"˜ZJšœ˜ J˜—Jšœ ˜ —šœœ˜Kšœ/˜3Kšœ,œ œœ˜J—Jšœ˜Jšœ˜—Jšœœ0˜˜>JšœE˜EJšœF˜FJ˜Jšœ˜——…—\²†¹