DIRECTORY Core, CoreClasses, CoreOps, CoreProperties, IO, MessageWindow, Pipal, PipalConnect, PipalCore, PipalInt, PipalMos, PipalSinix, RefTab, Rope, RopeList, SymTab, TerminalIO; PipalSinixImpl: CEDAR PROGRAM IMPORTS CoreClasses, CoreOps, CoreProperties, IO, MessageWindow, Pipal, PipalConnect, PipalCore, PipalInt, PipalMos, RefTab, Rope, RopeList, SymTab, TerminalIO EXPORTS PipalSinix SHARES PipalCore = BEGIN OPEN PipalSinix; CellType: TYPE = Core.CellType; Wire: TYPE = Core.Wire; WireSeq: TYPE = Core.WireSeq; Wires: TYPE = Core.Wires; Properties: TYPE = Core.Properties; ROPE: TYPE = Core.ROPE; ROPES: TYPE = LIST OF ROPE; Object: TYPE = Pipal.Object; Objects: TYPE = Pipal.Objects; rect: PROC [r: PipalInt.Rectangle] RETURNS [IO.Value] = { RETURN [IO.rope[PipalInt.RectangleToRope[r]]]; }; CreateRoot: PUBLIC PROC [fused: RefTab.Ref, size: NAT] RETURNS [wire: Wire] = { wire _ CoreOps.CreateWires[size: size]; [] _ RefTab.Store[fused, wire, NIL]; }; RootWire: PUBLIC PROC [fused: RefTab.Ref, wire: Wire] RETURNS [rootWire: Wire] = { IF wire=NIL THEN SIGNAL InternalBug[]; rootWire _ NARROW [RefTab.Fetch[fused, wire].val]; IF rootWire=NIL THEN RETURN [wire]; IF rootWire=wire THEN SIGNAL InternalBug[]; rootWire _ RootWire[fused, rootWire]; [] _ RefTab.Replace[fused, wire, rootWire]; }; EnumerateRoots: PUBLIC PROC [fused: RefTab.Ref, each: PROC [wire: Wire]] = { EachPair: RefTab.EachPairAction = {IF val=NIL THEN each[NARROW [key]]}; [] _ RefTab.Pairs[fused, EachPair]; }; PropFusionProc: TYPE = PROC [object: Object, prop: ATOM, value1, value2: REF ANY] RETURNS [value: REF ANY]; NameFusion: PropFusionProc = { value _ OrNames[object, NARROW [value1], NARROW [value2]]; }; DefaultFusion: PropFusionProc = { IF value1#NIL AND value2#NIL AND value1#value2 THEN SIGNAL FusionPropMismatch[object, prop, value1, value2]; value _ IF value1=NIL THEN value2 ELSE value1; }; FuseProperties: PUBLIC PROC [mode: Mode, object: Object, fused, root: Wire] = { EachProperty: PROC [prop: ATOM, val: REF ANY] = { rootValue: REF _ CoreProperties.GetWireProp[root, prop]; SELECT prop FROM CoreOps.nameProp => CoreProperties.PutWireProp[root, prop, NameFusion[object, prop, val, rootValue]]; mode.decoration.geometryProp => PipalCore.AddGeometry[mode.decoration, root, PipalCore.GetGeometry[mode.decoration, fused]]; mode.decoration.portProp => PipalCore.AddPort[mode.decoration, root, PipalCore.GetPort[mode.decoration, fused]]; -- this never happens during connector extraction, because pins are not yet there, but might occur when called from SisyphImpl.ProcessGlobalName ENDCASE => CoreProperties.PutWireProp[root, prop, DefaultFusion[object, prop, val, rootValue]]; }; CoreProperties.Enumerate[fused.properties, EachProperty]; }; DeleteFused: PROC [mode: Mode, object: Object, fused: RefTab.Ref, loser, winner: Wire] = { IF ~RefTab.Fetch[fused, loser].found THEN SIGNAL InternalBug[]; IF RootWire[fused, loser]#loser THEN SIGNAL InternalBug[]; IF ~RefTab.Fetch[fused, winner].found THEN SIGNAL InternalBug[]; IF RootWire[fused, winner]#winner THEN SIGNAL InternalBug[]; IF loser=winner THEN SIGNAL InternalBug[]; -- should never occur FuseProperties[mode, object, loser, winner]; loser.properties _ NIL; -- to help GC [] _ RefTab.Store[fused, loser, winner]; }; StructuredFusion: PUBLIC PROC [mode: Mode, object: Object, fused: RefTab.Ref, wire1, wire2: Wire] RETURNS [wire: Wire] = { wire1 _ RootWire[fused, wire1]; wire2 _ RootWire[fused, wire2]; IF wire1=wire2 THEN RETURN [wire1]; SELECT TRUE FROM wire1=wire2 => wire _ wire1; wire1.size=0 => {DeleteFused[mode, object, fused, wire1, wire2]; wire _ wire2}; wire2.size=0 => {DeleteFused[mode, object, fused, wire2, wire1]; wire _ wire1}; wire1.size=wire2.size => { wire _ CreateRoot[fused, wire1.size]; FOR i: NAT IN [0 .. wire.size) DO wire[i] _ StructuredFusion[mode, object, fused, wire1[i], wire2[i]]; ENDLOOP; DeleteFused[mode, object, fused, wire1, wire]; DeleteFused[mode, object, fused, wire2, wire]; }; ENDCASE => SIGNAL FusionStructureMismatch[object, wire1, wire2]; }; OrNames: PROC [object: Object, name1, name2: ROPE] RETURNS [name: ROPE _ NIL] = { IF name1=NIL THEN RETURN [name2]; IF name2=NIL THEN RETURN [name1]; IF Rope.Equal[name1, name2] THEN RETURN [name1]; SIGNAL FusionPropMismatch[object, CoreOps.nameProp, name1, name2]; }; LayoutProcessSatellites: PROC [object: Object, satellites: LIST OF ROPE, props: Core.Properties] RETURNS [Core.Properties] = { WHILE satellites#NIL DO props _ LayoutProcessName[object, satellites.first, props]; satellites _ satellites.rest; ENDLOOP; RETURN [props]; }; LayoutProcessName: PROC [object: Object, name: ROPE, props: Core.Properties] RETURNS [Core.Properties] = { name _ OrNames[object, name, NARROW [CoreProperties.GetProp[props, CoreOps.nameProp]]]; RETURN [CoreProperties.PutProp[props, CoreOps.nameProp, name]]; }; ComputeNameWires: PROC [mode: Mode, object: Object, fused: RefTab.Ref] RETURNS [nameToWires: SymTab.Ref] = { EachWire: PROC [wire: Wire] = { name: ROPE _ CoreOps.GetShortWireName[wire]; wires: Wires _ NARROW [SymTab.Fetch[nameToWires, name].val]; IF name=NIL OR CoreOps.Member[wires, wire] THEN RETURN; wires _ CONS [wire, wires]; [] _ SymTab.Store[nameToWires, name, wires]; }; nameToWires _ SymTab.Create[mod: 3]; -- contains (for every name) the list of roots that have it for name EnumerateRoots[fused, EachWire]; }; LayoutFusionByName: PUBLIC PostProcessProc = { EachNameWires: SymTab.EachPairAction = { name: ROPE = NARROW [key]; wires: Wires _ NARROW [val]; wire: Wire _ RootWire[fused, wires.first]; wires _ wires.rest; WHILE wires#NIL DO wire _ StructuredFusion[mode, object, fused, wire, wires.first]; PutF["Fusion by name for '%g'.\n", IO.rope[name]]; CoreProperties.PutWireProp[wire, $FusedByName, $FusedByName]; wires _ wires.rest; ENDLOOP; }; [] _ SymTab.Pairs[ComputeNameWires[mode, object, fused], EachNameWires]; }; NoFusionByName: PUBLIC PostProcessProc = { EachNameWires: SymTab.EachPairAction = { uniqueID: INT _ 0; name: ROPE = NARROW [key]; wires: Wires _ NARROW [val]; wire: Wire _ RootWire[fused, wires.first]; [] _ CoreOps.SetShortWireName[wire, name]; wires _ wires.rest; IF wires=NIL THEN RETURN; PutF["NO fusion by name for '%g'.\n", IO.rope[name]]; WHILE wires#NIL DO [] _ CoreOps.SetShortWireName[wires.first, IO.PutFR["%g$%g$", IO.rope[name], IO.int[uniqueID]]]; uniqueID _ uniqueID + 1; wires _ wires.rest; ENDLOOP; }; [] _ SymTab.Pairs[ComputeNameWires[mode, object, fused], EachNameWires]; }; SchematicsFusionByName: PUBLIC PostProcessProc = { EachNameWires: SymTab.EachPairAction = { name: ROPE = NARROW [key]; hasComponents: BOOL = CoreOps.ParseWireName[name].components#NIL; wires: Wires _ NARROW [val]; wire: Wire _ RootWire[fused, wires.first]; wires _ wires.rest; WHILE wires#NIL DO wire _ StructuredFusion[mode, object, fused, wire, wires.first]; PutF["Fusion by name for '%g'.\n", IO.rope[name]]; CoreProperties.PutWireProp[wire, $FusedByName, $FusedByName]; wires _ wires.rest; ENDLOOP; [] _ SymTab.Store[nameToWire, name, wire]; IF NOT hasComponents THEN [] _ CoreOps.SetShortWireName[wire, name] ELSE names _ CONS [name, names]; }; nameToWire: SymTab.Ref = SymTab.Create[mod: 11]; names: ROPES _ NIL; [] _ SymTab.Pairs[ComputeNameWires[mode, object, fused], EachNameWires]; FOR list: ROPES _ RopeList.Sort[names, RopeList.Compare], list.rest WHILE list#NIL DO name: ROPE _ list.first; wire: Wire = RootWire[fused, NARROW [SymTab.Fetch[nameToWire, name].val]]; base: ROPE; components: ROPES _ NIL; matchingWire: Wire; [base, components] _ CoreOps.ParseWireName[name]; matchingWire _ NARROW [SymTab.Fetch[nameToWire, base].val]; WHILE components#NIL DO index: INT _ -1; IF matchingWire=NIL THEN SIGNAL FusionByNameMismatch[object, IO.PutFR["Path name %g does not correspond to any wire", IO.rope[name]], wire]; matchingWire _ RootWire[fused, matchingWire]; FOR i: NAT IN [0 .. matchingWire.size) DO subWireName: ROPE _ CoreOps.GetShortWireName[matchingWire[i]]; IF subWireName=NIL THEN subWireName _ IF i<256 THEN numbers[i] ELSE IO.PutR1[IO.int[i]]; -- speedup hack to avoid allocating lots of ropes IF Rope.Equal[subWireName, components.first] THEN { IF index=-1 THEN index _ i ELSE FusionByNameMismatch[object, IO.PutFR["Current wire has 2 or more sub-wires with field `%g'", IO.rope[components.first]], wire]; }; ENDLOOP; IF index=-1 THEN SIGNAL FusionByNameMismatch[object, IO.PutFR["Current wire does not have a sub-wire with field `%g'", IO.rope[components.first]], wire]; matchingWire _ matchingWire[index]; components _ components.rest; ENDLOOP; [] _ StructuredFusion[mode, object, fused, matchingWire, wire]; ENDLOOP; }; FusionWire: PROC [mode: Mode, object: Object, fused: RefTab.Ref, publicToActual: RefTab.Ref, public: Wire, copyProps: BOOL] RETURNS [actual: Wire] = { EachProperty: PROC [prop: ATOM, val: REF ANY _ NIL] = { newVal: REF ANY _ SELECT prop FROM mode.decoration.portProp, mode.decoration.geometryProp => NIL, ENDCASE => val; CoreProperties.PutWireProp[actual, prop, newVal]; }; actual _ NARROW [RefTab.Fetch[publicToActual, public].val]; IF actual#NIL THEN RETURN; actual _ CreateRoot[fused, public.size]; IF copyProps THEN CoreProperties.Enumerate[public.properties, EachProperty]; FOR i: NAT IN [0 .. public.size) DO actual[i] _ FusionWire[mode, object, fused, publicToActual, public[i], copyProps]; ENDLOOP; [] _ RefTab.Store[publicToActual, public, actual]; }; FusionWireSeq: PROC [mode: Mode, object: Object, fused: RefTab.Ref, publicToActual: RefTab.Ref, public: WireSeq] RETURNS [actual: Wire] = { actual _ CoreOps.CreateWires[public.size]; FOR i: NAT IN [0 .. actual.size) DO actual[i] _ FusionWire[mode, object, fused, publicToActual, public[i], FALSE]; ENDLOOP; }; CreateDAGWireSeq: PROC [table: RefTab.Ref] RETURNS [wire: WireSeq] = { wires: LIST OF Wire _ NIL; EachKeyDelete: RefTab.EachPairAction = { WireDelete: PROC [wire: Wire] = { IF ~RefTab.Delete[table, wire] THEN RETURN; -- already done FOR i: NAT IN [0 .. wire.size) DO WireDelete[wire[i]]; ENDLOOP; }; wire: Wire _ NARROW [key]; FOR i: NAT IN [0 .. wire.size) DO WireDelete[wire[i]]; ENDLOOP; }; index: NAT _ 0; SummarizeWires: RefTab.EachPairAction = { wire[index] _ NARROW [key]; index _ index+1; }; [] _ RefTab.Pairs[table, EachKeyDelete]; wire _ CoreOps.CreateWires[RefTab.GetSize[table]]; [] _ RefTab.Pairs[table, SummarizeWires]; IF index#RefTab.GetSize[table] THEN SIGNAL InternalBug[]; }; checkOverlap: BOOL _ FALSE; MakeRecord: PROC [mode: Mode, object: Object, fused: RefTab.Ref, cellInstances: LIST OF CoreClasses.CellInstance] RETURNS [record: CellType] = { publics: RefTab.Ref _ RefTab.Create[5]; internals: RefTab.Ref _ RefTab.Create[5]; WireDagIfy: PROC [wire: Wire, maxIter: NAT _ 32] = { IF maxIter=0 THEN SIGNAL StructuralLoop[object, wire]; -- probably loop in the Wire structure IF RootWire[fused, wire]#wire THEN SIGNAL InternalBug[]; FOR i: NAT IN [0 .. wire.size) DO wire[i] _ RootWire[fused, wire[i]]; WireDagIfy[wire[i], maxIter-1]; ENDLOOP; }; InternalDagIfy: PROC [wire: Wire] = { IF CoreProperties.GetWireProp[wire, $Public]=$Public THEN {[] _ RefTab.Store[publics, wire, NIL]; CoreProperties.PutWireProp[wire, $Public, NIL]}; [] _ RefTab.Store[internals, wire, NIL]; WireDagIfy[wire]; }; EnumerateRoots[fused, InternalDagIfy]; FOR list: LIST OF CoreClasses.CellInstance _ cellInstances, list.rest WHILE list#NIL DO instance: CoreClasses.CellInstance _ list.first; actual: Wire _ instance.actual; FOR i: NAT IN [0 .. actual.size) DO wire: Wire _ RootWire[fused, actual[i]]; IF ~CoreOps.CorrectConform[wire, instance.type.public[i]] THEN SIGNAL StructureMismatch[object, i, actual, instance.type.public]; actual[i] _ wire; ENDLOOP; ENDLOOP; record _ CoreClasses.CreateRecordCell[ public: CreateDAGWireSeq[publics], internal: CreateDAGWireSeq[internals], instances: cellInstances, giveNames: TRUE ]; IF NOT checkOverlap THEN RETURN; }; debugCache: BOOL _ FALSE; objectCache: Pipal.ObjectCache _ Pipal.CreateObjectCache[]; CacheData: TYPE = RECORD [ mode: Mode, context: Context, result: REF, props: Properties _ NIL ]; SearchCache: PROC [object: Object, mode: Mode, context: Context] RETURNS [found: BOOL _ FALSE, result: REF, props: Properties] = { IF debugCache THEN RETURN; FOR list: LIST OF CacheData _ NARROW [RefTab.Fetch[objectCache, object].val], list.rest WHILE list#NIL DO IF list.first.mode=mode AND mode.objectEqual[object, list.first.context, context] THEN RETURN [found: TRUE, result: list.first.result, props: list.first.props]; ENDLOOP; }; AddInCache: PROC [object: Object, mode: Mode, context: Context, result: REF, props: Properties] = { cache: LIST OF CacheData _ NARROW [RefTab.Fetch[objectCache, object].val]; cache _ CONS [[mode: mode, context: context, result: result, props: props], cache]; [] _ RefTab.Store[objectCache, object, cache]; }; Extract: PUBLIC ExtractProc = { found: BOOL; [found, result, props] _ SearchCache[object, mode, context]; IF found THEN RETURN; [result, props] _ NonCachingExtract[object, mode, context]; AddInCache[object, mode, context, result, props]; }; NonCachingExtract: PUBLIC ExtractProc = { refProc: REF ExtractProc; refProc _ NARROW [Pipal.ObjectMethod[object, mode.extractMethod]]; [result, props] _ (IF refProc=NIL THEN ExtractConnectized ELSE refProc^)[object, mode, context]; IF result=NIL THEN RETURN; WITH result SELECT FROM wire: Wire => IF props#NIL THEN SIGNAL CallerBug[]; wires: Wires => IF props#NIL THEN SIGNAL CallerBug[]; cellType: CellType => IF NOT PipalCore.HasObject[mode.decoration, cellType] THEN SIGNAL CallerBug[]; -- decorations missing! ENDCASE => IF result#NIL THEN SIGNAL CallerBug[]; -- probably some ExtractProc is grossly wrong }; ExtractConnectized: PUBLIC ExtractProc = { SELECT PipalConnect.GetType[object, mode.connectMode] FROM null => result _ NIL; leaf => IF PipalConnect.CountPorts[object, mode.connectMode, PipalInt.AbutBox[object]]=1 THEN { wire: Wire _ CoreOps.CreateWire[]; PipalCore.PutPort[mode.decoration, wire, object]; result _ wire; } ELSE { wires: Wires _ NIL; EachPort: PipalConnect.EachPortProc = { wire: Wire _ CoreOps.CreateWire[]; IF port=Pipal.void THEN SIGNAL InternalBug[]; PipalCore.PutPort[mode.decoration, wire, PipalInt.TransformObject[transformation, port]]; wires _ CONS [wire, wires]; }; [] _ PipalConnect.EnumeratePorts[object, mode.connectMode, PipalInt.AbutBox[object], EachPort]; result _ wires; }; composite => { cc: PipalConnect.Composer _ PipalConnect.GetComposer[object, mode.connectMode, PipalInt.AbutBox[object]]; record: CellType _ ExtractConnector[mode, object, context, cc]; PipalCore.PutObject[mode.decoration, record, object]; result _ record; }; ENDCASE => SIGNAL CallerBug[]; }; PortToWireSequence: TYPE = RECORD [SEQUENCE size: NAT OF Core.Wire]; SubInstanceSeq: TYPE = RECORD [SEQUENCE size: NAT OF REF PortToWireSequence]; SetSubPorts: PROC [publicToActual: RefTab.Ref, child: Object, mode: Mode, childTrans: PipalInt.Transformation, addGeometry: BOOL] RETURNS [subPorts: REF PortToWireSequence] = { SearchWire: PipalConnect.EachPortProc = { EachWirePair: RefTab.EachPairAction = { pub: Wire = NARROW [key]; act: Wire = NARROW [val]; pubGeom: Object = PipalCore.GetPort[mode.decoration, pub]; IF pubGeom=Pipal.void THEN RETURN; IF NOT mode.connectMode.touch[mode.connectMode.touch, childTrans, pubGeom, transformation, port] THEN RETURN; subPorts[portIndex] _ act; IF NOT addGeometry THEN RETURN; PipalCore.AddGeometry[mode.decoration, act, PipalInt.TransformObject[childTrans, pubGeom]]; }; IF port=Pipal.void THEN SIGNAL InternalBug[]; subPorts[portIndex] _ NIL; [] _ RefTab.Pairs[publicToActual, EachWirePair]; IF subPorts[portIndex] = NIL THEN SIGNAL InternalBug[]; }; subPorts _ NEW [PortToWireSequence[PipalConnect.CountPorts[child, mode.connectMode, PipalInt.AbutBox[child]]]]; [] _ PipalConnect.EnumeratePorts[child, mode.connectMode, PipalInt.AbutBox[child], SearchWire, childTrans]; }; ExtractConnector: PROC [mode: Mode, object: Object, context: Context, cc: PipalConnect.Composer] RETURNS [record: CellType] = { index: NAT _ 0; portsToWires: REF PortToWireSequence; fused: RefTab.Ref _ RefTab.Create[3]; subInstances: REF SubInstanceSeq; currentInstances: LIST OF CoreClasses.CellInstance _ NIL; EachChild: PipalInt.EachChildProc = { subResult: REF; subProps: Properties; subType: PipalConnect.Type _ PipalConnect.GetType[child, mode.connectMode]; [subResult, subProps] _ Extract[child, mode, context]; IF subResult=NIL THEN {IF subType#null THEN SIGNAL CallerBug[]} ELSE WITH subResult SELECT FROM subWire: Wire => { dagTable: RefTab.Ref _ RefTab.Create[1]; [] _ FusionWire[mode, object, fused, dagTable, subWire, TRUE]; subInstances[index] _ SetSubPorts[dagTable, child, mode, transformation, TRUE]; }; subWires: Wires => { dagTable: RefTab.Ref _ RefTab.Create[9]; WHILE subWires#NIL DO [] _ FusionWire[mode, object, fused, dagTable, subWires.first, TRUE]; subWires _ subWires.rest; ENDLOOP; subInstances[index] _ SetSubPorts[dagTable, child, mode, transformation, TRUE]; }; subCellType: CellType => { publicToActual: RefTab.Ref _ RefTab.Create[(2*subCellType.public.size+3)/2]; instance: CoreClasses.CellInstance _ CoreClasses.CreateInstance[ actual: FusionWireSeq[mode, object, fused, publicToActual, subCellType.public], type: subCellType, props: subProps ]; PipalCore.PutTrans[mode.decoration, instance, transformation]; subInstances[index] _ SetSubPorts[publicToActual, child, mode, transformation, FALSE]; currentInstances _ CONS [instance, currentInstances]; }; ENDCASE => SIGNAL InternalBug[]; index _ index + 1; }; PutF["Extracting [%g] cell.\n", IO.rope[mode.decoration.name]]; subInstances _ NEW [SubInstanceSeq[PipalInt.CountChildren[cc.object]]]; portsToWires _ NEW [PortToWireSequence[cc.ports.size]]; [] _ PipalInt.Enumerate[cc.object, EachChild]; FOR i: NAT IN [0 .. cc.size) DO node: PipalConnect.Node = cc[i]; wire: Wire _ NIL; FOR bb: NAT IN [0 .. node.size) DO binding: PipalConnect.Binding _ node[bb]; actual: Wire _ subInstances[binding.childIndex][binding.nodeIndex]; wire _ IF wire = NIL THEN actual ELSE StructuredFusion[mode, object, fused, wire, actual]; ENDLOOP; IF wire=NIL THEN wire _ CreateRoot[fused, 0]; IF i { atom: ATOM = NARROW [annotation.value]; proc: ExtractProc _ FetchExtractProc[atom]; IF proc=NIL THEN { TerminalIO.PutF["*** ExtractProc $%g not registered. You must run the program defining it.\n", IO.atom[atom]]; SIGNAL CallerBug[]; }; [result, props] _ proc[annotation.child, mode, context]; }; PipalMos.indirectProp => { publicToActual: RefTab.Ref _ RefTab.Create[]; CopyPins: CoreOps.EachWirePairProc = { PipalCore.PutPort[mode.decoration, actualWire, PipalCore.GetPort[mode.decoration, publicWire]]; [] _ RefTab.Store[publicToActual, publicWire, actualWire]; }; indCT, icon: CellType; [result, props] _ Extract[annotation.child, mode, context]; indCT _ NARROW [result]; icon _ CreateIcon[indCT]; PipalCore.PutObject[mode.decoration, icon, object]; [] _ CoreOps.VisitBindingSeq[actual: icon.public, public: indCT.public, eachWirePair: CopyPins]; result _ icon; }; PipalMos.transistorProp => RETURN ExtractTransistor[object, mode, context]; Pipal.nameProp => { name: ROPE _ NARROW [annotation.value]; [result, props] _ NonCachingExtract[annotation.child, mode, context]; IF result=NIL THEN RETURN; WITH result SELECT FROM subWire: Wire => subWire.properties _ LayoutProcessName[object, name, subWire.properties]; subWires: Wires => SIGNAL CallerBug[]; -- what to do with that name! subCellType: CellType => subCellType.properties _ LayoutProcessName[object, name, subCellType.properties]; ENDCASE => SIGNAL InternalBug[]; }; ENDCASE => [result, props] _ ExtractConnectized[object, mode, context]; }; LayoutExtractStar: ExtractProc = { star: PipalMos.Star = NARROW [object]; satellites: LIST OF ROPE _ PipalMos.GetNonItalicRopes[star]; IF NOT star.overlayStar THEN { [result, props] _ Extract[star.master, mode, context]; IF result=NIL THEN RETURN; WITH result SELECT FROM subWire: Wire => { wire: Wire _ CoreOps.CopyWire[subWire]; PipalCore.PutPort[mode.decoration, wire, object]; wire.properties _ LayoutProcessSatellites[object, satellites, wire.properties]; result _ wire; }; subWires: Wires => SIGNAL CallerBug[]; -- what to do with that name! subCellType: CellType => props _ LayoutProcessSatellites[object, satellites, props]; ENDCASE => SIGNAL InternalBug[]; } ELSE { [result, props] _ NonCachingExtract[star.master, mode, context]; IF result=NIL THEN RETURN; WITH result SELECT FROM subWire: Wire => SIGNAL CallerBug[]; -- object satellite!? subWires: Wires => SIGNAL CallerBug[]; -- what to do with that name! subCellType: CellType => subCellType.properties _ LayoutProcessSatellites[object, satellites, subCellType.properties]; ENDCASE => SIGNAL InternalBug[]; }; }; ExtractTransistor: PUBLIC ExtractProc = { Decorate: PROC [port: CoreClasses.TransistorPort, geom: Object] = { wire: Wire = cellType.public[ORD [port]]; PipalCore.PutPort[mode.decoration, wire, geom]; PipalCore.PutGeometry[mode.decoration, wire, geom]; }; type: PipalMos.TransistorType; ch1, ch2, gate, bulk: Object; width, length: INT; coreType: CoreClasses.TransistorType; cellType: CellType; [type, ch1, ch2, gate, bulk, width, length] _ PipalMos.ExtractTransistor[object]; coreType _ SELECT type FROM nE => nE, pE => pE, ENDCASE => ERROR; cellType _ CoreClasses.CreateTransistor[ type: coreType, length: length, width: width ]; Decorate[gate, gate]; Decorate[ch1, ch1]; Decorate[ch2, ch2]; IF bulk#Pipal.void THEN Decorate[Vdd, bulk]; PipalCore.PutObject[mode.decoration, cellType, object]; result _ cellType; }; ExtractCellAsWire: PUBLIC ExtractProc = { wire: Wire _ CoreOps.CreateWire[]; PipalCore.PutPort[mode.decoration, wire, object]; result _ wire; }; ExtractNull: PUBLIC ExtractProc = {result _ NIL}; AlwaysTrue: PROC [Object, Context, Context] RETURNS [BOOL _ TRUE] = {}; iconClass: PUBLIC Core.CellClass _ CoreOps.SetClassPrintProc[NEW [Core.CellClassRec _ [name: "Icon", recast: RecastIcon, layersProps: TRUE]], PrintIcon]; CreateIcon: PUBLIC PROC [cellType: CellType, name: ROPE _ NIL, props: Properties _ NIL] RETURNS [icon: CellType] = { icon _ CoreOps.CreateCellType[ class: iconClass, public: CoreOps.CopyWire[cellType.public], data: cellType, name: name, props: props ]; }; RecastIcon: Core.RecastProc = {new _ NARROW [me.data]}; PrintIcon: CoreOps.PrintClassProc = { ct: CellType _ NARROW [data]; CoreOps.PrintIndent[indent, out]; out.PutF["Icon of `%g':\n", IO.rope[CoreOps.GetCellTypeName[ct]]]; CoreOps.PrintCellType[cellType: ct, out: out, indent: indent, level: level]; }; InternalBug: PUBLIC SIGNAL [] = CODE; CallerBug: PUBLIC SIGNAL [] = CODE; FusionPropMismatch: PUBLIC SIGNAL [object: Object, prop: ATOM, value1, value2: REF] = CODE; FusionStructureMismatch: PUBLIC SIGNAL [object: Object, wire1, wire2: Wire] = CODE; StructureMismatch: PUBLIC SIGNAL [object: Object, index: NAT, actual, subPublic: WireSeq] = CODE; FusionByNameMismatch: PUBLIC SIGNAL [object: Object, msg: ROPE, wire: Wire] = CODE; StructuralLoop: PUBLIC SIGNAL [object: Object, wire: Wire] = CODE; OutputType: TYPE = {none, terminal, messageWindow}; outputFlag: OutputType _ terminal; PutF: PUBLIC PROC [format: ROPE, v1, v2, v3, v4, v5: IO.Value _ [null[]]] = { SELECT outputFlag FROM terminal => TerminalIO.PutF[format, v1, v2, v3, v4, v5]; messageWindow => MessageWindow.Append[IO.PutFR[format, v1, v2, v3, v4, v5], TRUE]; ENDCASE => {}; }; layoutMode: PUBLIC Mode _ NEW [ModeRec _ [ decoration: PipalCore.layoutDecoration, extractMethod: Pipal.RegisterMethod["LayoutExtraction"], connectMode: PipalConnect.layoutMode, extractAnnotationProp: $CMosBExtractProc, -- for the sake of compatibility! objectEqual: AlwaysTrue, postProcessFused: LayoutFusionByName ]]; schematicsMode: PUBLIC Mode _ NIL; rawLayoutMode: PUBLIC Mode _ NIL; RopeArray: TYPE = ARRAY [0 .. 256) OF ROPE; numbers: REF RopeArray _ NEW [RopeArray]; FOR i: NAT IN [0 .. 256) DO numbers[i] _ IO.PutR1[IO.int[i]] ENDLOOP; RegisterExtractProc[$ExtractCellAsWire, ExtractCellAsWire]; RegisterExtractProc[$ExtractNull, ExtractNull]; PipalCore.RegisterRoutingLayer[$Ndif]; PipalCore.RegisterRoutingLayer[$Pdif]; PipalCore.RegisterRoutingLayer[$Pol]; PipalCore.RegisterRoutingLayer[$Met]; PipalCore.RegisterRoutingLayer[$Met2]; PipalCore.RegisterRoutingLayer[$Ovg]; Pipal.PutClassMethod[Pipal.annotationClass, layoutMode.extractMethod, NEW [ExtractProc _ LayoutExtractAnnotation]]; Pipal.PutClassMethod[PipalMos.starClass, layoutMode.extractMethod, NEW [ExtractProc _ LayoutExtractStar]]; END. τPipalSinixImpl.mesa Copyright Σ 1985, 1986, 1987, 1988 by Xerox Corporation. All rights reversed. Created by Bertrand Serlet August 15, 1985 2:09:54 pm PDT Bertrand Serlet June 7, 1988 3:12:41 pm PDT Pradeep Sindhu May 5, 1986 5:16:10 pm PDT Barth, April 18, 1986 4:42:48 pm PST gbb April 16, 1987 6:19:54 pm PDT Jean-Marc Frailong January 17, 1988 9:07:29 pm PST Type Aliases Wire Fusion The following PROC implements Fisher-Galler fusion, not for efficiency, but for simplicity This mechanism could be exported if we wanted that. Appends the properties of fused to the ones of root, but treating short names specially This proc really does the fusion of fused and root, by wiping fused of some tables, and adding interesting properties of fused to root. Satellites and Names We first fuse all the nameWire with same name, and at the same time prepare the list of all the names that have components We sort the names, using the trick that foo[2].mumble or foo[2][3] are after foo[2] in the lexicographic order Constructing WireSeq and CellTypes Creates a DAG Wire from a RefTab, getting rid of wires that have their father also in the list. delete all the sons 32 should be enough to avoid 815 We find out who are the internals, and we clean up wires We replace in all instances wires by their roots We build the CellType FOR list1: LIST OF CoreClasses.CellInstance _ cellInstances, list1.rest WHILE list1#NIL DO inst1: CoreClasses.CellInstance _ list1.first; bbox1: PipalInt.Rectangle _ PipalInt.BBox[PipalCore.GetObject[mode.decoration, inst1.type], PipalCore.GetTrans[mode.decoration, inst1]]; IF list1#NIL THEN FOR list2: LIST OF CoreClasses.CellInstance _ list1.rest, list2.rest WHILE list2#NIL DO inst2: CoreClasses.CellInstance _ list2.first; bbox2: PipalInt.Rectangle _ PipalInt.BBox[PipalCore.GetObject[mode.decoration, inst2.type], PipalCore.GetTrans[mode.decoration, inst2]]; IF NOT PipalInt.DoRectanglesIntersect[bbox1, bbox2] THEN LOOP; ENDLOOP; ENDLOOP; Extraction Maps object -> LIST OF CacheData We fill the cache We detect trivial causes of bugs! Maps a portIndex (as obtained by PipalConnect.EnumeratePorts to wires). What about computing subContext here, such as the overlap? it is impossible here to check for conformance, since fusion might have been done differently in different parts of the DAG What about modifying the context!? We set portsToWires, once all fusion is over Some Extract Procs Extraction mode procs Icon class Exceptions Progress Report Some Extraction Modes Initialization Layer properties Κ– "cedar" style˜codešœ™KšœN™NKšœ6Οk™9Kšœ+™+Kšœ&™)Kšœ!™$Kšœ™!Kšœ/™2—K™š œ˜ Kšœ,˜,Kšœ˜Kšœ@˜@Kšœ˜Kšœ˜—K˜•StartOfExpansion[]šΠbnœœ˜Kšœ'œo˜ŸKšœ ˜Kšœ ˜Kšœœ ˜—head™ Jšœ œ˜Jšœœ ˜Jšœ œ˜Jšœœ˜Jšœ œ˜#Jšœœœ˜Jš œœœœœ˜Jšœœ˜šœ œ˜J˜—šœœœœ ˜9Kšœœ$˜.Kšœ˜K˜——™ š Οn œœœœœ˜OJšœ'˜'Jšœœ˜$J˜J˜—JšœœH™ZšŸœœœ!œ˜RJšœœœœ˜&Jšœ œ!˜2Jšœ œœœ˜#Jšœœœ˜+Jšœ%˜%Jšœ+˜+J˜J˜—šŸœœœœ˜LJš Ÿœœœœœ ˜GJšœ#˜#K˜K˜—K™3šœœœœœœœ œœ˜kK˜—šž œ˜Kšœœ œ ˜:K˜K˜—šž œ˜!Jšœœœœœœœ2˜lJš œœœœœ˜.K˜J™—JšœW™WšŸœœœ4˜Oš Ÿ œœœœœ˜1Jšœ œ*˜8šœ˜Jšœh˜hJšœ|˜|JšœrΟcΠbc˜‚Jšœ^˜e—J˜—Jšœ9˜9J˜J™—Jšœ‡™‡šŸ œœI˜ZJšœ#œœ˜?Jšœœœ˜:Jšœ$œœ˜@Jšœ œœ˜Kšœ œœœœ œœœ  1˜Ššœ+œ˜3Jš œ œ œœ?œ ˜ Jšœ˜—Jšœ˜—Jš œ œœœ@œ ˜™Jšœ#˜#Jšœ˜Jšœ˜—Jšœ?˜?Jšœ˜—J˜——™"šŸ œœfœœ˜–š Ÿ œœœœœœ˜7šœœœœ˜"Jšœ:œ˜>Jšœ˜—Jšœ1˜1J˜—Jšœ œ,˜;Jšœœœœ˜Jšœ)˜)Jšœ œ;˜Lšœœœ˜#JšœR˜RJšœ˜—Jšœ2˜2J˜J˜—šŸ œœ^œ˜‹Jšœ*˜*šœœœœ˜$JšœGœ˜NJšœ˜—J˜J˜—Jšœ œT™ašŸœœœ˜FJšœœœœ˜šž œ˜(šŸ œœ˜!Jšœœœ ˜;šœœœ˜!Jšœ˜Jšœ˜—J˜—Jšœ œ˜šœœœœ˜"Jšœ™Jšœ˜Jšœ˜—J˜—Jšœœ˜šžœ˜)Jšœœ˜J˜J˜—Jšœ(˜(Jšœ2˜2Jšœ)˜)Jšœœœ˜9J˜J˜—šœœœ˜J˜—š Ÿ œœ@œœœ˜Jšœ'˜'Jšœ)˜)šŸ œœœ ˜4Jšœ ™ Jšœ œœ &˜]Jšœœœ˜8šœœœ˜!Jšœ#˜#Jšœ˜Jšœ˜—Jšœ˜—šŸœœ˜%šœ3˜9Jšœ"œ-œ˜X—Jšœ#œ˜(Jšœ˜Jšœ˜—Jšœ8™8Jšœ&˜&Jšœ0™0š œœœ5œœ˜WJšœ0˜0Jšœ˜šœœœ˜#Jšœ(˜(Jšœ8œœ=˜‚Jšœ˜Jšœ˜—Jšœ˜—Jšœ™šœ&˜&JšœI˜IJšœ˜Jšœ ˜J˜—Jšœœœœ˜ š ΠbkΟb’£’£6’£’£’™ZJš£.™.Jš£ˆ™ˆš’£’£’£’£’£’£3’£’£’™iJš£.™.Jš£ˆ™ˆJš’£’£.’£’£™>J™Jš’£™—Jš’£™—J˜——™ šœ œœ˜J˜—šœ;˜;Jšœœœ ™ —šœ œœ˜Jšœ˜Jšœœ˜$Jšœ˜J˜—š Ÿ œœ0œ œœ œ˜‚Jšœ œœ˜š œœœ œ4œœ˜iJš œœ7œœ œ6˜ Jšœ˜—J˜J˜—J™šŸ œœ8œ˜cJšœœœ œ)˜JJšœœG˜SJšœ.˜.J˜J˜—šŸœœ˜Jšœœ˜ Jšœ<˜JšœIœ˜OJ˜—šœ˜Jšœ(˜(šœ œ˜Jšœ?œ˜EJšœ˜Jšœ˜—JšœIœ˜OJ˜—šœ˜JšœL˜Lšœ@˜@JšœP˜PJšœ"˜"Jšœ˜—Jšœx™{Jšœ>˜>JšœOœ˜VJšœœ˜5J˜—Jšœœ˜#—J˜J˜J˜—Jšœ œ˜?Jšœœ5˜GJšœœ%˜7Jš£"™"Jšœ.˜.šœœœ˜J˜ Jšœ œ˜šœœœ˜"Jšœ)˜)JšœC˜CJš œœœœœ5˜ZJšœ˜—Jšœœœ˜-Jšœœ )˜YJšœ˜—JšœF˜FJšœ,™,šœœœ˜%Jšœ.˜.Jšœ ˜-Jšœ3˜3Jšœ6˜6Jšœ˜—Jšœ<˜