Ports.mesa
Barth, March 12, 1987 11:53:57 am PST
Gasbarro, January 23, 1986 11:32:11 am PST
Bertrand Serlet, January 27, 1986 4:01:32 pm PST
DIRECTORY BitOps, Core, CoreCreate;
Ports: CEDAR DEFINITIONS = BEGIN
Theory
A port is a DAG which is a subgraph of a Core.Wire DAG. A port requires that the leaves of the port DAG form a disjoint cover of the leaves of the Core.Wire DAG. This eliminates aliases of values.
A port is used for representing an interface to a Core.wire. A port defines an interface to a wire rather than the wire itself. Thus a port represents a current strength as well as a voltage level.
A voltage level in a port can be represented as a boolean value or as a member of the set L, H, or X. A leaf port can represent aggregates of either of these value sets. A current strength may be represented as an aggregate value or as a strength per voltage level.
Types
PortList: TYPE = LIST OF Port;
Port: TYPE = REF PortRec;
The comment definition of a port record captures the semantics. However it introduces a number of runtime checks and excess verbiage in the source. The uncommented definition is used to eliminate them. Unfortunately this reduces the amount of compile time checking which can be performed.
PortRec: TYPE = RECORD [
port: SELECT levelType: LevelType FROM
l => [d: Drive ← none, l: Level ← L],
b => [d: Drive ← none, b: BOOLFALSE],
ls => [ls: LevelSequence ← NIL, dt: SELECT driveType: DriveType FROM
aggregate => [d: Drive ← none],
seperate => [ds: DriveSequence ← NIL],
ENDCASE],
bs => [bs: BoolSequence ← NIL, dt: SELECT driveType: DriveType FROM
aggregate => [d: Drive ← none],
seperate => [ds: DriveSequence ← NIL],
ENDCASE],
c => [
fieldStart: [0..16),
c: CARDINAL ← 0,
dt: SELECT driveType: DriveType FROM
aggregate => [d: Drive ← none],
seperate => [ds: DriveSequence ← NIL],
ENDCASE],
lc => [
fieldStart: [0..32),
lc: LONG CARDINAL ← 0,
dt: SELECT driveType: DriveType FROM
aggregate => [d: Drive ← none],
seperate => [ds: DriveSequence ← NIL],
ENDCASE],
q => [
fieldStart: [0..64),
q: BitOps.BitQWord ← BitOps.BitQWordZero,
dt: SELECT driveType: DriveType FROM
aggregate => [d: Drive ← none],
seperate => [ds: DriveSequence ← NIL],
ENDCASE],
composite => [composite: SEQUENCE size: NAT OF Port],
ENDCASE];
PortRec: TYPE = RECORD [
levelType: LevelType ← composite,
driveType: DriveType ← aggregate,
d: Drive ← none,
l: Level ← L,
b: BOOLFALSE,
ds: DriveSequence ← NIL,
ls: LevelSequence ← NIL,
bs: BoolSequence ← NIL,
fieldStart: [0..64) ← 0,
c: BitOps.BitWord ← BitOps.BitWordZero,
lc: BitOps.BitDWord ← BitOps.BitDWordZero,
q: BitOps.BitQWord ← BitOps.BitQWordZero,
composite: SEQUENCE size: NAT OF Port];
LevelType: TYPE = {l, ls, b, bs, c, lc, q, composite};
DriveType: TYPE = {aggregate, seperate};
Drive: TYPE = {
expect, -- allows port to specify expected value
none, --from a test proc it means neither driven nor checked; in switch-level it means no strength at all
chargeWeak, chargeMediumWeak,
charge,
chargeMediumStrong, chargeStrong,
force, -- weakest drive level, allows test procs to check if device has tristated
driveWeak, driveMediumWeak,
drive,
driveMediumStrong, driveStrong,
infinite -- drive for nodes which have infinite current sources
};
Level: TYPE = {L, H, X};
DriveSequence: TYPE = REF DriveSequenceRec;
DriveSequenceRec: TYPE = RECORD [drives: PACKED SEQUENCE size: NAT OF Drive];
LevelSequence: TYPE = REF LevelSequenceRec;
LevelSequenceRec: TYPE = RECORD [levels: PACKED SEQUENCE size: NAT OF Level];
BoolSequence: TYPE = REF BoolSequenceRec;
BoolSequenceRec: TYPE = RECORD [bools: PACKED SEQUENCE size: NAT OF BOOL];
PortData: TYPE = REF PortDataRec;
PortDataRec: TYPE = RECORD [
levelType: LevelType,
driveType: DriveType,
drive: Drive,
drives: DriveSequence];
levelTypeNames: ARRAY LevelType OF Core.ROPE;
levelNames: ARRAY Level OF Core.ROPE;
driveTypeNames: ARRAY DriveType OF Core.ROPE;
driveNames: ARRAY Drive OF Core.ROPE;
Operations
FindLevelType: PROC [levelTypeID: Core.ROPE] RETURNS [levelType: LevelType];
FindLevel: PROC [levelID: Core.ROPE] RETURNS [level: Level];
FindDriveType: PROC [driveTypeID: Core.ROPE] RETURNS [driveType: DriveType];
FindDrive: PROC [driveID: Core.ROPE] RETURNS [drive: Drive];
CreatePort: PROC [cellType: Core.CellType, testerPort: BOOLFALSE] RETURNS [port: Port];
Uses inheritance to find properties that guide port creation.
RenewPort: PROC [cellType: Core.CellType, port: Port, testerPort: BOOLFALSE];
InitPort: PROC [wire: Core.Wire, levelType: LevelType ← b, driveType: DriveType ← aggregate, initDrive: Drive ← none, initDrives: DriveSequence ← NIL] RETURNS [sameWire: Core.Wire];
InitPorts: PROC [ct: Core.CellType, initType: LevelType ← l, initDrive: Drive ← none, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10: CoreCreate.WRNIL];
InitPortList: PROC [ct: Core.CellType, initType: LevelType ← l, initDrive: Drive ← none, ports: LIST OF CoreCreate.WR];
InitTesterDrive: PROC [wire: Core.Wire, initDrive: Drive ← none, initDrives: DriveSequence ← NIL];
If initdrives#NIL then the port created with testerPort=TRUE will have driveType=seperate.
InitTesterDrives: PROC [ct: Core.CellType, initDrive: Drive ← none, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10: CoreCreate.WRNIL];
InitTesterDriveList: PROC [ct: Core.CellType, initDrive: Drive ← none, ports: LIST OF CoreCreate.WR];
ITDList: PROC [public: Core.Wire, indicies: LIST OF NAT, initDrive: Drive];
IPList: PROC [public: Core.Wire, indicies: LIST OF NAT, levelType: LevelType, initDrive: Drive ← none];
WirePortType: PROC [cellType: Core.CellType, wire: Core.Wire] RETURNS [levelType: LevelType, driveType: DriveType];
PortLeaves: PROC [port: Port] RETURNS [leaves: CARDINAL];
PortIndex: PROC [wire: Core.Wire, name: Core.ROPE] RETURNS [NAT];
PortIndexes: PROC [wire: Core.Wire, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11: Core.ROPENIL] RETURNS [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11: NATLAST[NAT]];
CopyPortValue: PROC [from: Port, to: Port];
Raises an error if the ports are not isomorphic.
CheckPortValue: PROC [root: Core.Wire, truth: Port, question: Port];
Raises an error if the ports are not isomorphic or the question port does not match the requirements of the truth port. Uses wire to generate a sensible error message; it should be the wire which was the argument to CreatePort.
CheckError: SIGNAL [msg: Core.ROPE];
Enumerating Pairs
EachPortPairProc: TYPE = PROC [onePort: Port, anotherPort: Port] RETURNS [subElements: BOOLTRUE, quit: BOOLFALSE];
VisitPortPair: PROC [onePort: Port, anotherPort: Port, eachPortPair: EachPortPairProc] RETURNS [quit: BOOL];
TRUE is returned if some invocation of eachPortPair returns quit=TRUE or if the ports do not conform.
EachWirePortPairProc: TYPE = PROC [wire: Core.Wire, port: Port] RETURNS [subElements: BOOLTRUE, quit: BOOLFALSE];
VisitBinding: PROC [wire: Core.Wire, port: Port, eachWirePortPair: EachWirePortPairProc] RETURNS [quit: BOOL];
TRUE is returned if some invocation of eachWirePortPair returns quit=TRUE. Wire and port need not conform, but port must be a subgraph of wire. If the port is a strict subgraph of the wire then the EachWirePortPairProc will be called with port: NIL;
Logical Operations and Conversions
ConversionError: SIGNAL;
NotL: PROC [a: Level] RETURNS [b: Level];
AndL: PROC [a, b: Level] RETURNS [c: Level];
OrL: PROC [a, b: Level] RETURNS [c: Level];
XorL: PROC [a, b: Level] RETURNS [c: Level];
SumL: PROC [a, b, c: Level] RETURNS [carry, s: Level];
NotLS: PROC [a, b: LevelSequence];
CopyLS: PROC [from, to: LevelSequence];
SetLS: PROC [seq: LevelSequence, level: Level];
LSToRope, LevelSequenceToRope: PROC [container: LevelSequence, size: NAT ← 0, base: NAT ← 16] RETURNS [val: Core.ROPE];
LSToC: PROC [ls: LevelSequence] RETURNS [c: CARDINAL];
Raises ConversionError if some bit of the level sequence is an X or if the value is greater than LAST[CARDINAL]
LSToLC: PROC [ls: LevelSequence] RETURNS [lc: LONG CARDINAL];
Raises ConversionError if some bit of the level sequence is an X or if the value is greater than LAST[LONG CARDINAL]
LCToLS: PROC [lc: LONG CARDINAL, ls: LevelSequence];
Raises ConversionError if the level sequence is not large enough to hold the value.
END.