<> <> <> <> <> <> <> <> <<>> 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] = { <<32 should be enough to avoid 815>> 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[]; < LIST OF CacheData>> 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> FOR i: NAT IN [0 .. cc.ports.size) DO wire: Wire _ RootWire[fused, portsToWires[i]]; portsToWires[i] _ wire; -- useless of course! CoreProperties.PutWireProp[wire, $Public, $Public]; PipalCore.AddPort[mode.decoration, wire, cc.ports[i]]; ENDLOOP; record _ MakeRecord[mode, object, fused, currentInstances]; PutF["Extracted [%g] cell (%g instances)\n", IO.rope[mode.decoration.name], IO.int[PipalInt.CountChildren[cc.object]]]; }; <> registeredExtractProcs: RefTab.Ref _ RefTab.Create[]; RegisterExtractProc: PUBLIC PROC [key: ATOM, extractProc: ExtractProc] = { IF NOT RefTab.Store[registeredExtractProcs, key, NEW [ExtractProc _ extractProc]] THEN TerminalIO.PutF["ExtractProc overwritten for $%g.\n", IO.atom[key]]; }; FetchExtractProc: PUBLIC PROC [key: ATOM] RETURNS [extractProc: ExtractProc _ NIL] = { refProc: REF ExtractProc _ NARROW [RefTab.Fetch[registeredExtractProcs, key].val]; IF refProc#NIL THEN RETURN [refProc^]; }; LayoutExtractAnnotation: ExtractProc = { annotation: Pipal.Annotation = NARROW [object]; SELECT annotation.key FROM mode.extractAnnotationProp => { 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.