SEXImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reversed.
Louis Monier November 3, 1985 2:07:05 am PST
DIRECTORY
CD, CDBasics, CDCells, CDDirectory, CDInstances, CDPinObjects, CDProperties, CDRects, CDTexts, Core, CoreClasses, CoreCompose, CoreOps, CoreProperties, PWPins, RefTab, Rope, SEX, SymTab, PWObjects;
SEXImpl: CEDAR PROGRAM
IMPORTS CDBasics, CDCells, CDInstances, CDPinObjects, CDProperties, CDRects, CoreClasses, CoreCompose, CoreOps, CoreProperties, PWPins, RefTab, Rope, SEX
EXPORTS SEX
SHARES CDDirectory, CDRects, CDPinObjects =
BEGIN OPEN SEX;
Properties
extractObjProcProp: PUBLIC ATOM ← $ExtractObjProcProp;
Extraction Procedures
ExtractInst: PUBLIC ExtractInstProc = {
-- Look for an extract proc on the instance, then the object, then the class
refProc: REF ExtractInstProc ← NARROW [CDProperties.GetPropFromInstance[inst, extractObjProcProp]];
IF refProc=NIL THEN refProc ← NARROW [CDProperties.GetPropFromObject[inst.ob, extractObjProcProp]];
IF refProc=NIL THEN refProc ← NARROW [CDProperties.GetProp[inst.ob.class, extractObjProcProp]];
[cellType, ] ← IF refProc#NIL THEN refProc^[inst, context] ELSE DefaultExtractInst[inst, context];
};
DefaultExtractInst: ExtractInstProc = {
};
ExtractCell: ExtractInstProc = {
cellPtr: CD.CellPtr ← NARROW[inst.ob.specificRef];
cdInsts, subCells: CD.InstanceList;
public, internal: Wire;
wires, publics, internals: LIST OF Wire;
data: CoreClasses.RecordCellType;
cdInsts ← cellPtr.contents;
-- Pass 0: Produces a RefTab.Ref binding every instance to a wire, a list of wires, and a list of subCells; not clear we need the table anymore!
-- On the wire are found pins and all the geometry composing it
[wires, subCells] ← ConnectivitySearch[cdInsts];
-- Pass 1: create internal wires, def or implicit, and put actuals as props on the internal pins of the subcells
[internals, publics] ← MakeWires[wires, subCells, context];
-- Pass 2: treat the wires only used (parts of already defined wires)
FinishWires[wires, subCells, context, internals, publics];
internal ← CoreOps.CreateRecordWire[components: internals];
public ← CoreOps.CreateRecordWire[components: publics];
-- Pass 3: now all wires exist, and all pins of internal cells are decorated with actuals
-- Create instances
data ← NEW[CoreClasses.RecordCellTypeRec ← [
internal: internal,
instances: MakeInstances[subCells, context]]];
cellType ← NEW[Core.CellTypeRec ← [
name: cellPtr.name,
class: CoreClasses.recordCellClass,
public: public,
data: data]];
};
-- Pass 0
-- Brute force! The table associates with each instance a ref: this ref is either another entry in the table (CD.Instance), or a Wire if this instance is a root
ConnectivitySearch: PROC [cdInsts: CD.InstanceList] RETURNS [wires: LIST OF Wire, subCells: CD.InstanceList ← NIL] = {
CreateListOfWiresProc: RefTab.EachPairAction = {
IF ISTYPE[val, Wire] THEN wires ← CONS[NARROW[val], wires];
quit ← FALSE;
};
connectTab: RefTab.Ref ← RefTab.Create[]; -- [key: CD.Instance, val: some instance connected to it]
-- Take a look at all instances, create a wire and decorate it with pins and geometry
FOR l: CD.InstanceList ← cdInsts, l.rest WHILE l#NIL DO
inst: CD.Instance ← l.first;
wire: Wire ← NEW[Core.WireRec];
IF ~IsCell[inst] THEN -- first, every wire or pin is its own root
[] ← RefTab.Store[connectTab, inst, wire];
SELECT TRUE FROM
IsPin[inst] => {
AddPinPropOnWire[wire, inst];
AddWireGeometryPropOnWire[wire, inst];
};
IsRectangle[inst] => {
AddWireGeometryPropOnWire[wire, inst];
};
IsCell[inst] => {  -- add the pins of the cell as geometry only
cell: CD.Instance ← inst; -- to avoid name conflict
EachPin: PWPins.InstanceEnumerator = {
AddWireGeometryPropOnWire[wire, PWPins.TransformInstance[inst, cell.ob.size, cell.location, cell.orientation]];
};
[] ← PWPins.EnumerateEdgePins[cell.ob, EachPin];
subCells ← CONS[cell, subCells];
};
ENDCASE => ERROR; -- what could inst be?
ENDLOOP;
-- Now the O(n2) part
FOR l1: CD.InstanceList ← cdInsts, l1.rest WHILE l1#NIL DO
inst1: CD.Instance ← l1.first;
FOR l2: CD.InstanceList ← l1.rest, l2.rest WHILE l2#NIL DO
inst2: CD.Instance ← l2.first;
IF Touch[inst1, inst2] THEN {
root1: CD.Instance ← Root[connectTab, inst1];
root2: CD.Instance ← Root[connectTab, inst2];
wire1: Wire ← RootWire[connectTab, inst1];
wire2: Wire ← RootWire[connectTab, inst2];
MergeWireInfo[wire1, wire2];
[] ← RefTab.Store[connectTab, root2, root1]; -- both now point to wire1
};
ENDLOOP;
ENDLOOP;
-- Now make a list of all wires
[] ← RefTab.Pairs[connectTab, CreateListOfWiresProc];
};
-- Pass 1
-- A wire is a set of rectangles and pins connected together; its name and structure can be defined (once) by a satellite of the form "def: foo", where "def" is reserved;
-- An undefined wire is atomic unnamed.
MakeWires: PROC [wires: LIST OF Wire, subCells: CD.InstanceList, context: Context] RETURNS [publics, internals: LIST OF Wire] = {
def, use: ROPE; outPins, inPins: CD.InstanceList;
FOR l: LIST OF Wire ← wires, l.rest WHILE l#NIL DO
wire: Wire ← l.first;
newWire: Wire;
[def, use, outPins, inPins] ← InfoOnWire[wire, context];
IF Rope.Equal[def, NIL] OR ~Rope.Equal[use, NIL] THEN RETURN; -- for pass 2
IF ~Rope.Equal[def, NIL] AND ~Rope.Equal[use, NIL] THEN ERROR; -- et alors?
-- Create Internal
newWire ← CoreCompose.CreateWires[context, def]; -- hope it works for def=""
internals ← CONS[newWire, internals];
IF outPins#NIL THEN publics ← CONS[newWire, publics];
IF inPins#NIL THEN AttachWireAsActualOnEachInPin[newWire, inPins];
wire ← NIL;  -- somehow, I have to take it out for pass 2
ENDLOOP;
};
-- Pass 2
-- Now using exisiting wires for making actuals
FinishWires: PROC [wires: LIST OF Wire, subCells: CD.InstanceList, context: Context, publics, internals: LIST OF Wire] = {
def, use: ROPE; outPins, inPins: CD.InstanceList;
FOR l: LIST OF Wire ← wires, l.rest WHILE l#NIL DO
wire: Wire ← l.first;
subWire: Wire;
[def, use, outPins, inPins] ← InfoOnWire[wire, context];
IF outPins=NIL AND inPins=NIL THEN ERROR;
-- There is a use for sure
subWire ← FindSubWire[internals]; -- use CoreCompose
IF outPins#NIL THEN publics ← CONS[subWire, publics];
IF inPins#NIL THEN AttachWireAsActualOnEachInPin[subWire, inPins];
ENDLOOP;
};
-- Recursive call to get the cellType of subcells
MakeInstances: PROC [subCells: CD.InstanceList, context: Context] RETURNS [instances: CoreClasses.CellInstanceList] = {
FOR l: CD.InstanceList ← subCells, l.rest WHILE l#NIL DO
instances ← CONS[MakeInstance[l.first, context], instances];
ENDLOOP;
};
MakeInstance: PROC [cell: CD.Instance, context: Context] RETURNS [instance: CoreClasses.CellInstance]= {
};
AttachWireAsActualOnEachInPin: PROC [wire: Wire, inPins: CD.InstanceList] = {
};
FindSubWire: PROC [wires: LIST OF Wire] RETURNS [wire: Wire] = {
};
InfoOnWire: PROC [wire: Wire, context: Context] RETURNS [def, use: ROPE, outPins, inPins: CD.InstanceList] = {
outPins ← GetPinPropFromWire[wire];
};
MergeWireInfo: PROC [winner, looser: Wire] = {
AppendPinPropOnWire[winner, GetPinPropFromWire[looser]];
AppendWireGeometryPropOnWire[winner, GetWireGeometryPropFromWire[looser]];
};
-- The val in the table; NIL if not found
Up: PROC [table: RefTab.Ref, ref: REF] RETURNS [up: REFNIL] = {
up ← RefTab.Fetch[table, ref].val};
RootWire: PROC [table: RefTab.Ref, inst: CD.Instance] RETURNS [wire: Wire] = {
wire ← NARROW[Up[table, Root[table, inst]]];
};
-- The root, i.e. the last Up[Up[...[inst]...]] whose val is a wire
Root: PROC [table: RefTab.Ref, inst: CD.Instance] RETURNS [root: CD.Instance] = {
ref: REF ← inst;
up: REF ← Up[table, ref];
WHILE ~ISTYPE[up, Wire] DO ref ← up; up ← Up[table, ref]; ENDLOOP;
root ← NARROW[ref];
};
Operations for an easy management of properties
GetPinPropFromWire: PUBLIC PROC [wire: Wire] RETURNS [pins: LIST OF CD.Instance] = {
pins ← NARROW [CoreProperties.GetWireProp[wire, pinsProp]];
};
PutPinPropOnWire: PUBLIC PROC [wire: Wire, pins: LIST OF CD.Instance] = {
CoreProperties.PutWireProp[wire, pinsProp, pins];
};
AddPinPropOnWire: PUBLIC PROC [wire: Wire, pin: CD.Instance] = {
pins: LIST OF CD.Instance ← CONS [pin, NARROW [CoreProperties.GetWireProp[wire, pinsProp]]];
CoreProperties.PutWireProp[wire, pinsProp, pins];
};
AppendPinPropOnWire: PUBLIC PROC [wire: Wire, pins: LIST OF CD.Instance] = {
WHILE pins#NIL DO
AddWireGeometryPropOnWire[wire, pins.first];
pins ← pins.rest;
ENDLOOP;
};
GetWireGeometryPropFromWire: PUBLIC PROC [wire: Wire] RETURNS [geometry: LIST OF CD.Instance] = {
geometry ← NARROW [CoreProperties.GetWireProp[wire, wireGeometryProp]];
};
PutWireGeometryPropOnWire: PUBLIC PROC [wire: Wire, geometry: LIST OF CD.Instance] = {
CoreProperties.PutWireProp[wire, wireGeometryProp, geometry];
};
AddWireGeometryPropOnWire: PUBLIC PROC [wire: Wire, cdInstance: CD.Instance] = {
PutWireGeometryPropOnWire[wire, CONS [cdInstance, GetWireGeometryPropFromWire[wire]]];
};
AppendWireGeometryPropOnWire: PUBLIC PROC [wire: Wire, geometry: LIST OF CD.Instance] = {
WHILE geometry#NIL DO
AddWireGeometryPropOnWire[wire, geometry.first];
geometry ← geometry.rest;
ENDLOOP;
};
Geometrical Primitives
IsRectangle: PROC [inst: CD.Instance] RETURNS [BOOL] = {
RETURN[inst.ob.class=CDRects.bareRectClass]};
IsPin: PROC [inst: CD.Instance] RETURNS [BOOL] = {
RETURN[inst.ob.class=CDPinObjects.pinObjectsClass]};
IsCell: PROC [inst: CD.Instance] RETURNS [BOOL] = {
RETURN[CDCells.IsCell[inst.ob]]};
Touch: PROC [inst1, inst2: CD.Instance] RETURNS [touch: BOOLFALSE] = {
IF IsRectangle[inst1] AND IsRectangle[inst2] THEN
RETURN[TouchWires[InstToRect[inst1], InstToRect[inst2]]]
ELSE touch ← TouchListsRect[InstToRects[inst1], InstToRects[inst2]];
};
-- Special rule for two rectangles because crossing implies no contact
TouchWires: PROC [rect1, rect2: CD.Rect] RETURNS [BOOLFALSE] = {
IF ~CDBasics.Intersect[rect1, rect2] THEN RETURN[FALSE];
IF TouchOnlyOnCorner[rect1, rect2] THEN RETURN[TRUE];
};
-- The list of rectangles defining the contact points for this instance
InstToRects: PROC [inst: CD.Instance] RETURNS [listRect: LIST OF CD.Rect ← NIL] = {
SELECT TRUE FROM
IsRectangle[inst] OR IsPin[inst] => listRect ← CONS[InstToRect[inst]];
IsCell[inst] => { -- enumerate pins, turn into rects and CONS them
cell: CD.Instance ← inst; -- to avoid name conflict
EachPin: PWPins.InstanceEnumerator = {
pinRect: CD.Rect ← InstToRect[PWPins.TransformInstance[inst, cell.ob.size, cell.location, cell.orientation]];
listRect ← CONS[pinRect, listRect];
};
[] ← PWPins.EnumerateEdgePins[cell.ob, EachPin];
listRect ← NIL};
ENDCASE => ERROR;
};
TouchListsRect: PROC [listRect1, listRect2: LIST OF CD.Rect] RETURNS [BOOLFALSE] = {
FOR l1: LIST OF CD.Rect ← listRect1, l1.rest WHILE l1#NIL DO
rect1: CD.Rect ← l1.first;
FOR l2: LIST OF CD.Rect ← listRect2, l2.rest WHILE l2#NIL DO
IF TouchRects[rect1, l2.first] THEN RETURN[TRUE];
ENDLOOP;
ENDLOOP;
};
-- This rule does not apply for the intersection of two wires
TouchRects: PROC [rect1, rect2: CD.Rect] RETURNS [BOOLFALSE] = {
RETURN[CDBasics.Intersect[rect1, rect2]];
};
-- The rectangle corresponding to this instance
InstToRect: PROC [inst: CD.Instance] RETURNS [rect: CD.Rect] = {
rect ← CDInstances.InstRectI[inst]};
Satellites
-- Turn the satellites into properties and put them in the context
ParseSatellites: PROC [master: CD.Instance, context: Context] = {
ref: REF ← CDProperties.GetPropFromInstance[master, satellitesProp];
IF ref=NIL THEN RETURN;
FOR l: CD.InstanceList ← NARROW[ref], l.rest WHILE l#NIL DO
ParseSatellite[l.first, context];
ENDLOOP;
};
TextToPropLit: PROC [sat: CD.Instance, context: Context] RETURNS [prop: CoreCompose.PropertyLiteral]= {
text: ROPENARROW[sat.ob.specificRef, CDTexts.TextPtr].text;
prop ← NIL;
};
Initialization
[] ← CDProperties.RegisterProperty[extractObjProcProp, sexKey];
CDProperties.PutProp[CDPinObjects.pinObjectsClass, extractObjProcProp, NEW [ExtractObjProc ← PinExtractObj]];
CDProperties.PutProp[CDCells.cellClass, extractObjProcProp, NEW [ExtractObjProc ← CellExtractObj]];
CDProperties.PutProp[PWObjects.abutXClass, extractObjProcProp, NEW [ExtractObjProc ← AbutExtractObj]];
CDProperties.PutProp[PWObjects.abutYClass, extractObjProcProp, NEW [ExtractObjProc ← AbutExtractObj]];
CDProperties.PutProp[PWObjects.indirectClass, extractObjProcProp, NEW [ExtractObjProc ← PWCoreOperatorExtractObj]];
CDProperties.PutProp[PWCore.gateWayClass, extractObjProcProp, NEW [ExtractObjProc ← PWCoreOperatorExtractObj]];
END.