CDIn.mesa
Copyright © 1983, 1985 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: Jacobi, April 11, 1985 3:15:36 pm PST
DIRECTORY
Atom,
BasicTime,
Commander,
CD,
CDApplications,
CDBasics,
CDDirectory,
CDEvents,
CDIO,
CDOps USING [CreateDesign],
CDOrient,
CDPrivate,
CDProperties,
CDRects,
CDValue,
Convert,
FileNames,
FS,
IO,
List,
ProcessProps,
Rope,
RuntimeError USING [UNCAUGHT],
TerminalIO,
TokenIO,
CDInterestRects,
UserProfile;
CDIn:
CEDAR
MONITOR
IMPORTS Atom, BasicTime, Commander, Convert, CD, CDApplications, CDBasics, CDDirectory, CDEvents, CDIO, CDOps, CDOrient, CDPrivate, CDProperties, CDRects, CDValue, FileNames, FS, IO, List, ProcessProps, Rope, RuntimeError, TerminalIO, TokenIO, UserProfile, CDInterestRects
EXPORTS CDIO
SHARES CDDirectory, CDInterestRects =
BEGIN
--RELEASE: search for the string "RELEASE"
xChipndaleFile: INT = 12121983;
xVersion: INT = 8;
-- 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.ObPtr];
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 [
CD.ObPtr] =
INLINE
BEGIN
RETURN[indexTable.table[i]];
IF i<maxTableSize THEN RETURN[indexTable.table[i]]
ELSE RETURN [tableTable.tt[i/maxTableSize-1].table[i MOD maxTableSize]]
END;
SetTableEntry:
PROC[i:
INT, ob:
CD.ObPtr] =
INLINE
BEGIN
indexTable.table[i] ← ob;
IF i<maxTableSize THEN indexTable.table[i] ← ob
ELSE tableTable.tt[i/maxTableSize-1].table[i MOD maxTableSize] ← ob
END;
AllocateTables:
PROC[i:
INT] =
BEGIN
indexTable ← NEW[IndexTable[MIN[i, maxTableSize]]];
IF i>=maxTableSize
THEN {
TerminalIO.WriteRope["****design to big\n"];
ERROR
};
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
};
END;
signalOnPropertyProblem: BOOL ← TRUE; --set variable with debugger
ReadProperties:
PUBLIC PROC []
RETURNS [props:
CD.Properties←
NIL] =
BEGIN
PropertyProblem:
PROC [skip:
BOOL←
FALSE] = {
TerminalIO.WriteRope["**** property not readable"];
IF key#
NIL
THEN {
TerminalIO.WriteRope["; probably "];
TerminalIO.WriteRope[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[];
IF token.ref#$Property
THEN {
TokenIO.ReadAgain[];
RETURN [props];
};
key ← TokenIO.ReadPushFlag[];
propProcs ← CDProperties.FetchProcs[key];
IF propProcs#
NIL
AND propProcs.internalRead#
NIL
THEN {
props ← Atom.PutPropOnList[propList: props, prop: key, val: propProcs.internalRead[key]];
}
ELSE {
token ← TokenIO.ReadToken[];
IF token.kind=rope
OR token.kind=atom
OR token.kind=int
THEN
props ← Atom.PutPropOnList[propList: props, prop: key, val: token.ref]
ELSE
IF token.kind=popFlag
THEN {
TokenIO.ReadAgain[];
props ← Atom.PutPropOnList[propList: props, prop: key, val: key]
}
ELSE
IF token.kind=pushFlag
THEN {
IF token.ref=
NIL
OR token.ref=$properties
THEN {
propertieProps: CD.Properties ← ReadProperties[];
props ← Atom.PutPropOnList[propList: props, prop: key, val: propertieProps];
}
ELSE
IF token.ref=$layer
THEN {
lev: CD.Layer ← ReadLayer[];
props ← Atom.PutPropOnList[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];
ENDLOOP;
END;
SkipThrough:
PROC [] =
BEGIN
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;
END;
SetName:
PROC[me:
CD.ObPtr, r: Rope.
ROPE] ~
INLINE {
IF me.p.inDirectory THEN CDDirectory.ObToDirectoryProcs[me].setName[me, r]
};
ReadObjectDefinition:
PROC []
RETURNS [obj:
CD.ObPtr←
NIL] =
BEGIN
token: TokenIO.Token;
atom: ATOM = TokenIO.ReadPushFlag[];
p: REF READONLY CD.ObjectProcs ← CD.FetchObjectProcs[atom, designInReadOperation.technology];
IF p=
NIL
OR p.internalRead=
NIL
THEN {
TerminalIO.WriteRope["unknown object "];
TerminalIO.WriteRope[Atom.GetPName[atom]];
TerminalIO.WriteLn[];
SkipThrough[];
obj ← CDRects.CreateBareRect[[10, 10], CD.highLightError];
}
ELSE {
obj ← p.internalRead[];
IF obj=
NIL
OR obj.p=
NIL
THEN
obj ← NEW[CD.ObjectDefinition ← CDRects.CreateRect[[10, 10], CD.highLightError]^];
IF versionKey>0
THEN {
IF p.inDirectory
THEN {
name: Rope.ROPE ← TokenIO.ReadRope[];
SetName[obj, name];
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 CDInterestRects.AdjustInterest[obj]
}
};
END;
ReadObject:
PUBLIC
PROC []
RETURNS [
CD.ObPtr] =
BEGIN
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[]]
END;
setManually: INT ← 0; --used for saving old designs
specialForVersion4: BOOL ← FALSE;
ReadApplicationPtr:
PUBLIC
PROC []
RETURNS [
CD.ApplicationPtr] =
BEGIN
ap: CD.ApplicationPtr;
location: CD.DesignPosition ← ReadPosition[];
orientation: CD.Orientation ← CDIO.ReadOrientation[];
properties: CD.Properties ← ReadProperties[];
ob: CD.ObPtr ← ReadObject[];
IF versionKey>=8
THEN
--this is the current truth and normal case
ap ←
NEW[
CD.Application ← [
location: location,
orientation: orientation,
properties: properties,
ob: ob
]]
ELSE {
NewApplicationIX:
PROC [ob:
CD.ObPtr←
NIL, location:
CD.DesignPosition←[0,0], orientation:
CD.Orientation𡤀,
selected: BOOLEAN ← FALSE, properties: CD.Properties←NIL] RETURNS [CD.ApplicationPtr] =
BEGIN
off:
CD.DesignPosition = CDBasics.BaseOfRect[
CDOrient.MapRect[
itemInCell: ob.p.oldInsideRect[ob],
cellSize: ob.size,
cellInstOrient: orientation,
cellInstPos: [0, 0]
]];
a:
CD.ApplicationPtr =
NEW[
CD.Application ←
CD.Application[
ob: ob,
location: CDBasics.SubPoints[location, off],
orientation: orientation,
selected: selected,
properties: properties
]];
RETURN [a]
END;
IF versionKey>=5
THEN
ap ← NewApplicationIX[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.p.inDirectory THEN absoluteMode←TRUE ELSE absoluteMode←FALSE
ELSE absoluteMode←FALSE
}
ELSE
IF versionKey=3
THEN {
IF ob.p.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.p.inDirectory;
IF absoluteMode
THEN ap ←
NEW[
CD.Application ← [
location: location, orientation: orientation, properties: properties, ob: ob, selected: FALSE]]
ELSE ap ← NewApplicationIX[ob: ob, location: location,
orientation: orientation, properties: properties];
};
};
RETURN [ap];
END;
ReadApplicationList:
PUBLIC PROC []
RETURNS [list:
CD.ApplicationList←
NIL] =
BEGIN
num: INT = TokenIO.ReadInt[];
THROUGH [0..num)
DO
list ← CONS[ReadApplicationPtr[], list];
ENDLOOP
END;
ReadPushRec:
PROC []
RETURNS [pr:
CD.PushRec] =
BEGIN
token: TokenIO.Token ← TokenIO.ReadToken[];
dummy: CD.ObPtr;
IF token.ref=$Nil THEN pr.mightReplace←NIL
ELSE {
TokenIO.ReadAgain[];
pr.mightReplace ← ReadApplicationPtr[];
};
dummy ← ReadObjectDefinition[];
pr.changed ← pr.indirectlyChanged ← TRUE;
pr.specific ← NARROW[dummy.specificRef, CD.CellPtr];
pr.dummyCell ← CDApplications.NewApplicationI[ob: dummy];
END;
ReadPosition:
PROC []
RETURNS [pos:
CD.DesignPosition] =
BEGIN
pos.x ← TokenIO.ReadInt[];
pos.y ← TokenIO.ReadInt[];
END;
ReadLayer:
PUBLIC
PROC []
RETURNS [
CD.Layer] =
BEGIN
key: ATOM = TokenIO.ReadAtom[];
RETURN [CD.FetchLayer[designInReadOperation.technology, key]];
END;
ReadDesignData:
PROC [] =
BEGIN
index, directoryCount: INT;
token: TokenIO.Token;
obj: CD.ObPtr;
directoryCount ← TokenIO.ReadInt[];
AllocateTables[directoryCount+1]; -- ???
FOR n:
INT
IN [1..directoryCount]
DO
index ← TokenIO.ReadInt[];
obj ← ReadObjectDefinition[];
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.p.inDirectory
THEN {
name: Rope.ROPE = CDDirectory.Name[obj];
[] ← CDDirectory.Include[designInReadOperation, obj, name];
}
ENDLOOP;
designInReadOperation.properties ← ReadProperties[];
--this overwrites an old $FileVersion property read in the normal (wrong) way
CDProperties.PutPropOnDesign[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;
END;
ReadDesign:
PUBLIC
ENTRY
PROC [from:
REF←
NIL, check:
PROC [
CD.Design]
RETURNS [
BOOL] ←
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
BEGIN
ENABLE
UNWIND => {
indexTable ← NIL;
tableTable ← NIL;
designInReadOperation ← 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
BEGIN
ENABLE {
UNWIND => designInReadOperation ← NIL;
CDPrivate.DebugCall => REJECT;
TokenIO.EncodingError => {
TerminalIO.WriteRope["** TokenIO encoding problem\n"];
REJECT;
};
RuntimeError.
UNCAUGHT => {
TerminalIO.WriteRope["** problem while reading; abort or proceed\n"];
REJECT
};
};
DoWhileAttached:
INTERNAL
PROC [] =
--and always Release
BEGIN
ENABLE
UNWIND => {
designInReadOperation ← NIL;
TokenIO.ReleaseReader[];
};
TechnologyCheck:
INTERNAL
PROC [] =
--Side-effect: if bad, designInReadOperation is set to NIL
BEGIN
ENABLE UNWIND => {designInReadOperation ← NIL};
dont:
BOOL ← CDEvents.ProcessEvent[
ev: readEvent,
design: designInReadOperation,
x: NIL,
listenToDont: TRUE
].dont;
IF dont
THEN {
designInReadOperation ← NIL;
TerminalIO.WriteRope["Technology rejects read\n"];
}
END;
VersionAndSealCheck:
INTERNAL PROC [] =
BEGIN
--chipndale check
IF TokenIO.ReadInt[]#xChipndaleFile
THEN {
TerminalIO.WriteRope["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
TerminalIO.WriteRope["design was written with newer chipndaleversion\n"];
TerminalIO.WriteRope["get a new chipndale version\n"];
ERROR TokenIO.Error[other, "chipndale versionkey"];
}
ELSE
IF versionKey
IN [6..xVersion]
THEN {
-- not new but dont tell it
NULL
}
ELSE
IF versionKey
IN [5..xVersion]
THEN {
-- not new but everything ok
TerminalIO.WriteRope["design was written with older chipndaleversion\n"];
}
ELSE
IF versionKey
=4
THEN {
-- known problem versions
TerminalIO.WriteRope["********\n"];
TerminalIO.WriteRope["design was written with older chipndaleversion; filekey = 4\n"];
TerminalIO.WriteRope["Please convert also your other designs (by reading and subsequent writing)\n"];
TerminalIO.WriteRope["Check carefully the alignment of cells which have n-well\n"];
TerminalIO.WriteRope[" IF alignment is wrong THEN { try with a commandtool:\n"];
TerminalIO.WriteRope[" CD18InputToggle\n"];
TerminalIO.WriteRope[" }\n"];
TerminalIO.WriteRope["If the design looked bad, call Jacobi.pa, (I might help you, but also I'd like to know about the problem, and, whether the proposed fix helped)\n"];
TerminalIO.WriteRope["********\n"];
}
ELSE
IF versionKey=3
THEN {
-- known problem versions
TerminalIO.WriteRope["********\n"];
TerminalIO.WriteRope["design was written with older chipndaleversion; filekey = 3\n"];
TerminalIO.WriteRope["Please convert also your other designs (by reading and subsequent writing)\n"];
TerminalIO.WriteRope["Check carefully the alignment of cells which have n-well"];
TerminalIO.WriteRope["If the design looked bad, call Jacobi.pa, (I might help you, but also I'd like to know about the problem)\n"];
TerminalIO.WriteRope["********\n"];
}
ELSE
IF versionKey
IN [0..xVersion]
THEN {
-- not new but please convert
TerminalIO.WriteRope["********\n"];
TerminalIO.WriteRope["Design was written with older chipndaleversion\n"];
TerminalIO.WriteRope["Please convert also your other designs (by reading and subsequent writing)\n"];
TerminalIO.WriteRope["********\n"];
}
ELSE {
-- too old
TerminalIO.WriteRope["design was written with older chipndaleversion\n"];
TerminalIO.WriteRope["This version is no more supported\n"];
ERROR TokenIO.Error[other, "chipndale versionkey"];
};
};
--seal check
IF versionKey>0
THEN {
IF TokenIO.ReadInt[]#-1
THEN {
TerminalIO.WriteRope["File had not been properly closed; has bad seal\n"];
ERROR TokenIO.Error[other, "file had not been properly closed"];
};
};
END;
ReadVersionKeys:
PROC [design:
CD.Design] =
BEGIN
IF versionKey>=7
THEN {
designVersionKey ← TokenIO.ReadRope[];
};
IF Rope.IsEmpty[designVersionKey]
THEN
designVersionKey ← Convert.RopeFromTime[from: BasicTime.Now[], end: seconds];
CDProperties.PutPropOnDesign[design, $FileVersion, designVersionKey];
END;
-- DoWhileAttached
VersionAndSealCheck[];
technologyKey ← TokenIO.ReadAtom[];
technologyName ← TokenIO.ReadRope[];
technology ← CD.FetchTechnology[technologyKey];
IF technology=
NIL
THEN {
TerminalIO.WriteRope["technology '"];
TerminalIO.WriteRope[technologyName];
TerminalIO.WriteRope["' not loded\n"];
GOTO NotDoneAndRelease
};
designInReadOperation ← CDOps.CreateDesign[technology];
TechnologyCheck[];
IF designInReadOperation=NIL THEN GOTO NotDoneAndRelease;
designInReadOperation.name ← TokenIO.ReadRope[];
IF Rope.IsEmpty[designInReadOperation.name] THEN designInReadOperation.name ← fileName;
ReadVersionKeys[designInReadOperation]; --read before check, fixed again later
IF check#
NIL
THEN {
IF NOT check[designInReadOperation] THEN GOTO NotDoneAndRelease;
};
ReadDesignData[];
TokenIO.ReleaseReader[];
CDValue.Store[boundTo: designInReadOperation, key: $CDxFromFile, value: fileName];
EXITS
NotDoneAndRelease => {
designInReadOperation ← NIL;
TokenIO.ReleaseReader[];
};
END;
-- 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.WriteRope[r];
TerminalIO.WriteRope["... not attached\n"];
GOTO NotAttached
}
];
DoWhileAttached[];
EXITS
NotAttached => RETURN
END;
ReadName:
PROC []
RETURNS [name: Rope.
ROPE] =
BEGIN
wDir: Rope.ROPE ← FileNames.CurrentWorkingDirectory[];
TerminalIO.WriteRope[" input file"];
IF wDir#
NIL
THEN {
TerminalIO.WriteRope[" ("];
TerminalIO.WriteRope[wDir];
TerminalIO.WriteRope[")"];
};
name ← TerminalIO.RequestRope[" > "];
END;
-- begin ReadDesign
iDidTheOpen: BOOL ← FALSE;
name: Rope.ROPE;
-- open file; assign fileName and binfile
IF from#
NIL
AND
ISTYPE[from,
IO.
STREAM]
THEN {
fileName ← NIL;
binfile ← NARROW[from, IO.STREAM]
}
ELSE {
IF from=NIL THEN name ← ReadName[]
ELSE
IF
ISTYPE[from, Rope.
ROPE]
THEN {
name ← NARROW[from, Rope.ROPE];
IF Rope.IsEmpty[name] THEN name ← ReadName[];
}
ELSE {
TerminalIO.WriteRope["ReadDesign does not support type of 'from' parameter\n"];
GOTO NotOpened;
};
fileName ← MakeName[name, "dale"];
binfile ←
FS.StreamOpen[fileName !
FS.Error =>
IF error.group # bug
THEN {
TerminalIO.WriteRope[fileName];
TerminalIO.WriteRope[" not opened: "];
TerminalIO.WriteRope[error.explanation];
TerminalIO.WriteLn[];
GOTO NotOpened;
}];
iDidTheOpen ← TRUE;
TerminalIO.WriteRope[fileName];
TerminalIO.WriteRope[" opened \n"];
};
-- do the actual work
DoReadDesign[check];
design ← designInReadOperation;
-- finalize
designInReadOperation ← NIL;
indexTable ← NIL;
tableTable ← NIL;
IF iDidTheOpen THEN IO.Close[binfile];
RETURN [design];
EXITS
NotOpened =>
{
indexTable ← NIL;
tableTable ← NIL;
designInReadOperation ← NIL;
TerminalIO.WriteRope["Read not done\n"];
RETURN [NIL];
}
END;
ReadOrientation:
PUBLIC
PROC []
RETURNS [orientation:
CD.Orientation] =
BEGIN
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
END;
-- Working directories ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CheckWorkingDirectory:
PROC [wDir: Rope.
ROPE]
RETURNS [slashWDir: Rope.
ROPE] =
--if wDir is a directory, assign it to slashWDir
--else slashWDir ← nil
INLINE BEGIN
IF FileNames.IsADirectory[wDir]
AND
NOT FileNames.IsAPattern[wDir]
THEN {
length: INT;
slashWDir ← FileNames.ConvertToSlashFormat[wDir];
length ← slashWDir.Length[];
IF slashWDir = wDir
AND length > 0
AND slashWDir.Fetch[length - 1] = '/
THEN {
RETURN [slashWDir];
}
};
RETURN [NIL]
END;
SetWorkingDirectory:
PUBLIC
PROC [design:
REF, wDir: Rope.
ROPE] =
BEGIN
wDir ← CheckWorkingDirectory[wDir].slashWDir;
CDValue.Store[boundTo: design, key: $WorkingDirectory, value: wDir];
END;
wDirAtStart: Rope.ROPE = FileNames.CurrentWorkingDirectory[];
GetWorkingDirectory:
PUBLIC
PROC [design:
REF]
RETURNS [wDir: Rope.
ROPE←
NIL] =
BEGIN
server: Rope.ROPE = "indigo"; --RELEASE--
release: Rope.ROPE = "19";
main: Rope.ROPE = "/chipndale/5.2/";
WITH design
SELECT
FROM
des:
CD.Design => {
WITH CDValue.Fetch[boundTo: design, key: $WorkingDirectory, propagation: global]
SELECT
FROM
r: Rope.ROPE => wDir ← CheckWorkingDirectory[r];
ENDCASE => NULL;
};
tech:
CD.Technology => {
techName: Rope.ROPE ← tech.name;
IF techName=NIL THEN techName ← Atom.GetPName[tech.key];
wDir ← CheckWorkingDirectory[UserProfile.Token[
key: Rope.Cat["Chipndale.", techName, ".BaseDirectory"],
default: NIL
]];
IF wDir=NIL THEN wDir ← Rope.Cat["/", server, main, techName, release, "/"];
IF wDir=NIL THEN wDir ← GetWorkingDirectory[NIL];
IF wDir=NIL THEN wDir ← wDirAtStart;
};
ENDCASE => {
IF design=
NIL
THEN {
wDir ← CheckWorkingDirectory[
UserProfile.Token[key: "Chipndale.BaseDirectory", default: NIL]];
IF wDir=NIL THEN wDir ← Rope.Cat["/", server, main, "CD", release, "/"];
IF wDir=NIL THEN wDir ← wDirAtStart;
};
};
END;
UseWorkingDirectory:
PUBLIC
PROC [design:
REF]
RETURNS [wDir: Rope.
ROPE] =
--set's it for the running process
--return's it
BEGIN
wDir ← GetWorkingDirectory[design];
IF wDir#
NIL
THEN {
[] ← List.PutAssoc[key: $WorkingDirectory, val: wDir, aList: ProcessProps.GetPropList[]];
RETURN [wDir];
};
RETURN [FileNames.CurrentWorkingDirectory[]]
END;
TrailingChar:
PROC [base: Rope.
ROPE, char:
CHAR]
RETURNS [
INT] = {
--position of last "char", only before '!, '], '>, '/ considered
len: INT ← Rope.Length[base];
pos: INT ← len;
WHILE pos > 0
DO
SELECT Rope.Fetch[base, pos ← pos - 1]
FROM
char => RETURN [pos];
'!, '], '>, '/ => EXIT;
ENDCASE;
ENDLOOP;
RETURN [len];
};
MakeName:
PUBLIC
PROC [base: Rope.
ROPE,
ext: Rope.ROPE←NIL, wDir: Rope.ROPE←NIL, modifier: Rope.ROPE←NIL] RETURNS [Rope.ROPE] =
BEGIN
bang: INT = TrailingChar[base, '!];
--remove version number
r: Rope.ROPE ← base.Substr[len: bang];
--include modifier
IF ~modifier.IsEmpty[] THEN r ← r.Concat[modifier];
--include extension
IF ~ext.IsEmpty[]
AND (TrailingChar[r, '.]>=r.Length[])
THEN {
dot2: INT ← TrailingChar[ext, '.];
IF dot2>=ext.Length[] THEN r ← r.Cat[".", ext]
ELSE r ← r.Concat[ext.Substr[dot2]]
};
--include working directory
IF wDir#
NIL
THEN {
IF r.IsEmpty[] OR (r.Fetch[]#'/ AND r.Fetch[]#'[) THEN
r ← FileNames.Directory[wDir].Concat[r]
};
--put version number back
IF bang<Rope.Length[base]
THEN {
r ← r.Concat[base.Substr[bang]]
};
RETURN [r]
END;
MakeShortName:
PUBLIC PROC [design:
CD.Design]
RETURNS [name: Rope.
ROPE ←
NIL] =
BEGIN
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"
END;
NewDesignHasBeenCreated: CDEvents.EventProc =
-- PROC [event: REF, design: CD.Design, x: REF] --
--repaint captions and sometimes the contents
BEGIN
SetWorkingDirectory[design, FileNames.CurrentWorkingDirectory[]];
END;
CD18Input: Commander.CommandProc =
BEGIN
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"];
END;
-- Module Initialization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
readEvent: CDEvents.EventRegistration = CDEvents.RegisterEventType[$ReadTechnologyPrivate];
CDValue.EnregisterKey[key: $WorkingDirectory];
CDEvents.RegisterEventProc[$CreateNewDesign, NewDesignHasBeenCreated];
--fix a problem in CD18
Commander.Register[
key: "CD18InputToggle",
proc: CD18Input,
doc: "toggle input mode of cd18"
];
END.
versionKey 0
versionKey 1:
objects with children carry names
versionKey 2:
versionKey 3: June 15, 1984 3:46:13 pm PDT;
applications 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