ChipmonkCmosRead.mesa
Last Edited by: Kimr, October 26, 1983 9:39 am
Last Edited by: Jacobi, October 25, 1983 12:48 pm
Last Edited by: Jacobi, February 13, 1984 10:23 am
DIRECTORY
Atom USING [MakeAtom],
Basics USING [BITAND, BITSHIFT],CD,
CDApplications,
CDBusses USING [CreateBus],
CDCells USING [CreateEmptyCell],
CDCommands,
CDDirectory USING [Include],
CDExtras,
CDInline,
CDIOExtras,
CDOps,
CDOrient,
CDPrivate,
CDProperties,
CDRects USING [CreateRect],
CDRepetitions,
CDTexts,
CDViewer,
Convert,
Commander USING [CommandProc, Register],
CommandTool,
FileNames,
FS,
IO,
CMos,
CMosContacts,
CMosTransistors,
Rope,
TerminalIO,
ViewerClasses USING [Viewer];
ChipmonkCmosRead: CEDAR MONITOR
IMPORTS Atom, Basics, CDApplications, CDBusses, CDCells, CDCommands, CDDirectory, CDExtras, CDIOExtras, CDOps, CDPrivate, CDProperties, CDRects, CDRepetitions, CDTexts, CDViewer, Commander, FileNames, FS, IO, CMos, CMosContacts, CMosTransistors, CommandTool, Rope, TerminalIO
SHARES CDProperties =
BEGIN
-- global constants
lambdaInChipmonk: INTEGER = 2;
--In Chipndale we must make no assumptions about the
--value of lambda. It can (and does) change from time to time;
--but we know that chipndales lambda is >= 2
lambdaFactor: INT = CD.lambda/lambdaInChipmonk;
instance: INTEGER = 1;
transistor: INTEGER = 2; 
contact: INTEGER = 3;
wire: INTEGER = 4;
rectangle: INTEGER = 5;
text: INTEGER = 6;
bus: INTEGER = 7;
repeat: INTEGER = 8;
contTypALen: INTEGER = 12;
maxCellNum: INTEGER = 500;
codeWordForDataFile : CARDINAL = 123751B;
debugging: BOOLEAN = FALSE;
debug: BOOLEAN = FALSE;
atomTableSize: INTEGER = 256;
contTypA: ARRAY [1..contTypALen] OF contType = [
mDif, mPol, butt, burr,
mm2, mDif, mDif, mm2,
mm2, mm2, mm2, difShort];
contLevel: ARRAY [1..contTypALen] OF CD.Level = [
CMos.ndif, CMos.pol, CMos.ndif, CMos.ndif,
CMos.met2, CMos.pdif, CMos.nwelCont, CMos.ndif,
CMos.pol, CMos.ndif, CMos.ndif, CMos.ndif]; -- for versions < 6
fileLevel: ARRAY [0..15] OF CD.Level = [
CMos.cut, CMos.ndif, CMos.pol, CMos.met,
CMos.imp, CMos.ovg, CMos.bur, CMos.snerd,
CMos.cut2, CMos.pdif, CMos.pwelCont, CMos.met2,
CMos.pwel, CMos.nwel, CMos.nwelCont, CMos.NOcOL];
-- global vars
contType: TYPE = {burr, mDif, difShort, butt, mPol, mm2};
design: CD.Design;
cellNameA: REF ARRAY [0..maxCellNum] OF CD.ObPtr ← NEW[ARRAY [0..maxCellNum] OF CD.ObPtr];
atomTable: REF ARRAY [1..atomTableSize] OF ATOM ← NEW[ARRAY [1..atomTableSize] OF ATOM];
standardFont: REF CDTexts.FontRec = CDTexts.GetFont[key: $CDxCompatibilityFont, technology: CMos.cmos];
chipfile: IO.STREAM;
fileName: Rope.ROPE;
errs: INT 𡤀
NotYetImpl: PROC [] =
BEGIN
errs ← errs+1;
TerminalIO.WriteRope["?"];
END;
InWord: PROC RETURNS [INTEGER] =
BEGIN
highbyte: CARDINAL = LOOPHOLE[IO.GetChar[chipfile], CARDINAL];
lowbyte: CARDINAL = LOOPHOLE[IO.GetChar[chipfile], CARDINAL];
RETURN [ LOOPHOLE[(256*highbyte) + lowbyte, INTEGER] ];
END;
FileFormat: ERROR = CODE;
Lambda: PROCEDURE [i: INT] RETURNS [CD.DesignNumber] =
INLINE { RETURN [lambdaFactor*i] };
InOrientation: PROC [] RETURNS [CD.Orientation] =
INLINE BEGIN
i: INTEGER = InWord[];
IF i>=FIRST[CD.Orientation] AND i<=LAST[CD.Orientation] THEN RETURN [i]
ELSE ERROR FileFormat;
END;
InLevel: PROC [] RETURNS [CD.Level] =
INLINE BEGIN
i: INTEGER = InWord[];
IF i>= 0 AND i<= 15 THEN RETURN [fileLevel[i]]
ELSE ERROR FileFormat;
END;
NewCellName: PROC [index: INTEGER] RETURNS [cellName: Rope.ROPE] =
BEGIN
cellName ← IO.PutFR[ "cell#%d", IO.int[index]];
END;
InObject: PROC[version: INTEGER] RETURNS [obj: CD.ObPtr, rectProp: BOOLFALSE] =
BEGIN
j, k, w, l, we, le, dumsur: INTEGER;
kk: CARDINAL;
lev: CD.Level;
dumrope: Rope.ROPE;
IF debugging OR debug THEN
TerminalIO.WriteRope[" (Include new object ... "];
j ← InWord[];
SELECT j FROM
instance =>
BEGIN
k ← InWord[]; -- cell ID num
obj ← cellNameA[k];   
END;
transistor =>
BEGIN
aExt: CD.DesignNumber ← 0;
w ← InWord[];
l ← InWord[];
kk ← LOOPHOLE[InWord[]];
IF version > 4 AND LOOPHOLE[Basics.BITAND[kk, 10000B], CARDINAL] # 0 THEN
dumsur ← InWord[];
IF LOOPHOLE[Basics.BITAND[LOOPHOLE[kk, CARDINAL], 20000B], CARDINAL] # 0 THEN
aExt ← Lambda[InWord[]]; -- if angle get angle ext.
IF LOOPHOLE[Basics.BITAND[kk, 100000B], CARDINAL]#0 THEN {
IF version>7 THEN [] ← InWord[]; -- implant
};
we ← Basics.BITAND[Basics.BITSHIFT[kk, -6], 77B];
le ← Basics.BITAND[kk, 77B];
lev ← IF Basics.BITAND[kk, 10000B]#0 THEN CMos.pdif ELSE CMos.ndif;
SELECT TRUE FROM
LOOPHOLE[Basics.BITAND[kk, 40000B], CARDINAL] #0 =>
{obj ← NIL; TerminalIO.WriteRope[" error: pullup in cmos\n"]};
obj ← CMosTransistors.CreatePullUp[w: Lambda[w], l: Lambda[l], wExt: Lambda[we], lExt: Lambda[le], difLev: lev];
LOOPHOLE[Basics.BITAND[kk, 20000B], CARDINAL] #0 =>
obj ← CMosTransistors.CreateAngleTransistor[w: Lambda[w], l: Lambda[l], wExt: Lambda[we], lExt: Lambda[le], aExt: aExt, difLev: lev];
ENDCASE =>
obj ← CMosTransistors.CreateTransistor[w: Lambda[w], l: Lambda[l], wExt: Lambda[we], lExt: Lambda[le], difLev: lev];
END;
contact =>
BEGIN
j: CARDINALLOOPHOLE[InWord[]]; -- get contact type
k: CARDINAL ← Basics.BITAND[j, 37B]; -- get contact type
l: CARDINAL ← Basics.BITSHIFT[j, -8];
lev ← IF version > 5 THEN InLevel[] ELSE contLevel[k];
IF version > 4 THEN dumsur ← LOOPHOLE[InWord[]];
SELECT contTypA[k] FROM
mPol => obj ← CMosContacts.CreatePolyCon[Lambda[l]];
mDif => obj ← CMosContacts.CreateDifCon[Lambda[l], lev];
difShort => obj ← CMosContacts.CreateDifShortCon[lev];
butt => obj← CMosContacts.CreateButCon[lev];
burr => BEGIN
w ← LOOPHOLE[InWord[]];
k ← LOOPHOLE[InWord[]];
j ← Basics.BITSHIFT[k, -8];
obj ← CMosContacts.CreateBurCon[w: Lambda[w], l: Lambda[l], wex: Lambda[j], lex: Lambda[LOOPHOLE[Basics.BITAND[k, 37B], CARDINAL]], difLev: lev];
END;
mm2 => obj ← CMosContacts.CreateMmCon[Lambda[l], 0, 0];
ENDCASE => {TerminalIO.WriteRope[" Error in selecting contact type "]; ERROR};
END;
wire =>
BEGIN
w ← InWord[];
l ← InWord[];
lev ← InLevel[];
IF version > 4 AND lev = CMos.pdif THEN dumsur ← InWord[];
obj ← CDRects.CreateRect[[Lambda[w],Lambda[l]], lev];        
END;
rectangle =>
BEGIN
w ← InWord[];
l ← InWord[];
lev ← InLevel[];
obj ← CDRects.CreateRect[[Lambda[w], Lambda[l]], lev];  
rectProp ← TRUE;
END;
text => {
dumrope ← InString[];
obj ← CDTexts.CreateText[dumrope, standardFont]
}; 
bus =>
BEGIN
w: CD.DesignNumber = Lambda[InWord[]];
l: CD.DesignNumber = Lambda[InWord[]];
lev: CD.Level = InLevel[];
count: NAT = InWord[];
spacing: CD.DesignNumber = Lambda[InWord[]];
topInc: CD.DesignNumber = Lambda[InWord[]];
botInc: CD.DesignNumber = Lambda[InWord[]];
IF lev=CMos.pdif THEN {TerminalIO.WriteRope[" pdiffusion bus not implemented \n"]};
obj ← CDBusses.CreateBus[
sizeOfFirst: [w, l],
lev: lev,
count: count,
offset: [spacing, topInc],
lengIncrement: botInc-topInc
]; -- compare: obj ← Chipmonk.makeBus[l, w, lev, count, spacing, topInc, botInc];
END;
repeat =>
BEGIN
rob: CD.ObPtr = InObject[version].obj;
ignoredw: INT = InWord[]; -- ignored
ignoredl: INT = InWord[]; -- ignored
dx: CD.DesignNumber = Lambda[InWord[]];
dy: CD.DesignNumber = Lambda[InWord[]];
count: NAT ← InWord[];
orient: CD.Orientation ← InOrientation[];
obj ← CDRepetitions.CreateRepetition[design: design, ob: rob, count: count, offset: [dx, dy], orientation: orient];
END;
ENDCASE => {TerminalIO.WriteRope["** Erronous object\n"]; obj ← NIL};
IF debugging OR debug THEN
TerminalIO.WriteRope[" done) \n"];
END; -- of InObject
InList: PROC[ver: INTEGER] RETURNS [list: CD.ApplicationList ← NIL, length: INT] =
BEGIN
rectProp: BOOLFALSE;
appCount: INTEGER;
app: CD.ApplicationPtr;
ob: CD.ObPtr;
location: CD.DesignPosition;
orientation: CD.Orientation;
IF debugging OR debug THEN TerminalIO.WriteRope["start list\n"];
appCount ← InWord[];
FOR appNum: INTEGER IN [0..appCount) DO
location.x ← Lambda[InWord[]];
location.y ← Lambda[InWord[]];
orientation ← InOrientation[];
[ob, rectProp] ← InObject[ver];
IF ob#NIL THEN {
app ← CDApplications.NewApplicationI[ob: ob, location: location, orientation: orientation];
list ← CONS[app, list];
IF rectProp THEN CDProperties.PutPropOnApplication[onto: app, prop: $CDxChipmonkThinks, val: $Rect];
}
ELSE {
app ← NEW[CD.Application];
TerminalIO.WriteRope["nil object\n"]
};
IF ver > 3 THEN
BEGIN
propCount: INTEGER = InWord[];
FOR propNum: INTEGER IN [0..propCount) DO
InProp[app];
ENDLOOP;
END;
ENDLOOP;
IF debugging OR debug THEN TerminalIO.WriteRope["end list\n"];
RETURN[list, appCount];
END;
InProp: PROC [aptr: CD.ApplicationPtr] =
BEGIN
kind: INTEGER ← InWord[];
name: REF ← NIL;
value: REF;
SELECT kind FROM
1 => {
IF aptr=NIL OR aptr.ob=NIL OR ISTYPE[aptr.ob.specificRef, CD.RectPtr] THEN
name ← $SignalName
ELSE name ← $InstanceName;
value ← InString[];
};
2 => {
name ← InAtom[];
value ← InAtom[];
};
ENDCASE => {
name ← NIL;
TerminalIO.WriteRope["** unknown property kind\n"];
};
IF name#NIL AND aptr#NIL AND aptr.ob#NIL THEN
CDProperties.PutProp[onto: aptr, prop: name, val: value]
END;
InAtom: PROC [] RETURNS[a: ATOM] =
BEGIN
i: INTEGER ← InWord[];
IF i<0 THEN {
a ← atomTable[-i]
}
ELSE IF i>0 THEN {
a ← Atom.MakeAtom[InString[]];
IF i <= atomTableSize THEN atomTable[i] ← a
ELSE TerminalIO.WriteRope["** Atom table code wrong\n"];
}
ELSE {
TerminalIO.WriteRope["** Atom code wrong\n"];
a ← NIL
}
END;
InString: PROC [] RETURNS[s: Rope.ROPE] =
BEGIN
j, i, len: CARDINAL;
flg: BOOLEAN;
j ← LOOPHOLE[InWord[]];
len ← Basics.BITSHIFT[j, -8];
IF len = 0 THEN BEGIN s ← ""; RETURN; END;
flg ← TRUE;
FOR i IN [0..len) DO
IF flg THEN
s ← Rope.Cat[s, Rope.FromChar[LOOPHOLE[Basics.BITAND[j, 377B], CHAR]]]
ELSE
BEGIN
j ← LOOPHOLE[InWord[]];
s ← Rope.Cat[s, Rope.FromChar[LOOPHOLE[Basics.BITSHIFT[j, -8], CHAR]]];
END;
flg ← NOT flg;
ENDLOOP;
END;
FileOpened: PROC [name: Rope.ROPE] RETURNS [fileWasOpened: BOOLEAN] =
BEGIN
IF Rope.IsEmpty[name] THEN name ← TerminalIO.RequestRope["Input file > "];
fileName ← CDExtras.AppendExt[name, "chip"];
chipfile ← FS.StreamOpen[fileName ! FS.Error =>
IF error.group#bug THEN {
TerminalIO.WriteRope[fileName];
TerminalIO.WriteRope[" not opened: "];
TerminalIO.WriteRope[error.explanation];
TerminalIO.WriteLn[];
GOTO FileName
}];
TerminalIO.WriteRope["File being read is "];
TerminalIO.WriteRope[fileName];
TerminalIO.WriteRope["\n"];
fileWasOpened ← TRUE;
EXITS
FileName => {fileWasOpened ← FALSE};
END;
ResetSimplification: PROC[cell: CD.ObPtr, leng: INT𡤀] = INLINE
BEGIN
long: INT ~ MAX[MAX[cell.size.y, cell.size.x], 1];
short: INT ~ MAX[MIN[cell.size.y, cell.size.x], 1];
cp: CD.CellPtr ~ NARROW[cell.specificRef];
leng ← leng/2+6;
leng ← MAX[MIN[leng, 300], 8];
--make it symetric now using shorter size
IF cell.size.y>cell.size.x THEN {
leng ← (leng*long)/short;
};
leng ← MAX[MIN[leng, 600], 8];
--introduce longer side
leng ← (leng*3)/(2+(long/short)/2);
cp.simplifyOn ← MAX[MIN[leng, 600], 8];
END;
ReadChip: PROC =
BEGIN
ENABLE {
FileFormat => {
TerminalIO.WriteRope["\n**File-Format error\n"];
CDPrivate.Debug[msg: "file format; [proceed does not clobber other designs]"];
GOTO IOError;
};
IO.EndOfStream => {
TerminalIO.WriteRope["\n**end of stream error\n"];
CDPrivate.Debug[msg: "file format; [proceed does not clobber other designs]"];
GOTO IOError;
};
IO.Error => {
TerminalIO.WriteRope["\n**io error\n"];
--if you are debugging here: inspect "ec"
CDPrivate.Debug[msg: "io error [proceed does not clobber other designs]"];
GOTO IOError;
};
};
i, j, k, ver, cCnt, depht: INTEGER;
leng: INT;
ss: Rope.ROPE;
cdp: CD.ObPtr;
cellPtr: CD.CellPtr;
errs𡤀
i ← InWord[];
IF i # LOOPHOLE[codeWordForDataFile, INTEGER] AND
NOT TerminalIO.UserSaysYes[ "Doesn't look like a .chip file -- should program continue?"] THEN RETURN;
ver ← InWord[];
cCnt ← InWord[];
IF cCnt > maxCellNum THEN
BEGIN
TerminalIO.WriteRope["Too many different kinds of cells in design...aborting read\n"];
RETURN;
END;
IF ver < 3 THEN
BEGIN
TerminalIO.WriteRope[" Version number too low...aborting read\n"];
RETURN;
END;
IF ver>8 THEN
BEGIN
TerminalIO.WriteRope[" new chipmonk version unknown to chipndale...aborting read\n"];
RETURN;
END;
FOR j IN [0..cCnt] DO
cellNameA[j] ← CDCells.CreateEmptyCell[];
ENDLOOP;
TerminalIO.WriteRope["Starting cell directory\n"]; 
FOR k IN [1..cCnt] DO
j ← InWord[];
cdp ← cellNameA[j];
ss ← InString[];
cdp.size.x ← Lambda[InWord[]];
cdp.size.y ← Lambda[InWord[]];
[] ← InWord[]; -- this is some count in chipmonk ??
cellPtr ← NARROW[cdp.specificRef, CD.CellPtr];
[cellPtr.contents, leng] ← InList[ver];
ResetSimplification[cdp, leng];
IF NOT Rope.IsEmpty[ss] THEN
cellPtr.name ← ss
ELSE
cellPtr.name ← NewCellName[k];
[] ← CDDirectory.Include[design: design, object: cdp, fiddleName: TRUE];
ENDLOOP;
TerminalIO.WriteRope["Finished cell directory\n"];
depht ← IF ver<7 THEN 0 ELSE InWord[];
IF depht>0 THEN {
TerminalIO.WriteRope["***design was pushed in\nnot read in correctly\n"];
RETURN;
};
IF ver>=7 THEN {
fileChangeCode: INTEGER = InWord[];
};
design.actual.first.specific.contents ← InList[ver].list;
design.name ← fileName;
TerminalIO.WriteRope["Finished reading chip\n"];
IF errs>0 THEN
BEGIN
TerminalIO.WriteInt[errs];
errs ← 0;
TerminalIO.WriteRope[" unknown objects\n"];
END;
IO.Close[chipfile];
EXITS
IOError => {TerminalIO.WriteRope[" proceed; discard this design\n"];};
END; -- of ReadChip
CommandReadChip: ENTRY Commander.CommandProc =
BEGIN
ENABLE {
TerminalIO.UserAbort => GOTO UserAbrt;
UNWIND => NULL;
};
list: LIST OF Rope.ROPE;
length: NAT;
name: Rope.ROPE;
[list, length] ← CommandTool.ParseToList[cmd];
IF length=0 THEN name←NIL
ELSE IF length=1 THEN name←list.first
ELSE {
result←$Failure;
msg←"unknown arguments";
RETURN
};
design← CDOps.CreateDesign[CMos.cmos];
IF FileOpened[name] THEN {
ReadChip[];
CDCommands.SelectAll[design];
CDCommands.TransformSelected[design, CDOrient.rotate180+CDOrient.mirrorX];
CDCommands.DeselectAll[design];
[] ← CDViewer.CreateViewer[design];
CDIOExtras.SetDesignsWorkingDirectory[design, FileNames.CurrentWorkingDirectory[]];
};
EXITS
UserAbrt => {TerminalIO.WriteRope["read aborted\n"]};
END;
TestRead: ENTRY Commander.CommandProc =
BEGIN
ENABLE {
IO.EndOfStream => GOTO IOEnd;
UNWIND => NULL;
};
w: CARDINAL;
r: Rope.ROPE;
IF FileOpened[NIL] THEN {
TerminalIO.WriteRope["--startfile--\n"];
DO
w ← LOOPHOLE[InWord[]];
r ← IO.PutFR["%7b\n", IO.card[w]];
TerminalIO.WriteRope[r];
ENDLOOP;
};
EXITS
IOEnd => {TerminalIO.WriteRope["--endfile--\n"]};
END;
Commander.Register[
key: "CDTestRead",
proc: TestRead,
doc: "Reads file and display it on Terminal"
];
Commander.Register[
key: "CDReadCMos",
proc: CommandReadChip,
doc: "Reads old cmos Chipmonk file"
];
Commander.Register[
key: "CDReadCMCMos",
proc: CommandReadChip,
doc: "Reads old cmos Chipmonk file"
];
END.