URL
https://opencores.org/ocsvn/aemb/aemb/trunk
Subversion Repositories aemb
Compare Revisions
- This comparison shows the changes necessary to convert path
/aemb/trunk/sw/c
- from Rev 106 to Rev 191
- ↔ Reverse comparison
Rev 106 → Rev 191
/aeMB_testbench.c
0,0 → 1,379
/* $Id: aeMB_testbench.c,v 1.15 2008-01-31 19:07:14 sybreon Exp $ |
** |
** AEMB Function Verification C Testbench |
** Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <shawn.tan@aeste.net> |
** |
** This file is part of AEMB. |
** |
** AEMB is free software: you can redistribute it and/or modify it |
** under the terms of the GNU General Public License as published by |
** the Free Software Foundation, either version 3 of the License, or |
** (at your option) any later version. |
** |
** AEMB is distributed in the hope that it will be useful, but WITHOUT |
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
** or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public |
** License for more details. |
** |
** You should have received a copy of the GNU General Public License |
** along with AEMB. If not, see <http://www.gnu.org/licenses/>. |
*/ |
|
#include <malloc.h> |
#include <errno.h> |
#include <reent.h> |
#include <stdlib.h> |
|
#include "libaemb.h" |
|
/** |
INTERRUPT TEST |
|
This tests for the following: |
- Pointer addressing |
- Interrupt handling |
*/ |
|
void __attribute__ ((interrupt_handler)) int_handler(); |
volatile int service = 0xDEADDEAD; |
|
void int_service() |
{ |
int* pio = (int*)0xFFFFFFFC; |
*pio = 0x52544E49; // "INTR" |
service = 0; |
} |
|
void int_handler() |
{ |
int_service(); |
} |
|
/** |
INTERRUPT TEST ROUTINE |
*/ |
int int_test () |
{ |
// Delay loop until hardware interrupt triggers |
volatile int i; |
for (i=0; i < 999; i++) { |
if (service == 0) return 0; |
}; |
|
return -1; |
} |
|
/** |
FIBONACCI TEST |
http://en.literateprograms.org/Fibonacci_numbers_(C) |
|
This tests for the following: |
- Recursion & Iteration |
- 32/16/8-bit data handling |
*/ |
|
unsigned int fib_slow(unsigned int n) |
{ |
return n < 2 ? n : fib_slow(n-1) + fib_slow(n-2); |
} |
|
unsigned int fib_fast(unsigned int n) |
{ |
unsigned int a[3]; |
unsigned int *p=a; |
unsigned int i; |
|
for(i=0; i<=n; ++i) { |
if(i<2) *p=i; |
else { |
if(p==a) *p=*(a+1)+*(a+2); |
else if(p==a+1) *p=*a+*(a+2); |
else *p=*a+*(a+1); |
} |
if(++p>a+2) p=a; |
} |
|
return p==a?*(p+2):*(p-1); |
} |
|
int fib_test(int max) { |
unsigned int n; |
unsigned int fast, slow; |
// 32-bit LUT |
unsigned int fib_lut32[] = { |
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233 |
}; |
// 16-bit LUT |
unsigned short fib_lut16[] = { |
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233 |
}; |
// 8-bit LUT |
unsigned char fib_lut8[] = { |
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233 |
}; |
|
for (n=0;n<max;n++) { |
slow = fib_slow(n); |
fast = fib_fast(n); |
if ((slow != fast) || |
(fast != fib_lut32[n]) || |
(fast != fib_lut16[n]) || |
(fast != fib_lut8[n])) { |
return -1; |
} |
} |
return 0; |
} |
|
/** |
EUCLIDEAN TEST |
http://en.literateprograms.org/Euclidean_algorithm_(C) |
|
This tests for the following: |
- Modulo arithmetic |
- Goto |
*/ |
|
int euclid_gcd(int a, int b) { |
if (b > a) goto b_larger; |
while (1) { |
a = a % b; |
if (a == 0) return b; |
b_larger: |
b = b % a; |
if (b == 0) return a; |
} |
} |
|
int euclid_test(int max) |
{ |
int n; |
int euclid; |
// Random Numbers |
int euclid_a[] = { |
1804289383, 1681692777, 1957747793, 719885386, 596516649, |
1025202362, 783368690, 2044897763, 1365180540, 304089172, |
35005211, 294702567, 336465782, 278722862 |
}; |
int euclid_b[] = { |
846930886, 1714636915, 424238335, 1649760492, 1189641421, |
1350490027, 1102520059, 1967513926, 1540383426, 1303455736, |
521595368, 1726956429, 861021530, 233665123 |
}; |
|
// GCD |
int euclid_lut[] = { |
1, 1, 1, 2, 1, 1, 1, 1, 6, 4, 1, 3, 2, 1 |
}; |
|
for (n=0;n<max;n++) { |
euclid = euclid_gcd(euclid_a[n],euclid_b[n]); |
if (euclid != euclid_lut[n]) { |
return -1; |
} |
} |
return 0; |
} |
|
/** |
NEWTON-RHAPSON |
http://en.literateprograms.org/Newton-Raphson's_method_for_root_finding_(C) |
|
This tests for the following: |
- Multiplication & Division |
- Floating point arithmetic |
- Integer to Float conversion |
*/ |
|
float newton_sqrt(float n) |
{ |
float x = 0.0; |
float xn = 0.0; |
int iters = 0; |
int i; |
for (i = 0; i <= (int)n; ++i) |
{ |
float val = i*i-n; |
if (val == 0.0) |
return i; |
if (val > 0.0) |
{ |
xn = (i+(i-1))/2.0; |
break; |
} |
} |
while (!(iters++ >= 100 |
|| x == xn)) |
{ |
x = xn; |
xn = x - (x * x - n) / (2 * x); |
} |
return xn; |
} |
|
int newton_test (int max) { |
int n; |
float newt; |
// 32-bit LUT |
float newt_lut[] = { |
0.000000000000000000000000, |
1.000000000000000000000000, |
1.414213538169860839843750, |
1.732050776481628417968750, |
2.000000000000000000000000, |
2.236068010330200195312500, |
2.449489831924438476562500, |
2.645751237869262695312500, |
2.828427076339721679687500, |
3.000000000000000000000000, |
3.162277698516845703125000, |
3.316624879837036132812500, |
3.464101552963256835937500, |
3.605551242828369140625000, |
3.741657495498657226562500 |
}; |
|
for (n=0;n<max;n++) { |
newt = newton_sqrt(n); |
if (newt != newt_lut[n]) { |
return -1; |
} |
} |
return 0; |
} |
|
|
/** |
FSL TEST ROUTINE |
*/ |
|
int fsl_test () |
{ |
// TEST FSL1 ONLY |
int FSL = 0xCAFEF00D; |
|
asm ("PUT %0, RFSL1" :: "r"(FSL)); |
asm ("GET %0, RFSL1" : "=r"(FSL)); |
|
if (FSL != 0x01) return -1; |
|
asm ("PUT %0, RFSL31" :: "r"(FSL)); |
asm ("GET %0, RFSL31" : "=r"(FSL)); |
|
if (FSL != 0x1F) return -1; |
|
return 0; |
} |
|
/** |
MALLOC TEST |
Works well with newlib malloc routine. |
*/ |
|
int malloc_test() |
{ |
int *alloc; |
int *mpi = (int*)0xFFFFFFFF; |
alloc = malloc(8 * sizeof(int)); // allocate 32 byte |
*mpi = _REENT->_errno; // for debugging purpose |
return (alloc == NULL) ? -1 : 0; |
} |
|
/** |
MAIN TEST PROGRAMME |
|
This is the main test procedure. It will output signals onto the |
MPI port that is checked by the testbench. |
*/ |
|
int main () |
{ |
// Message Passing Port |
int* mpi = (int*)0xFFFFFFFF; |
|
// Number of each test to run |
int max = 10; |
|
// lock T0 if it's multi-threaded |
/* |
if ((aemb_isthreaded() == 0) && (aemb_isthread1() != 0)) { |
while (1) { |
asm volatile ("nop;"); |
} |
} |
*/ |
|
// Enable Global Interrupts |
aemb_enable_interrupt(); |
|
// INT TEST |
if (int_test() == -1) { *mpi = 0x4641494C; } |
|
// TEST MALLOC |
if (malloc_test() == -1) { *mpi = 0x4641494C; } |
|
// FSL TEST |
//if (fsl_test() == -1) { *mpi = 0x4641494C; } |
|
// Fibonacci Test |
if (fib_test(max) == -1) { *mpi = 0x4641494C; } |
|
// Euclid Test |
if (euclid_test(max) == -1) { *mpi = 0x4641494C; } |
|
// Newton-Rhapson Test |
if (newton_test(max) == -1) { *mpi = 0x4641494C; } |
|
// Disable Global Interrupts |
aemb_disable_interrupt(); |
|
// ALL PASSED |
return 0; |
} |
|
/* |
HISTORY |
$Log: not supported by cvs2svn $ |
Revision 1.14 2007/12/28 21:44:04 sybreon |
Added malloc() test |
|
Revision 1.13 2007/12/11 00:44:31 sybreon |
Modified for AEMB2 |
|
Revision 1.12 2007/11/18 19:41:45 sybreon |
Minor simulation fixes. |
|
Revision 1.11 2007/11/14 23:41:06 sybreon |
Fixed minor interrupt test typo. |
|
Revision 1.10 2007/11/14 22:12:02 sybreon |
Added interrupt test routine. |
|
Revision 1.9 2007/11/09 20:51:53 sybreon |
Added GET/PUT support through a FSL bus. |
|
Revision 1.8 2007/11/03 08:40:18 sybreon |
Minor code cleanup. |
|
Revision 1.7 2007/11/02 18:32:19 sybreon |
Enable MSR_IE with software. |
|
Revision 1.6 2007/04/30 15:57:10 sybreon |
Removed byte acrobatics. |
|
Revision 1.5 2007/04/27 15:17:59 sybreon |
Added code documentation. |
Added new tests that test floating point, modulo arithmetic and multiplication/division. |
|
Revision 1.4 2007/04/25 22:15:05 sybreon |
Added support for 8-bit and 16-bit data types. |
|
Revision 1.3 2007/04/04 14:09:04 sybreon |
Added initial interrupt/exception support. |
|
Revision 1.2 2007/04/04 06:07:45 sybreon |
Fixed C code bug which passes the test |
|
Revision 1.1 2007/03/09 17:41:57 sybreon |
initial import |
*/ |
/libaemb.h
0,0 → 1,215
/* $Id: libaemb.h,v 1.3 2007-12-16 03:26:37 sybreon Exp $ |
** |
** AEMB2 CUSTOM LIBRARY |
** |
** Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <shawn.tan@aeste.net> |
** |
** This file is part of AEMB. |
** |
** AEMB is free software: you can redistribute it and/or modify it |
** under the terms of the GNU Lesser General Public License as |
** published by the Free Software Foundation, either version 3 of the |
** License, or (at your option) any later version. |
** |
** AEMB is distributed in the hope that it will be useful, but WITHOUT |
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
** or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General |
** Public License for more details. |
** |
** You should have received a copy of the GNU Lesser General Public |
** License along with AEMB. If not, see <http:**www.gnu.org/licenses/>. |
*/ |
|
#ifndef LIBAEMB_H |
#define LIBAEMB_H |
|
#define AEMB_TXE 0x0100 |
#define AEMB_TXP 0x0400 |
#define AEMB_TX0 0x0300 |
#define AEMB_TX1 0x0700 |
#define AEMB_MSK 0x0F00 |
|
#define AEMB_BIP 0x0008 |
#define AEMB_CCC 0x0004 |
#define AEMB_ITE 0x0002 |
#define AEMB_BLE 0x0001 |
|
|
// Linker symbols |
extern void* _STACK_SIZE; |
extern void* _stack_end; |
|
|
void aemb_hook_init () asm ("_program_init"); |
void aemb_hook_clean () asm ("_program_clean"); |
|
inline void aemb_enable_interrupt (); |
inline void aemb_disable_interrupt (); |
inline int aemb_isthread1(); |
inline int aemb_isthread0(); |
inline int aemb_isthreaded(); |
|
/*! |
* Assembly macro to enable MSR_IE |
*/ |
void aemb_enable_interrupt () |
{ |
int msr, tmp; |
asm volatile ("mfs %0, rmsr;" |
"ori %1, %0, 0x02;" |
"mts rmsr, %1;" |
: "=r"(msr) |
: "r" (tmp) |
); |
} |
|
/*! |
* Assembly macro to disable MSR_IE |
*/ |
void aemb_disable_interrupt () |
{ |
int msr, tmp; |
asm volatile ("mfs %0, rmsr;" |
"andi %1, %0, 0xFD;" |
"mts rmsr, %1;" |
: "=r"(msr) |
: "r" (tmp) |
); |
} |
|
/*! |
* Bootstrap Hook Override |
*/ |
|
void aemb_hook_init () |
{ |
int msr, tmp; |
int stk_end, stk_siz; |
|
/* |
// Check to see if hardware threads are enabled |
if (((msr & AEMB_TXE) != AEMB_TXE) || |
// Check to see if second thread is started |
((msr & AEMB_TX1) == AEMB_TX1)) return; |
*/ |
//return; |
asm volatile ("mfs %0, rmsr;" |
// Check for BIP |
"andi %1, %0, %5;" |
"xori %1, %1, %5;" |
"beqi %1, 44;" |
|
// Check for TXE |
"andi %1, %0, %2;" |
"xori %1, %1, %2;" |
"bnei %1, 36;" |
|
// Check for TX1 |
"andi %1, %0, %3;" |
"xori %1, %1, %3;" |
"beqi %1, 20;" |
|
// reallocate stack pointer for T0 |
"ori %1, r0, %4;" |
"sra %1, %1;" |
"rsubk r1, %1, r1;" |
|
// reboot the machine |
//"brki r0, _crtinit;" |
"brid 0;" |
"nop;" |
|
// clear BIP |
"andni %1, %0, %5;" |
"mts rmsr, %1;" |
|
:"=r"(msr), "=r"(tmp) |
:"i"(AEMB_TXE), "i"(AEMB_TX1), "i"(&_STACK_SIZE), "i"(AEMB_BIP) |
); |
|
} |
|
/*! |
Undo the changes made by programme init |
*/ |
|
void aemb_hook_clean () |
{ |
int msr, tmp; |
int stk_end, stk_siz; |
|
/* |
// Check to see if hardware threads are enabled |
if (((msr & AEMB_TXE) != AEMB_TXE) || |
// Check to see if second thread is started |
((msr & AEMB_TX1) == AEMB_TX1)) return; |
*/ |
return; |
asm volatile ("mfs %0, rmsr;" |
"andi %1, %0, %2;" |
"xori %1, %1, %2;" |
"bnei %1, 28;" |
"andi %1, %0, %3;" |
"xori %1, %1, %3;" |
"beqi %1, 16;" |
|
// reallocate stack pointer for T0 |
"ori %1, r0, %4;" |
"sra %1, %1;" |
"addk r1, %1, r1;" |
|
:"=r"(msr), "=r"(tmp) |
:"i"(AEMB_TXE), "i"(AEMB_TX1), "i"(&_STACK_SIZE) |
); |
|
|
} |
|
/* Checks if it's T1, and returns 0 if true */ |
|
int aemb_isthread1 () |
{ |
int msr, tmp, res; |
asm volatile ("mfs %0, rmsr;" |
"andi %1, %0, %3;" |
"xori %1, %1, %3;" |
:"=r"(msr), "=r"(tmp) |
:"i"(AEMB_TXE), "i"(AEMB_TXP) |
); |
return tmp; |
} |
|
/* Checks if it's T0, and returns 0 if true */ |
|
int aemb_isthread0 () |
{ |
int msr, tmp, res; |
asm volatile ("mfs %0, rmsr;" |
"andi %1, %0, %3;" |
"xori %1, %1, %2;" |
:"=r"(msr), "=r"(tmp) |
:"i"(AEMB_TXP), "i"(AEMB_MSK) |
); |
return tmp; |
} |
|
/* Checks if TXE is available, and returns 0 if true */ |
|
int aemb_isthreaded () |
{ |
int msr, tmp, res; |
asm volatile ("mfs %0, rmsr;" |
"andi %1, %0, %2;" |
"xori %1, %1, %2;" |
:"=r"(msr), "=r"(tmp) |
:"i"(AEMB_TXE), "i"(AEMB_MSK) |
); |
return tmp; |
} |
|
#endif |
|
/* $Log: not supported by cvs2svn $ |
/* Revision 1.1 2007/12/11 00:44:04 sybreon |
/* initial import |
/* */ |