DIRECTORY Basics, BitOps, Convert, Core, CoreCreate, CoreIO, CoreOps, CoreProperties, HashTable, IO, RefText, Rope, Ports; PortsImpl: CEDAR PROGRAM IMPORTS Basics, BitOps, Convert, CoreIO, CoreOps, CoreProperties, HashTable, IO, RefText, Rope EXPORTS Ports = BEGIN OPEN Ports; levelTypeNames: PUBLIC ARRAY LevelType OF Core.ROPE _ [ "l", "ls", "b", "bs", "c", "lc", "q", "composite"]; levelNames: PUBLIC ARRAY Level OF Core.ROPE _ ["L", "H", "X"]; driveTypeNames: PUBLIC ARRAY DriveType OF Core.ROPE _ ["agg", "sep"]; driveNames: PUBLIC ARRAY Drive OF Core.ROPE _ [ "e", "n", "cw", "cmw", "c", "cms", "cs", "f", "dw", "dmw", "d", "dms", "ds", "i"]; portTesterDriveAtom: ATOM _ CoreIO.RegisterProperty[prop: CoreProperties.RegisterProperty[prop: $PortTesterDrive, properties: CoreProperties.Props[[CoreProperties.propPrint, NEW[CoreProperties.PropPrintProc _ PortDataPrint]]]], write: PortDataWrite, read: PortDataRead]; portDataAtom: ATOM _ CoreIO.RegisterProperty[prop: CoreProperties.RegisterProperty[prop: $PortData, properties: CoreProperties.Props[[CoreProperties.propPrint, NEW[CoreProperties.PropPrintProc _ PortDataPrint]]]], write: PortDataWrite, read: PortDataRead]; PortDataPrint: CoreProperties.PropPrintProc = { portData: PortData _ NARROW[val]; CoreOps.PrintIndent[indent, to]; IO.PutF[to, "%g: ", IO.atom[prop]]; IF prop=portDataAtom THEN { IO.PutRope[to, levelTypeNames[portData.levelType]]; IO.PutRope[to, " "]; }; IO.PutRope[to, driveTypeNames[portData.driveType]]; SELECT portData.driveType FROM aggregate => { IO.PutRope[to, " "]; IO.PutRope[to, driveNames[portData.drive]]; }; seperate => IF portData.drives#NIL THEN FOR i: NAT IN [0..portData.drives.size) DO IO.PutRope[to, " "]; IO.PutRope[to, driveNames[portData.drives[i]]]; ENDLOOP; ENDCASE => ERROR; }; PortDataWrite: CoreIO.PropWriteProc = { portData: PortData _ NARROW[value]; CoreIO.WriteID[h, levelTypeNames[portData.levelType]]; CoreIO.WriteID[h, driveTypeNames[portData.driveType]]; CoreIO.WriteID[h, driveNames[portData.drive]]; IF portData.drives=NIL THEN CoreIO.WriteInt[h, 0] ELSE { CoreIO.WriteInt[h, portData.drives.size]; FOR i: NAT IN [0..portData.drives.size) DO CoreIO.WriteID[h, driveNames[portData.drives[i]]]; ENDLOOP; }; }; PortDataRead: CoreIO.PropReadProc = { portData: PortData _ NEW[PortDataRec]; size: NAT; portData.levelType _ FindLevelType[CoreIO.ReadID[h]]; portData.driveType _ FindDriveType[CoreIO.ReadID[h]]; portData.drive _ FindDrive[CoreIO.ReadID[h]]; size _ CoreIO.ReadInt[h]; IF size>0 THEN { portData.drives _ NEW[DriveSequenceRec[size]]; FOR i: NAT IN [0..size) DO portData.drives[i] _ FindDrive[CoreIO.ReadID[h]]; ENDLOOP; }; value _ portData; }; FindLevelType: PUBLIC PROC [levelTypeID: Core.ROPE] RETURNS [levelType: LevelType] = { FOR lev: LevelType IN LevelType DO IF Rope.Equal[levelTypeNames[lev], levelTypeID] THEN {levelType _ lev; EXIT}; REPEAT FINISHED => ERROR; ENDLOOP; }; FindLevel: PUBLIC PROC [levelID: Core.ROPE] RETURNS [level: Level] = { FOR lev: Level IN Level DO IF Rope.Equal[levelNames[lev], levelID] THEN {level _ lev; EXIT}; REPEAT FINISHED => ERROR; ENDLOOP; }; FindDriveType: PUBLIC PROC [driveTypeID: Core.ROPE] RETURNS [driveType: DriveType] = { FOR drv: DriveType IN DriveType DO IF Rope.Equal[driveTypeNames[drv], driveTypeID] THEN {driveType _ drv; EXIT}; REPEAT FINISHED => ERROR; ENDLOOP; }; FindDrive: PUBLIC PROC [driveID: Core.ROPE] RETURNS [drive: Drive] = { FOR drv: Drive IN Drive DO IF Rope.Equal[driveNames[drv], driveID] THEN {drive _ drv; EXIT}; REPEAT FINISHED => ERROR; ENDLOOP; }; CreatePort: PUBLIC PROC [cellType: Core.CellType, testerPort: BOOL _ FALSE] RETURNS [port: Port] = { wireTab: HashTable.Table _ HashTable.Create[]; -- wire to port portAssignment: HashTable.Table _ HashTable.Create[]; -- wire to port MakePort: PUBLIC PROC [wire: Core.Wire] RETURNS [port: Port] = { IF (port _ NARROW[HashTable.Fetch[table: wireTab, key: wire].value])=NIL THEN { data: PortData _ NARROW[CoreProperties.InheritPublicProp[cellType: cellType, from: wire, prop: portDataAtom]]; levelType: LevelType _ WirePortType[cellType, wire].levelType; IF levelType=composite THEN { port _ NEW[PortRec[wire.size]]; FOR sub: NAT IN [0..wire.size) DO port[sub] _ MakePort[wire: wire[sub]]; ENDLOOP; } ELSE { port _ NEW[PortRec[0]]; port.levelType _ levelType; SELECT levelType FROM ls => { port.ls _ NEW[LevelSequenceRec[CoreOps.WireBits[wire]]]; FOR bit: NAT IN [0..port.ls.size) DO port.ls[bit] _ L; ENDLOOP; }; bs => { port.bs _ NEW[BoolSequenceRec[CoreOps.WireBits[wire]]]; FOR bit: NAT IN [0..port.bs.size) DO port.bs[bit] _ FALSE; ENDLOOP; }; c => port.fieldStart _ 16 - CoreOps.WireBits[wire]; lc => port.fieldStart _ 32 - CoreOps.WireBits[wire]; q => port.fieldStart _ 64 - CoreOps.WireBits[wire]; ENDCASE; IF testerPort THEN data _ NARROW[CoreProperties.InheritPublicProp[cellType: cellType, from: wire, prop: portTesterDriveAtom]]; IF data#NIL THEN SELECT data.driveType FROM aggregate => port.d _ data.drive; seperate => { port.driveType _ seperate; IF data.drives=NIL THEN { port.ds _ NEW[DriveSequenceRec[CoreOps.WireBits[wire]]]; FOR i: NAT IN [0..port.ds.size) DO port.ds[i] _ data.drive; ENDLOOP; } ELSE port.ds _ CopyDrives[data.drives]; SELECT levelType FROM ls => IF port.ds.size#port.ls.size THEN ERROR; bs => IF port.ds.size#port.bs.size THEN ERROR; c => IF port.ds.size#16 - port.fieldStart THEN ERROR; lc => IF port.ds.size#32 - port.fieldStart THEN ERROR; q => IF port.ds.size#64 - port.fieldStart THEN ERROR; ENDCASE; } ENDCASE => ERROR; AssignPort[wire, port]; }; IF NOT HashTable.Insert[table: wireTab, key: wire, value: port] THEN ERROR; }; }; AssignPort: PROC [wire: Core.Wire, port: Port] = { assigned: Port _ NARROW[HashTable.Fetch[table: portAssignment, key: wire].value]; IF assigned=NIL THEN {IF NOT HashTable.Insert[table: portAssignment, key: wire, value: port] THEN ERROR} ELSE IF assigned#port THEN ERROR; -- multiple ports represent one wire FOR i: CARDINAL IN [0..wire.size) DO AssignPort[wire[i], port]; ENDLOOP; }; port _ MakePort[cellType.public]; }; RenewPort: PUBLIC PROC [cellType: Core.CellType, port: Port, testerPort: BOOL _ FALSE] = { ResetPort: EachWirePortPairProc = { data: PortData _ NARROW[CoreProperties.InheritPublicProp[cellType: cellType, from: wire, prop: IF testerPort THEN portTesterDriveAtom ELSE portDataAtom]]; IF port=NIL THEN RETURN; port.d _ none; IF data#NIL THEN SELECT data.driveType FROM aggregate => port.d _ data.drive; seperate => IF data.drives=NIL THEN FOR i: NAT IN [0..port.ds.size) DO port.ds[i] _ data.drive; ENDLOOP ELSE FOR i: NAT IN [0..port.ds.size) DO port.ds[i] _ data.drives[i]; ENDLOOP; ENDCASE => ERROR; port.l _ L; port.b _ FALSE; IF port.ls#NIL THEN FOR i: NAT IN [0..port.ls.size) DO port.ls[i] _ L; ENDLOOP; IF port.bs#NIL THEN FOR i: NAT IN [0..port.bs.size) DO port.bs[i] _ FALSE; ENDLOOP; port.c _ BitOps.BitWordZero; port.lc _ BitOps.BitDWordZero; port.q _ BitOps.BitQWordZero }; [] _ VisitBinding[cellType.public, port, ResetPort]; }; FindWire: PROC [iconPublic: Core.Wire, name: CoreCreate.WR] RETURNS [iconWire: Core.Wire _ NIL] ~ { n: NAT; IF ISTYPE[name, Core.Wire] THEN iconWire _ NARROW[name] ELSE { n _ CoreOps.GetWireIndex[iconPublic, CoreOps.FixStupidRef[name]]; -- dies if -1 returned! iconWire _ iconPublic[n]; }; }; InitPort: PUBLIC PROC [wire: Core.Wire, levelType: LevelType _ b, driveType: DriveType _ aggregate, initDrive: Drive _ none, initDrives: DriveSequence _ NIL] RETURNS [sameWire: Core.Wire] = { PutPortData[prop: portDataAtom, wire: wire, levelType: levelType, driveType: driveType, initDrive: initDrive, initDrives: initDrives]; sameWire _ wire; }; InitPorts: PUBLIC PROC [ct: Core.CellType, initType: LevelType _ l, initDrive: Drive _ none, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10: CoreCreate.WR _ NIL] = { ports: LIST OF CoreCreate.WR _ NIL; IF n0#NIL THEN ports _ CONS[n0, ports]; IF n1#NIL THEN ports _ CONS[n1, ports]; IF n2#NIL THEN ports _ CONS[n2, ports]; IF n3#NIL THEN ports _ CONS[n3, ports]; IF n4#NIL THEN ports _ CONS[n4, ports]; IF n5#NIL THEN ports _ CONS[n5, ports]; IF n6#NIL THEN ports _ CONS[n6, ports]; IF n7#NIL THEN ports _ CONS[n7, ports]; IF n8#NIL THEN ports _ CONS[n8, ports]; IF n9#NIL THEN ports _ CONS[n9, ports]; IF n10#NIL THEN ports _ CONS[n10, ports]; InitPortList[ct, initType, initDrive, ports]; }; InitPortList: PUBLIC PROC [ct: Core.CellType, initType: LevelType _ l, initDrive: Drive _ none, ports: LIST OF CoreCreate.WR] = { InitP: PROC [ref: REF] = { wire: Core.Wire _ FindWire[ct.public, ref]; [] _ InitPort[wire: wire, levelType: initType, initDrive: initDrive]; }; FOR p: LIST OF CoreCreate.WR _ ports, p.rest UNTIL p=NIL DO InitP[p.first]; ENDLOOP; }; InitTesterDrive: PUBLIC PROC [wire: Core.Wire, initDrive: Drive _ none, initDrives: DriveSequence _ NIL] = { PutPortData[prop: portTesterDriveAtom, wire: wire, driveType: IF initDrives=NIL THEN aggregate ELSE seperate, initDrive: initDrive, initDrives: initDrives] }; InitTesterDrives: PUBLIC PROC [ct: Core.CellType, initDrive: Drive _ none, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10: CoreCreate.WR _ NIL] = { ports: LIST OF CoreCreate.WR _ NIL; IF n0#NIL THEN ports _ CONS[n0, ports]; IF n1#NIL THEN ports _ CONS[n1, ports]; IF n2#NIL THEN ports _ CONS[n2, ports]; IF n3#NIL THEN ports _ CONS[n3, ports]; IF n4#NIL THEN ports _ CONS[n4, ports]; IF n5#NIL THEN ports _ CONS[n5, ports]; IF n6#NIL THEN ports _ CONS[n6, ports]; IF n7#NIL THEN ports _ CONS[n7, ports]; IF n8#NIL THEN ports _ CONS[n8, ports]; IF n9#NIL THEN ports _ CONS[n9, ports]; IF n10#NIL THEN ports _ CONS[n10, ports]; InitTesterDriveList[ct, initDrive, ports]; }; InitTesterDriveList: PUBLIC PROC [ct: Core.CellType, initDrive: Drive _ none, ports: LIST OF CoreCreate.WR] = { InitP: PROC [ref: REF] = { wire: Core.Wire _ FindWire[ct.public, ref]; [] _ InitTesterDrive[wire: wire, initDrive: initDrive]; }; FOR p: LIST OF CoreCreate.WR _ ports, p.rest UNTIL p=NIL DO InitP[p.first]; ENDLOOP; }; PutPortData: PUBLIC PROC [prop: ATOM, wire: Core.Wire, levelType: LevelType _ b, driveType: DriveType _ aggregate, initDrive: Drive _ none, initDrives: DriveSequence _ NIL] = { CoreProperties.PutWireProp[on: wire, prop: prop, value: NEW[PortDataRec _ [ levelType: levelType, driveType: driveType, drive: initDrive, drives: CopyDrives[initDrives]]]]; }; ITDList: PUBLIC PROC [public: Core.Wire, indicies: LIST OF NAT, initDrive: Drive] ~ { FOR l: LIST OF NAT _ indicies, l.rest WHILE l#NIL DO [] _ InitTesterDrive[wire: public[l.first], initDrive: initDrive]; ENDLOOP; }; IPList: PUBLIC PROC [public: Core.Wire, indicies: LIST OF NAT, levelType: LevelType, initDrive: Drive _ none] ~ { FOR l: LIST OF NAT _ indicies, l.rest WHILE l#NIL DO [] _ InitPort[wire: public[l.first], levelType: levelType, initDrive: initDrive]; ENDLOOP; }; WirePortType: PUBLIC PROC [cellType: Core.CellType, wire: Core.Wire] RETURNS [levelType: LevelType, driveType: DriveType] = { data: PortData _ NARROW[CoreProperties.InheritPublicProp[cellType: cellType, from: wire, prop: portDataAtom]]; levelType _ IF data=NIL THEN IF wire.size=0 THEN b ELSE composite ELSE data.levelType; driveType _ IF data=NIL THEN aggregate ELSE data.driveType; }; PortLeaves: PUBLIC PROC [port: Port] RETURNS [leaves: CARDINAL] = { visited: HashTable.Table _ HashTable.Create[]; CountLeaves: PROC [port: Port] RETURNS [leaves: CARDINAL _ 0] = { IF NOT HashTable.Fetch[table: visited, key: port].found THEN { IF NOT HashTable.Insert[table: visited, key: port, value: $Visited] THEN ERROR; IF port.size=0 THEN leaves _ 1 ELSE FOR sub: NAT IN [0..port.size) DO leaves _ leaves + CountLeaves[port[sub]]; ENDLOOP; }; }; leaves _ CountLeaves[port]; }; PortIndex: PUBLIC PROC [wire: Core.Wire, name: Core.ROPE] RETURNS [index: NAT] = { index _ CoreOps.GetWireIndex[wire, name]; IF index=-1 THEN ERROR; -- not found }; PortIndexes: PUBLIC PROC [wire: Core.Wire, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11: Core.ROPE _ NIL] RETURNS [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11: NAT _ LAST[NAT]] ~ { IF n0#NIL THEN i0 _ PortIndex[wire, n0]; IF n1#NIL THEN i1 _ PortIndex[wire, n1]; IF n2#NIL THEN i2 _ PortIndex[wire, n2]; IF n3#NIL THEN i3 _ PortIndex[wire, n3]; IF n4#NIL THEN i4 _ PortIndex[wire, n4]; IF n5#NIL THEN i5 _ PortIndex[wire, n5]; IF n6#NIL THEN i6 _ PortIndex[wire, n6]; IF n7#NIL THEN i7 _ PortIndex[wire, n7]; IF n8#NIL THEN i8 _ PortIndex[wire, n8]; IF n9#NIL THEN i9 _ PortIndex[wire, n9]; IF n10#NIL THEN i10 _ PortIndex[wire, n10]; IF n11#NIL THEN i11 _ PortIndex[wire, n11]; }; CopyPortValue: PUBLIC PROC [from: Port, to: Port] = { CopyBits: EachPortPairProc = { IF onePort.levelType#anotherPort.levelType OR onePort.driveType#anotherPort.driveType THEN ERROR; IF onePort.levelType#composite THEN { anotherPort.d _ onePort.d; IF onePort.ds#NIL THEN FOR i: NAT IN [0..onePort.ds.size) DO anotherPort.ds[i] _ onePort.ds[i]; ENDLOOP; SELECT onePort.levelType FROM l => anotherPort.l _ onePort.l; ls => { IF anotherPort.ls.size#onePort.ls.size THEN ERROR; FOR bit: NAT IN [0..onePort.ls.size) DO anotherPort.ls[bit] _ onePort.ls[bit]; ENDLOOP; }; b => anotherPort.b _ onePort.b; bs => { IF anotherPort.bs.size#onePort.bs.size THEN ERROR; FOR bit: NAT IN [0..onePort.bs.size) DO anotherPort.bs[bit] _ onePort.bs[bit]; ENDLOOP; }; c => anotherPort.c _ onePort.c; lc => anotherPort.lc _ onePort.lc; q => anotherPort.q _ onePort.q; ENDCASE => ERROR; }; }; IF VisitPortPair[from, to, CopyBits] THEN ERROR; }; CheckPortValue: PUBLIC PROC [root: Core.Wire, truth: Port, question: Port] = { CheckBits: EachPortPairProc = { Complain: PROC = { SetErrorMessage: EachWirePortPairProc = { IF onePort=port THEN { quit _ TRUE; msg _ IO.PutFR["Port %g expected %g but has %g", IO.rope[CoreOps.GetFullWireName[root, wire]], IO.rope[PortRope[onePort]], IO.rope[PortRope[anotherPort]]]; IF onePort.ds#NIL THEN { msg _ Rope.Cat[msg, " with expect mask ",]; FOR i: NAT IN [0..onePort.ds.size) DO msg _ Rope.Cat[msg, driveNames[onePort.ds[i]]]; ENDLOOP; }; }; }; msg: Core.ROPE; IF NOT VisitBinding[root, truth, SetErrorMessage] THEN ERROR; SIGNAL CheckError[msg]; }; IF onePort.levelType#composite THEN SELECT onePort.driveType FROM aggregate => IF onePort.d=expect OR onePort.d=force THEN { SELECT onePort.levelType FROM l => IF anotherPort.l#onePort.l THEN Complain[]; ls => FOR bit: NAT IN [0..onePort.ls.size) DO IF anotherPort.ls[bit]#onePort.ls[bit] THEN Complain[]; ENDLOOP; b => IF anotherPort.b#onePort.b THEN Complain[]; bs => FOR bit: NAT IN [0..onePort.bs.size) DO IF anotherPort.bs[bit]#onePort.bs[bit] THEN Complain[]; ENDLOOP; c => IF anotherPort.c#onePort.c THEN Complain[]; lc => IF anotherPort.lc#onePort.lc THEN Complain[]; q => IF anotherPort.q#onePort.q THEN Complain[]; ENDCASE => ERROR; }; seperate => FOR i: NAT IN [0..onePort.ds.size) DO IF onePort.ds[i]=expect OR onePort.ds[i]=force THEN SELECT onePort.levelType FROM ls => IF anotherPort.ls[i]#onePort.ls[i] THEN {Complain[]; EXIT}; bs => IF anotherPort.bs[i]#onePort.bs[i] THEN {Complain[]; EXIT}; c => IF BitOps.EBFW[anotherPort.c, i, 16-anotherPort.fieldStart]#BitOps.EBFW[onePort.c, i, 16-onePort.fieldStart] THEN {Complain[]; EXIT}; lc => IF BitOps.EBFD[anotherPort.lc, i, 32-anotherPort.fieldStart]#BitOps.EBFD[onePort.lc, i, 32-onePort.fieldStart] THEN {Complain[]; EXIT}; q => IF BitOps.EBFQ[anotherPort.q, i, 64-anotherPort.fieldStart]#BitOps.EBFQ[onePort.q, i, 64-onePort.fieldStart] THEN {Complain[]; EXIT}; ENDCASE => ERROR; ENDLOOP; ENDCASE => ERROR; }; IF VisitPortPair[truth, question, CheckBits] THEN ERROR; }; CheckError: PUBLIC SIGNAL [msg: Core.ROPE] = CODE; VisitPortPair: PUBLIC PROC [onePort: Port, anotherPort: Port, eachPortPair: EachPortPairProc] RETURNS [quit: BOOL] = { subElements: BOOL; IF onePort.size#anotherPort.size OR onePort.levelType#anotherPort.levelType OR (onePort.levelType=ls AND anotherPort.ls.size#onePort.ls.size) OR (onePort.levelType=bs AND anotherPort.bs.size#onePort.bs.size) THEN RETURN [TRUE]; -- ports do not conform [subElements, quit] _ eachPortPair[onePort, anotherPort]; IF quit OR ~subElements THEN RETURN; FOR i: NAT IN [0..onePort.size) DO IF VisitPortPair[onePort[i], anotherPort[i], eachPortPair] THEN RETURN [TRUE]; ENDLOOP; quit _ FALSE; }; VisitBinding: PUBLIC PROC [wire: Core.Wire, port: Port, eachWirePortPair: EachWirePortPairProc] RETURNS [quit: BOOL] = { subElements: BOOL; [subElements, quit] _ eachWirePortPair[wire, port]; IF quit OR ~subElements THEN RETURN; FOR i: NAT IN [0..wire.size) DO IF VisitBinding[ wire[i], IF port = NIL THEN NIL ELSE IF port.levelType#composite THEN NIL ELSE port[i], eachWirePortPair] THEN RETURN [TRUE]; ENDLOOP; quit _ FALSE; }; CopyDrives: PROC [old: DriveSequence] RETURNS [new: DriveSequence _ NIL] = { IF old#NIL THEN { new _ NEW[DriveSequenceRec[old.size]]; FOR i: NAT IN [0..new.size) DO new[i] _ old[i]; ENDLOOP }; }; PortRope: PROC [port: Port] RETURNS [value: Core.ROPE _ NIL] = { SELECT port.levelType FROM l => value _ SELECT port.l FROM L => "0", X => "X", H => "1" ENDCASE => ERROR; ls => value _ LevelSequenceToRope[container: port.ls, size: port.ls.size]; b => value _ IF port.b THEN "1" ELSE "0"; bs => { FOR bit: NAT IN [0..port.bs.size) DO value _ Rope.Concat[value, IF port.bs[bit] THEN "1" ELSE "0"]; ENDLOOP; }; c => value _ Convert.RopeFromCard[from: port.c, base: 16]; lc => value _ Convert.RopeFromCard[from: port.lc, base: 16]; q => { ls: LevelSequence _ NEW[LevelSequenceRec[64-port.fieldStart]]; FOR i: NAT IN [0..ls.size) DO ls[i] _ IF BitOps.EBFQ[port.q, i, ls.size] THEN H ELSE L; ENDLOOP; value _ LevelSequenceToRope[container: ls, size: ls.size]; }; ENDCASE => ERROR; }; ConversionError: PUBLIC SIGNAL = CODE; NotL: PUBLIC PROC [a: Level] RETURNS [b: Level] = { b _ SELECT a FROM L => H, H => L, ENDCASE => X}; AndL: PUBLIC PROC [a, b: Level] RETURNS [c: Level] = { tt: ARRAY Level OF ARRAY Level OF Level = [[L, L, L], [L, H, X], [L, X, X]]; c _ tt[a][b]; }; OrL: PUBLIC PROC [a, b: Level] RETURNS [c: Level] = { tt: ARRAY Level OF ARRAY Level OF Level = [[L, H, X], [H, H, X], [X, X, X]]; c _ tt[a][b]; }; XorL: PUBLIC PROC [a, b: Level] RETURNS [c: Level] = { tt: ARRAY Level OF ARRAY Level OF Level = [[L, H, X], [H, L, X], [X, X, X]]; c _ tt[a][b]; }; SumL: PUBLIC PROC [a, b, c: Level] RETURNS [carry, s: Level] = { IF a=X OR b=X OR c=X THEN RETURN[X, X]; carry _ IF (a=H AND b=H) OR (b=H AND c=H) OR (c=H AND a=H) THEN H ELSE L; s _ IF (a=H AND b=H AND c=L) OR (b=H AND c=H AND a=L) OR (c=H AND a=H AND b=L) OR (a=L AND b=L AND c=L) THEN L ELSE H; }; NotLS: PUBLIC PROC [a, b: LevelSequence] = { FOR i: NAT IN [0..a.size) DO b[i] _ NotL[a[i]]; ENDLOOP; }; CopyLS: PUBLIC PROC [from, to: LevelSequence] = { FOR i: NAT IN [0..from.size) DO to[i] _ from[i]; ENDLOOP; }; SetLS: PUBLIC PROC [seq: LevelSequence, level: Level] = { FOR i: NAT IN [0..seq.size) DO seq[i] _ level; ENDLOOP; }; LSToRope, LevelSequenceToRope: PUBLIC PROC [container: LevelSequence, size: NAT _ 0, base: NAT _ 16] RETURNS [val: Core.ROPE _ NIL] = { bitsPerDigit: NAT _ BitOps.NBits[base]; scratch: REF TEXT; bitsInDigit: NAT; digitBitCount: NAT _ 0; allX: BOOL _ TRUE; someX: BOOL _ FALSE; digitVal: CARDINAL _ 0; IF size=0 THEN size _ container.size; scratch _ RefText.New[(size/bitsPerDigit)+1]; bitsInDigit _ IF size MOD bitsPerDigit = 0 THEN bitsPerDigit ELSE size MOD bitsPerDigit; FOR bit: NAT IN [0..size) DO bitVal: Level _ container[bit]; digitVal _ 2*digitVal; IF bitVal=X THEN someX _ TRUE ELSE { allX _ FALSE; IF bitVal=H THEN digitVal _ digitVal + 1; }; digitBitCount _ digitBitCount + 1; IF digitBitCount=bitsInDigit THEN { SELECT TRUE FROM allX => scratch _ RefText.InlineAppendChar[scratch, 'X]; someX => { scratch _ RefText.InlineAppendChar[scratch, '(]; FOR rescan: NAT DECREASING IN [0..bitsInDigit) DO scratch _ RefText.InlineAppendChar[scratch, SELECT container[bit-rescan] FROM L => '0, X => 'X, H => '1, ENDCASE => ERROR]; ENDLOOP; scratch _ RefText.InlineAppendChar[scratch, ')]; }; ENDCASE => scratch _ Convert.AppendCard[to: scratch, from: digitVal, base: base, showRadix: FALSE]; bitsInDigit _ bitsPerDigit; digitBitCount _ 0; allX _ TRUE; someX _ FALSE; digitVal _ 0; }; ENDLOOP; val _ Rope.FromRefText[scratch]; }; ToBool: PROC [level: Level] RETURNS [new: BOOL] = { new _ SELECT level FROM L => FALSE, X => ERROR ConversionError, H => TRUE, ENDCASE => ERROR; }; WordAsBits: TYPE = PACKED ARRAY [0..16) OF BOOL; DWordAsBits: TYPE = PACKED ARRAY [0..32) OF BOOL; LSToC: PUBLIC PROC [ls: LevelSequence] RETURNS [c: CARDINAL] = { asBits: WordAsBits _ ALL[FALSE]; IF ls.size>16 THEN ERROR; FOR bit: NAT IN [0..ls.size) DO asBits[bit+16-ls.size] _ ToBool[ls[bit]]; ENDLOOP; c _ LOOPHOLE[asBits]; }; LSToLC: PUBLIC PROC [ls: LevelSequence] RETURNS [lc: LONG CARDINAL] = { asBits: DWordAsBits _ ALL[FALSE]; IF ls.size>32 THEN ERROR; FOR bit: NAT IN [0..ls.size) DO asBits[bit+32-ls.size] _ ToBool[ls[bit]]; ENDLOOP; lc _ LOOPHOLE[Basics.SwapHalves[LOOPHOLE[asBits]]]; }; LCToLS: PUBLIC PROC [lc: LONG CARDINAL, ls: LevelSequence] = { FOR bit: NAT IN [0..ls.size) DO thisBit: NAT _ bit+32-ls.size; ls[bit] _ IF (IF thisBit < 16 THEN LOOPHOLE[Basics.HighHalf[lc], WordAsBits][thisBit] ELSE LOOPHOLE[Basics.LowHalf[lc], WordAsBits][thisBit - 16]) THEN H ELSE L; ENDLOOP; }; END. PortsImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Barth, March 12, 1987 11:53:52 am PST Gasbarro, January 23, 1986 11:40:29 am PST Bertrand Serlet, August 12, 1986 3:43:57 pm PDT Logical Operations and Conversions ΚΊ– "cedar" style˜codešœ™Kšœ Οmœ7™BK™%K™*K™/K™—KšΟk œXžœ˜zK˜•StartOfExpansion[]šΟb œžœž˜KšžœFžœ˜^Kšžœ˜ Kšœžœžœ˜—K˜š œžœžœ žœžœ˜7Kšœ3˜3—Kšœ ž œžœžœ˜>Kš œžœžœ žœžœ˜Eš œ žœžœžœžœ˜/KšœR˜RK˜—šœžœ•žœ]˜ŽK˜—šœžœŽžœ]˜€K˜šΟn œ"˜/Kšœžœ˜!Jšœ ˜ Kšžœžœ ˜#šžœžœ˜Kšžœ1˜3Kšžœ˜K˜—Kšžœ1˜3šžœž˜šœ˜Kšžœ˜Kšžœ)˜+K˜—šœ žœžœžœžœžœžœž˜RKšžœ˜Kšžœ-˜/Kšžœ˜—Kšžœžœ˜—K˜K˜—š  œ˜'Kšœžœ˜#Kšœ6˜6Kšœ6˜6Kšœ.˜.Kšžœžœžœ˜1šžœ˜Kšœ)˜)šžœžœžœž˜*Kšœ2˜2Kšžœ˜—K˜—K˜K˜—š  œ˜%Kšœžœ˜&Kšœžœ˜ Kšœ5˜5Kšœ5˜5Kšœ-˜-Kšœ˜šžœžœ˜Kšœžœ˜.šžœžœžœ ž˜Kšœ1˜1Kšžœ˜—K˜—Kšœ˜K˜K˜——š   œžœžœžœžœ˜Všžœžœ ž˜"Kšžœ.žœžœ˜MKšžœžœžœ˜Kšžœ˜—K˜K˜—š   œžœžœžœžœ˜Fšžœ žœž˜Kšžœ&žœžœ˜AKšžœžœžœ˜Kšžœ˜—K˜K˜—š   œžœžœžœžœ˜Všžœžœ ž˜"Kšžœ.žœžœ˜MKšžœžœžœ˜Kšžœ˜—K˜K˜—š   œžœžœžœžœ˜Fšžœ žœž˜Kšžœ&žœžœ˜AKšžœžœžœ˜Kšžœ˜—K˜K˜—š   œžœžœ'žœžœžœ˜dKšœ0Οc˜?Kšœ7‘˜Fš œžœžœžœ˜@šžœ žœ4žœžœ˜OKšœžœW˜nKšœ>˜>šžœžœ˜Kšœžœ˜šžœžœžœž˜!Kšœ&˜&Kšžœ˜—K˜—šžœ˜Kšœžœ ˜Kšœ˜šžœ ž˜šœžœ˜Kšœ žœ+˜8šžœžœžœž˜$K˜Kšžœ˜—K˜—šœžœ˜Kšœ žœ*˜7šžœžœžœž˜$Kšœžœ˜Kšžœ˜—K˜—Kšœ3˜3Kšœ4˜4Kšœ3˜3Kšžœ˜—Kšžœ žœžœ^˜~š žœžœžœžœž˜+Kšœ!˜!šœ ˜ Kšœ˜šžœ žœžœ˜Kšœ žœ+˜8šžœžœžœž˜"Kšœ˜Kšžœ˜—Kšœ˜—Kšžœ#˜'šžœ ž˜Kšœžœžœžœ˜.Kš œžœžœžœžœ˜.Kšœžœ#žœžœ˜5Kšœžœ#žœžœ˜6Kšœžœ#žœžœ˜5Kšžœ˜—K˜—Kšžœžœ˜—K˜K˜—Kšžœžœ:žœžœ˜KK˜—Kšœ˜—š  œžœ"˜2Kšœžœ:˜QKšžœ žœžœžœžœAžœžœ˜hKš žœžœžœžœ‘$˜Gšžœžœžœž˜$K˜Kšžœ˜—K˜—Kšœ!˜!˜K˜——š   œžœžœ3žœžœ˜ZK˜š  œ˜#Kš œžœHžœ žœžœ˜šKšžœžœžœžœ˜K˜š žœžœžœžœž˜+Kšœ!˜!šœ žœ žœž˜#šžœžœžœž˜"Kšœ˜Kšž˜—š žœžœžœžœž˜'Kšœ˜Kšžœ˜——Kšžœžœ˜—K˜ Kšœ žœ˜š žœ žœžœžœžœžœž˜6K˜Kšžœ˜—š žœ žœžœžœžœžœž˜6Kšœ žœ˜Kšžœ˜—Kšœ˜Kšœ˜Kšœ˜K˜K˜—Kšœ4˜4Kšœ˜K˜—š  œžœ*žœžœžœ˜cKšœžœ˜Kšžœžœžœ žœ˜7šžœ˜KšœC‘˜ZKšœ˜K˜—K˜K˜—š  œžœžœ„žœžœ˜ΏKšœ†˜†K˜Kšœ˜K˜—š   œžœžœžœžœ˜’Kš œžœžœ žœžœ˜#Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜)K˜-K˜K˜—š   œžœžœNžœžœ žœ˜š œžœžœ˜Kšœ*ž˜+KšœE˜EK˜—š žœžœžœ žœžœžœž˜;K˜Kšžœ˜—K˜K˜—š œžœžœHžœ˜lKš œ>žœ žœžœ žœ8˜›Kšœ˜K˜—š  œžœžœfžœžœ˜Kš œžœžœ žœžœ˜#Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜'Kšžœžœžœ žœ ˜)K˜*K˜K˜—š  œžœžœ5žœžœ žœ˜oš œžœžœ˜Kšœ+˜+Kšœ7˜7K˜—š žœžœžœ žœžœžœž˜;K˜Kšžœ˜—K˜K˜—š   œžœžœžœ„žœ˜°šœ7˜7šžœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ"˜"——Kšœ˜K˜—š Πbnœžœžœžœžœžœ˜Uš žœžœžœžœžœžœž˜4KšœB˜BKšžœ˜—K˜K˜—š ’œžœžœžœžœžœ4˜qš žœžœžœžœžœžœž˜4KšœQ˜QKšžœ˜—K˜K˜—š  œžœžœ,žœ1˜}KšœžœW˜nKšœ žœžœžœžœ žœžœ žœ˜VKš œ žœžœžœ žœ˜;Kšœ˜K˜—š   œžœžœžœ žœ˜CKšœ.˜.š  œžœžœ žœ ˜Ašžœžœ2žœ˜>Kšžœžœ>žœžœ˜OKšžœ žœ ˜š žœžœžœžœž˜&Kšœ)˜)Kšžœ˜—K˜—K˜—Kšœ˜Kšœ˜K˜—š   œžœžœžœžœ žœ˜RKšœ)˜)Kšžœ žœžœ‘ ˜$K˜K˜—š  œžœžœJžœžœžœ4žœžœžœ˜½Kšžœžœžœ˜(Kšžœžœžœ˜(Kšžœžœžœ˜(Kšžœžœžœ˜(Kšžœžœžœ˜(Kšžœžœžœ˜(Kšžœžœžœ˜(Kšžœžœžœ˜(Kšžœžœžœ˜(Kšžœžœžœ˜(Kšžœžœžœ˜+Kšžœžœžœ˜+K˜K˜—š  œžœžœ˜5K˜š œ˜Kšžœ)žœ)žœžœ˜ašžœžœ˜%Kšœ˜š žœ žœžœžœžœžœž˜Kšžœ˜—K˜—Kšœ:˜:Kšœ<˜<šœ˜Kšœžœ'˜>šžœžœžœž˜Kš œžœžœžœžœ˜9Kšžœ˜—Kšœ:˜:K˜—Kšžœžœ˜—Kšœ˜K˜—head™"š œžœžœžœ˜&K˜—š œžœžœ žœ˜3Kšœžœžœžœ˜0K˜—š œžœžœžœ˜6š œžœžœžœžœ˜)K˜ K˜ K˜ —Kšœ ˜ Kšœ˜K˜—š œžœžœžœ˜5š œžœžœžœžœ˜)K˜ K˜ K˜ —Kšœ ˜ K˜K˜—š œžœžœžœ˜6š œžœžœžœžœ˜)K˜ K˜ K˜ —Kšœ ˜ Kšœ˜K˜—š œžœžœžœ˜@Kš žœžœžœžœžœ˜'Kšœžœžœžœžœžœžœžœžœ˜IKšœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜vK˜K˜—š œžœžœ˜,Kš žœžœžœ žœžœ˜8K˜K˜—š œžœžœ˜1Kš žœžœžœžœžœ˜9K˜K˜—š œžœžœ'˜9Kš žœžœžœžœžœ˜7K˜K˜—š œ œžœžœ"žœ žœžœ žœžœ˜‡Kšœžœ˜'Kšœ žœžœ˜Kšœ žœ˜Kšœžœ˜Kšœžœžœ˜Kšœžœžœ˜Kšœ žœ˜Kšžœžœ˜%Kšœ-˜-Kš œžœžœžœžœžœ˜Xšžœžœžœ ž˜Kšœ˜Kšœ˜Kšžœ žœ ž˜šžœ˜Kšœžœ˜ Kšžœ žœ˜)K˜—Kšœ"˜"šžœžœž˜#šžœžœž˜Kšœ8˜8˜ Kšœ0˜0š žœ žœž œžœž˜1šœ,žœž˜MKšœ˜Kšœ˜Kšœ˜Kšžœžœ˜—Kšžœ˜—Kšœ0˜0K˜—KšžœUžœ˜c—Kšœ˜Kšœ˜Kšœžœ˜ Kšœžœ˜Kšœ ˜ K˜—Kšžœ˜—Kšœ ˜ K˜K˜—š œžœžœžœ˜3šœžœž˜Kšœžœ˜ Kšœžœ˜Kšœžœ˜ Kšžœžœ˜—K˜K˜—Kš œ žœžœžœ žœžœ˜0š œ žœžœžœ žœžœ˜1K˜—š  œžœžœžœžœ˜@Kšœžœžœ˜ Kšžœ žœžœ˜šžœžœžœž˜Kšœ)˜)Kšžœ˜—Kšœžœ ˜Kšœ˜K™—š  œžœžœžœžœžœ˜GKšœžœžœ˜!Kšžœ žœžœ˜šžœžœžœž˜Kšœ)˜)Kšžœ˜—Kšœžœžœ ˜3Kšœ˜K™K˜—š  œžœžœžœžœ˜>šžœžœžœž˜Kšœ žœ˜Kšœ žœžœžœ+žœžœ0žœžœ˜’Kšžœ˜—Kšœ˜K™K˜——Kšžœ˜K˜—…—SqΊ