ChipmonkCmosRead.mesa
Copyright © 1983, 1987 by Xerox Corporation. All rights reserved.
Last Edited by: Kimr, October 26, 1983 9:39 am
Last Edited by: Christian Jacobi, October 25, 1983 12:48 pm
Last edited by: Christian Jacobi, January 29, 1987 4:49:35 pm PST
DIRECTORY
Atom USING [MakeAtom],
Basics USING [BITAND, BITSHIFT],
CD,
CDInstances,
CDBasics,
CDBusCells USING [CreateBusCell],
CDCells,
CDCommandOps,
CDIO USING [MakeName],
CDDirectory USING [Include],
CDOps,
CDProperties,
CDRects USING [CreateRect],
CDRepetitions,
CDSequencer,
CDTexts,
CDViewer,
Commander USING [CommandProc, Register],
CommandTool,
FS,
IO,
CMos,
CMosCMContacts,
CMosCMTransistors,
Rope,
TerminalIO,
ViewerClasses USING [Viewer];
ChipmonkCmosRead:
CEDAR
MONITOR
IMPORTS Atom, Basics, CD, CDBasics, CDInstances, CDBusCells, CDCells, CDDirectory, CDIO, CDOps, CDCommandOps, CDProperties, CDRects, CDRepetitions, CDSequencer, CDTexts, CDViewer, Commander, FS, IO, CMos, CMosCMContacts, CMosCMTransistors, CommandTool, Rope, TerminalIO
SHARES CDProperties =
BEGIN
TransformSelected:
PROC [design:
CD.Design, transform:
CD.Orientation, base:
CD.Rect←[0, 0, -1, -1]] = {
ib, is, orientOff: CD.Position; r, oldbb: CD.Rect; oldPseudoCellT, newPseudoCellT: CD.Transformation;
sel: CD.InstanceList = CDInstances.OnlySelected[CDOps.InstList[design]];
IF sel=NIL THEN RETURN;
oldbb ← CDInstances.BoundingRectO[sel];
IF ~CDBasics.NonEmpty[base] THEN base ← CDInstances.BoundingRectI[sel];
ib ← CDBasics.BaseOfRect[base];
is ← CDBasics.SizeOfRect[base];
oldPseudoCellT ← [ib, original];
r ← CDBasics.MapRect[CDBasics.RectAt[[0,0], is], [[0,0], transform]];
orientOff ← CDBasics.BaseOfRect[r];
newPseudoCellT ← [CDBasics.SubPoints[ib, orientOff], transform];
FOR w:
CD.InstanceList ← sel, w.rest
WHILE w#
NIL
DO
pseudoCellRel: CD.Transformation ← CDBasics.DecomposeTransform[w.first.trans, oldPseudoCellT];
w.first.trans ← CDBasics.ComposeTransform[pseudoCellRel, newPseudoCellT]
ENDLOOP;
CDOps.Redraw[design, oldbb];
CDOps.Redraw[design, CDBasics.MapRect[CDBasics.DeMapRect[oldbb, oldPseudoCellT], newPseudoCellT]]
};
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 = CMos.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 = 1500;
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];
contLayer:
ARRAY [1..contTypALen]
OF
CD.Layer = [
CMos.ndif, CMos.pol, CMos.ndif, CMos.ndif,
CMos.met2, CMos.pdif, CMos.nwellCont, CMos.ndif,
CMos.pol, CMos.ndif, CMos.ndif, CMos.ndif
]; -- for versions < 6
cmToCDLayer:
ARRAY [0..15]
OF
CD.Layer = [
CMos.cut, CMos.ndif, CMos.pol, CMos.met,
CMos.imp, CMos.ovg, CMos.bur, CD.errorLayer --snerd-- ,
CMos.cut2, CMos.pdif, CMos.pwellCont, CMos.met2,
CMos.pwell, CMos.nwell, CMos.nwellCont, CD.errorLayer --NOcOL--
];
-- global vars
contType: TYPE = {burr, mDif, difShort, butt, mPol, mm2};
design: CD.Design;
cellNameA:
REF
ARRAY [0..maxCellNum]
OF
CD.Object
← NEW[ARRAY [0..maxCellNum] OF CD.Object];
atomTable:
REF
ARRAY [1..atomTableSize]
OF
ATOM
← NEW[ARRAY [1..atomTableSize] OF ATOM];
standardFont: CDTexts.CDFont = CDTexts.MakeFont[name: "Xerox/TiogaFonts/Tioga10"];
chipfile: IO.STREAM;
fileName: Rope.ROPE;
errs: INT 𡤀
NotYetImpl:
PROC [] = {
errs ← errs+1;
TerminalIO.PutRope["?"];
};
BadObject:
PROC [size:
CD.Position ← [4, 4]]
RETURNS [
CD.Object] = {
RETURN [CDRects.CreateRect[size, CD.errorLayer]]
};
InWord:
PROC
RETURNS [
INTEGER] = {
highbyte: CARDINAL = LOOPHOLE[IO.GetChar[chipfile], CARDINAL];
lowbyte: CARDINAL = LOOPHOLE[IO.GetChar[chipfile], CARDINAL];
RETURN [ LOOPHOLE[(256*highbyte) + lowbyte, INTEGER] ];
};
FileFormat: ERROR = CODE;
Lambda:
PROCEDURE [i:
INT]
RETURNS [
CD.Number] =
INLINE {
RETURN [lambdaFactor*i]
};
InOrientation:
PROC []
RETURNS [
CD.Orientation] =
INLINE {
i: INTEGER = InWord[];
IF i>=0 AND i<=15 THEN RETURN [VAL[i/4*2 + i MOD 2]] --different representation
ELSE ERROR FileFormat;
};
ToLayer:
PROC [i:
INTEGER]
RETURNS [
CD.Layer] =
INLINE {
IF i>= 0 AND i<= 15 THEN RETURN [cmToCDLayer[i]]
ELSE ERROR FileFormat;
};
InLayer:
PROC []
RETURNS [
CD.Layer] =
INLINE {
RETURN [ToLayer[InWord[]]]
};
NewCellName:
PROC [index:
INTEGER]
RETURNS [cellName: Rope.
ROPE] = {
cellName ← IO.PutFR[ "cell#%d", IO.int[index]];
};
InObject:
PROC[version:
INTEGER]
RETURNS [obj:
CD.Object, instProp:
REF←
NIL, instVal:
REF←
NIL] = {
j, k, w, l, we, le, dumsur: INTEGER;
kk: CARDINAL;
lev: CD.Layer;
dumrope: Rope.ROPE;
IF debugging
OR debug
THEN
TerminalIO.PutRope[" (Include new object ... "];
j ← InWord[];
SELECT j
FROM
instance => {
k ← InWord[]; -- cell ID num
obj ← cellNameA[k];
};
transistor => {
aExt: CD.Number ← 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.PutRope[" error: pullup in cmos\n"]};
obj ← CMosCMTransistors.CreatePullUp[w: Lambda[w], l: Lambda[l], wExt: Lambda[we], lExt: Lambda[le], difLev: lev];
LOOPHOLE[Basics.
BITAND[kk, 20000B],
CARDINAL] #0 =>
obj ← CMosCMTransistors.CreateAngleTransistor[w: Lambda[w], l: Lambda[l], wExt: Lambda[we], lExt: Lambda[le], aExt: aExt, difLev: lev];
ENDCASE =>
obj ← CMosCMTransistors.CreateTransistor[w: Lambda[w], l: Lambda[l], wExt: Lambda[we], lExt: Lambda[le], difLev: lev];
};
contact => {
j: CARDINAL ← LOOPHOLE[InWord[]]; -- get contact type
k: CARDINAL ← Basics.BITAND[j, 37B]; -- get contact type
l: CARDINAL ← Basics.BITSHIFT[j, -8];
lev ← IF version > 5 THEN InLayer[] ELSE contLayer[k];
IF version > 4 THEN dumsur ← LOOPHOLE[InWord[]];
SELECT contTypA[k]
FROM
mPol => obj ← CMosCMContacts.CreatePolyCon[Lambda[l]];
mDif => obj ← CMosCMContacts.CreateDifCon[Lambda[l], lev];
difShort => obj ← CMosCMContacts.CreateDifShortCon[lev];
butt => obj← CMosCMContacts.CreateButCon[lev];
burr =>
BEGIN
w ← LOOPHOLE[InWord[]];
k ← LOOPHOLE[InWord[]];
j ← Basics.BITSHIFT[k, -8];
obj ← CMosCMContacts.CreateBurCon[w: Lambda[w], l: Lambda[l], wex: Lambda[j], lex: Lambda[LOOPHOLE[Basics.BITAND[k, 37B], CARDINAL]], difLev: lev];
END;
mm2 => obj ← CMosCMContacts.CreateMmCon[Lambda[l], 0, 0];
ENDCASE => {TerminalIO.PutRope[" Error in selecting contact type "]; ERROR};
};
wire => {
i: INTEGER;
w ← InWord[];
l ← InWord[];
i ← InWord[];
lev ← ToLayer[i];
IF lev=CMos.pdif THEN lev ← CMos.wpdif;
SELECT i
FROM
7 => {instVal ← $snerdRect; instProp ← $SignalName};
15 => {instVal ← $NOcOLRect; instProp ← $SignalName};
ENDCASE => NULL;
IF version > 4 AND lev = CMos.wpdif THEN dumsur ← InWord[];
obj ← CDRects.CreateRect[[Lambda[w],Lambda[l]], lev];
};
rectangle => {
i: INTEGER;
w ← InWord[];
l ← InWord[];
instVal ← $Rect;
instProp ← $CDxChipmonkThinks;
i ← InWord[];
lev ← ToLayer[i];
IF lev=CMos.pdif THEN lev ← CMos.wpdif;
SELECT i
FROM
7 => {instVal ← $snerdRect; instProp ← $SignalName};
15 => {instVal ← $NOcOLRect; instProp ← $SignalName};
ENDCASE => NULL;
obj ← CDRects.CreateRect[[Lambda[w], Lambda[l]], lev];
};
text => {
dumrope ← InString[];
obj ← CDTexts.Create[dumrope, standardFont]
};
bus => {
w: CD.Number = Lambda[InWord[]];
l: CD.Number = Lambda[InWord[]];
lev: CD.Layer = InLayer[];
count: NAT = InWord[];
spacing: CD.Number = Lambda[InWord[]];
topInc: CD.Number = Lambda[InWord[]];
botInc: CD.Number = Lambda[InWord[]];
IF lev=CMos.pdif THEN {TerminalIO.PutRope["**bus implant is not drawn\n"]};
obj ← CDBusCells.CreateBusCell[
design: design,
sizeOfFirst: [w, l],
lev: lev,
count: count,
offset: [spacing, topInc],
lengIncrement: botInc-topInc
]; -- compare: obj ← Chipmonk.makeBus[l, w, lev, count, spacing, topInc, botInc];
};
repeat => {
rob: CD.Object = InObject[version].obj;
ignoredw: INT = InWord[]; -- ignored
ignoredl: INT = InWord[]; -- ignored
dx: CD.Number = Lambda[InWord[]];
dy: CD.Number = Lambda[InWord[]];
count: NAT ← InWord[];
orient: CD.Orientation ← InOrientation[];
obj ← CDRepetitions.CreateRepetition[design: design, ob: rob, count: count, offset: [dx, dy], orientation: orient];
};
ENDCASE => {
obj ← BadObject[];
TerminalIO.PutRope["** erronous object\n"];
};
}; -- InObject
InList:
PROC[ver:
INTEGER]
RETURNS [list:
CD.InstanceList ←
NIL, length:
INT] = {
instProp: REF ← NIL;
instVal: REF ← NIL;
instCount: INTEGER;
inst: CD.Instance;
ob: CD.Object;
location: CD.Position;
orientation: CD.Orientation;
IF debugging OR debug THEN TerminalIO.PutRope["start list\n"];
instCount ← InWord[];
FOR iNum:
INTEGER
IN [0..instCount)
DO
location.x ← Lambda[InWord[]];
location.y ← Lambda[InWord[]];
orientation ← InOrientation[];
[ob, instProp, instVal] ← InObject[ver];
IF ob=
NIL
THEN {
ob ← BadObject[];
TerminalIO.PutRope["nil object\n"]
};
inst ← CDInstances.NewInst[ob: ob];
inst.trans ← CDOps.FitObjectI[ob, location, orientation];
list ← CONS[inst, list];
IF instProp#
NIL
THEN
CDProperties.PutInstanceProp[onto: inst, prop: instProp, val: instVal];
IF ver > 3
THEN
BEGIN
propCount: INTEGER = InWord[];
FOR propNum:
INTEGER
IN [0..propCount)
DO
InProp[inst];
ENDLOOP;
END;
ENDLOOP;
IF debugging OR debug THEN TerminalIO.PutRope["end list\n"];
RETURN[list, instCount];
};
oldSigName: ATOM = Atom.MakeAtom["SIGNAL NAME"];
InProp:
PROC [inst:
CD.Instance] = {
kind: INTEGER ← InWord[];
name: REF ← NIL;
value: REF;
SELECT kind
FROM
1 => {
IF inst=
NIL
OR inst.ob=
NIL
OR
ISTYPE[inst.ob.specific,
CD.RectSpecific]
THEN
name ← $SignalName
ELSE name ← $InstanceName;
value ← InString[];
};
2 => {
name ← InAtom[];
value ← InAtom[];
IF name=oldSigName THEN name ← $SignalName;
};
ENDCASE => {
name ← NIL;
TerminalIO.PutRope["** unknown property kind\n"];
};
IF name#
NIL
AND inst#
NIL
AND inst.ob#
NIL THEN
CDProperties.PutProp[onto: inst, prop: name, val: value]
};
InAtom:
PROC []
RETURNS[a:
ATOM] = {
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.PutRope["** atom table code wrong\n"];
}
ELSE {
TerminalIO.PutRope["** atom code wrong\n"];
a ← NIL
}
};
InString:
PROC []
RETURNS[s: Rope.
ROPE] = {
j, len: CARDINAL;
flg: BOOLEAN;
j ← LOOPHOLE[InWord[]];
len ← Basics.BITSHIFT[j, -8];
IF len = 0 THEN BEGIN s ← ""; RETURN; END;
flg ← TRUE;
FOR i:
CARDINAL
IN [0..len)
DO
IF flg
THEN
s ← Rope.Cat[s, Rope.FromChar[LOOPHOLE[Basics.BITAND[j, 377B], CHAR]]]
ELSE {
j ← LOOPHOLE[InWord[]];
s ← Rope.Cat[s, Rope.FromChar[LOOPHOLE[Basics.BITSHIFT[j, -8], CHAR]]];
};
flg ← NOT flg;
ENDLOOP;
};
FileOpened:
PROC [name: Rope.
ROPE]
RETURNS [fileWasOpened:
BOOLEAN] = {
IF Rope.IsEmpty[name] THEN name ← TerminalIO.RequestRope["Input file > "];
fileName ← CDIO.MakeName[name, "chip"];
chipfile ← FS.StreamOpen[fileName !
FS.Error =>
IF error.group#bug
THEN {
TerminalIO.PutRopes[fileName, " not opened: ", error.explanation];
TerminalIO.PutRope["\n"];
GOTO FileName
}];
TerminalIO.PutRopes["File being read is ", fileName, "\n"];
fileWasOpened ← TRUE;
EXITS
FileName => {fileWasOpened ← FALSE};
};
signal: SIGNAL = CODE;
ReadChip:
PROC = {
ENABLE {
FileFormat => {
TerminalIO.PutRope["\n**File-Format error [proceed does not clobber other designs]\n"];
SIGNAL signal;
GOTO IOError;
};
IO.EndOfStream => {
TerminalIO.PutRope["\n**end of stream error [proceed does not clobber other designs]\n"];
SIGNAL signal;
GOTO IOError;
};
IO.Error => {
TerminalIO.PutRope["\n**io error[proceed does not clobber other designs]\n"];
--if you are debugging here: inspect "ec"
SIGNAL signal;
GOTO IOError;
};
};
i, j, k, ver, cCnt, depht: INTEGER;
leng: INT;
ss: Rope.ROPE;
cob: CD.Object;
cellSpecific: CD.CellSpecific;
errs ← 0;
i ← InWord[];
IF i # LOOPHOLE[codeWordForDataFile, INTEGER] AND NOT TerminalIO.Confirm["doesn't look like a .chip file -- should program continue?"] THEN RETURN;
ver ← InWord[];
cCnt ← InWord[];
IF cCnt > maxCellNum THEN CDSequencer.Quit["Too many different kinds of cells in design...aborting read\n"];
IF ver < 3 THEN CDSequencer.Quit[" Version number too low...aborting read\n"];
IF ver>8 THEN CDSequencer.Quit[" new chipmonk version unknown to chipndale...aborting read\n"];
FOR j
IN [0..cCnt]
DO
cellNameA[j] ← CDCells.CreateEmptyCell[];
ENDLOOP;
TerminalIO.PutRope["Starting cell directory\n"];
FOR k
IN [1..cCnt]
DO
name: Rope.ROPE ← NIL;
j ← InWord[];
cob ← cellNameA[j];
ss ← InString[];
--cob.size.x--[] ← Lambda[InWord[]];
--cob.size.y--[] ← Lambda[InWord[]];
[] ← InWord[]; -- this is some count in chipmonk ??
cellSpecific ← NARROW[cob.specific, CD.CellSpecific];
[cellSpecific.contents, leng] ← InList[ver];
IF NOT Rope.IsEmpty[ss] THEN name ← ss
ELSE name ← NewCellName[k];
[] ← CDDirectory.Include[design: design, object: cob, name: name, fiddle: TRUE];
IF CDCells.IsEmpty[cob]
THEN {
TerminalIO.PutRopes["** empty cell ", CD.Describe[cob, NIL, design], "\n"];
cellSpecific.contents ← LIST[CDInstances.NewInst[BadObject[]]];
};
[] ← CDCells.ResizeCell[NIL, cob];
CDCells.SetSimplificationTreshhold[cob];
ENDLOOP;
TerminalIO.PutRope["finished cell directory\n"];
depht ← IF ver<7 THEN 0 ELSE InWord[];
IF depht>0
THEN {
TerminalIO.PutRope["***design was pushed in; not read in correctly\n"];
RETURN;
};
IF ver>=7
THEN {
fileChangeCode: INTEGER = InWord[];
};
design.actual.first.specific.contents ← InList[ver].list;
design.name ← fileName;
TerminalIO.PutRope["Finished reading chip\n"];
IF errs>0
THEN {
TerminalIO.PutF1["%g unknown objects\n", IO.int[errs]];
errs ← 0;
};
IO.Close[chipfile];
EXITS IOError => {TerminalIO.PutRope[" proceed; discard this design\n"];};
}; -- ReadChip
CommandReadChip:
ENTRY Commander.CommandProc = {
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[];
CDOps.DeselectAll[design: design, setSelection: TRUE];
TransformSelected[design, rotate180X];
CDOps.DeselectAll[design];
[] ← CDViewer.CreateViewer[design];
};
EXITS
UserAbrt => {TerminalIO.PutRope["read aborted\n"]};
};
TestRead:
ENTRY Commander.CommandProc = {
ENABLE {
IO.EndOfStream => GOTO IOEnd;
UNWIND => NULL;
};
w: CARDINAL;
IF FileOpened[
NIL]
THEN {
TerminalIO.PutRope["--startfile--\n"];
DO
w ← LOOPHOLE[InWord[]];
TerminalIO.PutF1["%7b\n", IO.card[w]];
ENDLOOP;
};
EXITS IOEnd => {TerminalIO.PutRope["--endfile--\n"]};
};
CDCommandOps.RegisterWithMenu[$IOMenu, "chipmonk-output", "converts to old Chipmonk format", $ChipmonkOutput];
Commander.Register["///Commands/CDTestRead", TestRead, "ChipNDale test feature: Reads file and display it on Terminal"];
Commander.Register["///Commands/CDReadCMCMos", CommandReadChip, "Converts old cmos Chipmonk file to ChipNDale CMosA"];
END.