ChipmonkNMosRead.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 5:35 pm
DIRECTORY
Atom USING [MakeAtom],
Basics USING [BITAND, BITSHIFT],CD,
CDApplications,
CDBusses USING [CreateBus],
CDCells USING [CreateEmptyCell],
CDDirectory USING [Include],
CDCommands,
CDExtras,
CDInline,
CDIOExtras,
CDOps,
CDOrient,
CDPrivate,
CDProperties,
CDRects USING [CreateRect],
CDRepetitions,
CDTexts,
CDViewer,
Commander USING [CommandProc, Register],
CommandTool,
FileNames,
FS,
IO,
NMos,
NMosContacts,
NMosTransistors,
Rope USING [ROPE, Cat, IsEmpty, FromChar],
TerminalIO,
ViewerClasses USING [Viewer];
ChipmonkNMosRead: CEDAR MONITOR
IMPORTS Atom, Basics, CDApplications, CDBusses, CDCells, CDCommands, CDDirectory, CDExtras, CDIOExtras, CDOps, CDPrivate, CDProperties, CDRects, CDRepetitions, CDTexts, CDViewer, Commander, CommandTool, FileNames, FS, IO, NMos, NMosContacts, NMosTransistors, 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 = [
NMos.dif, NMos.pol, NMos.dif, NMos.dif,
NMos.met2, NMos.dif, NMos.nwelCont, NMos.dif,
NMos.pol, NMos.dif, NMos.dif, NMos.dif
]; -- for versions < 6
fileLevel: ARRAY [0..15] OF CD.Level = [
NMos.cut, NMos.dif, NMos.pol, NMos.met,
NMos.imp, NMos.ovg, NMos.bur, NMos.snerd,
NMos.cut2, NMos.NOcOL--pdif--, NMos.NOcOL--pwelcont--, NMos.met2,
NMos.NOcOL--pwel--, NMos.nwel, NMos.nwelCont, NMos.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: NMos.nmos];
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
impl: NMosTransistors.Implant ← NMosTransistors.enhancement;
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[kk, 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 impl ← InWord[] ELSE impl ← LAST[NMosTransistors.Implant]
};
we ← Basics.BITAND[Basics.BITSHIFT[kk, -6], 77B];
le ← Basics.BITAND[kk, 77B];
--lev ← IF Basics.BITAND[kk, 10000B] # LOOPHOLE[0] THEN NMos.pdif ELSE NMos.dif;
obj ← SELECT TRUE FROM
LOOPHOLE[Basics.BITAND[kk,40000B], CARDINAL] #0 =>
NMosTransistors.CreatePullUp[Lambda[w], Lambda[l], Lambda[we], Lambda[le]],
LOOPHOLE[Basics.BITAND[kk, 20000B], CARDINAL] #0 =>
NMosTransistors.CreateAngleTransistor[
w: Lambda[w], l: Lambda[l],
wExt: Lambda[we], lExt: Lambda[le], aExt: aExt,
implant: impl
],
ENDCASE =>
NMosTransistors.CreateTransistor[
w: Lambda[w], l: Lambda[l],
wExt: Lambda[we], lExt: Lambda[le],
implant: impl
];
END;
contact =>
BEGIN
j: CARDINALLOOPHOLE[InWord[]]; -- get contact type
kk: CARDINAL ← Basics.BITAND[j, 37B]; -- get contact type
l: CARDINAL ← Basics.BITSHIFT[j, -8];
lev ← IF version > 5 THEN InLevel[] ELSE contLevel[kk];
IF version > 4 THEN dumsur ← LOOPHOLE[InWord[]];
SELECT contTypA[kk] FROM
mPol => obj ← NMosContacts.CreatePolyCon[Lambda[l]];
mDif => obj ← NMosContacts.CreateDifCon[Lambda[l]];
-- difShort => obj ← NMosContacts.CreateDifShortCon[lev]; ************
butt => obj← NMosContacts.CreateButCon[];
burr => BEGIN
w ← LOOPHOLE[InWord[]];
kk ← LOOPHOLE[InWord[]];
j ← Basics.BITSHIFT[kk, -8];
obj ← NMosContacts.CreateBurCon[Lambda[w], Lambda[l], Lambda[j], Lambda[LOOPHOLE[Basics.BITAND[kk, 37B], CARDINAL]]];
END;
mm2 => obj ← NMosContacts.CreateMmCon[Lambda[l], 0, 0];
ENDCASE => ERROR;
END;
wire =>
BEGIN
w ← InWord[];
l ← InWord[];
lev ← InLevel[];
-- IF version > 4 AND lev = NMos.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[]];
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
--get file name
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, dummy, 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[]];
dummy ← InWord[];
cellPtr ← NARROW[cdp.specificRef, CD.CellPtr];
[cellPtr.contents, leng] ← InList[ver];
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[NMos.nmos];
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;
Commander.Register[
key: "CDReadNMos",
proc: CommandReadChip,
doc: "Reads old nmos Chipmonk file"
];
Commander.Register[
key: "CDReadCMNMos",
proc: CommandReadChip,
doc: "Reads old nmos Chipmonk file"
];
END.