-- definitions module for silicon (pretty picture) program
-- last modified by McCreight, December 21, 1983  10:00 AM
--  to incorporate multiple implant levels
-- modified by Petit, September 18, 1981  2:40 PM

DIRECTORY
  SegmentDefs,
  multiGraphicsDefs,
  StreamDefs;

ppdefs: DEFINITIONS IMPORTS SegmentDefs, multiGraphicsDefs, StreamDefs =
  BEGIN OPEN multiGraphicsDefs, StreamDefs;

  compileChecks: BOOLEAN = TRUE;

  INT: TYPE = LONG INTEGER;
  NAT: TYPE = INTEGER[0..LAST[INTEGER]];

  -- Note: The Chipmonk design coordinate system has x increasing to the right
  -- and y increasing downward.  [x: 0, y: 0] is the center of the design
  -- space.

  locNum: TYPE = INTEGER;
  Lambda, lambda: locNum = 2; -- 2 locNums per lambda
  Point: TYPE = RECORD [x, y: locNum];
  Rect: TYPE = RECORD [x1, y1, x2, y2: locNum];
  univ: Rect = [x1: -LAST[locNum], y1: -LAST[locNum],
    x2: LAST[locNum], y2: LAST[locNum]];
  universe: Rect -- ← univ -- ;
  orientation: TYPE = [0..7] ← 0; -- multiple of 45 degrees clockwise
  reflection: TYPE = [0..1] ← 0; -- 1 means mirror in x (x ← -x)
  orientationIndex: TYPE = [0..15] ← 0; -- = 2*orientation+reflection
  -- An orientationIndex idx is composed of two parts:
  --    a clockwise rotation of (idx/2)*45 degrees,
  --    followed by a reflection in x if (idx MOD 2)#0.
  -- Odd multiples of 45 degrees are not yet supported.

  Level: TYPE = MACHINE DEPENDENT{
    cut(0), dif(1), pol(2), met(3), imp(4), ovg(5), bur(6),
    snerd(7), cut2(8), pdif(9), pwelCont(10), met2(11), pwel(12),
    nwel(13), nwelCont(14), NOcOL(15),
    l16, l17, l18, l19, l20, l21, l22, l23, l24, l25, l26, l27, l28, l29, l30, l31,
    l32, l33, l34, l35, l36, l37, l38, l39, l40, l41, l42, l43, l44, l45, l46, l47,
    l48, l49, l50, l51, l52, l53, l54, l55, l56, l57, l58, l59, l60, l61, l62, l63};
  level: TYPE = Level[cut..NOcOL];
  unspecified: level = NOcOL;

  ppUncZone: UNCOUNTED ZONE;  -- zone where object's, list's, prop's,
    -- cList's, and rectList's live


--  I t e m   L i s t

  masterList: listPtr; -- design now being displayed
  listPtr: TYPE = LONG POINTER TO list ← NIL;
  list: TYPE = RECORD [
    nxt: listPtr,
    lx, ly: locNum,
    super: listPtr,
    ob: obPtr,
    selected, deleted, cfok, bfok: BOOLEAN ← FALSE,
    mark: [0..1] ← 0,
    idx, ridx: orientationIndex,  -- ridx is BITXOR[idx,1], i.e. reflected
    props: propPtr
    ];


--  I t e m   P r o p e r t y

  propPtr: TYPE = LONG POINTER TO prop ← NIL;
  prop: TYPE = RECORD [next: propPtr, attribute, value: Atom];

    putProp: PROC [lp: listPtr, attribute, value: Atom,
      allowDuplAttr: BOOLEAN ← FALSE];
    AppendProps: PROC [to: LONG STRING, from: propPtr, startPos: CARDINAL ← 0];

  Atom: TYPE = LONG POINTER TO READONLY StringBody ← NIL;

    MakeAtom: PROC [s: LONG STRING] RETURNS[Atom];
    AtomToString: PROC [a: Atom] RETURNS [LONG STRING] = INLINE
      {RETURN[LOOPHOLE[a]]};
    RestartAtoms: PROC;
    atomTableSize: INTEGER = 256;
    atomTable: ARRAY [1..atomTableSize] OF Atom;  -- for short I/O

--  O b j e c t

  obPtr: TYPE = LONG POINTER TO object ← NIL;
  cellPtr: TYPE = LONG POINTER TO cell object ← NIL;
  object: TYPE = RECORD [
    p: POINTER TO Procs,
    size: ARRAY [0..2] OF locNum, -- x IN [0..size[0](=size[2])), y IN [0..size[1])
    refCnt: CARDINAL,
    cache: CacheHandle,
    props: propPtr,
    auxPnt: auxPtr,
    l: level,
    surround:[0..31] ← 0,
    returnable, marked: BOOLEAN,
    varpart: SELECT otyp: typeOfObject FROM
      rect => NULL,
      wire => [super: LONG POINTER TO wire object ← NIL],
      xstr => [
        super: LONG POINTER TO xstr object ← NIL,
        width, length: locNum,
        wExt, lExt: locNum[0..63],
        impl: DepletionStrength,
        pullup, angle: BOOLEAN ← FALSE],
      cell => [
        cnt: CARDINAL,
        ptr: listPtr,
        super: cellPtr ← NIL],
      cont => [
        super: LONG POINTER TO cont object ← NIL,
        typ: contType,
        magicN,m2Ext,c2Ext: locNum[0..15] ← 0,
        lExt,wExt: locNum[0..255]←4],
      bus => [
        wspace, firstLength, topIncr, lenIncr, offsetFirst, wwidth: locNum ← 0,
        wCnt, tWhich,bWhich: INTEGER ← 0],
      text => [s: STRING],
      cnText => [
        s: STRING,
        np: cListPtr ← NIL,
        op: cellPtr ← NIL],
      ENDCASE];

  DepletionStrength: TYPE = [0..3] ← 0;
    enhancement: DepletionStrength = FIRST[DepletionStrength];
    zeroThresh: DepletionStrength = enhancement+1;
    weakDepletion: DepletionStrength = zeroThresh+1;
    strongDepletion: DepletionStrength = LAST[DepletionStrength];

  DepletionStrengthName: PROC [imp: DepletionStrength] RETURNS [STRING];

  Procs: TYPE = RECORD [ -- generic procedures for an object
    drawme: ARRAY orientationIndex OF drProc,
    setParm: parmProc,
    inBox: ibProc,
    inMe: inMeProc,
    release: relProc,
    anotherme: anoProc];

  drProc: TYPE = PROC [
    ob: obPtr, x, y: locNum, pr: POINTER TO drRecord];
  ibProc: TYPE = PROC [lp: listPtr, x1, y1, x2, y2: locNum]
    RETURNS [BOOLEAN];
  inMeProc: TYPE = PROC [
    ob: obPtr, x, y: locNum, o: orientationIndex]
    RETURNS [BOOLEAN];
  relProc: TYPE = PROC [ob: obPtr];
  anoProc: TYPE = PROC [ob: obPtr]
    RETURNS [obPtr];
  parmProc: TYPE = PROC [
    lp: listPtr, pt: parmType, dx, dy: locNum, cent: BOOLEAN]
    RETURNS [BOOLEAN];

  auxPtr: TYPE = LONG POINTER TO aux ← NIL;
  aux: TYPE; -- can be implemented by any application program

  CacheHandle: TYPE = LONG POINTER TO Cache ← NIL;
  Cache: TYPE;  -- of drawn bitmaps


--  N a m e d   C e l l s

  cellList: cListPtr; -- all the named cells
  cListPtr: TYPE = LONG POINTER TO cList ← NIL;
  cList: TYPE = RECORD [nxt: cListPtr, ob: obPtr, name: STRING];


--  P u s h e d  C e l l s

  cellStack: cellSEPtr; -- we are pushed down into this stack of cells
  cellSEPtr: TYPE = LONG POINTER TO cellSE ← NIL;
  cellSE: TYPE = RECORD [
    nxt: cellSEPtr,
    lp, instance, unDel: listPtr,
    dest: cellPtr,
    origSize: Point, -- of dest
    origBB: Rect, -- of instance
    changes: BOOLEAN,
    udg, udi: CARDINAL];

  UsuallyFalse: TYPE = BOOLEAN ← FALSE;
  wireOK: ARRAY level OF UsuallyFalse =
    [dif: TRUE, pdif: TRUE, pwelCont: TRUE, nwelCont: TRUE, -- s/d diffusions
    pol: TRUE, met: TRUE, met2: TRUE];


  Mode: TYPE = {wire, xstr, cell, null};

  -- MAGIC CONSTANTS:

  maxInfluence: locNum = 4*Lambda;
    -- max extension of influence (or well) beyond bounding box:
  wellSurround: locNum = 3*Lambda;
  butconSY: locNum = 6*Lambda;
  butconSX: locNum = 4*Lambda;
  butconGreenOff: locNum = Lambda;
  butconRedOff: locNum = (3*Lambda)/2;

  cWidth: locNum = 2*Lambda;
  cLength: locNum = 2*Lambda;
  wXExtension: locNum = 2*Lambda;
  lXExtension: locNum = 2*Lambda;

  cut2min: locNum = 3*Lambda;
  mmContExt: locNum = 2*Lambda;-- extension of met2 beyond cut2
  --m2DifContExt: locNum = (3*Lambda)/2;- extension of met2 beyond edge of dif in a
	--	met2-met-dif contact = (cut2min + 2*mmContExt - butconSX)/2
  welconSurround: locNum = 3*Lambda;-- min well surround around a well-contact

  -- switch controlling format of color screen:
  csHor: BOOLEAN = TRUE;
  -- TRUE for long direction horizontal, FALSE for vertical;
  colWidth: INTEGER = IF csHor THEN 640 ELSE 480;
  colHeight: INTEGER = IF csHor THEN 480 ELSE 640;
  bwBottom: INTEGER = 580;
  bwMsgTop: INTEGER = bwBottom;
  bwMsgBottom: INTEGER = 640;
  bwFeedTop:INTEGER=bwMsgBottom;

  --********** command interpreter stuff:

QuitSig: SIGNAL;
RestSig: SIGNAL;

keCheckProc:TYPE = PROC [k:keyEvent] RETURNS[return,execute:BOOLEAN];
	-- return true if command interpreter should return
	-- execute true if command interpreter should execute the keyEvent

CmdTwerp:PROC [keCheckProc] RETURNS[keyEvent];
CmdTwerpMess:PROC [os1,os2,os3:STRING,check:keCheckProc]
	RETURNS[keyEvent];


  -- kbd stuff:

  keyEvent: TYPE = RECORD [
    k: [0..77B], ctl: [0..31], mx: [0..2000], my: [0..1000]];
  nilKeyEvent: keyEvent = [k: 77B, ctl: 0, mx: 0, my: 0];

-- mx and my are the screen coordinates of the cursor when the keystroke
-- happened.  (0,0) is upper left of color screen.  (colWidth,0) is upper
-- left of B&W screen.  (colWidth,bwBottom) is upper left of feedback area.
-- ctl indicates which control keys were down, or which mouse button was
-- pushed.  k is the character key.

  --key encodings (k field of keyEvent):
  --	0-11B: "0" to "9" (add 60B for ascii)
  --	12B-43B: "A" to "Z" (add 67B for ascii upper case)
  --	44B: ";" key
  --	45B: "=" key
  --	46B: "," key
  --	47B: "-" key
  --	50B: "." key
  --	51B: "/" key
  --	52B: "'" key
  --	53B: "[" key
  --	54B: "\" key
  --	55B: "]" key
  --	56B: "DONE" key (blank one below DEL)(UNdo)
  --	57B: "←" key
  --	60B: CR key
  --	61B: LF key
  --	62B: BS key
  --	63B: DEL key
  --	64B: space bar
  --	65B: ESC
  --	66B: blank to right of RET (not used)
  --	67B: swat key (not used)
  --	70B: TAB (not used, - a ctrl key instead)
  --	71B: ???
  --	72B: ???
  --	73B: yellow mouse button up (release)
  --	74B: ???
  --	75B: ???
  --	76B: ???
  --	77B: No key (for use with mouse buttons)

  --ctrl key encodings (ctl field of keyEvent):
  --	1,2: Mouse buttons: 0-none, 1-red, 2-yellow, 3-blue
  --	4: CTRL
  --	10B: TAB
  --	20B: Shift (either)

    mouseRed: CARDINAL = 1;
    mouseYellow: CARDINAL = 2;
    mouseBlue: CARDINAL = 3;
    ctrlKey: CARDINAL = 4;
    tabKey: CARDINAL = 10B;
    shiftKey: CARDINAL = 20B;


  cursorOnBW: BOOLEAN;
  curx, cury: INTEGER;
  gridCol, gridBW: CARDINAL;

  mType: SegmentDefs.MachineType;
  color: TYPE = [0..15];

  -- ********
  bwScale: INTEGER;
  bwxoff, bwyoff: INTEGER;
  cScale: INTEGER;
  cxoff, cyoff: INTEGER;
  bwScaleN: INTEGER;
  bwScaleD: INTEGER;
  cScaleN: INTEGER;
  cScaleD: INTEGER;

  bwClipx1: INTEGER;
  bwClipx2: INTEGER;
  bwClipy1: INTEGER;
  bwClipy2: INTEGER;
  cClipx1: INTEGER;
  cClipx2: INTEGER;
  cClipy1: INTEGER;
  cClipy2: INTEGER;

  fnt: POINTER TO StrikeFont;

  typeOfObject: TYPE = {rect, wire, xstr, cell, cont, bus, text, cnText};
  contType: TYPE = {burr, mDif, difShort, butt, mPol, mm2};
    -- the first three types are also characterized by the layer of their
    -- diffusion: ndif, pdif, nwelCont, pwelCont.
  parmType: TYPE = {width, length, default, wSpace, lSpace, count, bSpace};

  cmdMask: TYPE = [0..7777B];
  -- 1=mark,2=draw,4=sel,10B=none,20B=ctrl,40B=tab,100B=ctrl-tab,
  --  200B=shift,400B=ctrl-shift,1000B=tab-shift,2000B=ctrl-tab-shift.

  cmdProc: TYPE = PROC [k: keyEvent ← nilKeyEvent];
  cmdLent: TYPE = RECORD [mask: cmdMask, proc: cmdProc];
  cmdEnt: TYPE = POINTER TO ARRAY [0..0) OF cmdLent;

  rems: TYPE = RECORD [r: Rect, l: level];
  remPages: CARDINAL = 20000/256;
  remLen: CARDINAL = (remPages*256)/SIZE[rems];

  markPnt, markDPnt, selMarkPnt: Point;

  rectListPtr: TYPE = LONG POINTER TO rectList ← NIL;
  rectList: TYPE = RECORD [
    nxt: rectListPtr, r: Rect, l: level, freebl: BOOLEAN];

  --********** screen update process stuff:

  sCmdType: TYPE = {nop, rect, sel, all};
  sCmd: TYPE = RECORD [
    cmd: sCmdType, ers: BOOLEAN, p: listPtr, r: Rect];

  drawProcer: TYPE = PROC [
    INTEGER, INTEGER, INTEGER, INTEGER, level, POINTER TO Rect];
  drawProcerc: TYPE = PROC [
    INTEGER, INTEGER, INTEGER, INTEGER, color, POINTER TO Rect];
  drawProcers: TYPE = PROC [
    INTEGER, INTEGER, INTEGER, INTEGER, STRING, POINTER TO Rect];
  drRecord: TYPE = RECORD [
    r,bigr: Rect,
    orArea, saveArea: drawProcer,
    outl: drawProcerc,
    dtxt: drawProcers,
    minSize: INTEGER,
    quickDraw: PROC [ob: ppdefs.obPtr, orient: ppdefs.orientationIndex,
      x, y: ppdefs.locNum, pr: POINTER TO ppdefs.drRecord]
      RETURNS [drawn: BOOLEAN] ← NIL];

  Raster: TYPE = LONG POINTER TO RasterDesc ← NIL;
  RasterDesc: TYPE = RECORD [
    nPixels: PixelPoint, -- .x is pixels*bits/pixel, .y is scan lines
    scanLineWords: INTEGER,
    map: LONG POINTER TO ARRAY [0..0) OF WORD
    ];

  PixelRect: TYPE = Rect;
  PixelPoint: TYPE = Point;
  Pixel: TYPE = INTEGER; -- along a vertical or horizontal line


  initRects: PROC;
  CenterAndScale: PROC [center: Point, scale: INTEGER, bw, col: BOOLEAN ← FALSE];
  reDrawRect: PROC [r: Rect, whenErase: CARDINAL, bw, col, all: BOOLEAN];
  drawNewlySel: PROC [p: listPtr];
  getColNewRect: PROC RETURNS [sCmd]; -- waits if none ready
  getBwNewRect: PROC RETURNS [sCmd]; -- waits if none ready

  --********* exports from ppspace.mesa

  swdsAloc: CARDINAL;
  lwdsAloc: LONG INTEGER;
  GetSuperPointer: PROC RETURNS [listPtr];
  GetCellSuper: PROC RETURNS [cellPtr];
  GetSpace: PROC [CARDINAL] RETURNS [LONG POINTER];
  FreeSpace: PROC [p: LONG POINTER];
  InitHeap: PROC [np: CARDINAL];
  EraseHeap: PROC;
  GetString: PROC [nchars: CARDINAL] RETURNS [s: STRING];
  FreeString: PROC [s: STRING];
  newString: PROC [s: STRING] RETURNS [ss: STRING];
  alocRectD: PROC RETURNS [p: LONG POINTER TO rect object];
  alocWireD: PROC RETURNS [p: LONG POINTER TO wire object];
  alocBusD:  PROC RETURNS [p: LONG POINTER TO bus object];
  alocXstrD: PROC RETURNS [p: LONG POINTER TO xstr object];
  alocCellD: PROC RETURNS [p: cellPtr];
  alocContD: PROC RETURNS [p: LONG POINTER TO cont object];
  alocTextD: PROC RETURNS [p: LONG POINTER TO text object];
  alocCnTextD: PROC RETURNS [p: LONG POINTER TO cnText object];
  alocList: PROC RETURNS [p: listPtr];
  alocCList: PROC RETURNS [p: cListPtr];
  freeList: PROC [listPtr];
  freeCell: PROC [p: cellPtr];

  --**** old ppprocdefs stuff:

  unDelGrpMax: CARDINAL = 10;
  unDelItemMax: CARDINAL = 300;
  unDelItemMin: CARDINAL = 30;

  unDelPnt: listPtr;
  unDelGrpCnt, unDelItemCnt: CARDINAL;

  anyChanges, sinceIOchanges: BOOLEAN;

  DiffusionType: TYPE = {n, p};
  diffusionType: DiffusionType;
  DiffusionPurpose: TYPE = {wiring, wellCont};
  diffusionPurpose: DiffusionPurpose;
  diffusionLevel: ARRAY DiffusionType OF ARRAY DiffusionPurpose OF level =
    [n: [wiring: dif, wellCont: nwelCont], p: [wiring: pdif, wellCont: pwelCont]];

  xRatiow: INTEGER; -- for transistors
  xRatiol: INTEGER;
  implant: DepletionStrength;
  pRatiow: INTEGER; -- for depletion pullup structures
  pRatiol: INTEGER;
  pushLevel: INTEGER;

  --**** from ppprocs?:

  minWidthAr: ARRAY level OF INTEGER;

  bwGrain: INTEGER;
  colGrain: INTEGER;
  abortColor, abortBW: BOOLEAN;

  redoCBBox: PROC;

  wireList: ARRAY level OF LONG POINTER TO wire object;
  tranList: LONG POINTER TO xstr object;
  puList: LONG POINTER TO xstr object;
  contList: LONG POINTER TO cont object;
  --doColRemember:PROC ;
  --doBwRemember: PROC ;

  inrect: PROC [x, y: INTEGER, lp: listPtr] RETURNS [BOOLEAN];
  whatLevels: PROC [lp: listPtr, x, y: locNum]
    RETURNS [levs: CARDINAL];
  flushDel: PROC [lp: listPtr];

  copyObject: PROC [lp, mp: listPtr, xoff, yoff: INTEGER]
    RETURNS [np: listPtr];
  minmax: PROC [lp: listPtr]
    RETURNS [mix, miy, max, may: INTEGER];
  typeInNum: PROC [os1, os2, os3: STRING]
    RETURNS [bb: BOOLEAN, ii: INTEGER, ke: keyEvent];
  typeIn: PROC [os1, os2, os3: STRING]
    RETURNS [bb: BOOLEAN, is: STRING, ke: keyEvent];
  typeInC: PROC [os1, os2, os3: STRING] RETURNS [kk: keyEvent];
  typeOut: PROC [os1, os2, os3: STRING];
  refreshTypeInScreen: PROC ;

  initColors: PROC;
  setColors: PROC;

  getchr: PROC RETURNS [ke: keyEvent];
  getNumber: PROC RETURNS [INTEGER];
  getstr: PROC [x, y: CARDINAL] RETURNS [BOOLEAN, STRING, keyEvent];


  -- ************

  xx, yy: INTEGER;
  bb: BOOLEAN;

  moveOb: PROC [p: listPtr, x, y: INTEGER];

  mergeRects: PROC [a, b: Rect] RETURNS [Rect];
  ClipRect: PROC [a, b: Rect] RETURNS [Rect] = INLINE -- intersection
    {RETURN[[x1: MAX[a.x1, b.x1], y1: MAX[a.y1, b.y1],
      x2: MIN[a.x2, b.x2], y2: MIN[a. y2, b.y2]]]};
  Empty: PROC [r: Rect] RETURNS[BOOLEAN] = INLINE
    {RETURN[r.x2<r.x1 OR r.y2<r.y1]}; -- for directed Rects
  cannonRect: PROC [r: Rect] RETURNS [Rect];
    -- produces a non-empty Rect

  getRect: PROC [l: listPtr] RETURNS [r: Rect];

  Mod: PROC [x: INTEGER, y: NAT] RETURNS [NAT] = INLINE
    {z: INTEGER = x MOD y; RETURN[IF z>=0 THEN z ELSE y+z]};

  END.