SinixRawCMosBImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reversed.
Created by Bertrand Serlet October 30, 1986 12:49:32 pm PST
Bertrand Serlet December 19, 1986 4:17:28 pm PST
DIRECTORY
CD, CDBasics, CDCells, CDDirectory, CDProperties, CDRects, CDSymbolicObjects, CDTexts, CMosB,
Core, CoreClasses, CoreGeometry, CoreOps, CoreProperties, HashTable, IO, PWObjects, Rope, Sinix, SinixOps, SinixRawCMosB, TerminalIO;
SinixRawCMosBImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDCells, CDDirectory, CDProperties, CDRects, CDSymbolicObjects, CDTexts, CMosB, CoreGeometry, CoreClasses, CoreOps, CoreProperties, HashTable, IO, PWObjects, Rope, Sinix, SinixOps, TerminalIO
EXPORTS SinixRawCMosB
SHARES CDCells, CDRects, CDSymbolicObjects, CDTexts = BEGIN
Types
CellType: TYPE = Core.CellType;
Wire: TYPE = Core.Wire;
Wires: TYPE = Core.Wires;
Object: TYPE = CD.Object;
Properties: TYPE = Core.Properties;
ROPE: TYPE = Core.ROPE;
Mode
standardMode: Sinix.Mode = SinixOps.GetExtractMode[CMosB.cmosB];
mode: PUBLIC Sinix.Mode ← NEW [Sinix.ModeRec ← [
extractProcProp: PWObjects.RegisterProp[$RawCMosBExtractProc, TRUE],
decoration: CoreGeometry.CreateDecoration["RawCMosB"],
nbOfLayers: standardMode.nbOfLayers,
instanceLayer: standardMode.instanceLayer,
touchProc: CoreGeometry.Touch,
fusionByName: none,
equalProc: SmallerOverlap,
userData: UserData
]];
we use the knowledge of what is the cache and what is the call
SmallerOverlap: PROC [obj: Object, cacheProperties: CD.PropList, cacheUserData: REF, properties: CD.PropList, userData: REF] RETURNS [cacheOK: BOOL] = {
cacheData: REF INT = NARROW [cacheUserData];
data: REF INT = NARROW [userData];
cacheOK ← Sinix.CompareProps[obj, cacheProperties, cacheUserData, properties, userData] AND cacheData^>=data^;
};
UserData: PROC [design: CD.Design] RETURNS [REF] = {RETURN [NEW [INT ← 0]]};
Extracting PadBlank
ExtractCellAsWire: Sinix.ExtractProc = {
EachInst: CDCells.InstEnumerator = {pins ← CONS [[inst.ob, inst.trans], pins]};
pins: CoreGeometry.Instances ← NIL;
wire: Wire ← CoreOps.CreateWire[];
CoreGeometry.PutPins[mode.decoration, wire, pins];
[] ← CDCells.EnumerateInstances[obj, EachInst];
result ← wire;
};
Marking Cells used once
Mark: PROC [design: CD.Design] RETURNS [total, marked: INT ← 0] = {
usage: HashTable.Table = HashTable.Create[]; -- maps every cell to the containing cell. Objects are keys, and values are either $unique, or $many if several cell contain that object.
CountEachUse: CDDirectory.EachEntryAction = {
EachInst: CDCells.InstEnumerator = {
value: REF = HashTable.Fetch[usage, inst.ob].value;
IF NOT CDCells.IsCell[inst.ob] THEN RETURN;
[] ← HashTable.Store[usage, inst.ob, IF value=NIL THEN $unique ELSE $many];
};
IF NOT CDCells.IsCell[ob] THEN RETURN;
total ← total + 1;
[] ← CDCells.EnumerateInstances[ob, EachInst];
};
MarkUniques: HashTable.EachPairAction = {
IF value=$many THEN RETURN;
marked ← marked + 1;
CDProperties.PutProp[key, $RawFlatten, $RawFlatten];
};
[] ← CDDirectory.Enumerate[design, CountEachUse];
[] ← HashTable.Pairs[usage, MarkUniques];
};
Computing corresponding cells
MatchSourceToExtracted: PROC [sourcePublic: Wire, extractedCT: CellType, name: ROPENIL, props: Properties ← NIL] RETURNS [new: CellType] = {
FillTable: PROC [extractedWire: Wire] = {
FillTableInternal: PROC [sourcePublic, newPublic: Wire] = {
prevSource: Wire;
sourcePins: CoreGeometry.Instances ← CoreGeometry.GetPins[standardMode.decoration, sourcePublic];
IF NOT CoreGeometry.TouchListList[sourcePins, extractedPins] THEN RETURN;
prevSource ← NARROW [HashTable.Fetch[table, extractedWire].value];
IF prevSource#NIL AND prevSource#newPublic THEN ERROR;
[] ← HashTable.Store[table, extractedWire, newPublic];
};
EachWirePair: CoreOps.EachWirePairProc = {FillTableInternal[actualWire, publicWire]};
extractedPins: CoreGeometry.Instances ← CoreGeometry.GetPins[mode.decoration, extractedWire];
[] ← CoreOps.VisitBindingSeq[sourcePublic, public, EachWirePair];
};
public: Wire ← CoreOps.CopyWire[sourcePublic];
table: HashTable.Table ← HashTable.Create[];
CoreOps.VisitRootAtomics[extractedCT.public, FillTable];
new ← CoreClasses.CreatePermutedRecordCell[iconPublic: public, schCell: extractedCT, table: table, name: name, props: props];
};
Cell extraction
ExplicitPins: CoreOps.EachWireProc = {
CoreGeometry.PutPins[mode.decoration, wire, CoreGeometry.GetPins[mode.decoration, wire]];
};
RawExtractCell: Sinix.ExtractProc = {
flattenSomeChild: BOOLFALSE;
rct: CoreClasses.RecordCellType;
new, record: CellType;
newInternals: Wires ← NIL; -- used only if flatten of a child necessary
instances: LIST OF CoreClasses.CellInstance ← NIL; -- used only if flatten of a child necessary
[result, props] ← Sinix.ExtractCell[obj, mode, properties, userData];
record ← NARROW [result];
rct ← NARROW [record.data];
IF rct.size=0 THEN CoreProperties.PutCellTypeProp[record, $RawFlatten, $Keep];
IF CDProperties.GetObjectProp[obj, $RawFlatten]=$RawFlatten THEN CoreProperties.PutCellTypeProp[record, $RawFlatten, $Smash];
FOR i: NAT IN [0 .. rct.size) DO
IF CoreProperties.GetCellTypeProp[rct[i].type, $RawFlatten]#NIL THEN flattenSomeChild ← TRUE;
ENDLOOP;
IF flattenSomeChild OR CoreProperties.GetCellTypeProp[record, $RawFlatten]#NIL THEN [] ← CoreOps.VisitWireSeq[record.public, ExplicitPins];
[] ← CoreOps.VisitWireSeq[record.public, ExplicitPins]; -- we want to avoid the TransWireIR lazyness which is using the InterestRect
IF NOT flattenSomeChild THEN RETURN;
TerminalIO.PutF["In cell %g, flattening:", IO.rope[CDDirectory.Name[obj]]];
we explicit the pins to avoid circularity (and to gain some speed up in the shared case)
[] ← CoreOps.VisitWireSeq[record.public, ExplicitPins];
FOR i: NAT IN [0 .. rct.size) DO
IF CoreProperties.GetCellTypeProp[rct[i].type, $RawFlatten]=NIL
THEN instances ← CONS [rct[i], instances]
ELSE {
The following code does not deal properly with DAGS. Who cares?
CreateWire: PROC [old: Wire] RETURNS [wire: Wire] = {
geometry: CoreGeometry.Instances ← CoreGeometry.GetGeometry[mode.decoration, old];
IF geometry#NIL THEN geometry ← LIST [CoreGeometry.Transform[trans, geometry.first]]; -- Hack to save some space for now!
wire ← CoreOps.CreateWire[];
CoreGeometry.PutGeometry[mode.decoration, wire, geometry];
newInternals ← CONS [wire, newInternals];
};
AddInTable: PROC [subInternal: Wire] = {
IF HashTable.Fetch[intToInt, subInternal].value#NIL THEN RETURN;
[] ← HashTable.Store[intToInt, subInternal, CreateWire[subInternal]];
};
CreateActual: PROC [oldAct: Wire] RETURNS [newAct: Wire] = {
newAct ← NARROW [HashTable.Fetch[intToInt, oldAct].value];
IF newAct#NIL THEN RETURN;
IF oldAct.size=0
THEN [] ← HashTable.Store[intToInt, oldAct, newAct ← CreateWire[oldAct]]
ELSE {
newAct ← CoreOps.CreateWires[size: oldAct.size];
FOR i: NAT IN [0 .. oldAct.size) DO newAct[i] ← CreateActual[oldAct[i]] ENDLOOP;
};
};
DecorateBinding: HashTable.EachPairAction = {
pub: Wire = NARROW [key];
act: Wire = NARROW [value];
geometry: CoreGeometry.Instances ← CoreGeometry.GetGeometry[mode.decoration, pub];
IF geometry#NIL THEN CoreGeometry.AddGeometry[
mode.decoration, act, LIST [CoreGeometry.Transform[trans, geometry.first]]
]; -- Hack to save some space for now!
};
name: ROPE = CoreOps.GetCellTypeName[rct[i].type];
trans: CoreGeometry.Transformation = CoreGeometry.GetTrans[mode.decoration, rct[i]];
subrct: CoreClasses.RecordCellType = NARROW [rct[i].type.data];
intToInt: HashTable.Table ← CoreOps.CreateBindingTable[rct[i].type.public, rct[i].actual];
[] ← HashTable.Pairs[intToInt, DecorateBinding];
IF NOT Rope.Equal[CDDirectory.Name[CoreGeometry.GetObject[mode.decoration, rct[i].type]], name] THEN ERROR;
TerminalIO.PutF[" %g[%g]", IO.rope[name], IO.int[subrct.size]];
CoreOps.VisitRootAtomics[subrct.internal, AddInTable];
FOR j: NAT IN [0 .. subrct.size) DO
instance: CoreClasses.CellInstance ← CoreClasses.CreateInstance[actual: CreateActual[subrct[j].actual], type: subrct[j].type, props: subrct[j].properties];
CoreGeometry.PutTrans[mode.decoration, instance, CDBasics.ComposeTransform[itemInCell: CoreGeometry.GetTrans[mode.decoration, subrct[j]], cellInWorld: trans]];
instances ← CONS [instance, instances]
ENDLOOP;
-- We flush the Sinix cache for name
IF CoreProperties.GetCellTypeProp[rct[i].type, $RawFlatten]=$Smash THEN Sinix.FlushCache[CoreGeometry.GetObject[mode.decoration, rct[i].type]];
};
ENDLOOP;
new ← CoreClasses.CreateRecordCell[record.public, CoreOps.UnionWire[rct.internal, CoreOps.CreateWire[newInternals]], instances, NIL, record.properties, TRUE];
CoreGeometry.PutObject[mode.decoration, new, CoreGeometry.GetObject[mode.decoration, record]];
IF CDProperties.GetObjectProp[obj, $RawFlatten]#$RawFlatten AND instances=NIL THEN CoreProperties.PutCellTypeProp[new, $RawFlatten, $Keep];
TerminalIO.PutF[".\n"];
result ← new;
};
Initialization
Same: PROC [nameOrClass: REF] = {
class: CD.ObjectClass;
WITH nameOrClass SELECT FROM
c: CD.ObjectClass => class ← c;
r: ATOM  => class ← CD.FetchObjectClass[r, CMosB.cmosB];
ENDCASE  => ERROR;
CDProperties.PutProp[class, mode.extractProcProp, CDProperties.GetProp[class, standardMode.extractProcProp]];
};
Registering extract procs
Sinix.RegisterExtractProc[$RawExtractCell, RawExtractCell];
Sinix.RegisterExtractProc[$ExtractCellAsWire, ExtractCellAsWire];
Cells
CDProperties.PutProp[CDCells.pCellClass, mode.extractProcProp, $RawExtractCell];
Pins
Same[CDSymbolicObjects.pinClass]; Same[CDSymbolicObjects.segmentClass]; Same[CDSymbolicObjects.markClass];
Rectangles
Same[CDRects.bareRectClass];
Contacts
Same[$C2SimpleCon]; Same[$C2WellSimpleCon];
Same[$C2LargeSimpleCon]; Same[$C2LargeWellSimpleCon];
Same[$C2DifShortCon]; Same[$C2WellDifShortCon];
Same[$C2Via]; Same[$C2LargeVia];
Diffusion wires
Same[$C2PDifRect]; Same[$C2NDifRect];
Transistors
Same[$C2Trans]; Same[$C2WellTrans];
Angle Transistors
Same[$C2LTrans]; Same[$C2LWellTrans];
Texts
Same[CDTexts.rigidTextClass];
Same[CDTexts.flipTextClass];
SinixOps.RegisterModeCommands[mode, CMosB.cmosB];
END.