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, 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
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 cellSpecific.name ← ss
ELSE cellSpecific.name ← NewCellName[k];
[] ← CDDirectory.Include[design: design, object: cob, fiddle: TRUE];
IF CDCells.IsEmpty[cob]
THEN {
TerminalIO.PutRopes["** empty cell ", cellSpecific.name, "\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.