-- ChipNetDefs.mesa

-- last modified by E. McCreight, September 12, 1983  11:14 AM
-- written by E. McCreight, November 3, 1981  12:14 PM

DIRECTORY
  InlineDefs,
  MiscDefs,
  ppdefs,
  StreamDefs,
  ZoneAllocDefs;

ChipNetDefs: DEFINITIONS IMPORTS InlineDefs =
  BEGIN

  --  T y p e s

  NanoMeters: TYPE = LONG INTEGER; -- on the silicon

  Coord: TYPE = NanoMeters;
  LocNumScale: TYPE = {lambdaRelative, absolute};
  CoordPoint: TYPE = RECORD[x, y: Coord];
  CoordRect: TYPE = RECORD[x1, y1, x2, y2: Coord];
    -- [x1..x2), [y1..y2)
  Interval: TYPE = RECORD[min,max: Coord];
    -- [min..max)

  ExtractLevel: TYPE = ppdefs.Level[cut..l39] ← unknown;

  unknown: ExtractLevel = NOcOL;
  nWell: ExtractLevel = nwel;
  nWellRequired: ExtractLevel = l16;
  nWellForbidden: ExtractLevel = l17;
  pWell: ExtractLevel = pwel;
  pWellRequired: ExtractLevel = l18;
  pWellForbidden: ExtractLevel = l19;
  nDepletion: ExtractLevel = imp;
  nDepletionRequired: ExtractLevel = l20;
  nDepletionForbidden: ExtractLevel = l21;
  nBuriedContact: ExtractLevel = bur;
  nBuriedContactRequired: ExtractLevel = l22;
  nBuriedContactForbidden: ExtractLevel = l23;
  thinOx: ExtractLevel = l24;
  nPlus: ExtractLevel = dif;
  nPlusRequired: ExtractLevel = l25;
  nPlusForbidden: ExtractLevel = l26;
  pPlus: ExtractLevel = pdif;
  pPlusRequired: ExtractLevel = l27;
  pPlusForbidden: ExtractLevel = l28;
  nImplant: ExtractLevel = l29;
  pImplant: ExtractLevel = l30;
  nGate: ExtractLevel = l31;
  nGateRequired: ExtractLevel = l32;
  nGateForbidden: ExtractLevel = l33;
  pGate: ExtractLevel = l34;
  pGateRequired: ExtractLevel = l35;
  pGateForbidden: ExtractLevel = l36;
  poly: ExtractLevel = pol;
  polyRequired: ExtractLevel = l37;
  polyForbidden: ExtractLevel = l38;
  cutForbidden: ExtractLevel = l39;
  metal: ExtractLevel = met;
  via: ExtractLevel = cut2;
  metal2: ExtractLevel = met2;
  pad: ExtractLevel = ovg;

  LevCoordRect: TYPE = RECORD[lev: ExtractLevel,
    r: CoordRect];

  PropPtr: TYPE = LONG POINTER TO ppdefs.prop ← NIL;

  Conductors: TYPE = {ndif, pdif, poly, metal, metal2};

  NetPtr, netPtr, netIntPtr: TYPE = LONG POINTER TO Net ← NIL;
  CanonNetPtr: TYPE = LONG POINTER TO canon Net ← NIL;
  LinkNetPtr: TYPE = LONG POINTER TO link Net ← NIL;
  Net, net: TYPE = RECORD[
    refs: CARDINAL ← 1, -- number of references passing through
    rest: SELECT type: * FROM
      link => [nxt: netIntPtr],
      canon => [id: NetIdPtr],
      ENDCASE
    ];

  NetIdPtr: TYPE = LONG POINTER TO NetId ← NIL;
  FreeNetIdPtr: TYPE = LONG POINTER TO free NetId ←
    NIL;
  NormalNetIdPtr: TYPE = LONG POINTER TO normal NetId ← NIL;

  NetId: TYPE = RECORD
    [next: NetIdPtr, -- in allNets chain
    final: LevCoordRect ← [r: [x1: FIRST[Coord], x2: FIRST[Coord],
      y1: FIRST[Coord], y2: FIRST[Coord]]],
      -- final.x2 is the greatest x value at which
      -- any piece of geometry
      -- known to belong to this net exists.
    violations: ViolationListPtr, -- potential violations involving this net
    details: SELECT type: * FROM
      free => [nextFree: FreeNetIdPtr],
      well => [attachedTo: NetPtr],
      normal =>
        [
        lastX: Coord ← LAST[Coord],
          -- last value of x where caps were changed
        caps: ARRAY Conductors OF LayerCap,
        source: CellCallPtr, -- highest named source for
          -- this net, or if none are named, highest unnamed source
        hasPathToGnd, hasPathToVdd, hasDepletionPullup:
          BOOLEAN ← FALSE,
        couldBeLogo: BOOLEAN ← TRUE, -- if all metal
        name: SELECT nameClass: * FROM
          anonymous => [],
          numeric => [n: CARDINAL],
          qualified => [see: CellIndex -- (in .source) -- ],
          named => [name: ppdefs.Atom],
          ENDCASE
          ],
        ENDCASE
    ] ← [details: normal[lastX: 0, name: anonymous[]]];


  ViolationListPtr: TYPE = LONG POINTER TO ViolationList ← NIL;
  ViolationList: TYPE = RECORD [
    next: ViolationListPtr,
    v: Violation
    ];

  Violation: TYPE = RECORD [
    place: ppdefs.Point ← [0,0],
    info: SELECT type: * FROM
      unknown, cantCheck => NULL,
      tooNarrow, noNetToWell, bogusTransistor,
        coverageNeeded, coverageForbidden =>
          [lev: ExtractLevel],
      tooClose => [lev1, lev2: ExtractLevel, n1, n2: netPtr],
      coverageForbiddenIfNetsDiffer =>
        [lev: ExtractLevel, n1, n2: netPtr],
      differentNetsToWell =>
        [lev: ExtractLevel, wellNode, n: netPtr],
      terminalsUnconnected => [item: ItemRef],
      terminalsShorted => [item1, item2: ItemRef],
      ENDCASE
    ];

  LayerCapPtr: TYPE = LONG POINTER TO LayerCap ← NIL;
  LayerCap: TYPE = RECORD [
    cutSides: CARDINAL ← 0,
    cutWidth: ppdefs.locNum ← 0,
    perimeter: LONG CARDINAL ← 0, -- locNum's
    area: LONG CARDINAL ← 0 -- locNum↑2
    ];

  SortClass: TYPE = {minX, maxX, minY, maxY};
  orientToSortClass: ARRAY ppdefs.orientationIndex OF SortClass;

  FeaturePtr: TYPE = LONG POINTER TO Feature ← NIL;
  Feature: TYPE = RECORD[ -- cut by scan line
    cover: CoordRect,
    lev: ExtractLevel,
    caller: ItemRef,
    net: netIntPtr
    ];


  CellInstPt: TYPE = RECORD [ -- priority queue item
    x: Coord,
    call: ItemRef
    ];


  ItemRef: TYPE = RECORD[
    head: InstancePtr,
    idx: CellIndex ← 0 -- in head.seq[?] according
      -- to head.orient
    ];

  CellCallPtr: TYPE = LONG POINTER TO cell Instance ← NIL;
  XstrCallPtr: TYPE = LONG POINTER TO xstr Instance ← NIL;
  InstancePtr: TYPE = LONG POINTER TO Instance ← NIL;
  Instance: TYPE = RECORD[
    min: CoordPoint, -- as placed
    orient: ppdefs.orientationIndex ← 0, -- as placed
    proto: ProtoPtr,
    caller: ItemRef,
    sibling: InstancePtr,
    nets: SELECT type: * FROM -- depending on .proto.ob.otyp
      cell =>
        [
        offspring: InstancePtr,
        clusters: ClusterPtr,
        nets: NormalNetIdPtr
        ],
      xstr =>
        [
        map: ARRAY XstrTerminals OF netPtr,
        sameHash: XstrCallPtr,
        inSimFile: BOOLEAN ← FALSE
        ],
      cont => [net: netPtr],
      ENDCASE
    ];

  XstrTerminals: TYPE = {gate, source, drain};

  ClusterPtr: TYPE = LONG POINTER TO Cluster ← NIL;
  Cluster: TYPE = RECORD[
    next: ClusterPtr,
    netName: ppdefs.Atom,
    first: MustConnect
    ];

  MustConnectPtr: TYPE = LONG POINTER TO MustConnect ← NIL;
  MustConnect: TYPE = RECORD[
    next: MustConnectPtr,
    net: netPtr,
    source: ItemRef -- not counted in netMap, but
      -- counted in unsatisfied
    ];


  ProtoPtr: TYPE = LONG POINTER TO CellProto ← NIL;
  CellProto: TYPE = RECORD[
    ob: LONG POINTER TO ppdefs.object, -- cell, repeat
    name: STRING ← NIL, -- from cList
    size: CoordPoint,
    itemCount: CellIndex ← 0,
    stretchMasks: BOOLEAN ← TRUE,
    locNumScale: LocNumScale ← lambdaRelative,
    lp: ppdefs.listPtr ← NIL, -- of itemCount elements
    seq: ARRAY SortClass OF ListPtrSeqPtr,
    connections: ARRAY SortClass OF ConnectorPtr
    ];

  CellIndex: TYPE = CARDINAL;

  ListPtrSeqPtr: TYPE = LONG POINTER TO ListPtrSeq ← NIL;
  ListPtrSeq: TYPE = RECORD[
    lp: SEQUENCE count: CellIndex OF ppdefs.listPtr
    ];


  ConnectorPtr: TYPE = LONG POINTER TO Connector ← NIL;
  Connector: TYPE = RECORD [
    next: ConnectorPtr,
    lev: ExtractLevel,
    range: Interval, -- the range of distances down
      -- the left edge of the bounding box, or to the right
      -- along the top edge of the bounding box.
    depth: Coord,
      -- inward from the edge of the bounding box
    net: netIntPtr
    ];

  --  C o n s t a n t s

  checkAll: BOOLEAN = FALSE; -- turns on all structure-
    -- checking routines.

  featureDelay: ppdefs.locNum = 8*ppdefs.Lambda;

  levelMap: ARRAY ppdefs.level OF ExtractLevel;
  levelNames: ARRAY ExtractLevel OF STRING;
  isConductor: ARRAY ExtractLevel OF BOOLEAN;

  --  V a r i a b l e s

  featureZ, netZ, netIdZ, instanceZ, clusterZ, transZ, uz:
    UNCOUNTED ZONE;

  origCifScale: INTEGER; -- centiMicrometers per lambda
  lambdaRelativeCoordScale: Coord; -- Coords per ppdefs.locNum
  coordScale: ARRAY LocNumScale OF Coord;

  deltaOrigin: CoordPoint; -- actual - ideal

  currentX: Coord; -- scan increases in x

  notingMark: BOOLEAN; -- for debugging
  extractCaps: BOOLEAN;
  allNets: NetIdPtr;

  signalName, instanceName: READONLY ppdefs.Atom;

  externalWiringFinished: BOOLEAN; -- for "magical" wiring, to be added later

  --  P r o c e d u r e s

  ASSERT: PROC [condition: BOOLEAN] = INLINE {IF NOT condition THEN ERROR};

  WriteSimFile: PROC [c: CellCallPtr];
   -- explores the call tree rooted at c

  AddExternalWiring: PROC [fileName: STRING, root: CellCallPtr];
    -- Reads external wiring spec from file, compares with terminals in
    -- call tree rooted at root.

  AppendLongString: PROC [to, from: LONG STRING];

  FindPropValue: PROC [lp: ppdefs.listPtr, attribute: ppdefs.Atom]
    RETURNS [value: ppdefs.Atom];

  FindInheritedPropValue: PROC [item: ItemRef, attribute: ppdefs.Atom]
    RETURNS [value: ppdefs.Atom];

  AppendAtom: PROC [s: LONG STRING, atom: ppdefs.Atom];

  AppendNet: PROC [s: STRING, net: netPtr]
    RETURNS [CanonNetPtr];

  AppendNetId: PROC [s: STRING, netId: NormalNetIdPtr];

  AppendTerminalName:
    PROC [s: STRING, c: ItemRef];

  AppendCallerChain, AppendCallerLink:
    PROC [s: STRING, c: InstancePtr];

  AppendLocNum: PROC [s: STRING, n: ppdefs.locNum];

  AppendCoord: PROC [s: STRING, n: Coord];

  AppendCard: PROC [s: STRING,
    n: LONG CARDINAL];


  HeSetsParamsAndSaysYes: PROC [s1, s2: STRING ← NIL]
    RETURNS [bit: BOOLEAN];

  ItemInWorld: PROC [c: ItemRef] RETURNS [CoordRect];

  SortOrder: ARRAY SortClass OF
    PROC [lp1, lp2: ppdefs.listPtr] RETURNS [BOOLEAN];

  SortListPtrSeq: PROC [lps: ListPtrSeqPtr,
    less: PROC [lp1, lp2: ppdefs.listPtr] RETURNS [BOOLEAN]
    ];


  NewNet: PROC [initRefs: CARDINAL ← 1]
    RETURNS [CanonNetPtr];

  MergeNets: PROC [n1, n2: netPtr]
    RETURNS [CanonNetPtr];
    -- n1, n2 # NIL

  RefCanonNet: PROC [n: netPtr, newRefs: INTEGER ← 1]
    RETURNS [CanonNetPtr];

  UpdateAreas: PROC [n: NormalNetIdPtr];

  GetNormalNetId: PROC [n: LONG POINTER TO netPtr]
    RETURNS [NormalNetIdPtr];

  CanonNet: PROC [n: netPtr]
    RETURNS [CanonNetPtr] = INLINE
    {RETURN[RefCanonNet[n: n, newRefs: 0]]};

  DeRefNet: PROC [n: netPtr, removedRefs: INTEGER ← 1]
    RETURNS [CanonNetPtr] = INLINE
    BEGIN
    [] ← RefCanonNet[n: n, newRefs: -removedRefs];
    RETURN[NIL];
    END;

  FeatureNet: PROC [f: FeaturePtr] RETURNS [CanonNetPtr];
    -- doesn't increase ref count, forces f.net to be non-nil

  MergeFeatureNets: PROC [f1, f2: FeaturePtr];


  ItemRefToLp: PROC [c: ItemRef]
    RETURNS [ppdefs.listPtr] = INLINE
    {RETURN[c.head.proto.seq[orientToSortClass[c.head.orient]]
      [c.idx]]};

  CoordSize: PROC [size: CoordPoint,
    orient: ppdefs.orientationIndex] RETURNS [CoordPoint] =
    INLINE
    {RETURN[IF InlineDefs.BITAND[orient, 4]=0 THEN size
      ELSE [x: size.y, y: size.x]]};

  ScaleToChipmonk: PROC [x: Coord]
    RETURNS [ppdefs.locNum] = INLINE
    {RETURN[InlineDefs.LowHalf[x/lambdaRelativeCoordScale]]};

  ScalePointToChipmonk: PROC [p: CoordPoint]
    RETURNS [ppdefs.Point] = INLINE
    {RETURN[[x: ScaleToChipmonk[p.x+deltaOrigin.x],
      y: ScaleToChipmonk[p.y+deltaOrigin.y]]]};

  ScaleFromChipmonk: PROC [x: ppdefs.locNum]
    RETURNS [Coord] = INLINE
    {RETURN[x*lambdaRelativeCoordScale]};

  ScalePointFromChipmonk: PROC [p: ppdefs.Point]
    RETURNS [CoordPoint] = INLINE
    {RETURN[[x: ScaleFromChipmonk[p.x]-deltaOrigin.x,
      y: ScaleFromChipmonk[p.y]-deltaOrigin.y]]};

  RefCoordPt: PROC [r: CoordRect] RETURNS [ppdefs.Point];

  ShowFeature: PROC [f: FeaturePtr];
    -- shows it on the screen from debugger

  END. -- of ChipNetDefs