Mult:
CEDAR
PROGRAM
IMPORTS BigCardinals, FS, IO, Random, Rope
EXPORTS =
BEGIN
OPEN TamarinOpsUtils;
mpyCommand: TYPE = MACHINE DEPENDENT {Lower(0), SignedUpper(1), UnSignedUpper(2)};
InitializeFile:
PROC [vStream:
IO.
STREAM] ~ {
IO.PutF[vStream, "0 0 0 60 1f | xxxxxxxx\n"];
IO.PutF[vStream, "0 0 0 60 1f | xxxxxxxx\n\n"];
};
WriteVector:
PROC [vStream:
IO.
STREAM, d1, d2:
CARD, command:
NAT] ~ {
resultH, resultL: TamarinOps.Word;
upperResult: CARD;
resultRope, upperResultRope, lowerResultRope: Rope.ROPE;
bigResult: BigCardinals.BigCARD;
bigD1, bigD2: BigCardinals.BigCARD;
bigD1 ← BigCardinals.BigFromCard[d1];
bigD2 ← BigCardinals.BigFromCard[d2];
bigResult ← BigCardinals.BigMultiply[bigD1, bigD2];
resultRope ← BigCardinals.BigToHexRope[bigResult];
upperResultRope ←
IF (Rope.Length[resultRope] > 8)
THEN
Rope.Substr[resultRope, 0, (Rope.Length[resultRope] - 8)] ELSE "0";
lowerResultRope ←
IF (Rope.Length[resultRope] < 9)
THEN resultRope
ELSE
Rope.Substr[resultRope, (Rope.Length[resultRope] - 8), 8];
SELECT command
FROM
0 => {
-- signed lower mpy
[resultH, resultL] ← TamarinBlocks.Multiplier[CardToWord[d1], CardToWord[d2]];
IO.PutF[vStream, "%x %x 0 60 1f | xxxxxxxx\n", IO.card[d1], IO.card[d2]];
FOR i:
NAT
IN [0..8)
DO
IO.PutF[vStream, "0 0 1 00 7f | xxxxxxxx\n"];
ENDLOOP;
IO.PutF[vStream, "0 0 0 70 0f | "];
IO.PutF[vStream, lowerResultRope];
IO.PutF[vStream, "\n\n"];
};
1 => {
-- Upper signed mpy
[resultH, resultL] ← TamarinBlocks.Multiplier[CardToWord[d1], CardToWord[d2]];
IO.PutF[vStream, "%x %x 0 62 1c | xxxxxxxx\n", IO.card[d1], IO.card[d2]];
FOR i:
NAT
IN [0..8)
DO
IO.PutF[vStream, "0 0 2 00 7f | xxxxxxxx\n"];
ENDLOOP;
IO.PutF[vStream, "0 0 1 00 7f | xxxxxxxx\n"];
IO.PutF[vStream, "0 0 0 70 0f | "];
IO.PutF[vStream, upperResultRope];
IO.PutF[vStream, "\n\n"];
};
2 => {
[resultH, resultL] ← TamarinBlocks.Multiplier[CardToWord[d1], CardToWord[d2]];
IO.PutF[vStream, "%x %x 0 60 1f | xxxxxxxx\n", IO.card[d1], IO.card[d2]];
FOR i: NAT IN [0..8) DO
IO.PutF[vStream, "0 0 2 00 7f | xxxxxxxx\n"];
ENDLOOP;
IO.PutF[vStream, "0 0 1 00 7f | xxxxxxxx\n"];
upperResult ← WordToCard[resultH];
IF (d1 > 7fffffffh) THEN upperResult ← upperResult + d2; -- adjust for unsigned
IO.PutF[vStream, "0 0 0 70 0f | %x\n\n", IO.card[upperResult]];
};
ENDCASE => {
-- do Lower as default
NULL;
[resultH, resultL] ← TamarinBlocks.Multiplier[CardToWord[d1], CardToWord[d2]];
IO.PutF[vStream, "%x %x 0 60 1f | xxxxxxxx\n", IO.card[d1], IO.card[d2]];
FOR i: NAT IN [0..8) DO
IO.PutF[vStream, "0 0 1 00 7f | xxxxxxxx\n"];
ENDLOOP;
IO.PutF[vStream, "0 0 0 70 0f | %x\n\n", IO.card[WordToCard[resultL]]];
};
};
OpenVectorFile:
PROC [fileName: Rope.
ROPE]
RETURNS [vs:
IO.
STREAM]~ {
RETURN [FS.StreamOpen[fileName, $create]];
};
CloseVectorFile:
PROC [vs:
IO.
STREAM] ~ {
IO.PutF[vs, ".\n\n"]; -- Put the end of simulation token
IO.Close[vs];
};
GenerateVector:
PROC [rs: Random.RandomStream]
RETURNS [d1, d2:
CARD, mode:
NAT] ~ {
number: INT;
signD1, signD2: BOOL;
intd1, intd2: INT;
number ← Random.ChooseInt[rs, 0, LAST[INT] - 1];
signD1 ← (number MOD 2) = 0;
number ← Random.ChooseInt[rs, 0, LAST[INT] - 1];
intd1 ← IF signD1 THEN number ELSE -number;
d1 ← LOOPHOLE[intd1, CARD];
number ← Random.ChooseInt[rs, 0, LAST[INT] - 1];
signD2 ← (number MOD 2) = 0;
number ← Random.ChooseInt[rs, 0, LAST[INT] - 1];
intd2 ← IF signD2 THEN number ELSE -number;
d2 ← LOOPHOLE[intd2, CARD];
mode ← Random.ChooseInt[rs, 0, LAST[INT] - 1] MOD 2;
RETURN [d1, d2, mode];
};
vectorFile: Rope.ROPE ← "BigMpyTestVecs.tioga";
vectorStream: IO.STREAM ← NIL;
randomStream: Random.RandomStream;
randSeed: NAT;
numVectors: NAT;
mode: NAT;
d1, d2: CARD;
randSeed ← 0;
numVectors ← 1000;
vectorStream ← OpenVectorFile[vectorFile];
randomStream ← Random.Create[LAST[INT], randSeed];
InitializeFile[vectorStream];
FOR i:
NAT
IN [1..numVectors]
DO
[d1, d2, mode] ← GenerateVector[randomStream];
mode ← 0; -- Testing out only the lower for now
WriteVector[vectorStream, d1, d2, mode];
ENDLOOP;
CloseVectorFile[vectorStream];