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 4, 1986 4:14:56 pm PST
DIRECTORY
CD, CDCells, CDDirectory, CDProperties, CDRects, CDSymbolicObjects, CDTexts, CMosB,
Core, CoreClasses, CoreGeometry, CoreOps, CoreProperties, HashTable, IO, PW, Rope, Sinix, SinixOps, SinixRawCMosB, TerminalIO;
SinixRawCMosBImpl: CEDAR PROGRAM
IMPORTS CD, CDCells, CDDirectory, CDProperties, CDRects, CDSymbolicObjects, CDTexts, CMosB, CoreGeometry, CoreClasses, CoreOps, CoreProperties, HashTable, IO, PW, Rope, Sinix, SinixOps, TerminalIO
EXPORTS SinixRawCMosB
SHARES CDCells, CDRects, CDSymbolicObjects, CDTexts, Sinix = 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: PW.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 = {
pins: LIST OF CD.Instance ← NARROW [obj.specificRef, CD.CellPtr].contents;
wire: Wire ← CoreOps.CreateWire[];
CoreGeometry.PutPins[mode.decoration, wire, pins];
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 = {
cp: CD.CellPtr;
IF NOT CDCells.IsCell[ob] THEN RETURN;
total ← total + 1;
cp ← NARROW [ob.specificRef];
FOR il: CD.InstanceList ← cp.contents, il.rest WHILE il#NIL DO
value: REF = HashTable.Fetch[usage, il.first.ob].value;
IF NOT CDCells.IsCell[il.first.ob] THEN LOOP;
[] ← HashTable.Store[usage, il.first.ob, IF value=NIL THEN $unique ELSE $many];
ENDLOOP;
};
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: LIST OF CD.Instance ← 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: LIST OF CD.Instance ← 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;
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];
IF NOT flattenSomeChild THEN RETURN;
TerminalIO.WriteF["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: LIST OF CD.Instance ← CoreGeometry.GetGeometry[mode.decoration, old];
IF geometry#NIL THEN geometry ← LIST [CoreGeometry.Transform[transf, 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: LIST OF CD.Instance ← CoreGeometry.GetGeometry[mode.decoration, pub];
IF geometry#NIL THEN CoreGeometry.PutGeometry[
mode.decoration,
act,
CONS [CoreGeometry.Transform[transf, geometry.first], CoreGeometry.GetGeometry[mode.decoration, act]]
]; -- Hack to save some space for now!
};
name: ROPE = CoreOps.GetCellTypeName[rct[i].type];
transf: CD.Instance = CoreGeometry.GetTransf[mode.decoration, rct[i]];
subObj: CD.Object = transf.ob;
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[subObj], name] THEN ERROR;
TerminalIO.WriteF[" %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.PutTransf[mode.decoration, instance, CoreGeometry.Transform[transf, CoreGeometry.GetTransf[mode.decoration, subrct[j]]]];
instances ← CONS [instance, instances]
ENDLOOP;
-- We flush the Sinix cache for name
IF CoreProperties.GetCellTypeProp[rct[i].type, $RawFlatten]=$Smash THEN CDProperties.PutObjectProp[subObj, Sinix.cacheProp, NIL];
};
ENDLOOP;
result ← CoreClasses.CreateRecordCell[record.public, CoreOps.UnionWire[rct.internal, CoreOps.CreateWire[newInternals]], instances, NIL, record.properties, TRUE];
IF CDProperties.GetObjectProp[obj, $RawFlatten]#$RawFlatten AND instances=NIL THEN CoreProperties.PutCellTypeProp[NARROW [result], $RawFlatten, $Keep];
TerminalIO.WriteF[".\n"];
};
Initialization
Meme: PROC [className: ATOM] = {Same[CD.FetchObjectClass[className, CMosB.cmosB]]};
Same: PROC [class: CD.ObjectClass] = {
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.cellClass, mode.extractProcProp, $RawExtractCell];
Pins
Same[CDSymbolicObjects.pinClass]; Same[CDSymbolicObjects.segmentClass]; Same[CDSymbolicObjects.markClass];
Rectangles
Same[CDRects.bareRectClass];
Contacts
Meme[$C2SimpleCon]; Meme[$C2WellSimpleCon];
Meme[$C2LargeSimpleCon]; Meme[$C2LargeWellSimpleCon];
Meme[$C2DifShortCon]; Meme[$C2WellDifShortCon];
Meme[$C2Via]; Meme[$C2LargeVia];
Diffusion wires
Meme[$C2PDifRect]; Meme[$C2NDifRect];
Transistors
Meme[$C2Trans]; Meme[$C2WellTrans];
Angle Transistors
Meme[$C2LTrans]; Meme[$C2LWellTrans];
Texts
Same[CDTexts.textClass];
SinixOps.RegisterExtractCommand[CMosB.cmosB, mode, "Raw Extraction", $RawCMosBExtract];
SinixOps.RegisterHighlightCommand[CMosB.cmosB, mode, "Raw Highlight", $RawCMosBHighlight];
END.