<Simulation>NewRose>Rosemary.DF>> <> DIRECTORY Inline, IntTypes, Rope, Rosemary, VFonts; IntTypesImpl: CEDAR PROGRAM IMPORTS Inline, Rope, VFonts EXPORTS IntTypes = BEGIN OPEN IntTypes; ROPE: TYPE = Rope.ROPE; WordPtr: TYPE = Rosemary.WordPtr; SignalType: TYPE = Rosemary.SignalType; SignalTypeRep: TYPE = Rosemary.SignalTypeRep; SignalTypeList: TYPE = LIST OF SignalType; WordPair: TYPE = ARRAY [0..1] OF CARDINAL; MaskedValue: TYPE = REF MaskedValueRep; MaskedValueRep: TYPE = RECORD [m, v: Value]; IntData: TYPE = REF IntDataRep; IntDataRep: TYPE = RECORD [bits: CARDINAL]; Bit: PUBLIC SignalType; intTypes: SignalTypeList _ NIL; decode: ARRAY CHARACTER OF [0..16] _ ALL[16]; encode: ARRAY [0..16) OF ROPE _ ALL[NIL]; lowMask, highMask: ARRAY [1..32] OF CARDINAL; verboten: ARRAY [0..16) OF CARDINAL _ [0, 65535-1, 65535-3, 65535-7, 65535-15, 65535-31, 65535-63, 65535-127, 65535-255, 65535-511, 65535-1023, 65535-2047, 65535-4095, 65535-8191, 65535-16383, 32768]; IntNot: PUBLIC PROC [bitWidth: [1..32], bits: LONG CARDINAL] RETURNS [inverted: LONG CARDINAL] = BEGIN LOOPHOLE[inverted, WordPair][0] _ Inline.BITAND[Inline.BITNOT[LOOPHOLE[bits, WordPair][0]], lowMask[bitWidth]]; LOOPHOLE[inverted, WordPair][1] _ Inline.BITAND[Inline.BITNOT[LOOPHOLE[bits, WordPair][1]], highMask[bitWidth]]; END; IntType: PUBLIC PROC [bitWidth: CARDINAL] RETURNS [st: SignalType] = BEGIN FOR it: SignalTypeList _ intTypes, it.rest WHILE it # NIL DO id: IntData _ NARROW[it.first.typeData]; IF id.bits = bitWidth THEN RETURN [it.first]; ENDLOOP; intTypes _ CONS[st _ MakeIntOfWidth[bitWidth], intTypes]; END; MakeIntOfWidth: PROC [bitWidth: CARDINAL] RETURNS [st: SignalType] = BEGIN st _ NEW [SignalTypeRep _ [ toRope: IntToRope, fromRope: IntFromRope, init: NIL, maxWidth: MaxWidthOfInt, parseTest: TestFromRope, unParseTest: TestToRope, typeData: NEW [IntDataRep _ [bitWidth]] ]]; END; MaxWidthOfInt: Rosemary.MaxWidthProc = TRUSTED BEGIN id: IntData _ NARROW[typeData]; RETURN [ --MAX[-- --VFonts.StringWidth["0"]*id.bits + VFonts.StringWidth["B"],-- (VFonts.StringWidth["F", font]*(id.bits+3))/4 + VFonts.StringWidth["H"] --]-- ]; END; TestFromRope: Rosemary.TestParseProc = BEGIN id: IntData _ NARROW[typeData]; wordWidth: CARDINAL _ (id.bits + 15)/16; base, test: CARDINAL; dl, sign: INTEGER _ 1; v: Value _ NEW [ValueRec[0]]; m: Value _ NEW [ValueRec[0]]; IF rope.Length[] < 1 THEN RETURN [FALSE, NIL, NIL] ELSE BEGIN SELECT rope.Fetch[rope.Length[] - 1] FROM 'b, 'B => {base _ 2; dl _ 1}; 'o, 'O => {base _ 8; dl _ 1}; 'd, 'D => {base _ 10; dl _ 1}; 'h, 'H => {base _ 16; dl _ 1}; IN ['2..'9] => {base _ 10; dl _ 0}; 'A, 'a, 'c, 'C, 'e, 'E, 'f, 'F => {base _ 16; dl _ 0}; ENDCASE => {base _ 2; dl _ 0}; FOR i: CARDINAL IN [0 .. rope.Length[] - dl) DO c: CHARACTER _ rope.Fetch[i]; v _ Multiply[v, base]; m _ Multiply[m, base]; IF c = 'x OR c = 'X THEN BEGIN m _ Add[m, base-1]; END ELSE BEGIN d: [0..16] _ decode[c]; IF d > base THEN RETURN [FALSE, NIL, NIL]; v _ Add[v, d]; END; ENDLOOP; END; IF MAX[v.length, m.length] > wordWidth THEN RETURN [FALSE, NIL, NIL]; IF wordWidth < 1 THEN RETURN [FALSE, NIL, NIL]; v _ Truncate[v, wordWidth]; m _ Truncate[m, wordWidth]; test _ Inline.BITAND[v[0], verboten[id.bits MOD 16]]; IF 0 # test THEN RETURN [FALSE, NIL, NIL]; test _ Inline.BITAND[m[0], verboten[id.bits MOD 16]]; IF 0 # test THEN RETURN [FALSE, NIL, NIL]; testData _ NEW [MaskedValueRep _ [m: m, v: v]]; success _ TRUE; testProc _ TestInt; END; TestToRope: Rosemary.TestUnParseProc = BEGIN id: IntData _ NARROW[typeData]; mv: MaskedValue _ NARROW[testData]; IF mv = NIL THEN rope _ "??" ELSE rope _ EncodeMV[mv.m, mv.v, 16, id.bits !CantEncode => {rope _ EncodeMV[mv.m, mv.v, 2, id.bits]; CONTINUE}]; IF subject # NIL THEN rope _ Rope.Cat[subject, "=", rope]; END; CantEncode: ERROR = CODE; EncodeMV: PROC [m, v: Value, base: [2..16], bits: CARDINAL] RETURNS [rope: ROPE] = BEGIN digits: CARDINAL _ (bits + base - 1)/base; rope _ IF base = 16 THEN "H" ELSE IF base = 2 THEN "B" ELSE ERROR; FOR i: CARDINAL IN [1 .. digits] DO vRem, mRem: CARDINAL; [v, vRem] _ DivMod[v, base]; [m, mRem] _ DivMod[m, base]; IF mRem = 0 THEN rope _ encode[vRem].Concat[rope] ELSE IF mRem+1 = base THEN rope _ Rope.Concat["X", rope] ELSE ERROR CantEncode[]; ENDLOOP; END; IntFromRope: Rosemary.FromRopeProc = BEGIN id: IntData _ NARROW[typeData]; wordWidth: CARDINAL _ (id.bits + 15)/16; base, test: CARDINAL; dl, sign: INTEGER _ 1; v: Value _ NEW [ValueRec[0]]; IF rope.Length[] < 1 THEN RETURN [FALSE] ELSE BEGIN SELECT rope.Fetch[rope.Length[] - 1] FROM 'b, 'B => {base _ 2; dl _ 1}; 'o, 'O => {base _ 8; dl _ 1}; 'd, 'D => {base _ 10; dl _ 1}; 'h, 'H => {base _ 16; dl _ 1}; ENDCASE => {base _ 10; dl _ 0}; FOR i: CARDINAL IN [0 .. rope.Length[] - dl) DO c: CHARACTER _ rope.Fetch[i]; IF c = '- THEN sign _ -sign ELSE BEGIN d: [0..16] _ decode[c]; IF d > base THEN RETURN [FALSE]; v _ Add[Multiply[v, base], d]; END; ENDLOOP; END; IF v.length > wordWidth THEN RETURN [FALSE]; IF wordWidth < 1 THEN RETURN [TRUE]; v _ Truncate[v, wordWidth]; test _ Inline.BITAND[v[0], verboten[id.bits MOD 16]]; IF 0 # test THEN RETURN [FALSE]; ValueToWP[v, where, wordWidth]; success _ TRUE; END; IntToRope: Rosemary.ToRopeProc = BEGIN id: IntData _ NARROW[typeData]; wordWidth: CARDINAL _ (id.bits + 15)/16; digits: CARDINAL _ (id.bits + 3)/4; v: Value _ ValueFromWP[where, wordWidth]; rope _ "H"; FOR i: CARDINAL IN [1 .. digits] DO rem: CARDINAL; [v, rem] _ DivMod[v, 16]; rope _ encode[rem].Concat[rope]; ENDLOOP; END; TestInt: Rosemary.TestProc = TRUSTED BEGIN id: IntData _ NARROW[typeData]; mv: MaskedValue _ NARROW[testData]; other: CARDINAL _ verboten[id.bits MOD 16]; wordCount: CARDINAL _ (id.bits+15)/16; wmo: CARDINAL _ wordCount - 1; IF wordCount < 1 THEN ERROR; IF wordCount # mv.v.length THEN RETURN [FALSE]; IF wordCount # mv.m.length THEN RETURN [FALSE]; FOR i: CARDINAL IN [0..wordCount) DO diff: CARDINAL _ Inline.BITXOR[mv.v[wmo - i], (where+i)^]; diff _ Inline.BITAND[diff, Inline.BITNOT[Inline.BITOR[other, mv.m[i]]]]; IF diff # 0 THEN RETURN [FALSE]; other _ 0; ENDLOOP; passes _ TRUE; END; ValueToWP: PROC [v: Value, wp: WordPtr, words: CARDINAL] = TRUSTED BEGIN wmo: CARDINAL _ words - 1; IF words < 1 THEN ERROR; FOR i: CARDINAL IN [0..words) DO (wp+i)^ _ v[wmo - i] ENDLOOP; END; ValueFromWP: PROC [wp: WordPtr, words: CARDINAL] RETURNS [v: Value] = TRUSTED BEGIN wmo: CARDINAL _ words - 1; IF words < 1 THEN ERROR; v _ NEW [ValueRec[words]]; FOR i: CARDINAL IN [0..words) DO v[wmo - i] _ (wp+i)^ ENDLOOP; END; Value: TYPE = REF ValueRec; ValueRec: TYPE = RECORD [chunks: SEQUENCE length: CARDINAL OF CARDINAL]; < decreasing significance>> Multiply: PROC [v: Value, f: CARDINAL] RETURNS [p: Value] = BEGIN prod: LONG CARDINAL _ 0; p _ NEW [ValueRec[v.length + 1]]; FOR i: CARDINAL DECREASING IN [0..p.length) DO IF i > 0 THEN prod _ prod + LONG[v[i-1]] * f; p[i] _ prod MOD 65536; prod _ prod / 65536; ENDLOOP; p _ Truncate[p, Significance[p]]; END; DivMod: PROC [v: Value, d: CARDINAL] RETURNS [q: Value, rem: CARDINAL] = BEGIN r: LONG CARDINAL _ 0; q _ NEW[ValueRec[v.length]]; FOR i: CARDINAL IN [0..v.length) DO prod: LONG CARDINAL _ d; r _ r * 65536 + v[i]; q[i] _ r/d; r _ r - prod * q[i]; ENDLOOP; rem _ r; q _ Truncate[q, Significance[q]]; END; Add: PROC [v: Value, s: CARDINAL] RETURNS [w: Value] = BEGIN carry: LONG CARDINAL _ s; w _ NEW[ValueRec[v.length + 1]]; FOR i: CARDINAL DECREASING IN [0..w.length) DO IF i > 0 THEN carry _ carry + v[i-1]; w[i] _ carry MOD 65536; carry _ carry / 65536; ENDLOOP; w _ Truncate[w, Significance[w]]; END; Significance: PROC [v: Value] RETURNS [s: CARDINAL] = BEGIN FOR s IN [0..v.length) DO IF v[s] # 0 THEN RETURN [v.length - s]; ENDLOOP; s _ 0; END; Truncate: PROC [v: Value, len: CARDINAL] RETURNS [w: Value] = BEGIN w _ NEW [ValueRec[len]]; FOR i: CARDINAL IN (0..len] DO w[len - i] _ IF i <= v.length THEN v[v.length - i] ELSE 0; ENDLOOP; END; Setup: PROC = BEGIN n: CARDINAL _ 1; lowMask _ ALL[65535]; highMask _ ALL[0]; FOR i: CARDINAL IN [1 .. 16] DO highMask[16+i] _ lowMask[i] _ n; n _ n + n + 1; ENDLOOP; 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; encode _ ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"]; Bit _ IntType[1]; END; Setup[]; END.