SinixRawCMosBImpl.mesa
Copyright Ó 1985, 1987 by Xerox Corporation. All rights reversed.
Created by Bertrand Serlet October 30, 1986 12:49:32 pm PST
Bertrand Serlet July 13, 1987 11:11:00 pm PDT
Last Edited by: Louis Monier March 3, 1987 10:28:59 pm PST
DIRECTORY
CD, CDBasics, CDCells, CDDirectory, CDProperties, CDRects, CDRoutingObjects, CDSymbolicObjects, CDTexts, CMosB,
Core, CoreClasses, CoreGeometry, CoreGeometryBackdoor, CoreOps, CoreProperties,
IO, PW, RefTab, Rope, Sinix, SinixOps, SinixRawCMosB, TerminalIO;
SinixRawCMosBImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDCells, CDDirectory, CDProperties, CDRects, CDRoutingObjects, CDSymbolicObjects, CDTexts, CMosB, CoreGeometry, CoreGeometryBackdoor, CoreClasses, CoreOps, CoreProperties, IO, PW, RefTab, 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];
justKeepOne: BOOLFALSE;
mode: PUBLIC Sinix.Mode ← NEW [Sinix.ModeRec ← [
extractProcProp: PW.RegisterProp[$RawCMosBExtractProc, TRUE],
decoration: CoreGeometry.CreateDecoration["RawCMosB"],
instanceEqualProc: InstanceEqual,
objectEqualProc: ObjectEqual,
nbOfLayers: standardMode.nbOfLayers,
instanceLayer: standardMode.instanceLayer,
touchProc: standardMode.touchProc,
fusionByName: none,
userData: UserData,
nameProc: standardMode.nameProc
]];
Attention: we use the knowledge of what is the cache and what is the call
ObjectEqual: PROC [obj: Object, cacheUserData: REF, userData: REF] RETURNS [cacheOK: BOOL] = {
cacheData: REF INT = NARROW [cacheUserData];
data: REF INT = NARROW [userData];
RETURN [cacheData^>=data^];
};
InstanceEqual: PROC [obj: Object, cacheProperties: CD.PropList, cacheUserData: REF, properties: CD.PropList, userData: REF] RETURNS [cacheOK: BOOL] = {
cacheOK ← Sinix.CompareProperties[obj, cacheProperties, cacheUserData, properties, userData] AND ObjectEqual[obj, cacheUserData, userData];
};
UserData: PROC [design: CD.Design] RETURNS [REF] = {RETURN [NEW [INT ← 0]]};
Marking Cells used once
Mark: PROC [design: CD.Design] RETURNS [total, marked: INT ← 0] = {
usage: RefTab.Ref = RefTab.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.EachObjectProc = {
EachInst: CDCells.InstEnumerator = {
value: REF = RefTab.Fetch[usage, inst.ob].val;
IF NOT CDCells.IsCell[inst.ob] THEN RETURN;
[] ← RefTab.Store[usage, inst.ob, IF value=NIL THEN $unique ELSE $many];
};
IF NOT CDCells.IsCell[me] THEN RETURN;
total ← total + 1;
[] ← CDCells.EnumerateInstances[me, EachInst];
};
MarkUniques: RefTab.EachPairAction = {
IF val=$many THEN RETURN;
marked ← marked + 1;
CDProperties.PutProp[key, $RawFlatten, $RawFlatten];
};
[] ← CDDirectory.EnumerateDesign[design, CountEachUse];
[] ← RefTab.Pairs[usage, MarkUniques];
};
Cell extraction
IsOverglass: PROC [obj: CD.Object] RETURNS [BOOL] = {
RETURN [obj.class=CDRects.bareRectClass AND obj.layer=CMosB.ovg];
};
same as CoreGeometry.GetGeometry, but only keeps 1 instances (+ all overglass rectangles!).
SpecialGetGeometry: PROC [wire: Wire] RETURNS [geometry: CoreGeometry.Instances ← NIL, ovg: BOOLFALSE] = {
ConsEachGeom: CoreGeometry.EachInstanceProc = {
SELECT TRUE FROM
IsOverglass[instance.obj] => {ovg ← TRUE; geometry ← CONS [instance, geometry]};
geometry=NIL => geometry ← LIST [instance];
ENDCASE => IF NOT justKeepOne THEN geometry ← CONS [instance, geometry];
};
[] ← CoreGeometry.EnumerateGeometry[mode.decoration, wire, ConsEachGeom];
};
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 NOT flattenSomeChild THEN RETURN;
TerminalIO.PutF["In cell %g, flattening:", IO.rope[PW.Name[obj]]];
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; ovg: BOOL;
[geometry, ovg] ← SpecialGetGeometry[old];
geometry ← CoreGeometry.TransformList[trans, geometry];
wire ← CoreOps.CreateWire[];
CoreGeometry.PutGeometry[mode.decoration, wire, geometry];
newInternals ← CONS [wire, newInternals];
};
AddInTable: PROC [subInternal: Wire] = {
IF RefTab.Fetch[intToInt, subInternal].val#NIL THEN RETURN;
[] ← RefTab.Store[intToInt, subInternal, CreateWire[subInternal]];
};
CreateActual: PROC [oldAct: Wire] RETURNS [newAct: Wire] = {
newAct ← NARROW [RefTab.Fetch[intToInt, oldAct].val];
IF newAct#NIL THEN RETURN;
IF oldAct.size=0
THEN [] ← RefTab.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: RefTab.EachPairAction = {
pub: Wire = NARROW [key];
act: Wire = NARROW [val];
CoreGeometry.AddGeometry[
mode.decoration, act,
CoreGeometry.TransformList[trans, SpecialGetGeometry[pub].geometry]
]; -- 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: RefTab.Ref ← CoreOps.CreateBindingTable[rct[i].type.public, rct[i].actual];
[] ← RefTab.Pairs[intToInt, DecorateBinding];
IF NOT Rope.Equal[PW.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. When we flush, we do not need to explicit the pins because there is no circularity
IF CoreProperties.GetCellTypeProp[rct[i].type, $RawFlatten]=$Smash
THEN Sinix.FlushCache[CoreGeometry.GetObject[mode.decoration, rct[i].type]];
};
ENDLOOP;
IF instances=NIL AND newInternals=NIL AND record.public.size=1 AND rct.internal.size=1 THEN {result ← record.public[0]; RETURN}; -- optimization good for Big contacts!
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]];
Commented for testing
If obj had already the $RawFlatten property, fine. If it did not have it and we have zero instance, let's make sure we'll flatten this cell. We do not flatten cell with only one instance, since wire decorations might kill us!
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];
Cells
CDProperties.PutProp[CDCells.pCellClass, mode.extractProcProp, $RawExtractCell];
Same[CDRoutingObjects.routingClass];
Same[PW.rotationClass];
Pins
Same[CDSymbolicObjects.pinClass]; Same[CDSymbolicObjects.segmentClass]; Same[CDSymbolicObjects.markClass];
Rectangles
Same[CDRects.bareRectClass];
Same[CDRects.wellRectClass];
Contacts
Same[$C2SimpleCon]; Same[$C2WellSimpleCon];
Same[$C2LargeSimpleCon]; Same[$C2LargeWellSimpleCon];
Same[$C2DifShortCon]; Same[$C2DiffShortCon]; Same[$C2WellDifShortCon];
Same[$C2Via]; Same[$C2LargeVia];
Transistors
Same[$C2Trans]; Same[$C2WellTrans];
Angle Transistors
Same[$C2LTrans]; Same[$C2LWellTrans];
Texts
Same[CDTexts.rigidTextClass];
Same[CDTexts.flipTextClass];
SinixOps.RegisterModeCommands[mode, CMosB.cmosB];
CoreGeometryBackdoor.RegisterDecorationIO[mode.decoration]
END.