StixParserImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Louis Monier December 6, 1985 2:28:13 pm PST
DIRECTORY
CD, CDBasics, CDCells, CDInstances, CDOrient, CDSymbolicObjects, CDProperties, CDRects,
Core, CoreClasses, CoreOps, CoreProperties,
PW, PWPins, Rope,
Sinix,
Stix, StixParser;
StixParserImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDCells, CDInstances, CDSymbolicObjects, CDProperties, CDRects, CoreClasses, CoreOps, CoreProperties, PW, PWPins, Rope, Sinix, Stix
EXPORTS StixParser =
BEGIN OPEN Stix, StixParser;
Input procedure
-- The proc uses Sinix to create a new celltype decorated with CD geometry, translate every Instance into a StickPtr (or several) and decorates the celltype with these StickPtrs.
InputStix: PUBLIC PROC [cell: Object, from: CD.Design] RETURNS [cellType: CellType] = {
-- Put the properties on generic contacts and transistors for Sinix
DecorateSpecials[cell];
-- Get a decorated CellType from Sinix
cellType ← Sinix.ExtractCell[cell].cellType;
-- Get the input technology (useless!)
InitTechno[from.technology];
-- Decorate the CellType with the corresponding StickPtrs
AddStixObjects[cellType];
-- Finish it
FinishCell[cellType];
};
-- Decorate the CellType with the corresponding StickPtrs
AddStixObjects: PROC [cellType: CellType] ~ {
PublicPins: CoreOps.EachWireProc ~ {
-- maybe I just ignore since the pins also appear on the internal wire
};
PutStixGeomOnWire: CoreOps.EachWireProc ~ {
FOR l: InstanceList ← Sinix.GetWireGeometryPropFromWire[wire], l.rest WHILE l#NIL DO
TranslateWireGeom[l.first, cellType, wire]; -- pin, contact or wire
ENDLOOP;
};
recCell: RecordCell ← NARROW[cellType.data];
cell: Object ← NARROW[CoreProperties.GetCellTypeProp[cellType, Sinix.layoutProp]];
cellPtr: CD.CellPtr ← NARROW[cell.specificRef, CD.CellPtr];
-- Create a new symbolic (empty) cell, and bind it to the CellType
stickCell: StickPtr ← CreateStickCell[name: cellPtr.name];
PutStickPtr[cellType, stickCell];
stickCell.properties ← CoreProperties.PutProp[stickCell.properties, extractedCoreProp, cellType];
-- Translate every CD.Instance into a StickPtr (and bind it ?)
[] ← CoreOps.VisitWire[cellType.public, PublicPins]; -- pinsProp
[] ← CoreOps.VisitWire[recCell.internal, PutStixGeomOnWire]; -- wireGeometryProp
FOR i: NAT IN [0..recCell.size) DO   -- instanceProp
inst: Instance;
coreInst: CoreInst ← recCell[i];
inst ← NARROW[CoreProperties.GetCellInstanceProp[coreInst, Sinix.instanceProp]];
TranslateTransistor[inst, coreInst, cellType];
ENDLOOP;
};
InsertInStickCell: PROC [stickPtr: StickPtr, cellType: CellType] ~ {
cell: StickPtr ← GetStickPtr[cellType];
stickCell: StickCell ← NARROW[cell.data];
};
-- Binds the StickPtr corresponding to the instance to the wire
TranslateWireGeom: PROC [inst: Instance, cellType: CellType, wire: Wire] ~ {
stickPtr: StickPtr ← SELECT TRUE FROM
IsContact[inst.ob] => TranslateContact[inst, cellType, wire],
IsRect[inst.ob] => TranslateWire[inst, cellType, wire],
ENDCASE => NIL; -- HighLightInstance[cell, inst, "unknown"] and log on terminal?
IF stickPtr=NIL THEN RETURN;
AppendWireGeom[wire, stickPtr];
InsertInStickCell[stickPtr, cellType];
};
TranslateContact: PROC [inst: Instance, cellType: CellType, wire: Wire] RETURNS [stickPtr: StickPtr] = {
stickPtr ← CreateContact[
node: OriginOnGrid[inst, cellType, wire]];
};
TranslateWire: PROC [inst: Instance, cellType: CellType, wire: Wire] RETURNS [stickPtr: StickPtr] = {
ref: REF ← CDProperties.GetPropFromInstance[inst, stickWidthProp];
stickPtr ← CreateWire[
n1: OriginOnGrid[inst, cellType, wire],
n2: OtherEndOnGrid[inst, cellType, wire],
color: ToColor[inst.ob.layer],
width: IF ref#NIL THEN NARROW[ref, REF INT]^ ELSE 0];
};
-- Inserts three wires to make the transistor stretchable
TranslateTransistor: PROC [inst: Instance, coreInst: CoreInst, cellType: CellType] = {
IncludeExtraWireProc: CoreOps.EachWirePairProc = {
[actualWire: Core.Wire, publicWire: Core.Wire] RETURNS [subWires: BOOL ← TRUE, quit: BOOL ← FALSE]
extraWire: StickPtr;
pin, pinOutside: Instance;
pinName: ROPE;
node: Node;
i: INT;
IF publicWire.size#0 THEN RETURN; -- deal with atomic wires only
pin ← NARROW[CoreProperties.GetWireProp[publicWire, Sinix.pinsProp], InstanceList].first;
pinName ← CDSymbolicObjects.GetName[pin];
i ← SELECT TRUE FROM-- same as in DecorateTr
Rope.Equal[pinName, "gate"] => 0,
Rope.Equal[pinName, "ch1"] => 1,
Rope.Equal[pinName, "ch2"] => 2,
ENDCASE => ERROR;
pinOutside ← PWPins.TransformInstance[pin, inst.ob.size, inst.location, inst.orientation];
node ← CreateNode[PutOnGrid[PW.GetLocation[pinOutside, cell]], actualWire, cellType];
prNodes[i] ← CreateNode[node.pos, actualWire, cellType, TRUE];
extraWire ← CreateWire[n1: prNodes[i], n2: node, color: pinColors[i]];
AppendWireGeom[actualWire, extraWire];
InsertInStickCell[extraWire, cellType];
};
trans: StickPtr;
cell: Object ← NARROW[CoreProperties.GetCellTypeProp[cellType, Sinix.layoutProp]];
color: Color ← SELECT TRUE FROM
IsNTr[inst.ob] => nTrColor,
IsPTr[inst.ob] => pTrColor,
ENDCASE => NIL; -- HighLightInstance[cell, inst, "unknown"] and log on terminal?
pinColors: ARRAY [0..3) OF Color ← [trGateColor, color, color];
prNodes: ARRAY [0..3) OF Node;
-- Create the three private and three public nodes . . .
[] ← CoreOps.VisitBinding[coreInst.actual, coreInst.type.public, IncludeExtraWireProc];
-- and the objects defined with respect to these nodes
trans ← CreateTransistor[
gate: prNodes[0], ch1: prNodes[1], ch2: prNodes[2],
color: color,
width: GetInt[inst, stickWidthProp],
length: GetInt[inst, stickLengthProp]];
-- Bind the Stix transistor corresponding to the transistor or subcell to the CellInstance
PutInstance[coreInst, trans];
InsertInStickCell[trans, cellType];
};
GetInt: PROC [inst: Instance, prop: ATOM] RETURNS [INT] ~ {
ref: REF ← CDProperties.GetPropFromInstance[inst, prop];
RETURN [IF ref#NIL THEN NARROW[ref, REF INT]^ ELSE 0];
};
Symbolic input conventions
-- for positions: target lambda = (source int/grid) (see Chubby)
-- for width: target lambda = source int (which the user should think of as target lambda)
contactName: PUBLIC ROPE ← "StixContact";
nTransistorName: PUBLIC ROPE ← "StixNeTr";
pTransistorName: PUBLIC ROPE ← "StixPeTr";
stickWidthProp: PUBLIC ATOM ← $stickWidthProp;
stickLengthProp: PUBLIC ATOM ← $stickLengthProp;
lambda: INT; -- lambda in the source design
grid: INT;  -- all objects endpoints (nodes) should be on this grid (not necessary)
-- The following procs define the input accepted by the parser
IsRect: PROC [ob: Object] RETURNS [BOOL] = {
RETURN[ob.class.wireTyped AND ~ob.class.symbolic]};
IsContact: PROC [ob: Object] RETURNS [BOOL] = {
RETURN[IsNamedCell[ob, contactName]]};
IsNTr: PROC [ob: Object] RETURNS [BOOL] = {
RETURN[IsNamedCell[ob, nTransistorName]]};
IsPTr: PROC [ob: Object] RETURNS [BOOL] = {
RETURN[IsNamedCell[ob, pTransistorName]]};
IsTransistor: PROC [ob: Object] RETURNS [BOOL] = {
RETURN[IsNTr[ob] OR IsPTr[ob]]};
IsNamedCell: PROC [ob: Object, name: ROPE] RETURNS [BOOL] = {
RETURN[CDCells.IsCell[ob] AND
Rope.Equal[NARROW[ob.specificRef, CD.CellPtr].name, name]]};
TouchGenericContact: Sinix.TouchProc = {RETURN [TRUE]};
-- Decorates the special objects (symbolic transistors and contacts) for Sinix's use. Must be done after the interactive edition (which might include an IO to file which would destroy these properties) but before any extraction
DecorateSpecials: PROC [cell: Object] ~ {
contents: InstanceList ← NARROW[cell.specificRef, CD.CellPtr].contents;
nTrCt, pTrCt: CellType ← NIL;
DecorateTr: PROC [ob: Object, ct: CellType] ~ {
FindTrPins: CDSymbolicObjects.InstEnumerator ~ {
name: ROPE ← CDSymbolicObjects.GetName[inst];
index: INTSELECT TRUE FROM
Rope.Equal[name, "gate"] => 0,
Rope.Equal[name, "ch1"] => 1,
Rope.Equal[name, "ch2"] => 2,
ENDCASE => ERROR;
pins: InstanceList ← LIST[inst];
CoreProperties.PutWireProp[ct.public[index], Sinix.pinsProp, pins];
};
[] ← CDSymbolicObjects.EnumerateSymbolicObs[ob, FindTrPins];
};
-- look for special objects
FOR l: InstanceList ← contents, l.rest WHILE l#NIL DO
ob: Object ← l.first.ob;
SELECT TRUE FROM
IsContact[ob] => { -- Generic Contact is extracted like a wire
CDProperties.PutPropOnObject[ob, Sinix.extractProcProp,
NEW[Sinix.ExtractProc ← Sinix.ExtractWire]];
CDProperties.PutPropOnObject[ob, Sinix.touchProcProp,
NEW[Sinix.TouchProc ← TouchGenericContact]];
};
IsNTr[ob] => { -- Generic Transistors: we put result of the extraction directly
IF nTrCt=NIL THEN {
nTrCt ← CoreClasses.CreateTransistor[[type: nE]];
DecorateTr[ob, nTrCt]};
CDProperties.PutPropOnObject[ob, Sinix.extractedCoreProp, nTrCt]};
IsPTr[ob] => {
IF pTrCt=NIL THEN {
pTrCt ← CoreClasses.CreateTransistor[[type: pE]];
DecorateTr[ob, pTrCt]};
CDProperties.PutPropOnObject[ob, Sinix.extractedCoreProp, pTrCt]};
ENDCASE => NULL;
ENDLOOP;
};
-- Nearest point on the grid, e.g. divide coords by stickGrid(=32) and round; the result is thus expressed in target lambda.
-- Later this numbers will be multiplied by a large constant to make sure that we always do a compaction, not a stretch; it does not cost anything and makes things simpler;
PutOnGrid: PROC [pos: CD.Position] RETURNS [gridPos: CD.Position] = {
-- why always say "round" ?
Chubby: PROC [n: INT] RETURNS [g: INT] = {RETURN [((n+grid/2)/grid)]};
gridPos ← [Chubby[pos.x], Chubby[pos.y]]};
OriginOnGrid: PROC [inst: Instance, cellType: CellType, wire: Wire] RETURNS [Node] ~ {
cell: Object ← NARROW[CoreProperties.GetCellTypeProp[cellType, Sinix.layoutProp]];
RETURN[CreateNode[PutOnGrid[PW.GetLocation[inst, cell]], wire, cellType]];
};
OtherEndOnGrid: PROC [inst: Instance, cellType: CellType, wire: Wire] RETURNS [Node] ~ {
rect: CD.Rect ← CDInstances.InstRectI[inst];
cell: Object ← NARROW[CoreProperties.GetCellTypeProp[cellType, Sinix.layoutProp]];
pos2: CD.Position ← PutOnGrid[CDBasics.AddPoints[
PW.GetLocation[inst, cell],
CDBasics.SizeOfRect[rect]]];
RETURN[CreateNode[pos2, wire, cellType]];
};
Layers
-- used when inputing stick representation from any decent technology
-- simply return the atom associated with the layer
ToColor: PROC [cdLayer: Layer] RETURNS [color: Color] ~ {color ← CD.LayerKey[cdLayer];};
Accessing the source technology
InitTechno: PROC [techno: Techno] ~ {
lambda ← techno.lambda;
grid ← 4*lambda;
};
HighLighting errors utilities (should be exported by Sinix)
HighLightInstance: PROC [cell: CD.Object, inst: CD.Instance, msg: ROPENIL] = {
cellPtr: CD.CellPtr ← NARROW [cell.specificRef];
hinst: CD.Instance ← NEW [CD.InstanceRep ← [
ob: CDRects.CreateRect[inst.ob.size, CD.highLightShade],
location: inst.location, orientation: inst.orientation]];
-- put msg as a InstanceName of hinst so it can be read by selecting it
CDProperties.PutPropOnInstance[hinst, $SignalName, msg];
cellPtr.contents ← CONS [hinst, cellPtr.contents];
};
Initialization
[] ← CDProperties.RegisterProperty[stickWidthProp, $Stix];
CDProperties.InstallProcs[prop: stickWidthProp, new: [makeCopy: CDProperties.CopyVal]];
[] ← CDProperties.RegisterProperty[stickLengthProp, $Stix];
CDProperties.InstallProcs[prop: stickLengthProp, new: [makeCopy: CDProperties.CopyVal]];
END.