CDIn.mesa
Copyright © 1983, 1986 by Xerox Corporation. All rights reserved.
Last Edited by: Kimr, November 28, 1983 10:22 am
Last Edited by: Jacobi, February 8, 1984 9:41 am
Last Edited by: Christian Jacobi, September 2, 1986 2:53:49 pm PDT
gbb April 4, 1986 3:21:48 pm PST
DIRECTORY
Atom,
Ascii,
BasicTime,
Commander,
CD,
CDCells,
CDBasics,
CDDirectory,
CDEnvironment,
CDEvents,
CDInstances,
CDIO,
CDSequencer USING [CheckAborted],
CDOps USING [CreateDesign],
CDOrient,
CDPrivate,
CDProperties,
CDRects,
CDValue,
Convert,
FileNames,
FS,
IO,
PropertyLists,
Rope,
RuntimeError USING [UNCAUGHT],
TerminalIO,
TokenIO,
CDOldInterestRects;
CDIn:
CEDAR
MONITOR
IMPORTS Atom, BasicTime, Commander, Convert, CD, CDBasics, CDCells, CDDirectory, CDEnvironment, CDEvents, CDInstances, CDIO, CDOps, CDOrient, CDPrivate, CDProperties, CDRects, CDSequencer, CDValue, FileNames, FS, IO, PropertyLists, Rope, RuntimeError, TerminalIO, TokenIO, CDOldInterestRects
EXPORTS CDIO
SHARES CD, CDDirectory, CDOldInterestRects =
BEGIN
--RELEASE: search for the string "RELEASE"
xChipndaleFile: INT = 12121983;
xVersion: INT = 15;
-- global vars
versionKey: PUBLIC INT;
designInReadOperation: PUBLIC CD.Design ← NIL;
designVersionKey: Rope.ROPE ← NIL;
binfile: IO.STREAM;
IndexTable: TYPE = RECORD[table: SEQUENCE max: CARDINAL OF CD.Object];
TableTable: TYPE = RECORD[tt: SEQUENCE max: CARDINAL OF REF IndexTable];
fileName: Rope.ROPE;
indexTable: REF IndexTable ← NIL;
tableTable: REF TableTable ← NIL;
maxTableSize: INT = 32000;
GetTableEntry:
PROC[i:
INT]
RETURNS [ob:
CD.Object] =
INLINE {
ob ←
IF i<maxTableSize THEN indexTable.table[i]
ELSE tableTable.tt[i/maxTableSize-1].table[i MOD maxTableSize];
IF ob=NIL THEN Write["*** object failed to read back\n"];
};
SetTableEntry:
PROC[i:
INT, ob:
CD.Object] =
INLINE {
IF i<maxTableSize THEN indexTable.table[i] ← ob
ELSE tableTable.tt[i/maxTableSize-1].table[i MOD maxTableSize] ← ob
};
AllocateTables:
PROC[i:
INT] = {
indexTable ← NEW[IndexTable[MIN[i, maxTableSize]]];
IF i>=maxTableSize
THEN {
tableTable ← NEW[TableTable[i/maxTableSize]];
FOR n:
INT
IN [0..i/maxTableSize)
DO
-- don't be picky with size if it is anyway as big
tableTable.tt[n] ← NEW[IndexTable[maxTableSize]]
ENDLOOP
};
};
Write:
PROC [r: Rope.
ROPE] = {
TerminalIO.WriteRope[r]
};
signalOnPropertyProblem: BOOL ← TRUE; --set variable with debugger
ReadProperties:
PUBLIC
PROC []
RETURNS [props:
CD.PropList←
NIL] = {
PropertyProblem:
PROC [skip:
BOOL←
FALSE] = {
Write["**** property not readable"];
IF key#
NIL
THEN {
TerminalIO.WriteRopes["; probably ", Atom.GetPName[key]];
};
TerminalIO.WriteLn[];
IF signalOnPropertyProblem THEN SIGNAL TokenIO.EncodingError;
IF skip THEN SkipThrough;
};
key: ATOM;
propProcs: CDProperties.PropertyProcs;
token: TokenIO.Token;
DO
token ← TokenIO.ReadToken[];
SELECT token.ref
FROM
$Property => {
--with a write proc
key ← TokenIO.ReadPushFlag[];
propProcs ← CDProperties.FetchProcs[key];
IF propProcs#
NIL
AND propProcs.internalRead#
NIL
THEN {
props ← PropertyLists.PutProp[propList: props, prop: key, val: propProcs.internalRead[key]];
}
ELSE
IF versionKey>=12
THEN {
n: Rope.ROPE ← Atom.GetPName[key];
TerminalIO.WriteRopes["**** property ", n, " not registered\n"];
CDEnvironment.ExecFileEntry[n, designInReadOperation.technology];
propProcs ← CDProperties.FetchProcs[key];
IF propProcs#
NIL
AND propProcs.internalRead#
NIL
THEN {
props ← PropertyLists.PutProp[propList: props, prop: key, val: propProcs.internalRead[key]];
}
ELSE {
Write["failed"];
IF signalOnPropertyProblem THEN SIGNAL TokenIO.EncodingError;
};
}
ELSE {
token ← TokenIO.ReadToken[];
IF token.kind=rope
OR token.kind=atom
OR token.kind=int
THEN
props ← PropertyLists.PutProp[propList: props, prop: key, val: token.ref]
ELSE
IF token.kind=popFlag
THEN {
TokenIO.ReadAgain[];
props ← PropertyLists.PutProp[propList: props, prop: key, val: key]
}
ELSE
IF token.kind=pushFlag
THEN {
IF token.ref=
NIL
OR token.ref=$properties
THEN {
propertieProps: CD.PropList ← ReadProperties[];
props ← PropertyLists.PutProp[propList: props, prop: key, val: propertieProps];
}
ELSE
IF token.ref=$layer
THEN {
lev: CD.Layer ← ReadLayer[];
props ← PropertyLists.PutProp[propList: props, prop: key, val: CDPrivate.layers[lev]]
}
ELSE PropertyProblem[skip: FALSE];
token ← TokenIO.ReadToken[];
IF token.kind#popFlag THEN PropertyProblem[skip: TRUE]
}
ELSE PropertyProblem[]
};
token ← TokenIO.ReadToken[];
IF token.kind#popFlag THEN PropertyProblem[skip: TRUE];
};
$DefaultProperty => {
token ← TokenIO.ReadToken[];
key ← NARROW[token.ref];
propProcs ← CDProperties.FetchProcs[key];
IF propProcs#
NIL
AND propProcs.internalRead#
NIL
THEN {
Write["**** property registered and not readable"];
PropertyProblem[];
};
IF token.kind=rope
OR token.kind=atom
OR token.kind=int
THEN {
token ← TokenIO.ReadToken[];
IF token.kind=rope
OR token.kind=atom
OR token.kind=int
THEN
props ← PropertyLists.PutProp[propList: props, prop: key, val: token.ref]
ELSE PropertyProblem[];
}
ELSE
IF token.kind=pushFlag
THEN {
kind: ATOM ← TokenIO.ReadAtom[];
IF kind=$properties
THEN {
propertieProps: CD.PropList ← ReadProperties[];
props ← PropertyLists.PutProp[propList: props, prop: key, val: propertieProps];
}
ELSE
IF kind=$layer
THEN {
lev: CD.Layer ← ReadLayer[];
props ← PropertyLists.PutProp[propList: props, prop: key, val: CDPrivate.layers[lev]]
}
ELSE
IF kind=$ropeList
THEN {
rList: LIST OF Rope.ROPE ← NIL;
token ← TokenIO.ReadToken[];
WHILE token.kind=rope
DO
rList ← CONS[NARROW[token.ref, Rope.ROPE], rList];
token ← TokenIO.ReadToken[];
ENDLOOP;
TokenIO.ReadAgain[];
props ← PropertyLists.PutProp[propList: props, prop: key, val: rList]
}
ELSE PropertyProblem[skip: FALSE];
token ← TokenIO.ReadToken[];
IF token.kind#popFlag THEN PropertyProblem[skip: TRUE]
}
ELSE PropertyProblem[]
};
ENDCASE => {
TokenIO.ReadAgain[];
RETURN [props];
};
ENDLOOP;
};
SkipThrough:
PROC [] = {
token: TokenIO.Token;
layer: INT ← 0;
DO
token ← TokenIO.ReadToken[];
IF token.kind=pushFlag THEN layer ← layer+1
ELSE IF token.kind=popFlag THEN layer ← layer-1;
IF layer<0 THEN EXIT;
ENDLOOP;
};
SetName:
PROC[me:
CD.Object, r: Rope.
ROPE] ~
INLINE {
IF me.class.inDirectory THEN CDDirectory.ObToDirectoryProcs[me].setName[me, r]
};
ReadObjectDefinition:
PROC [pushRec:
BOOL ←
FALSE]
RETURNS [obj:
CD.Object←
NIL] = {
token: TokenIO.Token; index: INT ← -1; name: Rope.ROPE;
atom: ATOM = TokenIO.ReadPushFlag[];
class: CD.ObjectClass ← CD.FetchObjectClass[atom, designInReadOperation.technology];
CDSequencer.CheckAborted[designInReadOperation];
IF class=
NIL
OR class.internalRead=
NIL
THEN {
n: Rope.ROPE ← Atom.GetPName[atom];
TerminalIO.WriteRopes["object class ", n, " not registered\n"];
CDEnvironment.ExecFileEntry[n, designInReadOperation.technology];
class ← CD.FetchObjectClass[atom, designInReadOperation.technology];
};
IF class=
NIL
OR class.internalRead=
NIL
THEN {
TerminalIO.WriteRopes["reading object class", Atom.GetPName[atom], " failed\n"];
SkipThrough[];
obj ← CDRects.CreateBareRect[[10, 10], CD.errorLayer];
RETURN
};
IF versionKey>=15
THEN {
IF class.inDirectory
THEN {
index ← TokenIO.ReadInt[];
}
ELSE {
token: TokenIO.Token ← TokenIO.ReadToken[];
IF token.ref=$CDIOUseTable THEN index ← TokenIO.ReadInt[]
ELSE TokenIO.ReadAgain[]
};
};
obj ← class.internalRead[];
IF obj=
NIL
OR obj.class=
NIL
THEN
obj ← NEW[CD.ObjectRep ← CDRects.CreateRect[[10, 10], CD.errorLayer]^];
IF index>0 THEN SetTableEntry[index, obj];
IF versionKey>0
THEN {
IF class.inDirectory
THEN {
name ← TokenIO.ReadRope[];
IF versionKey<=4 THEN [] ← TokenIO.ReadRope[]; --ignore an old versionkey feature
};
};
token ← TokenIO.ReadToken[];
IF token.kind#popFlag
THEN {
TokenIO.ReadAgain[];
obj.properties ← ReadProperties[];
TokenIO.ReadPopFlag[];
IF versionKey<8 THEN CDOldInterestRects.AdjustInterest[obj];
--border was'nt a very public feature in 12; might be removed
IF versionKey=12
THEN {
IF CDCells.IsCell[obj]
AND CDProperties.GetObjectProp[obj, $border]#
NIL
THEN {
CDProperties.PutProp[obj, $border, NIL];
CDCells.SetBorder[obj, TRUE];
}
}
};
IF obj.class.inDirectory
THEN {
SetName[obj, name];
IF versionKey>=15
THEN {
IF ~IsOwner[obj, designInReadOperation]
AND ~pushRec
THEN
[] ← CDDirectory.Include[designInReadOperation, obj, name];
};
};
};
ReadObject:
PUBLIC
PROC []
RETURNS [
CD.Object] = {
t: TokenIO.Token = TokenIO.ReadToken[];
IF t.kind=int
THEN {
-- instance
ins: INT ← NARROW[t.ref, REF INT]^;
RETURN [GetTableEntry[ins]]
};
TokenIO.ReadAgain;
RETURN [ReadObjectDefinition[]]
};
setManually: INT ← 0; --used for saving old designs
specialForVersion4: BOOL ← FALSE;
ReadInstance:
PUBLIC
PROC []
RETURNS [
CD.Instance] = {
inst: CD.Instance;
location: CD.Position ← ReadPos[];
orientation: CD.Orientation ← CDIO.ReadOrientation[];
properties: CD.PropList ← ReadProperties[];
ob: CD.Object ← ReadObject[];
IF versionKey>=9
THEN
--this is the current truth and normal case
inst ←
NEW[
CD.InstanceRep ← [
location: location,
orientation: orientation,
properties: properties,
ob: ob
]]
ELSE {
OldNewInstIX:
PROC [ob:
CD.Object←
NIL, location:
CD.Position←[0,0], orientation:
CD.Orientation𡤀, selected:
BOOLEAN ←
FALSE, properties:
CD.PropList←
NIL]
RETURNS [
CD.Instance] = {
off:
CD.Position = CDBasics.BaseOfRect[
CDOrient.MapRect[
itemInCell: CDOldInterestRects.InsideRect[ob],
cellSize: ob.size,
cellInstOrient: orientation,
cellInstPos: [0, 0]
]];
a:
CD.Instance =
NEW[
CD.InstanceRep ←
CD.InstanceRep[
ob: ob,
location: CDBasics.SubPoints[location, off],
orientation: orientation,
selected: selected,
properties: properties
]];
RETURN [a]
};
IF versionKey>=8
THEN
inst ←
NEW[
CD.InstanceRep ← [
location: location,
orientation: orientation,
properties: properties,
ob: ob
]]
ELSE
IF versionKey>=5
THEN
inst ← OldNewInstIX[ob: ob, location: location, orientation: orientation, properties: properties]
ELSE {
--ancient cases
absoluteMode: BOOL ← TRUE;
IF versionKey<3 THEN absoluteMode←TRUE
ELSE
IF versionKey=4
THEN {
IF specialForVersion4
THEN
IF ob.class.inDirectory THEN absoluteMode←TRUE ELSE absoluteMode←FALSE
ELSE absoluteMode←FALSE
}
ELSE
IF versionKey=3
THEN {
IF ob.class.inDirectory THEN absoluteMode←TRUE ELSE absoluteMode←FALSE
};
IF setManually=1 THEN absoluteMode←TRUE
ELSE IF setManually=2 THEN absoluteMode←FALSE
ELSE IF setManually=3 THEN absoluteMode←ob.class.inDirectory;
IF absoluteMode
THEN inst ←
NEW[
CD.InstanceRep ← [
location: location, orientation: orientation, properties: properties, ob: ob, selected: FALSE]]
ELSE inst ← OldNewInstIX[ob: ob, location: location,
orientation: orientation, properties: properties];
};
};
RETURN [inst];
};
ReadInstanceList:
PUBLIC
PROC []
RETURNS [list:
CD.InstanceList←
NIL] = {
num: INT = TokenIO.ReadInt[];
THROUGH [0..num)
DO
list ← CONS[ReadInstance[], list];
ENDLOOP
};
ReadPos:
PUBLIC
PROC []
RETURNS [p:
CD.Position] = {
p.x ← TokenIO.ReadInt[];
p.y ← TokenIO.ReadInt[];
};
ReadRect:
PUBLIC
PROC []
RETURNS [r:
CD.Rect] = {
r.x1 ← TokenIO.ReadInt[];
r.y1 ← TokenIO.ReadInt[];
r.x2 ← TokenIO.ReadInt[];
r.y2 ← TokenIO.ReadInt[];
};
ReadPushRec:
PROC []
RETURNS [pr:
CD.PushRec] = {
token: TokenIO.Token ← TokenIO.ReadToken[];
dummy: CD.Object;
IF token.ref=$Nil THEN pr.mightReplace←NIL
ELSE {
TokenIO.ReadAgain[];
pr.mightReplace ← ReadInstance[];
};
dummy ← ReadObjectDefinition[pushRec: TRUE];
CDProperties.PutObjectProp[dummy, $dummyCell, $TRUE];
pr.changed ← pr.indirectlyChanged ← TRUE;
pr.specific ← NARROW[dummy.specificRef, CD.CellPtr];
IF versionKey>=11
THEN {
pr.specific.dIr ← ReadRect[];
IF pr.specific.useDIr THEN pr.specific.ir ← pr.specific.dIr;
};
pr.dummyCell ← CDInstances.NewInst[ob: dummy];
};
ReadLayer:
PUBLIC
PROC []
RETURNS [
CD.Layer] = {
key: ATOM ← TokenIO.ReadAtom[];
The layer keys have changed from ChipNDale 2.2 to ChipNDale 2.3. The following is a nasty hack to fix it. Note that this is only a translation of the leyer keys. It does not contemplate the conversion from whatever to the new comment layer
IF
CDIO.VersionKey[]<=12
THEN {
The layer keys have changed from ChipNDale 2.2 to ChipNDale 2.3. The following is a nasty hack to fix it. Note that this is only a translation of the leyer keys. It does not contemplate the conversion from whatever to the new comment layer
-- New layer keys for CD 2.3
SELECT key
FROM
$combined => key ← $undefLayer;
$highLightShade => key ← $shadeLayer;
$highLightError => key ← $errorLayer;
$backGround => key ← $backGround;
ENDCASE => NULL;
};
RETURN [CD.FetchLayer[designInReadOperation.technology, key]];
};
IsOwner:
PROC [ob:
CD.Object, d:
CD.Design]
RETURNS [
BOOL] = {
x: REF ~ (IF d=NIL THEN NIL ELSE d.reserved);
RETURN [ CDProperties.GetObjectProp[ob, $OwnerDesign]=x ];
};
ReadSubObjects:
PROC [] = {
token: TokenIO.Token; obj: CD.Object;
DO
token ← TokenIO.ReadToken[];
TokenIO.ReadAgain[];
IF token.kind#pushFlag AND token.kind#int THEN EXIT;
obj ← ReadObject[];
ENDLOOP;
};
ReadDesignData:
PROC [] = {
index, directoryCount: INT;
token: TokenIO.Token;
obj: CD.Object;
directoryCount ← TokenIO.ReadInt[];
AllocateTables[directoryCount+1];
IF versionKey>=15 THEN ReadSubObjects[]
ELSE {
FOR n:
INT
IN [1..directoryCount]
DO
index ← TokenIO.ReadInt[];
obj ← ReadObject[];
SetTableEntry[index, obj];
IF versionKey=0
THEN {
token ← TokenIO.ReadToken[];
WHILE token.kind=rope
DO
name: Rope.ROPE = NARROW[token.ref];
obx: INT = TokenIO.ReadInt[];
[] ← CDDirectory.Include[designInReadOperation, GetTableEntry[obx], name];
token ← TokenIO.ReadToken[];
ENDLOOP;
TokenIO.ReadAgain[];
}
ELSE
IF obj.class.inDirectory
THEN {
--hack to simplify some read procedures...
IF ~IsOwner[obj, designInReadOperation]
THEN {
name: Rope.ROPE = CDDirectory.Name[obj];
[] ← CDDirectory.Include[designInReadOperation, obj, name];
}
}
ENDLOOP;
};
designInReadOperation.properties ← NEW[CD.PropList←ReadProperties[]];
--this overwrites an previous $FileVersion property read in the normal (wrong) way
CDProperties.PutDesignProp[designInReadOperation, $FileVersion, designVersionKey];
designInReadOperation.actual ← NIL;
DO
token ← TokenIO.ReadToken[];
IF token.ref#$Push
THEN {
TokenIO.ReadAgain[];
EXIT;
};
designInReadOperation.actual ← CONS[ReadPushRec[], designInReadOperation.actual];
ENDLOOP;
token ← TokenIO.ReadToken[];
IF token.ref#$EndOfDesign THEN SIGNAL TokenIO.EncodingError;
};
ReadDesign:
PUBLIC
ENTRY
PROC [from:
REF←
NIL, check:
PROC [
CD.Design]
RETURNS [
BOOL] ←
NIL, wDir: Rope.
ROPE ←
NIL]
RETURNS [
CD.Design] = {
--from is either a IO.STREAM, a Rope.ROPE, or NIL
--check: (called if non NIL), is called after technology and design-name is initialized
-- read proceeds only if check returns TRUE
--returns NIL if design not read in successfully
--viewer is not opened
ENABLE
UNWIND => {
indexTable ← NIL;
tableTable ← NIL;
designInReadOperation ← NIL;
};
wDirUsed: Rope.ROPE ← NIL;
design: CD.Design; -- is initialized before return only
-- all internal routines use designInReadOperation in place of design
DoReadDesign:
INTERNAL
PROC [check:
PROC [
CD.Design]
RETURNS [
BOOL]] = {
-- result design returned in designInReadOperation
-- handles all the TokenIO business
ENABLE {
UNWIND => designInReadOperation ← NIL;
TokenIO.EncodingError => {
Write["** TokenIO encoding problem\n"];
REJECT;
};
RuntimeError.
UNCAUGHT => {
Write["** problem while reading; abort or proceed\n"];
REJECT
};
};
DoWhileAttached:
INTERNAL
PROC [] = {
--and always Release
ENABLE
UNWIND => {
designInReadOperation ← NIL;
TokenIO.ReleaseReader[];
};
TechnologyCheck:
INTERNAL
PROC [] = {
--Side-effect: if bad, designInReadOperation is set to NIL
ENABLE UNWIND => {designInReadOperation ← NIL};
dont:
BOOL ← CDEvents.ProcessEvent[
ev: readEvent,
design: designInReadOperation,
x: NIL,
listenToDont: TRUE
].dont;
IF dont
THEN {
designInReadOperation ← NIL;
Write["Technology rejects read\n"];
}
};
VersionAndSealCheck:
INTERNAL
PROC [] = {
--ChipNDale check
IF TokenIO.ReadInt[]#xChipndaleFile
THEN {
Write["File is not a ChipNDale design\n"];
ERROR TokenIO.Error[other, "ChipNDale filekey"];
};
--version check
versionKey ← TokenIO.ReadInt[];
IF versionKey#xVersion
THEN {
IF versionKey>xVersion
THEN {
-- too new
Write["design was written with newer ChipNDale version\n"];
Write["get a new ChipNDale version\n"];
ERROR TokenIO.Error[other, "ChipNDale versionkey"];
}
ELSE
IF versionKey
IN [13..xVersion]
THEN {
-- not new but dont tell it
NULL
}
ELSE
IF versionKey
IN [5..xVersion]
THEN {
-- not new but everything ok
Write["design was written with older chipndaleversion\n"];
}
ELSE
IF versionKey=4
THEN {
-- known problem versions
Write["********\n"];
Write["design was written with old chipndaleversion; filekey = 4\n"];
Write["Please convert all your designs (by reading and subsequent writing)\n"];
Write["Check carefully the alignment of cells which have n-well\n"];
Write[" IF alignment is wrong THEN { try with a commandtool:\n"];
Write[" CD18InputToggle\n"];
Write[" and try again\n"];
Write[" }\n"];
Write["********\n"];
}
ELSE
IF versionKey=3
THEN {
-- known problem versions
Write["********\n"];
Write["design was written with old chipndaleversion; filekey = 3\n"];
Write["Please convert all your designs (by reading and subsequent writing)\n"];
Write["Check carefully the alignment of cells which have n-well"];
Write["********\n"];
}
ELSE
IF versionKey
IN [0..xVersion]
THEN {
-- not new but please convert
Write["********\n"];
Write["Design was written with old chipndaleversion\n"];
Write["Please convert all your designs (by reading and subsequent writing)\n"];
Write["********\n"];
}
ELSE {
-- too old
Write["design was written with old chipndaleversion\n"];
Write["This version is no more supported\n"];
ERROR TokenIO.Error[other, "ChipNDale versionkey"];
};
};
--seal check
IF versionKey>0
THEN {
IF TokenIO.ReadInt[]#-1
THEN {
Write["File had not been properly closed; has bad seal\n"];
ERROR TokenIO.Error[other, "file had not been properly closed"];
};
};
};
ReadVersionKeys:
PROC [design:
CD.Design] = {
IF versionKey>=7
THEN {
designVersionKey ← TokenIO.ReadRope[];
};
IF Rope.IsEmpty[designVersionKey]
THEN
designVersionKey ← Convert.RopeFromTime[from: BasicTime.Now[], end: seconds];
CDProperties.PutDesignProp[design, $FileVersion, designVersionKey];
};
ReadDesignName:
PROC []
RETURNS [name: Rope.
ROPE] = {
name ← TokenIO.ReadRope[];
IF Rope.IsEmpty[name]
THEN {
name ← FileNames.GetShortName[fileName, TRUE];
name ← Rope.Substr[name, 0, Rope.Index[name, 0, ".dale", FALSE]]
}
};
-- DoWhileAttached
VersionAndSealCheck[];
technologyKey ← TokenIO.ReadAtom[];
technologyName ← TokenIO.ReadRope[];
technology ← CDEnvironment.LoadTechnology[technologyKey, technologyName];
IF technology=NIL THEN GOTO NotDoneAndRelease;
designInReadOperation ← CDOps.CreateDesign[technology];
TechnologyCheck[];
IF designInReadOperation=NIL THEN GOTO NotDoneAndRelease;
designInReadOperation.name ← ReadDesignName[];
ReadVersionKeys[designInReadOperation]; --read before check, fixed again later
IF check#
NIL
THEN {
IF NOT check[designInReadOperation] THEN GOTO NotDoneAndRelease;
};
ReadDesignData[];
CDEnvironment.SetWorkingDirectory[designInReadOperation, wDirUsed];
CDValue.Store[boundTo: designInReadOperation, key: $CDxFromFile, value: fileName];
CDValue.Store[boundTo: designInReadOperation, key: $CDxLastFile, value: fileName];
TokenIO.ReleaseReader[];
EXITS
NotDoneAndRelease => {
designInReadOperation ← NIL;
TokenIO.ReleaseReader[];
};
};
-- DoReadDesign
technology: CD.Technology;
technologyKey: ATOM;
technologyName: Rope.ROPE;
designInReadOperation ← NIL;
TokenIO.AttachReader[binfile !
TokenIO.Error => {
r: Rope.ROPE ← "bad explanation";
IF ISTYPE[explanation, Rope.ROPE] THEN r←NARROW[explanation];
TerminalIO.WriteRopes[r, "... not attached\n"];
GOTO NotAttached
}
];
DoWhileAttached[];
EXITS
NotAttached => RETURN
};
-- begin ReadDesign
iDidTheOpen: BOOL ← FALSE;
name: Rope.ROPE;
streamOptions:
FS.StreamOptions ←
ALL[
TRUE];
streamOptions[tiogaRead] ← FALSE;
streamOptions[commitAndReopenTransOnFlush] ← FALSE;
streamOptions[truncatePagesOnClose] ← TRUE;
streamOptions[finishTransOnClose] ← TRUE;
streamOptions[closeFSOpenFileOnClose] ← TRUE;
-- open file; assign fileName and binfile
IF wDir=NIL THEN wDir ← FileNames.CurrentWorkingDirectory[];
IF from#
NIL
AND
ISTYPE[from,
IO.
STREAM]
THEN {
fileName ← NIL;
binfile ← NARROW[from, IO.STREAM]
}
ELSE {
ReadName:
PROC [wDir: Rope.
ROPE]
RETURNS [name: Rope.
ROPE] = {
Write[Rope.Cat[" input file (", wDir, ")"]];
name ← TerminalIO.RequestRope[" > "];
};
IF from=NIL THEN name ← ReadName[wDir]
ELSE
IF
ISTYPE[from, Rope.
ROPE]
THEN {
name ← NARROW[from, Rope.ROPE];
IF Rope.IsEmpty[name] THEN name ← ReadName[wDir];
}
ELSE {
Write["ReadDesign does not support type of 'from' parameter\n"];
GOTO NotOpened;
};
fileName ← CDEnvironment.MakeName[name, "dale", wDir];
binfile ←
FS.StreamOpen[fileName, $read, streamOptions !
FS.Error =>
IF error.group # bug
THEN {
Write[Rope.Cat[fileName, " not opened: ", error.explanation, "\n"]];
GOTO NotOpened;
}];
wDirUsed ← FileNames.Directory[fileName];
iDidTheOpen ← TRUE;
Write[Rope.Cat[fileName, " opened \n"]];
};
-- do the actual work
DoReadDesign[check];
design ← designInReadOperation;
-- finalize
designInReadOperation ← NIL; indexTable ← NIL; tableTable ← NIL;
IF iDidTheOpen THEN IO.Close[binfile];
[] ← CDEvents.ProcessEvent[ev: afterInputEvent, design: design, x: NIL, listenToDont: FALSE];
RETURN [design];
EXITS
NotOpened => {
indexTable ← NIL; tableTable ← NIL; designInReadOperation ← NIL;
RETURN [NIL];
}
};
ReadOrientation:
PUBLIC
PROC []
RETURNS [orientation:
CD.Orientation] = {
i: INT = TokenIO.ReadInt[];
IF versionKey<=3
THEN {
IF i IN [0..15] THEN orientation ← i/4*2 + i MOD 2 ELSE SIGNAL TokenIO.EncodingError;
}
ELSE
IF i IN [0..7] THEN orientation ← i ELSE SIGNAL TokenIO.EncodingError
};
MakeName:
PUBLIC
PROC [base: Rope.
ROPE, ext: Rope.
ROPE←
NIL, wDir: Rope.
ROPE←
NIL, modifier: Rope.
ROPE←
NIL]
RETURNS [Rope.
ROPE] = {
RETURN [CDEnvironment.MakeName[base, ext, wDir, modifier]];
};
SetWorkingDirectory:
PUBLIC
PROC [design:
REF, wDir: Rope.
ROPE] = {
CDEnvironment.SetWorkingDirectory[design, wDir];
};
GetWorkingDirectory:
PUBLIC
PROC [design:
REF]
RETURNS [wDir: Rope.
ROPE←
NIL] = {
RETURN [CDEnvironment.GetWorkingDirectory[design]];
};
MakeShortName:
PUBLIC
PROC [design:
CD.Design]
RETURNS [name: Rope.
ROPE ←
NIL] = {
TrailingDot:
PROC [base: Rope.
ROPE]
RETURNS [
INT] = {
--position of last dot
len: INT ← Rope.Length[base];
pos: INT ← len;
WHILE pos > 0
DO
SELECT Rope.Fetch[base, pos ← pos - 1]
FROM
'. => RETURN [pos];
'!, '], '>, '/ => EXIT;
ENDCASE;
ENDLOOP;
RETURN [len];
};
SuggestedModule:
PROC [base: Rope.
ROPE]
RETURNS [Rope.
ROPE] = {
--given a filename, suggests a modulename
len, dot: INT;
base ← FileNames.GetShortName[base];
len ← Rope.Length[base];
dot ← TrailingDot[base];
IF len>dot
AND Rope.Equal[Rope.Substr[base, dot+1], "dale",
FALSE]
THEN
base ← Rope.Substr[base, 0, dot];
RETURN [base]
};
--MakeShortName
WITH CDValue.Fetch[boundTo: design, key: $CDxFromFile]
SELECT
FROM
r: Rope.ROPE => name ← SuggestedModule[r];
ENDCASE => NULL;
IF name=NIL THEN name ← design.name;
IF name=NIL THEN name ← "noname"
};
CD18Input: Commander.CommandProc = {
--fix an old old problem
specialForVersion4 ← ~specialForVersion4;
IF specialForVersion4
THEN
cmd.out.PutRope["Fileformat: switch to old version of cd18\n"]
ELSE
cmd.out.PutRope["Fileformat: switch to last version of cd18\n"];
};
readEvent: CDEvents.EventRegistration = CDEvents.RegisterEventType[$ReadTechnologyPrivate];
afterInputEvent: CDEvents.EventRegistration = CDEvents.RegisterEventType[$AfterInput];
Commander.Register["///Commands/CD18InputToggle", CD18Input, "toggle input mode of cd18"];
END.
Version history
versionKey 0
versionKey 1:
objects with children carry names
versionKey 2:
versionKey 3: June 15, 1984 3:46:13 pm PDT;
instances position is its innerrect; this allows to shrink or grow the nwell from cmos
versionKey 4: October 20, 1984 9:36:34 am PDT;
orientation changed
probably while lifetime of 4:
properties which are propertylists are automatically included
versionKey 5: December 14, 1984 10:07:59 am PST;
insiderect for cells no more done with properties; key is removed
versionKey 6: February 1, 1985 4:43:29 pm PST;
properties which are layers are automatically included
versionKey 7: March 26, 1985 12:33:22 pm PST;
file versionkey property included
versionKey 8: April 15, 1985 3:26:35 pm PST;
cd-coords base to file again...
cells get origin and interestrect
imports get interestrect
versionKey 9: May 29, 1985 7:51:45 pm PDT;
CD21
versionKey 10: May 29, 1985 7:51:45 pm PDT;
CD22
Atomicobject have the interest rect on the file
versionKey 11: May 29, 1985 7:51:45 pm PDT;
(CD22)
pushed records get the default interest rect
versionKey 12: January 28, 1986 2:23:27 pm PST;
(CD22)
default properties get $DefaultProperty key
versionKey 13: March 11, 1986 4:17:16 pm PST;
(CD23)
cells may have drawBorder field
gbb April 4, 1986 3:19:31 pm PST
The atoms for the keys of the technology independent layers have changed.
changes to: ReadLayer: if versionKey[]<=12 translate atoms.
versionKey 15: June 20, 1986 9:53:19 am PDT;
Global changes
Number of object for object table is now inside object definition
Directory include is performed for all objects in directory, independent of source.
Objects not in directory have special option to be put in table.