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:
BOOL←
FALSE] =
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],
END;
contact =>
BEGIN
j: CARDINAL ← LOOPHOLE[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: BOOL ← FALSE;
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.