[Indigo]<Rosemary>®>Rosemary.DF=>SwitchTypesImpl.Mesa
Last Edited by: Spreitzer, May 1, 1985 8:24:44 pm PDT
Last Edited by: Barth, April 23, 1984 5:37:27 pm PST
Last Edited by: Gasbarro, August 16, 1984 4:22:48 pm PDT
DIRECTORY Atom, Basics, IO, List, NumTypes, Rope, RoseRun, RoseTranslateTypes, RoseTypes, SignalTypeRegistration, SwitchNumConvert, SwitchTypes, VFonts;
SwitchTypesImpl: CEDAR PROGRAM
IMPORTS Atom, IO, NumTypes, Rope, RoseRun, RoseTranslateTypes, SignalTypeRegistration, SwitchNumConvert, VFonts
EXPORTS SwitchTypes =
BEGIN OPEN RoseTypes, SwitchTypes;
refInput:  PUBLIC REF Strength ← NEW [Strength ← input];
refDriveStrong: PUBLIC REF Strength ← NEW [Strength ← driveStrong];
refDrive:  PUBLIC REF Strength ← NEW [Strength ← drive];
refDriveWeak: PUBLIC REF Strength ← NEW [Strength ← driveWeak];
refChargeStrong: PUBLIC REF Strength ← NEW [Strength ← chargeStrong];
refCharge: PUBLIC REF Strength ← NEW [Strength ← charge];
refChargeWeak: PUBLIC REF Strength ← NEW [Strength ← chargeWeak];
refNone:  PUBLIC REF Strength ← NEW [Strength ← none];
bitProcs: NodeProcs ← NEW [NodeProcsRep ← [
UserDescription: BitUserDescription,
ListFormats: BitListFormats,
GetFormat: BitGetFormat,
MesaForSelf: BitMesaForSelf,
SelectorOffset: BitSelectorOffset,
SubType: BitSubType,
Bits: BitBits,
MesaRepresentation: BitMesaRepresentation,
Equivalent: BitEquivalent,
SimpleEquivalent: BitSimpleEquivalent,
Transduce: SwitchNumConvert.Transduce,
InitPort: BitInitPort,
InitQ: BitInitQ,
InitUD: BitInitUD,
NewVal: BitNewVal,
CopyVal: BitCopyVal,
NewQ: BitNewQ,
NewUD: BitNewUD,
QFromNode: BitQFromNode,
UDFromNode: BitUDFromNode,
ValFromNode: BitValFromNode,
SetNode: BitSetNode,
CompareUD: BitCompareUD
]];
bitType: PUBLIC NodeType ← NEW [NodeTypeRep[atom] ← [
procs: bitProcs,
typeData: NIL,
simple: FALSE,
structure: atom[$DigitalWire]]];
shortBitFormat: Format ← NEW [FormatRep ← [
FormatValue: BitFormatValue,
ParseValue: BitParseValue,
FormatTest: BitFormatTest,
ParseTest: BitParseTest,
MaxWidth: BitMaxWidth,
key: "short"]];
longBitFormat: Format ← NEW [FormatRep ← [
FormatValue: LBitFormatValue,
ParseValue: LBitParseValue,
FormatTest: BitFormatTest,
ParseTest: BitParseTest,
MaxWidth: LBitMaxWidth,
key: "long"]];
initBitFormat: Format ← NEW [FormatRep ← [
ParseValue: InitialBitParse,
key: "init"]];
Int: TYPE = RoseTranslateTypes.Int;
one: Int ← NEW [RoseTranslateTypes.IntRep ← [RoseTranslateTypes.nullSR, 1]];
Holder: TYPE = LONG POINTER TO SwitchValHolder;
ConstructBitType: PROC [parms: REF ANY --UNION [BindingList, Args]--] RETURNS [type: NodeType] --RoseTranslateTypes.NodeTypeConstructor-- =
BEGIN
type ← bitType;
END;
BitUserDescription: PROC [NodeType] RETURNS [r: ROPE] = {r ← "Switch"};
BitListFormats: PROC [NodeType] RETURNS [l: RopeList] =
{l ← LIST ["short", "long"]};
BitGetFormat: PROC [nt: NodeType, fmtKey: ROPE] RETURNS [Format] =
{RETURN [IF fmtKey.Equal["init"] THEN initBitFormat ELSE IF fmtKey.Equal["long", FALSE] OR fmtKey.Equal["QUD"] THEN longBitFormat ELSE shortBitFormat]};
BitMesaForSelf: PROC [NodeType] RETURNS [m: Mesa] =
{m ← [mesa: "SwitchTypes.bitType", imports: LIST["SwitchTypes"]]};
BitSelectorOffset: PROC [nt: NodeType, s: Selector] RETURNS [o: NAT] = {
o ← WITH s SELECT FROM
whole => 0,
number, range => ERROR,
ENDCASE => ERROR};
BitSubType: PROC [nt: NodeType, s: Selector] RETURNS [snt: NodeType] = {
snt ← WITH s SELECT FROM
whole => nt,
number, range => ERROR,
ENDCASE => ERROR};
BitBits: PROC [NodeType] RETURNS [container, data, leftPad: INT] = {RETURN [bpw, bitsPerSwitchVal, bpw-bitsPerSwitchVal]};
BitMesaRepresentation: PROC [NodeType] RETURNS [m: Mesa] =
{m ← [mesa: "SwitchTypes.SwitchVal", directory: LIST["SwitchTypes"]]};
BitEquivalent: PROC [self, other: NodeType] RETURNS [eqv: BOOL] = {
IF self # bitType THEN ERROR;
eqv ← other = bitType OR other = oneBitSwitches};
BitSimpleEquivalent: PROC [NodeType] RETURNS [NodeType] =
{RETURN [NumTypes.boolType]};
BitInitPort: PROC [n: Node, p: Ptr] = TRUSTED {
nh: Holder ← PtrToHolder[n.valPtr];
ph: Holder ← PtrToHolder[p];
ph.held ← nh.held};
PtrToHolder: PROC [p: Ptr] RETURNS [h: Holder] = {
IF p.bit # 0 THEN ERROR;
TRUSTED {h ← LOOPHOLE[p.word]};
};
BitInitQ: PROC [n: Node] = {
nh: Holder ← PtrToHolder[n.valPtr];
TRUSTED {nh.held.s[q] ← n.strength}};
BitInitUD: PROC [n: Node] = TRUSTED {
nh: Holder ← PtrToHolder[n.valPtr];
u, d: Strength;
[u, d] ← Parts[nh.held.val, n.strength];
nh.held.s[u] ← Block[u, nh.held.s[q]];
nh.held.s[d] ← Block[d, nh.held.s[q]];
n.isInput ← nh.held.s[q] = input};
BitNewVal: PROC [n: Node] RETURNS [delay: BOOL] = TRUSTED {
nh: Holder ← PtrToHolder[n.valPtr];
temp: Level ←
IF nh.held.s[u] = none AND nh.held.s[d] > none THEN L ELSE
IF nh.held.s[d] = none AND nh.held.s[u] > none THEN H ELSE
X;
delay ← FALSE;
IF n.XPhobic AND temp = X THEN delay ← TRUE ELSE nh.held.val ← temp;
};
BitCopyVal: PROC [nt: NodeType, from, to: Ptr] = TRUSTED {
hFrom: Holder ← PtrToHolder[from];
hTo: Holder ← PtrToHolder[to];
hTo.held.val ← hFrom.held.val};
BitNewQ: PROC [n: Node, p: Ptr] RETURNS [b: BOOLEAN] = TRUSTED {
h: Holder ← PtrToHolder[p];
nh: Holder ← PtrToHolder[n.valPtr];
IF b ← h.held.s[q] > nh.held.s[q] THEN nh.held.s[q] ← h.held.s[q]};
BitNewUD: PROC [n: Node, p: Ptr] RETURNS [b: BOOLEAN] = TRUSTED {
h: Holder ← PtrToHolder[p];
nh: Holder ← PtrToHolder[n.valPtr];
u: Strength ← Block[h.held.s[u], nh.held.s[q]];
d: Strength ← Block[h.held.s[d], nh.held.s[q]];
b ← FALSE;
IF u > nh.held.s[u] THEN {b ← TRUE; nh.held.s[u] ← u};
IF d > nh.held.s[d] THEN {b ← TRUE; nh.held.s[d] ← d}};
BitQFromNode: PROC [n: Node, to: Ptr] = TRUSTED {
h: Holder ← PtrToHolder[to];
nh: Holder ← PtrToHolder[n.valPtr];
h.held.s[q] ← nh.held.s[q]};
BitUDFromNode: PROC [n: Node, to: Ptr] = TRUSTED {
h: Holder ← PtrToHolder[to];
nh: Holder ← PtrToHolder[n.valPtr];
h.held.s[u] ← nh.held.s[u];
h.held.s[d] ← nh.held.s[d]};
BitValFromNode: PROC [n: Node, to: Ptr] = TRUSTED {
h: Holder ← PtrToHolder[to];
nh: Holder ← PtrToHolder[n.valPtr];
h.held.val ← nh.held.val};
BitSetNode: PROC [n: Node, to: Ptr] = TRUSTED {
h: Holder ← PtrToHolder[to];
nh: Holder ← PtrToHolder[n.valPtr];
nh.held ← h.held};
BitCompareUD: PROC [nt: NodeType, p1, p2: Ptr] RETURNS [diff: BOOL] = TRUSTED {
h1: Holder ← PtrToHolder[p1];
h2: Holder ← PtrToHolder[p2];
diff ← h1.held.s[u] # h2.held.s[u] OR h1.held.s[d] # h2.held.s[d]};
Block: PUBLIC PROC [a, b: Strength] RETURNS [c: Strength] =
{c ← IF a < b THEN none ELSE a};
Parts: PROC [l: Level, s: Strength] RETURNS [u, d: Strength] = {
RETURN [
SELECT l FROM
L => none,
H, X => s,
ENDCASE => ERROR,
SELECT l FROM
H => none,
L, X => s,
ENDCASE => ERROR]};
BitFormatValue: PROC [node: Node, fmt: Format, p: Ptr] RETURNS [r: ROPE] = {
h: Holder ← PtrToHolder[p];
TRUSTED {r ← levelToRope[h.held.val]}};
BitParseValue: PROC [node: Node, fmt: Format, p: Ptr, s: STREAM] RETURNS [success: BOOLEAN] = {
h: Holder ← PtrToHolder[p];
ans: Level;
success ← TRUE;
ans ← GetLevel[s !IO.EndOfStream, IO.Error => {success ← FALSE; CONTINUE}];
IF NOT success THEN RETURN;
TRUSTED {h.held.val ← ans};
};
InitialBitParse: PROC [node: Node, fmt: Format, p: Ptr, s: STREAM] RETURNS [success: BOOLEAN] = {
h: Holder ← PtrToHolder[p];
ans: Level;
val: ATOM ← Atom.MakeAtom[s.GetID[]];
success ← TRUE;
SELECT val FROM
$steady => ans ← L;
$initial => ans ← X;
$vdd => ans ← H;
$gnd => ans ← L;
ENDCASE => success ← FALSE;
IF NOT success THEN RETURN;
TRUSTED {h.held.val ← ans};
};
LBitFormatValue: PROC [node: Node, fmt: Format, p: Ptr] RETURNS [r: ROPE] = TRUSTED {
h: Holder ← PtrToHolder[p];
r ← Rope.Cat[
strengthToRope[h.held.s[q]],
strengthToRope[h.held.s[u]],
strengthToRope[h.held.s[d]],
levelToRope[h.held.val],
strengthToRope[node.strength]]
.Cat[IF NOT node.XPhobic THEN "*" ELSE IF RoseRun.Delayed[node] THEN "+" ELSE "-"]};
LBitParseValue: PROC [node: Node, fmt: Format, p: Ptr, s: STREAM] RETURNS [success: BOOLEAN] = TRUSTED {
h: Holder ← PtrToHolder[p];
newStrength: Strength;
newSV: SwitchVal ← [];
success ← TRUE;
newSV.s[q] ← GetStrength[s !IO.EndOfStream, IO.Error => {success ← FALSE; CONTINUE}];
IF NOT success THEN RETURN;
newSV.s[u] ← GetStrength[s !IO.EndOfStream, IO.Error => {success ← FALSE; CONTINUE}];
IF NOT success THEN RETURN;
newSV.s[d] ← GetStrength[s !IO.EndOfStream, IO.Error => {success ← FALSE; CONTINUE}];
IF NOT success THEN RETURN;
newSV.val ← GetLevel[s !IO.EndOfStream, IO.Error => {success ← FALSE; CONTINUE}];
IF NOT success THEN RETURN;
newStrength ← GetStrength[s !IO.EndOfStream, IO.Error => {success ← FALSE; CONTINUE}];
IF NOT success THEN RETURN;
IF p = node.valPtr THEN node.strength ← newStrength;
h.held ← newSV;
};
GetLevel: PROC [s: STREAM] RETURNS [l: Level] =
BEGIN
char: CHARACTER;
[] ← s.SkipWhitespace[];
IF s.EndOf[] THEN ERROR IO.EndOfStream[stream: s];
char ← s.GetChar[];
SELECT char FROM
'L => l ← L;
'H => l ← H;
'X => l ← X;
ENDCASE => ERROR IO.Error[stream: s, ec: SyntaxError];
END;
GetStrength: PROC [s: STREAM] RETURNS [strength: Strength] =
BEGIN
char: CHARACTER;
asRope: ROPE;
[] ← s.SkipWhitespace[];
IF s.EndOf[] THEN ERROR IO.EndOfStream[stream: s];
char ← s.GetChar[];
asRope ← Rope.FromChar[char];
FOR strength IN Strength DO
IF strengthToRope[strength].Equal[asRope, FALSE] THEN RETURN;
ENDLOOP;
ERROR IO.Error[stream: s, ec: SyntaxError];
END;
BitFormatTest: PROC [nt: NodeType, fmt: Format, test: NodeTest] RETURNS [r: ROPE] =
BEGIN
r ← SELECT test.data FROM $L => "L", $H => "H", $X => "X", ENDCASE => "??";
END;
BitParseTest: PROC [nt: NodeType, fmt: Format, s: STREAM] RETURNS [success: BOOLEAN, test: NodeTest] =
BEGIN
ans: Level;
success ← TRUE;
ans ← GetLevel[s !IO.EndOfStream, IO.Error => {success ← FALSE; CONTINUE}];
IF NOT success THEN RETURN;
test.proc ← BitTest;
test.data ← SELECT ans FROM L => $L, H => $H, X => $X, ENDCASE => ERROR;
END;
BitTest: PROC [where: Ptr, testData: REF ANY, nodeType: NodeType] RETURNS [passes: BOOLEAN] --NodeTestProc-- =
BEGIN
l: Level ← SELECT testData FROM $L => L, $H => H, $X => X, ENDCASE => ERROR;
TRUSTED {passes ← PtrToHolder[where].held.val = l};
END;
BitMaxWidth: PROC [nt: NodeType, fmt: Format, font: VFonts.Font] RETURNS [INT] =
{RETURN [VFonts.StringWidth["H", font]]};
LBitMaxWidth: PROC [nt: NodeType, fmt: Format, font: VFonts.Font] RETURNS [INT] =
{RETURN [VFonts.StringWidth["555H55+", font]]};
NodeTypeList: TYPE = LIST OF ArrayNodeType;
switchTypes: NodeTypeList ← NIL;
Bundle: PUBLIC PROC [bits: CARDINAL] RETURNS [nt: NodeType] =
BEGIN
FOR it: NodeTypeList ← switchTypes, it.rest WHILE it # NIL DO
IF it.first.length = bits THEN RETURN [it.first];
ENDLOOP;
switchTypes ← CONS[nt ← MakeSwitchOfWidth[bits], switchTypes];
END;
MakeSwitchOfWidth: PROC [bits: CARDINAL] RETURNS [nt: ArrayNodeType] =
BEGIN
nt ← NEW [NodeTypeRep[array] ← [
procs: switchProcs,
typeData: NIL,
simple: FALSE,
structure: array[bits, NARROW[bitType]]]];
END;
switchProcs: NodeProcs ← NEW [NodeProcsRep ← [
UserDescription: SwitchUserDescription,
ListFormats: SwitchListFormats,
GetFormat: SwitchGetFormat,
MesaForSelf: SwitchMesaForSelf,
SelectorOffset: SwitchSelectorOffset,
SubType: SwitchSubType,
Bits: SwitchBits,
MesaRepresentation: SwitchMesaRepresentation,
Equivalent: SwitchEquivalent,
SimpleEquivalent: SwitchSimpleEquivalent,
Transduce: SwitchNumConvert.Transduce,
InitPort: SwitchesInitPort,
InitQ: SwitchesInitQ,
InitUD: SwitchesInitUD,
NewVal: SwitchesNewVal,
CopyVal: SwitchesCopyVal,
NewQ: SwitchesNewQ,
NewUD: SwitchesNewUD,
QFromNode: SwitchesQFromNode,
UDFromNode: SwitchesUDFromNode,
ValFromNode: SwitchesValFromNode,
SetNode: SwitchesSetNode,
CompareUD: SwitchesCompareUD
]];
ConstructSwitchType: RoseTranslateTypes.NodeTypeConstructor--PROC [parms: REF ANY - -UNION [BindingList, Args]- -] RETURNS [type: SwitchType]-- =
BEGIN
bits: Int ← NARROW[RoseTranslateTypes.GetParm[n: 1, name: "bits", parms: parms, default: one]];
type ← Bundle[bits.i];
END;
bpw: NAT = Basics.bitsPerWord;
SwitchUserDescription: PROC [nt: NodeType] RETURNS [ud: ROPE] = {
ant: ArrayNodeType ← NARROW[nt];
ud ← IO.PutFR["Switch[%g]", IO.int[ant.length]]};
SwitchListFormats: PROC [NodeType] RETURNS [l: RopeList] = {l ← sfl};
SwitchGetFormat: PROC [nt: NodeType, key: ROPE] RETURNS [fmt: Format] = {
atom: ATOM ← Atom.MakeAtom[key];
fmt ← NARROW[Atom.GetProp[atom: atom, prop: switchFmtKey]];
};
SwitchMesaForSelf: PROC [nt: NodeType] RETURNS [m: Mesa] = {
ant: ArrayNodeType ← NARROW[nt];
m ← [
mesa: IO.PutFR["SwitchTypes.Bundle[%g]", IO.int[ant.length]],
imports: LIST["SwitchTypes"]]};
SwitchSelectorOffset: PROC [nt: NodeType, s: Selector] RETURNS [o: NAT] = {
o ← WITH s SELECT FROM
number => index*bpw,
whole => 0,
range => bpw*(IF up THEN first ELSE first+1-count),
ENDCASE => ERROR;
};
SwitchSubType: PROC [nt: NodeType, s: Selector] RETURNS [snt: NodeType] = {
snt ← WITH s SELECT FROM
whole => nt,
number => bitType,
range => Bundle[count],
ENDCASE => ERROR;
};
SwitchBits: PROC [nt: NodeType] RETURNS [container, data, leftPad: INT] = {
ant: ArrayNodeType ← NARROW[nt];
container ← bpw*((ant.length + switchValsPerWord -1)/switchValsPerWord);
data ← container;
leftPad ← 0;
};
SwitchMesaRepresentation: PROC [nt: NodeType] RETURNS [m: Mesa] = {
ant: ArrayNodeType ← NARROW[nt];
m ← [
mesa: IO.PutFR["PACKED ARRAY [0 .. %g) OF SwitchTypes.SwitchVal", IO.int[ant.length]],
directory: LIST["SwitchTypes"]]};
sfl: RopeList ← LIST["short", "long"];
switchFmtKey: REF ROPENEW [ROPE ← "Switch Format Key"];
shortSwitchesFormat: Format ← NEW [FormatRep ← [
FormatValue: SwitchesFormatValue,
ParseValue: SwitchesParseValue,
FormatTest: NIL,
ParseTest: NIL,
MaxWidth: SwitchesMaxWidth,
key: "switches"]];
longSwitchesFormat: Format ← NEW [FormatRep ← [
FormatValue: SwitchesLongFormatValue,
ParseValue: SwitchesLongParseValue,
FormatTest: NIL,
ParseTest: NIL,
MaxWidth: SwitchesLongMaxWidth,
key: "long"]];
initSwitchesFormat: Format ← NEW [FormatRep ← [
ParseValue: InitialSwitchesParse,
key: "init"]];
Switches: TYPE = LONG POINTER TO PACKED ARRAY NAT OF SwitchVal;
PtrToSwitches: PROC [p: Ptr] RETURNS [ss: Switches] = {
IF p.bit # 0 THEN ERROR;
TRUSTED {ss ← LOOPHOLE[p.word]}};
SwitchEquivalent: PROC [self, other: NodeType] RETURNS [eqv: BOOL] = {
ant: ArrayNodeType ← NARROW[self];
IF ant.element # bitType THEN ERROR;
eqv ← other = self OR (other = bitType AND ant.length=1);
};
SwitchSimpleEquivalent: PROC [self: NodeType] RETURNS [NodeType] = {
ant: ArrayNodeType ← NARROW[self];
RETURN [NumTypes.NumType[ant.length]]};
SwitchesInitPort: PROC [n: Node, p: Ptr] = TRUSTED {
ant: ArrayNodeType ← NARROW[n.type];
ns: Switches ← PtrToSwitches[n.valPtr];
s: Switches ← PtrToSwitches[p];
FOR i: CARDINAL IN [0 .. ant.length) DO
s[i] ← ns[i];
ENDLOOP};
SwitchesInitQ: PROC [n: Node] = TRUSTED {
ant: ArrayNodeType ← NARROW[n.type];
ns: Switches ← PtrToSwitches[n.valPtr];
FOR i: CARDINAL IN [0 .. ant.length) DO ns[i].s[q] ← n.strength ENDLOOP};
SwitchesInitUD: PROC [n: Node] = TRUSTED {
ant: ArrayNodeType ← NARROW[n.type];
ns: Switches ← PtrToSwitches[n.valPtr];
n.isInput ← TRUE;
FOR i: CARDINAL IN [0 .. ant.length) DO
u, d: Strength;
[u, d] ← Parts[ns[i].val, n.strength];
ns[i].s[u] ← Block[u, ns[i].s[q]];
ns[i].s[d] ← Block[d, ns[i].s[q]];
n.isInput ← n.isInput AND ns[i].s[q] = input;
ENDLOOP};
SwitchesNewVal: PROC [n: Node] RETURNS [delay: BOOL] = TRUSTED {
ant: ArrayNodeType ← NARROW[n.type];
ns: Switches ← PtrToSwitches[n.valPtr];
delay ← FALSE;
FOR i: CARDINAL IN [0 .. ant.length) DO
temp: Level ←
IF ns[i].s[u] = none AND ns[i].s[d] > none THEN L ELSE
IF ns[i].s[d] = none AND ns[i].s[u] > none THEN H ELSE
X;
IF n.XPhobic AND temp = X THEN delay ← TRUE ELSE ns[i].val ← temp;
ENDLOOP;
};
SwitchesCopyVal: PROC [nt: NodeType, from, to: Ptr] = TRUSTED {
ant: ArrayNodeType ← NARROW[nt];
sFrom: Switches ← PtrToSwitches[from];
sTo: Switches ← PtrToSwitches[to];
FOR i: INTEGER IN [0 .. ant.length) DO
sTo[i].val ← sFrom[i].val;
ENDLOOP};
SwitchesNewQ: PROC [n: Node, p: Ptr] RETURNS [b: BOOLEAN] = TRUSTED {
ant: ArrayNodeType ← NARROW[n.type];
ns: Switches ← PtrToSwitches[n.valPtr];
s: Switches ← PtrToSwitches[p];
b ← FALSE;
FOR i: CARDINAL IN [0 .. ant.length) DO
IF s[i].s[q]>ns[i].s[q] THEN {ns[i].s[q] ← s[i].s[q]; b ← TRUE};
ENDLOOP};
SwitchesNewUD: PROC [n: Node, p: Ptr] RETURNS [b: BOOLEAN] = TRUSTED {
ant: ArrayNodeType ← NARROW[n.type];
ns: Switches ← PtrToSwitches[n.valPtr];
s: Switches ← PtrToSwitches[p];
b ← FALSE;
FOR i: CARDINAL IN [0 .. ant.length) DO
u: Strength ← Block[s[i].s[u], ns[i].s[q]];
d: Strength ← Block[s[i].s[d], ns[i].s[q]];
IF u > ns[i].s[u] THEN {ns[i].s[u] ← u; b ← TRUE};
IF d > ns[i].s[d] THEN {ns[i].s[d] ← d; b ← TRUE};
ENDLOOP};
SwitchesQFromNode: PROC [n: Node, to: Ptr] = TRUSTED {
ant: ArrayNodeType ← NARROW[n.type];
ns: Switches ← PtrToSwitches[n.valPtr];
s: Switches ← PtrToSwitches[to];
FOR i: CARDINAL IN [0 .. ant.length) DO s[i].s[q] ← ns[i].s[q] ENDLOOP};
SwitchesUDFromNode: PROC [n: Node, to: Ptr] = TRUSTED {
ant: ArrayNodeType ← NARROW[n.type];
ns: Switches ← PtrToSwitches[n.valPtr];
s: Switches ← PtrToSwitches[to];
FOR i: CARDINAL IN [0 .. ant.length) DO
s[i].s[u] ← ns[i].s[u];
s[i].s[d] ← ns[i].s[d];
ENDLOOP};
SwitchesValFromNode: PROC [n: Node, to: Ptr] = TRUSTED {
ant: ArrayNodeType ← NARROW[n.type];
ns: Switches ← PtrToSwitches[n.valPtr];
s: Switches ← PtrToSwitches[to];
FOR i: CARDINAL IN [0 .. ant.length) DO s[i].val ← ns[i].val ENDLOOP};
SwitchesSetNode: PROC [n: Node, to: Ptr] = TRUSTED {
ant: ArrayNodeType ← NARROW[n.type];
ns: Switches ← PtrToSwitches[n.valPtr];
s: Switches ← PtrToSwitches[to];
FOR i: CARDINAL IN [0 .. ant.length) DO ns[i] ← s[i] ENDLOOP};
SwitchesCompareUD: PROC [nt: NodeType, p1, p2: Ptr] RETURNS [diff: BOOL] = TRUSTED {
ant: ArrayNodeType ← NARROW[nt];
s1: Switches ← PtrToSwitches[p1];
s2: Switches ← PtrToSwitches[p2];
FOR i: NAT IN [0 .. ant.length) DO
IF s1[i].s[u] # s2[i].s[u] OR s1[i].s[d] # s2[i].s[d] THEN RETURN [TRUE];
ENDLOOP;
diff ← FALSE};
SwitchesLongFormatValue: PROC [node: Node, fmt: Format, p: Ptr] RETURNS [rope: ROPE] = TRUSTED {
ant: ArrayNodeType ← NARROW[node.type];
s: Switches ← PtrToSwitches[p];
rope ← "";
FOR i: INTEGER IN [0 .. ant.length) DO
rope ← rope.Cat[
strengthToRope[s[i].s[q]],
strengthToRope[s[i].s[u]],
strengthToRope[s[i].s[d]],
levelToRope[s[i].val]];
ENDLOOP;
rope ← rope.Cat[
strengthToRope[node.strength],
IF NOT node.XPhobic THEN "*" ELSE IF RoseRun.Delayed[node] THEN "+" ELSE "-"];
};
SwitchSeq: TYPE = RECORD [switches: PACKED SEQUENCE length: NAT OF SwitchVal];
SwitchesLongParseValue: PROC [node: Node, fmt: Format, p: Ptr, s: STREAM] RETURNS [success: BOOLEAN] = TRUSTED {
ant: ArrayNodeType ← NARROW[node.type];
ss: Switches ← PtrToSwitches[p];
bits: INTEGER ← ant.length;
newStrength: Strength;
ts: REF SwitchSeq ← NEW [SwitchSeq[bits]];
success ← TRUE;
FOR i: INTEGER IN [0 .. bits) DO
ts[i].s[q] ← GetStrength[s !IO.EndOfStream, IO.Error => {success ← FALSE; CONTINUE}];
IF NOT success THEN RETURN;
ts[i].s[u] ← GetStrength[s !IO.EndOfStream, IO.Error => {success ← FALSE; CONTINUE}];
IF NOT success THEN RETURN;
ts[i].s[d] ← GetStrength[s !IO.EndOfStream, IO.Error => {success ← FALSE; CONTINUE}];
IF NOT success THEN RETURN;
ts[i].val ← GetLevel[s !IO.EndOfStream, IO.Error => {success ← FALSE; CONTINUE}];
IF NOT success THEN RETURN;
ENDLOOP;
newStrength ← GetStrength[s !IO.EndOfStream, IO.Error => {success ← FALSE; CONTINUE}];
IF NOT success THEN RETURN;
FOR i: INTEGER IN [0 .. bits) DO ss[i] ← ts[i] ENDLOOP;
IF p = node.valPtr THEN {node.strength ← newStrength};
};
SwitchesLongMaxWidth: PROC [nt: NodeType, fmt: Format, font: VFonts.Font] RETURNS [INT] =
BEGIN
ant: ArrayNodeType ← NARROW[nt];
bits: INTEGER ← ant.length;
RETURN [VFonts.StringWidth["555H", font]*bits + VFonts.StringWidth["55+", font]]
END;
InitialSwitchesParse: PROC [node: Node, fmt: Format, p: Ptr, s: STREAM] RETURNS [success: BOOLEAN] =
BEGIN
ant: ArrayNodeType ← NARROW[node.type];
ss: Switches ← PtrToSwitches[p];
bits: INTEGER ← ant.length;
atom: ATOM ← Atom.MakeAtom[s.GetID[]];
val: Level;
success ← TRUE;
SELECT atom FROM
$initial => val ← X;
$steady => val ← L;
$vdd => val ← H;
$gnd => val ← L;
ENDCASE => success ← FALSE;
IF NOT success THEN RETURN;
FOR i: INTEGER IN [0 .. bits) DO
TRUSTED {ss[i].val ← val};
ENDLOOP;
END;
SwitchesFormatValue: PROC [node: Node, fmt: Format, p: Ptr] RETURNS [rope: ROPE] = {
ant: ArrayNodeType ← NARROW[node.type];
ss: Switches ← PtrToSwitches[p];
bits: INTEGER ← ant.length;
rope ← "";
FOR i: INTEGER IN [0 .. bits) DO
TRUSTED {rope ← rope.Cat[levelToRope[ss[i].val]]};
ENDLOOP;
};
levelToRope: ARRAY Level OF ROPE ← ["L", "H", "X"];
strengthToRope: ARRAY Strength OF ROPE ← ["2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];
SwitchesParseValue: PROC [node: Node, fmt: Format, p: Ptr, s: STREAM] RETURNS [success: BOOLEAN] =
BEGIN
ant: ArrayNodeType ← NARROW[node.type];
ss: Switches ← PtrToSwitches[p];
bits: INTEGER ← ant.length;
success ← TRUE;
FOR i: INTEGER IN [0 .. bits) DO
l: Level;
l ← GetLevel[s !IO.EndOfStream, IO.Error => {success ← FALSE; CONTINUE}];
IF NOT success THEN RETURN;
TRUSTED {ss[i].val ← l};
ENDLOOP;
END;
SwitchesMaxWidth: PROC [nt: NodeType, fmt: Format, font: VFonts.Font] RETURNS [INT] =
BEGIN
ant: ArrayNodeType ← NARROW[nt];
bits: INTEGER ← ant.length;
RETURN [VFonts.StringWidth["H", font]*bits]
END;
BSwitchFormatValue: PROC [node: Node, fmt: Format, p: Ptr] RETURNS [rope: ROPE] =
BEGIN
ant: ArrayNodeType ← NARROW[node.type];
ss: Switches ← PtrToSwitches[p];
bits: INTEGER ← ant.length;
base: CARDINALNARROW[fmt.formatData, REF CARDINAL]^;
bitsPerDigit: CARDINAL ← bitsPerBase[base];
digits: INTEGER ← (bits + bitsPerDigit - 1) / bitsPerDigit;
rope ← baseKeys[base];
FOR d: INTEGER IN [0 .. digits) DO
r: INTEGER ← bits - d * bitsPerDigit;
n: CARDINAL ← 0;
xless: BOOLTRUE;
FOR i: INTEGER IN [MAX[r - bitsPerDigit, 0] .. r) DO
n ← n + n;
TRUSTED {SELECT ss[i].val FROM
L => NULL;
X => xless ← FALSE;
H => n ← n + 1;
ENDCASE => ERROR};
ENDLOOP;
rope ← (IF xless THEN encode[n] ELSE "?").Concat[rope];
ENDLOOP;
END;
baseKeys: ARRAY [2 .. 16] OF ROPE = ["B", "R3", "R4", "R5", "R6", "R7", "O", "R9", "D", "R11", "R12", "R13", "R14", "R15", "H"];
numToLevel: ARRAY [0 .. 1] OF Level = [L, H];
bitsPerBase: ARRAY [2 .. 16] OF CARDINAL = [1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4];
decode: ARRAY CHARACTER OF [0..16] ← ALL[16];
encode: ARRAY [0..16) OF ROPE = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];
BSwitchParseValue: PROC [node: Node, fmt: Format, p: Ptr, s: STREAM] RETURNS [success: BOOLEAN] =
BEGIN
ant: ArrayNodeType ← NARROW[node.type];
ss: Switches ← PtrToSwitches[p];
bits: INTEGER ← ant.length;
rope: ROPE ← s.GetTokenRope[IO.IDProc].token;
rlen, rend: INTEGER ← rope.Length[];
base: CARDINAL ← 0;
fb: REF CARDINALNARROW[fmt.formatData];
bitsPerDigit: CARDINAL;
IF rlen < 1 THEN RETURN [FALSE];
SELECT rope.Fetch[rlen - 1] FROM
'b, 'B => {base ← 2; rend ← rlen - 1};
'o, 'O => {base ← 8; rend ← rlen - 1};
'h, 'H => {base ← 16; rend ← rlen - 1};
'a, 'A, 'c, 'C, 'd, 'D, 'e, 'E, 'f, 'F => {base ← 16};
ENDCASE => {base ← fb^};
bitsPerDigit ← bitsPerBase[base];
FOR d: INT IN [1 .. rend] DO
c: CHAR ← rope.Fetch[rend - d];
digit: [0 .. 16] ← decode[c];
x: BOOL ← c = 'x OR c = 'X;
IF (digit > base) AND (NOT x) THEN RETURN [FALSE];
ENDLOOP;
FOR d: INT IN [1 .. rend] DO
c: CHAR ← rope.Fetch[rend - d];
digit: [0 .. 16] ← decode[c];
x: BOOL ← c = 'x OR c = 'X;
FOR b: CARDINAL IN [1 .. bitsPerDigit] DO
l: Level ← IF x THEN X ELSE numToLevel[digit MOD 2];
i: INTEGER ← bits - (d-1)*bitsPerDigit - b;
next: [0 .. 16] ← digit / 2;
IF i >= 0 THEN TRUSTED {ss[i].val ← l};
digit ← next;
ENDLOOP;
ENDLOOP;
success ← TRUE;
END;
BSwitchMaxWidth: PROC [nt: NodeType, fmt: Format, font: VFonts.Font] RETURNS [INT] =
BEGIN
ant: ArrayNodeType ← NARROW[nt];
bits: INTEGER ← ant.length;
base: REF CARDINALNARROW[fmt.formatData];
bitsPerDigit: CARDINAL ← bitsPerBase[base^];
digits: INTEGER ← (bits + bitsPerDigit - 1) / bitsPerDigit;
RETURN [VFonts.StringWidth["H", font]*(digits+1)]
END;
AddFormat: PROC [key: ROPE, base: CARDINAL] RETURNS [fmt: Format] =
BEGIN
atom: ATOM ← Atom.MakeAtom[key];
fmt ← NEW [FormatRep ← [
FormatValue: BSwitchFormatValue,
ParseValue: BSwitchParseValue,
FormatTest: NIL,
ParseTest: NIL,
MaxWidth: BSwitchMaxWidth,
formatData: NEW [CARDINAL ← base],
key: key]];
Atom.PutProp[atom: atom, prop: switchFmtKey, val: fmt];
sfl ← CONS[key, sfl];
END;
IsSwitchType: PUBLIC PROC [nt: NodeType] RETURNS [switchy: BOOLEAN] = {
WITH nt SELECT FROM
ant: ArrayNodeType => switchy ← IsSwitchType[ant.element];
ant: AtomNodeType => switchy ← ant = bitType;
ENDCASE => ERROR};
defaultSwitchesFormat: Format ← NIL;
oneBitSwitches: ArrayNodeType ← NARROW[Bundle[1]];
Start: PROC =
BEGIN
FOR c: CARDINAL IN [0..9] DO
decode['0 + c] ← c;
ENDLOOP;
FOR c: CARDINAL IN [0..5] DO
decode['A + c] ← 10 + c;
decode['a + c] ← 10 + c;
ENDLOOP;
Atom.PutProp[atom: $short, prop: switchFmtKey, val: shortSwitchesFormat];
Atom.PutProp[atom: $long, prop: switchFmtKey, val: longSwitchesFormat];
Atom.PutProp[atom: $QUD, prop: switchFmtKey, val: longSwitchesFormat];
Atom.PutProp[atom: $init, prop: switchFmtKey, val: initSwitchesFormat];
[] ← AddFormat["2", 2];
[] ← AddFormat["8", 8];
[] ← AddFormat["16", 16];
defaultSwitchesFormat ← AddFormat["", 16];
SignalTypeRegistration.RegisterNodeTypeConstructor["SWITCH", ConstructSwitchType];
SignalTypeRegistration.RegisterNodeTypeConstructor["BIT", ConstructBitType];
END;
Start[];
END.