SisyphImpl.mesa
Copyright Ó 1985, 1986, 1987 by Xerox Corporation. All rights reserved.
Created by Sindhu and Serlet, November 27, 1985 9:11:39 pm PDT
Pradeep Sindhu March 26, 1987 12:07:45 pm PST
Barth, October 15, 1986 10:25:34 am PDT
Bertrand Serlet, March 10, 1987 11:02:58 pm PST
Jean-Marc Frailong March 25, 1987 12:56:08 pm PST
Christian Jacobi, July 15, 1986 6:24:40 pm PDT
DIRECTORY
AMTypes USING [Copy, TV, TVEqual],
AMBridge USING [SomeRefFromTV, TVForFrame, TVForReferent],
AMModel USING [Context],
AMModelBridge USING [ContextForFrame],
CD, CDCells, CDDirectory, CDImports, CDImportsBackdoor, CDLayers, CDProperties, CDRects, CDRemote, CDSatellites, CDSequencer, CDSymbolicObjects, CDTexts,
Core, CoreClasses, CoreOps, CoreProperties,
CoreGeometry,
HashTable, IO,
Interpreter USING [Evaluate],
PrincOpsUtils,
PWObjects,
Rope,
RopeList,
Sinix,
Sisyph,
SymTab,
TerminalIO;
SisyphImpl:
CEDAR
PROGRAM
IMPORTS AMBridge, AMModelBridge, AMTypes, CDCells, CDDirectory, CDImports, CDImportsBackdoor, CDLayers, CDProperties, CDRects, CDRemote, CDSatellites, CDSequencer, CDTexts, CoreClasses, CoreOps, CoreProperties, CoreGeometry, HashTable, Interpreter, IO, PrincOpsUtils, PWObjects, Rope, RopeList, Sinix, SymTab, TerminalIO
EXPORTS Sisyph
SHARES CDCells, CDImports, CDRects, CDRemote, CDTexts, Sinix =
BEGIN OPEN Sisyph;
Constants and Variables
expressionsProp:
PUBLIC
ATOM ← PWObjects.RegisterProp[$SisyphExpressions,
TRUE];
designRope:
PRIVATE
ROPE ← "design";
name of Sisyph variable that holds the ChipNDale design.
cellIconRope: PUBLIC ROPE ← "cI";
wireIconRope: PUBLIC ROPE ← "wI";
wireRope: PUBLIC ROPE ← "wire";
nameRope: PUBLIC ROPE ← "name";
globalNamesRope:
PRIVATE
ROPE ← "globalNames";
name of Sisyph variable that represents a list of names of global wires.
corePropsRope: PUBLIC ROPE ← "coreProps";
coreInstPropsRope: PUBLIC ROPE ← "coreInstProps";
cdObjRope:
PRIVATE
ROPE ← "cdObj";
name of Sisyph variable that holds the CD object being extracted.
localVariablesRopes:
ROPES =
LIST ["&", cellIconRope, wireIconRope, nameRope, wireRope, corePropsRope, coreInstPropsRope];
ignoreMeProp:
PRIVATE
ATOM ← PWObjects.RegisterProp[$SisyphIgnoreMe,
TRUE];
property whose presence indicates that the instance should be ignored during extraction. Present for backward compatibility only. Use $ExtractNull instead. We should get rid of it one day.
parmNamesProp: PUBLIC ATOM ← PWObjects.RegisterProp[$SisyphParmNames, TRUE];
defaultGlobalNames:
PUBLIC
ROPES ←
LIST ["Vdd", "Gnd"];
mode:
PUBLIC Sinix.Mode ←
NEW [Sinix.ModeRec ← [
extractProcProp: PWObjects.RegisterProp[$SisyphExtractProc, TRUE],
decoration: CoreGeometry.CreateDecoration["Sisyph"],
equalProc: ResultEqual,
instanceLayer: Sinix.DefaultInstanceLayer,
userData: DefaultUserData,
fusionByName: schematics,
touchProc: Touch
]];
ExtractProcs
This is the top-level extract proc. It evaluates the arguments to the schematic and then calls either ExtractCellIcon or Sinix.ExtractCell to do its job.
ExtractSchematic: Sinix.ExtractProc = {
cx: Context;
coreProps: Core.Properties;
resultRope: ROPE;
[cx, resultRope] ← EvaluateParameters[userData, obj, properties, IsResultExpression];
EvaluateResult[cx, resultRope];
coreProps ← GetCoreProps[cx];
props ← GetCoreInstProps[cx];
SELECT
TRUE
FROM
Rope.Match["*cI*←*", resultRope] => {
cellType: CellType ← ExtractCellIcon[obj, cx];
cellType.properties ← PutCoreProps[cellType.properties, coreProps];
result ← cellType;
};
Rope.Match["*wI*←*", resultRope] => {
wire: Wire ← ExtractWireIcon[obj, cx];
wire.properties ← PutCoreProps[wire.properties, coreProps];
result ← wire;
};
Rope.Match["*wire*←*", resultRope] => ERROR;
ENDCASE => {
name: ROPE ← GetName[cx];
cellType: CellType;
[result, props] ← Sinix.ExtractCell[obj, mode, properties, cx];
cellType ← NARROW [result];
ProcessGlobalNames[cellType, cx];
IF name=NIL THEN name ← CDNameToCTName[CDDirectory.Name[obj], ".sch"];
cellType ← CoreOps.SetCellTypeName[cellType, name];
cellType.properties ← PutCoreProps[cellType.properties, coreProps];
};
};
ExtractWire: Sinix.ExtractProc = {
wire: Wire;
cx: Context;
name: ROPE;
resultRope: ROPE;
coreInstProps: Core.Properties;
IF obj.class#CDRects.bareRectClass THEN ERROR;
IF obj.layer#CD.commentLayer THEN ERROR;
IF obj.layer#CD.commentLayer THEN
IF CDLayers.Kind[obj.layer]#paint OR CD.LayerTechnology[obj.layer]#NIL THEN ERROR;
[cx, resultRope] ← EvaluateParameters[userData, obj, properties, IsResultExpression];
EvaluateResult[cx, resultRope];
wire ← GetWireCore[cx];
name ← GetName[cx];
coreInstProps ← GetCoreInstProps[cx];
IF wire=NIL THEN wire ← CoreOps.CreateWire[name: name];
CoreGeometry.PutPins[mode.decoration, wire, LIST [[obj]]];
wire.properties ← PutCoreProps[wire.properties, coreInstProps];
result ← wire;
};
ExtractImport: Sinix.ExtractProc = {
cx: Context = NARROW [userData];
design: CD.Design ← GetDesign[cx];
import: CDImports.ImportSpecific = NARROW [obj.specific];
importDesign: CD.Design;
importObj: CD.Object;
CDSequencer.CheckAborted[design];
importDesign ← CDRemote.FetchDesign[design, import.designName];
IF import.boundInstance=
NIL
OR importDesign=
NIL
THEN {
-- try to load the missing design
loaded: BOOL = CDImportsBackdoor.LoadDesign[into: design, importeeName: import.designName, overload: true, allowConflicts: interactive, useCache: TRUE];
IF
NOT loaded
THEN {
-- loading failed
TerminalIO.PutF["*** Error: Cannot load import %g[%g] which is unbound.\n", IO.rope[import.objectName], IO.rope[import.designName]];
ERROR;
};
importDesign ← CDRemote.FetchDesign[design, import.designName];
IF import.boundInstance=
NIL
THEN {
-- Object not bound yet
TerminalIO.PutF["*** Error: Object %g[%g] is unbound within %g.\n", IO.rope[import.objectName], IO.rope[import.designName], IO.rope[design.name]];
ERROR;
};
IF importDesign=
NIL
THEN {
-- can't find the design in the cache
TerminalIO.PutF["*** Error: Cannot reach design %g from design %g.\n", IO.rope[import.designName], IO.rope[design.name]];
ERROR;
};
};
importObj ← import.boundInstance.ob;
RETURN Sinix.Extract[obj: importObj, mode: mode, properties: properties, userData: Create[importDesign, cx]];
};
ES,
ExtractSchematicByName:
PUBLIC
PROC [name:
ROPE, cx: Context]
RETURNS [CellType] = {
design: CD.Design = GetDesign[cx];
obj: CD.Object = CDDirectory.Fetch[design, name].object;
IF obj=NIL THEN {TerminalIO.PutF["*** Error: ES cannot find object '%g' in design '%g'.\n", IO.rope[name], IO.rope[design.name]]; ERROR};
RETURN [NARROW [Sinix.Extract[obj: obj, mode: mode, properties: NIL, userData: cx].result]];
};
This proc is called for cell icons. If a core definition is found then it is returned, otherwise a core cell of class Unspecified is returned.
ExtractCellIcon:
PROC [icon:
CD.Object, cx: Context]
RETURNS [cellType: CellType] = {
SmashPins: CoreOps.EachWireProc = {CoreGeometry.PutPins[mode.decoration, wire, NIL]};
iconCT: CellType;
name: ROPE;
iconCT ← NARROW [Sinix.ExtractCell[icon, mode, NIL, cx].result];
Compute core for the schematic
cellType ← GetCellIconCore[cx];
name ← GetName[cx];
IF cellType=
NIL
THEN {
IF name=NIL THEN name ← CDNameToCTName[CDDirectory.Name[icon], ".icon"];
cellType ← CoreOps.CreateCellType[class: CoreClasses.unspecifiedCellClass, public: iconCT.public, name: name];
}
ELSE {
IF name=NIL THEN name ← CoreOps.GetCellTypeName[cellType];
IF name=NIL THEN name ← CDNameToCTName[CDDirectory.Name[icon], ".icon"];
cellType ← CreateIcon[cellType: cellType, name: name];
};
We smash the pins decoration that could sit on cellType
[] ← CoreOps.VisitWireSeq[cellType.public, SmashPins];
CoreGeometry.PutObject[mode.decoration, cellType, icon];
Check public
IF
NOT CheckAndDecorate[icon, iconCT.public, cellType.public, GetGlobalNames[cx]]
THEN {
TerminalIO.PutF["*** Error: icon public and schematic public for cell icon %g do NOT conform\n", IO.rope[CDDirectory.Name[icon]]];
TerminalIO.PutF["Icon public is:"];
CoreOps.PrintWire[wire: iconCT.public, out: TerminalIO.CreateStream[], level: LAST [NAT]];
TerminalIO.PutF["\nSchematic public is:"];
CoreOps.PrintWire[wire: cellType.public, out: TerminalIO.CreateStream[], level: LAST [NAT]];
TerminalIO.PutF["\n"];
ERROR
}
};
This proc is called for wire icons. If a core definition is found it is returned, otherwise an error is signalled. As for cell icons, pins provide the attatchment points to the wire.
ExtractWireIcon:
PROC [icon:
CD.Object, cx: Context]
RETURNS [result: Wire] = {
iconCT: CellType ← NARROW [Sinix.ExtractCell[icon, mode, NIL, cx].result];
result ← GetWireIconCore[cx];
IF result=NIL THEN ERROR;
Check wire
IF iconCT.public.size=1
THEN {
special case
CoreGeometry.PutPins[mode.decoration, result, CoreGeometry.GetPins[mode.decoration, iconCT.public[0]]];
RETURN;
};
IF ~CheckAndDecorate[icon, iconCT.public, CoreOps.CreateWire[
LIST [result]]]
THEN {
TerminalIO.PutF["*** Error: icon wire and result wire for wire icon %g don't conform\n", IO.rope[CDDirectory.Name[icon]]];
TerminalIO.PutF["Icon wire is:"];
CoreOps.PrintWire[wire: iconCT.public, out: TerminalIO.CreateStream[], level: LAST [NAT]];
TerminalIO.PutF["\nResult wire is:"];
CoreOps.PrintWire[wire: result, out: TerminalIO.CreateStream[], level: LAST [NAT]];
TerminalIO.PutF["\n"];
ERROR
}
};
Context Handling Procedures
InitLocalVariables:
PUBLIC
PROC [cx: Context, obj:
CD.Object] = {
IF cx=NIL THEN ERROR;
Store[cx, cellIconRope, NEW [CellType ← NIL]];
Store[cx, wireIconRope, NEW [Wire ← NIL]];
Store[cx, wireRope, NEW [Wire ← NIL]];
Store[cx, nameRope, NEW [ROPE ← NIL]];
Store[cx, corePropsRope, NEW [Core.Properties ← NIL]];
Store[cx, coreInstPropsRope, NEW [Core.Properties ← NIL]];
Store[cx, cdObjRope, NEW [CD.Object ← obj]]
};
Create:
PUBLIC
PROC [design:
CD.Design, previousCx: Context ←
NIL]
RETURNS [cx: Context] = {
cx ← IF previousCx=NIL THEN SymTab.Create[] ELSE Copy[previousCx];
Store[cx, designRope, NEW [CD.Design ← design]];
Insert[cx, globalNamesRope, NEW [ROPES ← defaultGlobalNames]];
Store[cx, "&", NEW [INT ← 0]];
FOR exprs:
ROPES ←
NARROW [CDProperties.GetDesignProp[design, expressionsProp]], exprs.rest
WHILE exprs#
NIL
DO
Eval[cx, exprs.first];
ENDLOOP;
FOR satellites:
ROPES ← CDSatellites.GetSatelliteRopes[design], satellites.rest
WHILE satellites#
NIL
DO
Eval[cx, satellites.first];
ENDLOOP;
InitLocalVariables[cx, NIL];
};
Copy:
PUBLIC
PROC [cx: Context]
RETURNS [newCx: Context] = {
CopyItem: SymTab.EachPairAction = {
tv: AMTypes.TV ← NARROW[val];
[] ← SymTab.Store[newCx, key, AMTypes.Copy[tv]]; quit ← FALSE;
};
IF cx=NIL THEN ERROR;
newCx ← SymTab.Create[];
[] ← SymTab.Pairs[cx, CopyItem];
};
Store:
PUBLIC
PROC [cx: Context, var:
ROPE, value:
REF ←
NIL] = {
[] ← SymTab.Store[cx, var, TVFromRef[value]];
};
Insert:
PUBLIC
PROC [cx: Context, var:
ROPE, value:
REF ←
NIL] = {
[] ← SymTab.Insert[cx, var, TVFromRef[value]];
};
FetchInt:
PUBLIC
PROC [cx: Context, var:
ROPE]
RETURNS [found:
BOOL, value:
INT] = {
ref: SymTab.Val;
[found, ref] ← SymTab.Fetch[cx, var];
IF NOT found THEN RETURN;
value ← NARROW [RefFromTV[ref], REF INT]^;
};
Eval:
PUBLIC
PROC [cx: Context, expr:
ROPE, cedarCx: AMModel.Context ←
NIL] =
TRUSTED {
result: AMTypes.TV;
errorRope: ROPE;
noResult: BOOL;
IF cedarCx=
NIL
THEN cedarCx ← AMModelBridge.ContextForFrame[
AMBridge.TVForFrame[
PrincOpsUtils.GetReturnFrame[]
]
];
[result, errorRope, noResult] ← Interpreter.Evaluate[rope: expr, context: cedarCx, symTab: cx];
IF errorRope=NIL THEN RETURN;
SIGNAL InterpreterError[cx, expr, errorRope];
ERROR;
};
ContextEqual:
PROC [cx1, cx2: Context, parmNames:
ROPES]
RETURNS [
BOOL] = {
Returns FALSE iff a is a subset of b
IsDifferent:
PROC [a, b: Context]
RETURNS [
BOOL] = {
CheckAbsentInb: SymTab.EachPairAction = {
found: BOOL;
bVal: SymTab.Val;
If its a local variable then return right away
IF RopeList.Memb[localVariablesRopes, key] THEN RETURN [FALSE];
If its not a parameter then return right away also
IF parmNames#NIL AND NOT RopeList.Memb[parmNames, key] THEN RETURN [FALSE];
It is a parameter. Check if its there in the context and equal
[found, bVal] ← SymTab.Fetch[b, key];
IF ~found THEN RETURN [TRUE];
IF TVEqual[bVal, val] THEN RETURN [FALSE];
RETURN [TRUE];
};
RETURN [SymTab.Pairs[a, CheckAbsentInb]];
};
RETURN [cx1=cx2 OR (NOT IsDifferent[cx1, cx2] AND NOT IsDifferent[cx2, cx1])]
ResultEqual:
PROC [obj:
CD.Object, p1:
CD.PropList, ud1:
REF, p2:
CD.PropList, ud2:
REF]
RETURNS [
BOOL] = {
cx1: Context ← NARROW [ud1];
cx2: Context ← NARROW [ud2];
instArgs1: ROPES ← NARROW [CDProperties.GetListProp[p1, expressionsProp]];
satArgs1: ROPES ← NARROW [CDProperties.GetListProp[p1, Sinix.satellitesProp]];
instArgs2: ROPES ← NARROW [CDProperties.GetListProp[p2, expressionsProp]];
satArgs2: ROPES ← NARROW [CDProperties.GetListProp[p2, Sinix.satellitesProp]];
parmNames: ROPES ← NARROW [CDProperties.GetObjectProp[obj, parmNamesProp]];
Handle zero parameters as a special case
IF parmNames#NIL AND Rope.Equal[parmNames.first, "0"] THEN RETURN [TRUE];
RETURN [EqualRopes[instArgs1, instArgs2] AND EqualRopes[satArgs1, satArgs2] AND ContextEqual[cx1, cx2, parmNames]];
};
Icon class
iconClass:
PUBLIC Core.CellClass ← CoreOps.SetClassPrintProc[
NEW [Core.CellClassRec ← [name: "Icon", recast: RecastIcon, layersProps:
TRUE]], PrintIcon];
CreateIcon:
PUBLIC
PROC [cellType: CellType, name:
ROPE ←
NIL, props: Core.Properties ←
NIL]
RETURNS [icon: CellType] = {
icon ← CoreOps.CreateCellType[
class: iconClass,
public: CoreOps.CopyWire[cellType.public],
data: cellType,
name: name,
props: props];
};
RecastIcon: Core.RecastProc = {new ←
NARROW [me.data]};
PrintIcon: CoreOps.PrintClassProc = {
ct: CellType ← NARROW [data];
CoreOps.PrintIndent[indent, out];
out.PutF["Icon of `%g':\n", IO.rope[CoreOps.GetCellTypeName[ct]]];
CoreOps.PrintCellType[cellType: ct, out: out, indent: indent, level: level];
};
Conveniences
EqualRopes:
PUBLIC
PROC [ropes1, ropes2:
ROPES]
RETURNS [
BOOL] = {
FOR r1:
ROPES ← ropes1, r1.rest
WHILE r1#
NIL
DO
IF NOT RopeList.Memb[ropes2, r1.first] THEN RETURN [FALSE];
ENDLOOP;
FOR r2:
ROPES ← ropes2, r2.rest
WHILE r2#
NIL
DO
IF NOT RopeList.Memb[ropes1, r2.first] THEN RETURN [FALSE];
ENDLOOP;
RETURN [TRUE];
Cons:
PUBLIC
PROC [r:
ROPE, lor:
ROPES]
RETURNS [
ROPES] = {
RETURN [CONS [r, lor]];
};
List:
PUBLIC
PROC [r1, r2, r3, r4, r5, r6:
ROPE ←
NIL]
RETURNS [lor:
ROPES ←
NIL] = {
IF r6#NIL THEN lor ← CONS [r6, lor];
IF r5#NIL THEN lor ← CONS [r5, lor];
IF r4#NIL THEN lor ← CONS [r4, lor];
IF r3#NIL THEN lor ← CONS [r3, lor];
IF r2#NIL THEN lor ← CONS [r2, lor];
IF r1#NIL THEN lor ← CONS [r1, lor];
};
Utilities for the implementation
EvaluateResult:
PROC [cx: Context, resultRope:
ROPE] = {
IF resultRope=NIL THEN RETURN;
SpeedUp Hack -- avoids evaluating expressions containing ExtractSchematicByName
IF Rope.Match["cI ← ES[\"*\", cx]", resultRope]
THEN {
pos1: INT ← Rope.Find[s1: resultRope, s2: "\""];
pos2: INT ← Rope.Find[s1: resultRope, s2: "\"", pos1: pos1+1];
name: ROPE ← Rope.Substr[resultRope, pos1+1, pos2-pos1-1];
Store[cx, cellIconRope, NEW [CellType ← ES[name, cx]]];
RETURN
};
Eval[cx, resultRope];
};
CheckAndDecorate:
PROC [icon:
CD.Object, drawnPublic, resultPublic: Wire, globalNames:
ROPES ←
NIL]
RETURNS [ok:
BOOL ←
TRUE] = {
iconName: ROPE = CDDirectory.Name[icon];
resultToDrawn: HashTable.Table ← HashTable.Create[]; -- associates resultPublic to drawnPublic
Construct the association by searching in resultPublic for every name found in drawnPublic
FOR i:
NAT
IN [0 .. drawnPublic.size)
DO
EachResultWire: CoreOps.EachWireProc = {
resultName: ROPE ← CoreOps.GetShortWireName[wire];
IF NOT Rope.Equal[resultName, drawnName] THEN RETURN;
IF wire=resultWire THEN RETURN;
IF resultWire#NIL THEN {TerminalIO.PutF["*** Cell %g: Drawn Icon has a wire %g whose name appears more than once in the schematic\n", IO.rope[iconName], IO.rope[drawnName]]; quit ← TRUE; ok ← FALSE; RETURN};
resultWire ← wire;
};
drawnWire: Wire ← drawnPublic[i];
drawnName: ROPE ← CoreOps.GetShortWireName[drawnWire];
resultWire: Wire ← NIL;
IF drawnName=NIL THEN {TerminalIO.PutF["*** Cell %g: Drawn Icon has an unnamed wire\n", IO.rope[iconName]]; ok ← FALSE; LOOP};
IF CoreOps.VisitWire[resultPublic, EachResultWire] THEN LOOP;
IF resultWire=NIL THEN {TerminalIO.PutF["*** Cell %g: Drawn Icon has wire %g that doesn't correspond to any wire in the schematic\n", IO.rope[iconName], IO.rope[drawnName]]; ok ← FALSE; LOOP};
We decorate the resultWire with the pins of drawnWire
CoreGeometry.PutPins[mode.decoration, resultWire, CoreGeometry.GetPins[mode.decoration, drawnWire]];
[] ← HashTable.Store[resultToDrawn, resultWire, drawnWire];
ENDLOOP;
Ensure that each resultPublic corresponds to some iconic Wire (apart may be from the wires in globalNames). Warning only for those.
FOR i:
NAT
IN [0 .. resultPublic.size)
DO
resultWire: Wire ← resultPublic[i];
resultName: ROPE ← CoreOps.GetShortWireName[resultWire];
drawnWire: Wire ← NARROW [HashTable.Fetch[resultToDrawn, resultWire].value];
IF resultName=NIL THEN LOOP;
IF drawnWire#NIL THEN LOOP;
IF RopeList.Memb[globalNames, resultName] THEN LOOP;
TerminalIO.PutF["*** Warning in Cell %g: schematic has wire %g that corresponds to no wire in the drawn Icon\n", IO.rope[iconName], IO.rope[resultName]];
ENDLOOP;
};
MarkInvisibleInstances: CDEvents.EventProc = {
MarkForEachCell: CDDirectory.EachEntryAction = {
IF CDCells.IsCell[ob] THEN {
cellPtr: CD.CellPtr ← NARROW [ob.specificRef];
All this code is there only to be backward compatible. To be deleted soon
FOR l: LIST OF CD.Instance ← cellPtr.contents, l.rest WHILE l#NIL DO
IF CDProperties.GetListProp[l.first.properties, ignoreMeProp]#NIL
THEN {CDProperties.PutProp[l.first, mode.extractProcProp, $ExtractNull]; CDProperties.PutProp[l.first, ignoreMeProp, NIL]};
ENDLOOP;
}
};
IF design=NIL THEN RETURN; -- design is sometimes NIL!!
[] ← CDDirectory.Enumerate[design, MarkForEachCell];
};
ProcessGlobalName:
PROC [record: CellType, name:
ROPE] = {
globals: Wires;
ReplaceSeq:
PROC [old: WireSeq]
RETURNS [new: WireSeq] = {
new ← old;
FOR i: NAT IN [0 .. old.size) DO new[i] ← Replace[old[i]] ENDLOOP;
};
Replace:
PROC [old: Wire]
RETURNS [new: Wire] = {
IF old.size#0 THEN RETURN [ReplaceSeq[old]];
RETURN [IF CoreOps.Member[globals, old] THEN global ELSE old];
};
ReplaceAndCleanSeq:
PROC [old: WireSeq]
RETURNS [new: WireSeq] = {
news: Wires ← LIST [global];
FOR i:
NAT
IN [0 .. old.size)
DO
new ← Replace[old[i]];
IF NOT CoreOps.Member[news, new] THEN news ← CONS [new, news];
ENDLOOP;
new ← CoreOps.CreateWire[news];
};
InsertGlobal:
PROC [wire: Wire] = {
IF wire.size#0 THEN SIGNAL GlobalNonAtomic[record, name, wire];
IF NOT CoreOps.Member[globals, wire] THEN globals ← CONS [wire, globals];
};
FindGlobals: CoreOps.EachWirePairProc = {
actualName: ROPE = CoreOps.GetShortWireName[actualWire];
publicName: ROPE = CoreOps.GetShortWireName[publicWire];
IF NOT Rope.Equal[publicName, name] THEN RETURN; -- not a sub global candidate
IF actualName=NIL OR Rope.Equal[actualName, name] THEN InsertGlobal[actualWire];
};
FindWire: CoreOps.EachWireProc = {
IF Rope.Equal[CoreOps.GetShortWireName[wire], name] THEN InsertGlobal[wire];
};
rct: CoreClasses.RecordCellType = NARROW [record.data];
global: Wire;
FOR i:
NAT
IN [0..rct.size)
DO
[] ← CoreOps.VisitBindingSeq[rct[i].actual, rct[i].type.public, FindGlobals];
ENDLOOP;
[] ← CoreOps.VisitWireSeq[rct.internal, FindWire];
IF globals=NIL THEN RETURN;
global ← CoreOps.SetShortWireName[globals.first, name];
globals ← globals.rest;
record.public ← ReplaceAndCleanSeq[record.public];
rct.internal ← ReplaceAndCleanSeq[rct.internal];
FOR i: NAT IN [0..rct.size) DO rct[i].actual ← ReplaceSeq[rct[i].actual] ENDLOOP;
WHILE globals#
NIL
DO
Sinix.FuseProperties[mode, globals.first, global, CoreOps.GetCellTypeName[record]];
globals ← globals.rest;
ENDLOOP;
};
Touch: CoreGeometry.TouchProc = {
IF instance1.obj.class#CDRects.bareRectClass OR instance2.obj.class#CDRects.bareRectClass THEN ERROR; -- the only thing we know is Rectangles!
IF ~SilTouchRect[CoreGeometry.InlineBBox[instance1], CoreGeometry.InlineBBox[instance2]] THEN RETURN;
IF instance1.obj.layer=instance2.obj.layer THEN RETURN [TRUE];
RETURN [CDLayers.AbstractToPaint[instance1.obj.layer]=CDLayers.AbstractToPaint[instance2.obj.layer]];
};
SilTouchRect:
PROC [r1, r2:
CD.Rect]
RETURNS [
BOOL] =
INLINE {
Intersect:
PROC [i1min, i1max, i2min, i2max:
CD.Number]
RETURNS [
BOOL] =
INLINE {
RETURN [(i1max >= i2min) AND (i2max >= i1min)];
};
Adjoin:
PROC [i1min, i1max, i2min, i2max:
CD.Number]
RETURNS [
BOOL] =
INLINE {
RETURN [(i2min >= i1min
AND i2min <= i1max
AND i2max >= i1max)
OR
(i1min >= i2min AND i1min <= i2max AND i1max >= i2max)];
};
RETURN [(Intersect[r1.x1, r1.x2, r2.x1, r2.x2] AND Adjoin[r1.y1, r1.y2, r2.y1, r2.y2]) OR (Intersect[r1.y1, r1.y2, r2.y1, r2.y2] AND Adjoin[r1.x1, r1.x2, r2.x1, r2.x2])]
};
GetCoreProps:
PUBLIC
PROC [cx: Context]
RETURNS [Core.Properties] = {
found: BOOL;
ref: SymTab.Val;
[found, ref] ← SymTab.Fetch[cx, corePropsRope];
IF found
THEN RETURN [NARROW [RefFromTV[ref], REF Core.Properties]^]
ELSE ERROR
};
GetCoreInstProps:
PUBLIC
PROC [cx: Context]
RETURNS [Core.Properties] = {
found: BOOL;
ref: SymTab.Val;
[found, ref] ← SymTab.Fetch[cx, coreInstPropsRope];
IF found
THEN RETURN [NARROW [RefFromTV[ref], REF Core.Properties]^]
ELSE ERROR
};
GetCellIconCore:
PROC [cx: Context]
RETURNS [Core.CellType] = {
found: BOOL;
ref: SymTab.Val;
[found, ref] ← SymTab.Fetch[cx, cellIconRope];
IF found
THEN RETURN [NARROW [RefFromTV[ref], REF Core.CellType]^]
ELSE ERROR
};
GetWireIconCore:
PROC [cx: Context]
RETURNS [Wire] = {
found: BOOL;
ref: SymTab.Val;
[found, ref] ← SymTab.Fetch[cx, wireIconRope];
IF found
THEN RETURN [NARROW [RefFromTV[ref], REF Wire]^]
ELSE ERROR
};
GetWireCore:
PROC [cx: Context]
RETURNS [Wire] = {
found: BOOL;
ref: SymTab.Val;
[found, ref] ← SymTab.Fetch[cx, wireRope];
IF found
THEN RETURN [NARROW [RefFromTV[ref], REF Wire]^]
ELSE ERROR
};
GetName:
PROC [cx: Context]
RETURNS [
ROPE] = {
found: BOOL;
ref: SymTab.Val;
[found, ref] ← SymTab.Fetch[cx, nameRope];
IF found
THEN RETURN [NARROW [RefFromTV[ref], REF ROPE]^]
ELSE ERROR
};
GetDesign:
PUBLIC
PROC [cx: Context]
RETURNS [
CD.Design] = {
found: BOOL;
ref: SymTab.Val;
[found, ref] ← SymTab.Fetch[cx, designRope];
IF found
THEN RETURN [NARROW [RefFromTV[ref], REF CD.Design]^]
ELSE ERROR
};
GetGlobalNames:
PUBLIC
PROC [cx: Context]
RETURNS [
ROPES] = {
found: BOOL;
ref: SymTab.Val;
[found, ref] ← SymTab.Fetch[cx, globalNamesRope];
IF found
THEN RETURN [NARROW [RefFromTV[ref], REF ROPES]^]
ELSE ERROR
};
GetCDObj:
PUBLIC
PROC [cx: Context]
RETURNS [
CD.Object] = {
found: BOOL;
ref: SymTab.Val;
[found, ref] ← SymTab.Fetch[cx, cdObjRope];
IF found
THEN RETURN [NARROW [RefFromTV[ref], REF CD.Object]^]
ELSE ERROR
};
RefFromTV:
PROC [tv:
REF]
RETURNS [
REF] = {
IF tv=NIL THEN RETURN [NIL];
IF ~ISTYPE [tv, AMTypes.TV] THEN ERROR;
TRUSTED {RETURN [AMBridge.SomeRefFromTV[tv]]};
};
TVFromRef:
PROC [ref:
REF]
RETURNS [AMTypes.
TV] =
TRUSTED {
RETURN [AMBridge.TVForReferent[ref]];
};
TVEqual:
PROC [tv1, tv2:
REF]
RETURNS [
BOOL] = {
IF AMTypes.TVEqual[tv1, tv2] THEN RETURN [TRUE];
WITH RefFromTV[tv1]
SELECT
FROM
rr1:
REF
ROPES =>
WITH RefFromTV[tv2]
SELECT
FROM
rr2: REF ROPES => RETURN [EqualRopes[rr1^, rr2^]];
ENDCASE => RETURN [FALSE];
more cases could be added in the SELECT statement, but some are not necessary (for example REF INT, due to the behavior of AMTypes.TVEqual).
ENDCASE => RETURN [FALSE];
};
PutCoreProps:
PROC [onto, from: Core.Properties]
RETURNS [new: Core.Properties] = {
PutProp:
PROC [prop:
ATOM, val:
REF
ANY] = {
new ← CoreProperties.PutProp[new, prop, val];
};
new ← onto;
CoreProperties.Enumerate[from, PutProp];
};
CDNameToCTName:
PROC [cdName, dropPart:
ROPE]
RETURNS [ctName:
ROPE] = {
ctName ← Rope.Substr[cdName, 0, Rope.Index[cdName, 0, dropPart]];
};
DefaultUserData:
PROC [design:
CD.Design]
RETURNS [
REF] ~ {
RETURN [Create[design]];
};
Exceptions
GlobalNonAtomic:
PUBLIC
SIGNAL [record: CellType, name:
ROPE, wire: Wire] =
CODE;
InterpreterError: PUBLIC SIGNAL [cx: Context, expr, errorRope: ROPE] = CODE;
Semi-public Utilities
IsResultExpression:
PUBLIC
PROC [expr:
ROPE]
RETURNS [
BOOL] = {
RETURN [
Rope.Match["*cI*←*", expr] OR
Rope.Match["*wI*←*", expr] OR
Rope.Match["*wire*←*", expr]
]
};
EvaluateParameters:
PUBLIC
PROC [userData:
REF, obj:
CD.Object, properties:
CD.PropList, isResultExpression:
PROC [
ROPE]
RETURNS [
BOOL]]
RETURNS [cx: Context, resultRope:
ROPE ←
NIL] = {
EvalExprs:
PROC [exprs:
ROPES, inst:
BOOL] = {
tempResult: ROPE ← NIL;
WHILE exprs#
NIL
DO
expr: ROPE ← exprs.first;
SELECT
TRUE
FROM
isResultExpression[expr] => {
IF tempResult#NIL THEN {TerminalIO.PutF["*** Error: multiple result expressions encountered: '%g' and '%g'.\n", IO.rope[expr], IO.rope[tempResult]]; ERROR};
tempResult ← expr;
};
inst
AND Rope.Match["*name*←*", expr] => {
expr ← Rope.Replace[expr, Rope.Find[expr, "name"], 4, "&"];
Eval[cx, expr];
Store[cx, coreInstPropsRope, NEW [Core.Properties ← CoreProperties.PutProp[GetCoreInstProps[cx], CoreOps.nameProp, NARROW [RefFromTV[SymTab.Fetch[cx, "&"].val], REF ROPE]^]]];
};
Rope.Find[s1: expr, s2: "←"] # -1 AND Rope.Index[s1: expr, s2: "←"]<Rope.Index[s1: expr, s2: ":"] => Eval[cx, expr];
Rope.Find[s1: expr, s2: ":"] # -1 => {
atomRope: ROPE ← Rope.Substr[expr, 0, Rope.Find[s1: expr, s2: ":"]];
valueRope: ROPE ← Rope.Substr[expr, 1+Rope.Find[s1: expr, s2: ":"]];
IF inst
THEN expr ← Rope.Cat["coreInstProps ← CoreProperties.PutProp[coreInstProps, $", atomRope, ", ", valueRope, "]"]
ELSE expr ← Rope.Cat["coreProps ← CoreProperties.PutProp[coreProps, $", atomRope, ", ", valueRope, "]"];
Eval[cx, expr]
};
inst => {
previousProps: Core.Properties ← GetCoreInstProps[cx];
previousName: ROPE ← NARROW [CoreProperties.GetProp[previousProps, CoreOps.nameProp]];
IF previousName#
NIL
AND
NOT Rope.Equal[previousName, expr]
THEN {
TerminalIO.PutF["*** Error in object '%g': Conflicting names '%g' and '%g' [probably two satellites].\n", IO.rope[CDDirectory.Name[obj]], IO.rope[previousName], IO.rope[expr]]; ERROR;
};
Store[cx, coreInstPropsRope, NEW [Core.Properties ← CoreProperties.PutProp[previousProps, CoreOps.nameProp, expr]]];
};
ENDCASE => Store[cx, nameRope, NEW [ROPE ← expr]];
exprs ← exprs.rest;
ENDLOOP;
IF tempResult#NIL THEN resultRope ← tempResult;
};
cx ← Copy[NARROW [userData]];
CDSequencer.CheckAborted[GetDesign[cx]];
InitLocalVariables[cx, obj];
EvalExprs[NARROW [CDProperties.GetObjectProp[obj, expressionsProp]], FALSE];
EvalExprs[NARROW [CDProperties.GetObjectProp[obj, Sinix.satellitesProp]], FALSE];
EvalExprs[NARROW [CDProperties.GetListProp[properties, expressionsProp]], TRUE];
EvalExprs[NARROW [CDProperties.GetListProp[properties, Sinix.satellitesProp]], TRUE];
};
ProcessGlobalNames:
PUBLIC
PROC [record: CellType, cx: Context] = {
FOR names:
ROPES ← GetGlobalNames[cx], names.rest
WHILE names#
NIL
DO
ProcessGlobalName[record, names.first];
ENDLOOP;
};
Module Initialization
Sinix.RegisterExtractProc[$SisyphExtractSchematic, ExtractSchematic];
Sinix.RegisterExtractProc[$SisyphExtractWire, ExtractWire];
Sinix.RegisterExtractProc[$SisyphExtractImport, ExtractImport];
CDProperties.PutProp[CDCells.pCellClass, mode.extractProcProp, $SisyphExtractSchematic];
CDProperties.PutProp[CDRects.bareRectClass, mode.extractProcProp, $SisyphExtractWire];
CDProperties.PutProp[CDTexts.rigidTextClass, mode.extractProcProp, $ExtractNull];
CDProperties.PutProp[CDTexts.flipTextClass, mode.extractProcProp, $ExtractNull];
CDProperties.PutProp[CDImports.importsClass, mode.extractProcProp, $SisyphExtractImport];
CDEvents.RegisterEventProc[$AfterInput, MarkInvisibleInstances];
END.
Jean-Marc Frailong March 25, 1987 11:22:16 am PST
Corrected ExtractImport to permit extraction of 2nd level imports (misfeature of CDImport / CDRemote). Code will need rewrite for CD25.
changes to: DIRECTORY added CDImportsBackdoor, ExtractImport improved forced cache loading of missing imports