[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 ROPE ← NEW [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: CARDINAL ← NARROW[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: BOOL ← TRUE;
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 CARDINAL ← NARROW[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 CARDINAL ← NARROW[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.