singrdk/base/Applications/CHello2/CHello2.sg

709 lines
23 KiB
Plaintext
Raw Normal View History

2008-03-05 09:52:00 -05:00
////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: CHello.cs
//
// Note: Simple Singularity test program.
//
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using Microsoft.Singularity;
using Microsoft.Singularity.Directory;
using Microsoft.Singularity.V1.Services;
using Microsoft.Singularity.Io;
namespace Microsoft.Singularity.Applications
{
public class CHello
{
public static int Main(String[] args)
{
Console.WriteLine("Hello World!");
ProtocolTester.UnitTest_LDPC o = new ProtocolTester.UnitTest_LDPC();
o.Run();
return 0;
}
}
}
namespace Microsoft.SPOT
{
/// <include file='doc\Debug.uex' path='docs/doc[@for="Trace"]/*' />
public abstract class Trace
{
/// <include file='doc\Debug.uex' path='docs/doc[@for="Trace.Print"]/*' />
[System.Diagnostics.ConditionalAttribute("TINYCLR_TRACE")]
static public void Print( string text )
{
Debug.Print( text );
}
}
/// <include file='doc\Debug.uex' path='docs/doc[@for="Debug"]/*' />
public abstract class Debug
{
static public void Print( string text )
{
Console.WriteLine( text );
}
static public void DumpBuffer( byte[] buf, bool fCRC, bool fOffset )
{
if(buf == null) return;
int offset = 0;
int len = buf.Length;
while(len > 0)
{
int row = len > 16 ? 16 : len;
int i;
if(fOffset) Console.Write( "{0:X8}:", offset );
for(i=0; i<16; i++)
{
if(i<row)
{
Console.Write( " {0:X2}", buf[i+offset] );
}
else
{
Console.Write( " " );
}
}
Console.Write( " " );
for(i=0; i<row; i++)
{
byte c = buf[i+offset];
if(c <= 0x1F) c = (byte)'.';
if(c >= 0x7F) c = (byte)'.';
Console.Write( "{0}", (char)c );
}
offset += row;
len -= row;
Console.WriteLine();
}
Console.WriteLine();
}
}
public abstract class Math
{
static System.Random s_rnd = new System.Random();
static public int Random( int modulo )
{
return s_rnd.Next( modulo );
}
}
}
namespace Microsoft.SPOT.Hardware
{
public abstract class Radio
{
static public void XorData( byte[]! left, byte[]! right )
{
for(int i=0; i<left.Length; i++)
{
left[i] ^= right[i];
}
}
}
}
namespace Microsoft.DirectBand
{
internal class CreateNonNullArray<T>
{
T[]! elements;
int count;
public CreateNonNullArray( int n )
{
this.elements = new T[n];
this.count = 0;
base();
}
public void InitNext( T elem )
{
if(this.count < elements.Length)
{
this.elements[this.count++] = elem;
}
else
{
throw new InvalidOperationException( "Too many elements initialized" );
}
}
public T[]! GetArray()
{
if(count != elements.Length)
{
throw new InvalidOperationException("Not all elements initialized");
}
return this.elements;
}
}
public class LDPC
{
public static T[]![]! ConstructArray<T>( int i, int j )
{
CreateNonNullArray<T[]!> nna = new CreateNonNullArray<T[]!>( i );
for(int k=0; k < i; k++)
{
nna.InitNext( new T[j] );
}
return nna.GetArray();
}
static public byte[]![]! Solve( byte[][] dataPackets, byte[][] eccPackets, int[] eccIndex, int totalEccPackets, int totalDataPackets, int missedDataPackets, int receivedEccPackets, int pktLen )
{
// dataPackets x0 = actual N - k data packets received (blanks in the missing locations)
// eccPackets rhs = actual kp EC packets received
// eccIndex gotec = array contains indices of EC packet received
// totalEccPackets M = total length of EC stream
// totalDataPackets N = total length of data stream
// missedDataPackets kk = number of data packets missed
// receivedEccPackets kp = number of EC packets received
// AA = M * N matrix used to get the EC packets at encoder
if(dataPackets == null) throw new NullReferenceException();
if(eccPackets == null) throw new NullReferenceException();
if(eccIndex == null) throw new NullReferenceException();
int maxMN = (totalEccPackets > totalDataPackets) ? totalEccPackets : totalDataPackets;
bool[] pseudo = new bool[maxMN];
int i;
int j;
int k;
for(i=0; i < maxMN; i += 5) pseudo[i] = true;
for(i=0; i < maxMN; i += 7) pseudo[i] = true;
for(i=0; i < maxMN; i += 13) pseudo[i] = true;
for(i=0; i < maxMN; i += 17) pseudo[i] = true;
for(i=0; i < maxMN; i += 19) pseudo[i] = true;
for(i=0; i < maxMN; i += 33) pseudo[i] = true;
for(i=0; i < maxMN; i += 37) pseudo[i] = true;
//bool[][] A = new bool[receivedEccPackets][];
//for(i=0; i < receivedEccPackets; i++)
//{
// A[i] = new bool[missedDataPackets];
//} // The actual matrix to be inverted (submatrix of AA)
bool[]![]! A = ConstructArray<bool>( receivedEccPackets, missedDataPackets );
int[]! miss = new int[missedDataPackets + 1]; // Indices of the missing data packets
int c = 0;
for(i = 0; i < missedDataPackets; i++)
{
while(c < totalDataPackets && dataPackets[c] != null)
{
c++;
}
//Microsoft.SPOT.Debug.Print( "Missing: " + c );
miss[i] = c++;
}
// Get miss array
miss[missedDataPackets] = -1;
for(i=0; i < receivedEccPackets; i++)
{
byte[] t = eccPackets[i]; if(t == null) throw new NullReferenceException();
t = (byte[])t.Clone(); if(t == null) throw new NullReferenceException();
eccPackets[i] = t;
// What's the actual system we have to solve
for(j=0; j < missedDataPackets; j++)
{
int idx = eccIndex[i] + miss[j];
//A[i][j] = AA[eccIndex[i]][miss[j]];
A[i][j] = pseudo[ idx < maxMN ? idx : idx - maxMN ];
}
}
for(j = 0; j < totalDataPackets; j++)
{
byte[] dataPacket = dataPackets[j];
if(dataPacket != null)
{
// Packet j is not a missing packet
for(i = 0; i < receivedEccPackets; i++)
{
int idx = eccIndex[i] + j;
if(pseudo[ idx < maxMN ? idx : idx - maxMN ]) /*AA[eccIndex[i]][j]*/
{
//Microsoft.SPOT.Debug.Print( "XOR: eccPackets[" + i + "], dataPackets[" + j + "]" );
byte[] eccPacket = eccPackets[i];
if(eccPacket != null)
{
Microsoft.SPOT.Hardware.Radio.XorData( eccPacket, dataPacket );
}
}
}
}
}
//DumpMatrix( "Beginning:", A, kp, kk );
// Now set up some variables and do the LU decomposition
//byte[][] y = new byte[missedDataPackets+1][]; // Intermediate solution
//byte[][] xhat = new byte[missedDataPackets+1][];
//
//
//for(i=0; i < missedDataPackets+1; i++)
//{
// y [i] = new byte[ pktLen ];
// xhat[i] = new byte[ pktLen ];
//}
byte[]![]! y = ConstructArray<byte>( missedDataPackets+1, missedDataPackets+1 );
byte[]![]! xhat = ConstructArray<byte>( missedDataPackets+1, missedDataPackets+1 );
int i2;
int j2;
int p;
//DumpMatrix( "Beginning:", A, kp, kk );
for(k = 0; k < missedDataPackets; k++)
{
p = k;
// Find a remaining row with non-zero k-th element
while(A[p][k] == false)
{
p++;
if(p == receivedEccPackets)
{
//Microsoft.SPOT.Debug.Print( "Non-triangular matrix?" );
//return null;
throw new Exception( "Non-triangular matrix?" );
}
}
if(p != k)
{
//Microsoft.SPOT.Debug.Print( "Swap: " + p + " " + k );
// Swap row k and row p
for(j2 = 0; j2 < missedDataPackets; j2++)
{
bool temp = A[k][j2];
A[k][j2] = A[p][j2];
A[p][j2] = temp;
}
byte[] packetTemp = eccPackets[k];
eccPackets[k] = eccPackets[p];
eccPackets[p] = packetTemp;
//DumpMatrix( "After:", A, kp, kk );
}
for(i2 = k + 1; i2 < receivedEccPackets; i2++)
{
if(A[i2][k] == A[k][k])
{
//Microsoft.SPOT.Debug.Print( "Mix rows: " + i2 + " " + k );
for(j2 = k + 1; j2 < missedDataPackets; j2++)
{
A[i2][j2] ^= A[k][j2];
}
//DumpMatrix( "After:", A, kp, kk );
}
}
}
//DumpMatrix( "After:", A, kp, kk );
//////////////////////////////////////////////////////////
// Solve Ly = Pb
for(i2 = 0; i2 < missedDataPackets; i2++)
{
y[i2] = (byte[]!)eccPackets[i2];
for(j2 = 0; j2 < i2; j2++)
{
//y[i2] = (sbyte) (((y[i2] ^ (A[i2][j2] * y[j2])) & 0x000000ff));
if(A[i2][j2])
{
//Microsoft.SPOT.Debug.Print( "XOR: y[" + i2 + "], y[" + j2 + "]" );
Microsoft.SPOT.Hardware.Radio.XorData( y[i2], y[j2] );
}
}
}
// Now solve Ux = y
for(i2 = missedDataPackets - 1; i2 >= 0; i2--)
{
xhat[i2] = y[i2];
for(j2 = i2 + 1; j2 < missedDataPackets; j2++)
{
//xhat[i2] = (sbyte) (((xhat[i2] ^ (A[i2][j2] * xhat[j2])) & 0x000000ff));
if(A[i2][j2])
{
//Microsoft.SPOT.Debug.Print( "XOR: xhat[" + i2 + "], xhat[" + j2 + "]" );
Microsoft.SPOT.Hardware.Radio.XorData( xhat[i2], xhat[j2] );
}
}
}
for(i2 = 0; i2 < missedDataPackets; i2++)
{
// Rogue value to indicate non-invertible
if(A[i2][i2] == false)
{
//return null;
throw new Exception( "Non-invertible matrix?" );
}
}
return xhat;
}
static public byte[][] GenerateEC( byte[][] dataPackets, int totalEccPackets, int totalDataPackets, int pktLen )
{
int maxMN = (totalEccPackets > totalDataPackets) ? totalEccPackets : totalDataPackets;
int i;
int j;
if(dataPackets == null) throw new NullReferenceException();
bool[] pseudo = new bool[maxMN];
for(i=0; i < maxMN; i += 5) pseudo[i] = true;
for(i=0; i < maxMN; i += 7) pseudo[i] = true;
for(i=0; i < maxMN; i += 13) pseudo[i] = true;
for(i=0; i < maxMN; i += 17) pseudo[i] = true;
for(i=0; i < maxMN; i += 19) pseudo[i] = true;
for(i=0; i < maxMN; i += 33) pseudo[i] = true;
for(i=0; i < maxMN; i += 37) pseudo[i] = true;
byte[][] eccPackets = new byte[totalEccPackets][];
for(i=0; i < totalEccPackets; i++)
{
eccPackets[i] = new byte[ pktLen ];
}
for(i=0; i < totalEccPackets; i++)
{
// Generate the EC stream
for(j=0; j < totalDataPackets; j++)
{
//ec[i] = (sbyte) (((ec[i] ^ (AA[i][j] * x[j])) & 0x000000ff));
int idx = i + j;
if(pseudo[ idx < maxMN ? idx : idx - maxMN ]) /*AA[i][j]*/
{
byte[] eccPacket = eccPackets[i];
byte[] dataPacket = dataPackets[j];
if(eccPacket != null && dataPacket != null)
{
Microsoft.SPOT.Hardware.Radio.XorData( eccPacket, dataPacket );
}
}
}
}
return eccPackets;
}
}
}
namespace ProtocolTester
{
public class UnitTest_LDPC
{
// main program written by hpleung
// Procedure:
// 1. Generate Random Data Unit
// 2. Generate Error Correction Unit
// 3. Inject Errors in The Random Data Unit
// 4. Decode
// 5. Make sure after decoding data is fully received
// Run it with run.exe nDataPacket nErrorCorrection nPercentageLoss nIteration
//
public void Run()
{
//for quick correctness verification
Microsoft.SPOT.Debug.Print( "LPDC Test Started" );
// for(int i=0; i<100; i++)
// {
// RunPass( 40, 40, 40, 106 );
// }
// return;
for(int nPacketLength=10; nPacketLength <= 120; nPacketLength = nPacketLength + 10)
{
RunPass( nPacketLength, nPacketLength, 40, 106 );
}
}
public void RunPass( int nDataPacketCount, int nErrorCorrectionCount, int nPercentageLoss, int nPacketSize )
{
byte[][] arrDataPacket = new byte[nDataPacketCount][];
byte[][] arrDataReceived = new byte[nDataPacketCount][];
byte[][] arrErrorCorrectionStream = null;
int nDataLossCount = 0;
int i;
//randomly generate some data
PopulatePacket( arrDataPacket, nPacketSize );
for(i=0; i<nDataPacketCount; i++)
{
Randomize( arrDataPacket[i] );
}
Microsoft.SPOT.Debug.Print( "Randomly generated packets" );
//
// Now do the encoding
//
// Generate the full EC stream
//
arrErrorCorrectionStream = Microsoft.DirectBand.LDPC.GenerateEC( arrDataPacket, nErrorCorrectionCount, nDataPacketCount, nPacketSize );
if(arrErrorCorrectionStream == null) throw new NullReferenceException();
Microsoft.SPOT.Debug.Print( "Encoding Finished" );
// we do not like this- we want to make sure we lose
// appropriately the number of packets
// why? Because we want to know exactly how much we lose
// as the cpu utilization depends on the number of packet to correct
int nPacketToLossFix = (nPercentageLoss * nDataPacketCount) / 100;
#if LDPC_DROPINORDER
for(i=0; i<nDataPacketCount; i++)
{
if(i >= nPacketToLossFix)
{
arrDataReceived[i] = arrDataPacket[i];
}
else
{
arrDataReceived[i] = null;
}
}
#else
int nPacketToGet = nDataPacketCount - nPacketToLossFix;
while(nPacketToGet > 0)
{
i = Microsoft.SPOT.Math.Random( nDataPacketCount - 1 );
//Microsoft.SPOT.Debug.Print( "Picked " + i );
if(arrDataReceived[i] == null)
{
arrDataReceived[i] = arrDataPacket[i];
nPacketToGet--;
}
}
#endif
for(i=0; i<nDataPacketCount; i++)
{
if(arrDataReceived[i] == null)
{
nDataLossCount++;
}
}
Microsoft.SPOT.Debug.Print( "We have simulated Packet receiving with loss " + nDataLossCount );
// Now we determine how many EC packet we want to receive
int nErrorPacketToReceive;
if(nDataLossCount * 108 > (nDataLossCount + 5) * 100)
{
nErrorPacketToReceive = (int)((nDataLossCount * 108)/100) ;
}
else
{
nErrorPacketToReceive = nDataLossCount + 5;
}
if(nErrorPacketToReceive > nErrorCorrectionCount)
{
nErrorPacketToReceive = nErrorCorrectionCount;
}
int[]! arrECPacketReceived = new int [nErrorPacketToReceive];
byte[][] arrRHS = new byte[nErrorPacketToReceive][];
// Randomly Pick up Error Packets
for(i=0; i<arrECPacketReceived.Length;i++)
{
int nECPacketPositionReceived = GetNextRandomPosition( arrECPacketReceived, i );
arrRHS [i] = arrErrorCorrectionStream[nECPacketPositionReceived];
arrECPacketReceived[i] = nECPacketPositionReceived;
}
Microsoft.SPOT.Debug.Print( "Error Correction Packet Pickup Simulation Done" );
//--//
//Now let decode it
DateTime start = DateTime.Now;
byte[]![]! arrCorrectedPackets = Microsoft.DirectBand.LDPC.Solve( arrDataReceived ,
arrRHS ,
arrECPacketReceived ,
nErrorCorrectionCount ,
nDataPacketCount ,
nDataLossCount ,
nErrorPacketToReceive ,
nPacketSize );
TimeSpan totalExecutionTime = DateTime.Now - start;
//int calls = Microsoft.SPOT.Hardware.Radio.XorDataCalls;
Microsoft.SPOT.Debug.Print( "Data = " + nDataPacketCount + " EC = " + nErrorCorrectionCount + " Loss = " + nPercentageLoss + " Picked EC = " + nErrorPacketToReceive + " Duration: " + totalExecutionTime.ToString() );
bool bSame = true;
if(arrCorrectedPackets != null)
{
//Microsoft.SPOT.Debug.Print( "Cormac Says : All Data Has Been Recovered" );
int pos = 0;
for(i=0; i<arrDataPacket.Length; i++)
{
if(arrDataReceived[i] == null)
{
if(SameContents( arrCorrectedPackets[pos], arrDataPacket[i] ) == false)
{
Microsoft.SPOT.Debug.Print( "Mismatch: " + i );
Microsoft.SPOT.Debug.DumpBuffer( arrCorrectedPackets[pos], false, true );
Microsoft.SPOT.Debug.DumpBuffer( arrDataPacket [i ], false, true );
bSame = false;
}
pos++;
}
}
}
else
{
bSame = false;
//Microsoft.SPOT.Debug.Print( "Cormac Says: All Data Has not been recovered" );
}
if(bSame)
{
Microsoft.SPOT.Debug.Print( "SUCCESS --- No Mismatch" );
}
else
{
Microsoft.SPOT.Debug.Print( "BUGBUG - We have a mismatch" );
}
//Microsoft.SPOT.Debug.Print( "Total XOR on Packet " + calls );
Microsoft.SPOT.Debug.Print( "" );
}
public int GetNextRandomPosition( int[]! arrECPacketReceived, int nFilled )
{
bool bFound = false;
int nPosition = 0;
while(bFound == false)
{
bFound = true;
nPosition = Microsoft.SPOT.Math.Random( arrECPacketReceived.Length );
//make sure we did not already picked it
for(int i=0;i<nFilled;i++)
{
if(arrECPacketReceived[i] == nPosition)
{
bFound = false;
break;
}
}
}
return nPosition;
}
public void PopulatePacket( byte[][] arrPacket, int nPacketSize )
{
if(arrPacket == null) throw new NullReferenceException();
for(int i=0; i<arrPacket.Length; i++)
{
arrPacket[i] = new byte[ nPacketSize ];
}
}
static int last = 0;
public void Randomize( byte[] data )
{
if(data == null) throw new NullReferenceException();
for(int i=0; i<data.Length; i++)
{
data[i] = (byte)(last+i);//(byte)Microsoft.SPOT.Math.Random( 255 );
}
last++;
}
public bool SameContents( byte[] left, byte[] right )
{
if(left == null) throw new NullReferenceException();
if(right == null) throw new NullReferenceException();
for(int i=0; i<left.Length; i++)
{
if(left[i] != right[i]) return false;
}
return true;
}
}
}