package wcet.mrtc;
//import edu.uci.eecs.doc.clepsydra.loop.LoopBound;
/**
* A demonstration for CRC (Cyclic Redundancy Check) operation on 40 bytes of data.
* The CRC is manipulated as two functions, icrc1 and icrc. icrc1 is for one
* character and icrc uses icrc1 for a string. The input string is stored in array
* lin[]. icrc is called two times, one for X-Modem string CRC and the other for
* X-Modem packet CRC.
*
* WCET aspect: Complex loops, lots of decisions, loop bounds depend on function
* arguments, function that executes differently the first time it is called.
*
* Ported from C code written by Sung-Soo Lim for the SNU-RT benchmark suite with
* modifications by Jan Gustafsson. See <a
* href="http://www.mrtc.mdh.se/projects/wcet/benchmarks.html">Maelardalen WCET
* Benchmarks</a>.
*/
public class CyclicRedundancyCheck
{
private static final byte[] it = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15};
// FIXME: The original C code used unsigned char and unsigned short types for these fields. They were changed to int types in the Java version to prevent casting to char/short/int, which currently causes problems for the Clepsydra WCET analyzer. However, this is wasteful of memory because int types take up 32 bits while chars take up 8 and shorts 16.
private int[] lin;
private int[] icrctb;
private int[] rchr;
private boolean initialized;
public CyclicRedundancyCheck()
{
lin = new int[256];
icrctb = new int[256];
rchr = new int[256];
// Convert the character string to an integer array
byte[] linBytes = "asdffeagewaHAFEFaeDsFEawFdsFaefaeerdjgp".getBytes();
for (int i = 0; i < linBytes.length; i++)
{
lin[i] = linBytes[i];
}
}
private int loByte(int x)
{
return x & 0xFF;
}
private int hiByte(int x)
{
return x >> 8;
}
private int icrc1(int crc, int onech)
{
int ans = crc ^ onech << 8;
//@LoopBound(max=8)
for (int i = 0; i < 8; i++) // @WCA loop=8
{
// In the code below, masking off the lower 16 bits simulates
// the 16-bit overflow on the left shift that occurs implicitly
// in the original C code as a result of the 16-bit short integer
// data type.
if ((ans & 0x8000) != 0)
{
ans = ((ans <<= 1) & 0xFFFF) ^ 4129;
}
else
{
ans = (ans << 1) & 0xFFFF;
}
}
return ans;
}
private int icrc(int crc, int len, int jinit, int jrev)
{
int tmp1, tmp2, j, cword = crc;
if (!initialized)
{
initialized = true;
//@LoopBound(max=256)
for (j = 0; j <= 255; j++) // @WCA loop=256
{
icrctb[j] = icrc1(j << 8, 0);
rchr[j] = it[j & 0xF] << 4 | it[j >> 4];
}
}
if (jinit >= 0)
{
cword = jinit | (jinit << 8);
}
else if (jrev < 0)
{
cword = rchr[hiByte(cword)] | rchr[loByte(cword)] << 8;
}
//@LoopBound(max=42) // Maximum value depends on input parameter
for (j = 1; j <= len; j++) // @WCA loop=42
{
if (jrev < 0)
{
tmp1 = rchr[lin[j]] ^ hiByte(cword);
}
else
{
tmp1 = lin[j] ^ hiByte(cword);
}
cword = icrctb[tmp1] ^ loByte(cword) << 8;
}
if (jrev >= 0)
{
tmp2 = cword;
}
else
{
tmp2 = rchr[hiByte(cword)] | rchr[loByte(cword)] << 8;
}
return tmp2;
}
public void crc(int i[])
{
int i1, i2;
int n;
n = 40;
lin[n + 1] = 0;
i1 = icrc(0, n, 0, 1);
lin[n + 1] = hiByte(i1);
lin[n + 2] = loByte(i1);
i2 = icrc(i1, n + 2, 0, 1);
i[0] = i1;
i[1] = i2;
}
public static void main(String[] args)
{
int[] i = new int[2];
CyclicRedundancyCheck crc = new CyclicRedundancyCheck();
crc.crc(i);
System.out.println("i1=" + i[0]);
System.out.println("i2=" + i[1]);
}
}