initial commit

This commit is contained in:
Max 2024-12-16 10:04:11 +08:00
commit fe6046f6ee
22 changed files with 2092 additions and 0 deletions

7
.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
*.a
*.so
*.o
*.o.*
*.elf
tags
TAGS

42
Makefile Normal file
View file

@ -0,0 +1,42 @@
CROSS_COMPILE :=
CC := $(CROSS_COMPILE)gcc
OBJDUMP := $(CROSS_COMPILE)objdump
AR := $(CROSS_COMPILE)ar
# CFLAGS =-march=rv64gcv -mabi=lp64d
CFLAGS += -I./
CFLAGS += -Itcm/
CFLAGS += -Iudma/
TCM_SRC=tcm/tcm.c
DMA_SRC=udma/udma.c
AIMM_SRC=aimm.c
TESTS_SRC= tests/tcm_test.c
# tests/tcm_thread.c \
# tests/tcm_malloc.c \
# tests/tcm_rand_access.c
CSRC= time_us.c \
main.c
all:
@echo Build...
@$(CC) -o tcm.o -c $(TCM_SRC) $(CFLAGS)
@$(CC) -o udma.o -c $(DMA_SRC) $(CFLAGS)
@$(CC) -o aimm.o -c $(AIMM_SRC) $(CFLAGS)
@$(AR) rcs libaimm.a aimm.o udma.o tcm.o
@$(CC) -g -Og -o app.elf $(CSRC) $(TESTS_SRC) $(CFLAGS) -static -lpthread -L. -laimm
clean:
rm -f *.o;
rm -f *.out;
rm -f *.elf;
rm -f *.i;
rm -f *.s;
rm -f *.a;
rm -f *.so;

90
aimm.c Normal file
View file

@ -0,0 +1,90 @@
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include "tcm.h"
#include "udma.h"
#define TCM_MALLOC_SIZE (128*1024)
int aimm_init(void)
{
if (tcm_init() < 0) return -1;
if (udma_init() < 0) return -1;
return 0;
}
int aimm_deinit(void)
{
tcm_deinit();
udma_deinit();
return 0;
}
void *aimm_tcm_malloc(size_t size)
{
if (size % TCM_MALLOC_SIZE != 0) {
return NULL;
}
return tcm_malloc(size);
}
void *aimm_tcm_malloc_sync(size_t size, int timeout)
{
if (size % TCM_MALLOC_SIZE != 0) {
return NULL;
}
return tcm_malloc_sync(size, timeout);
}
void *aimm_dram_malloc(size_t size)
{
return udma_malloc(size);
}
void *aimm_dram_realloc(void *ptr, size_t size)
{
udma_free(ptr);
return udma_malloc(size);
}
void *aimm_tcm_calloc(size_t nmemb, size_t size)
{
if ((size * nmemb) % TCM_MALLOC_SIZE != 0) {
return NULL;
}
return tcm_calloc(nmemb, size);
}
void *aimm_dram_calloc(size_t nmemb, size_t size)
{
return udma_malloc(nmemb * size);
}
void aimm_tcm_free(void *ptr)
{
tcm_free(ptr);
}
void aimm_dram_free(void *ptr)
{
udma_free(ptr);
}
void *aimm_memcpy(void *dst, void *src, size_t size)
{
// only support dram ---> tcm
if (is_tcm_mm(dst) != 0 || is_udma_mm(src) != 0) {
return NULL;
}
return udma_memcpy(dst, src, size);
}

65
aimm.h Normal file
View file

@ -0,0 +1,65 @@
#ifndef __AIMM_H__
#define __AIMM_H__
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
int aimm_init(void);
/**
\brief De-initialize Tcm Interface.
\param[in] None
\return Error code
*/
int aimm_deinit(void);
/**
\brief Allocates size bytes and returns a pointer to the allocated memory
\param[in] size allocated memory size(bytes)
\param[in] timeout allocated wait time(ms)
\return a pointer to the allocated memory
*/
void *aimm_tcm_malloc(size_t size);
void *aimm_dram_malloc(size_t size);
void *aimm_tcm_malloc_sync(size_t size, int timeout);
/**
\brief Changes the size of the memory block pointed to by ptr to size bytes
\param[in] ptr an old pointer to the allocated memory
\param[in] size allocated memory size(bytes)
\return a new pointer to the allocated memoryError code
*/
void *aimm_tcm_realloc(void *ptr, size_t size);
void *aimm_dram_realloc(void *ptr, size_t size);
/**
\brief Allocates memory for an array of nmemb elements of size bytes each and returns a pointer to the allocated memory
\param[in] nmenb nmemb elements
\param[in] size allocated memory size(bytes)
\return a pointer to the allocated memoryError code
*/
void *aimm_tcm_calloc(size_t nmemb, size_t size);
void *aimm_dram_calloc(size_t nmemb, size_t size);
/**
\brief Frees the memory space pointed to by ptr
\param[in] ptr a pointer to the allocated memoryError code
\return None
*/
void aimm_tcm_free(void *ptr);
void aimm_dram_free(void *ptr);
/**
\brief Frees the memory space pointed to by ptr
\param[in] ptr a pointer to the allocated memoryError code
\return None
*/
void *aimm_memcpy(void *dst, void *src, size_t size);
#ifdef __cplusplus
}
#endif
#endif

89
list.h Normal file
View file

@ -0,0 +1,89 @@
#ifndef __AIMM_LIST_H__
#define __AIMM_LIST_H__
#ifdef __cplusplus
extern "C" {
#endif
struct list_head {
struct list_head *next, *prev;
};
#define offsetof(type, member) ((size_t)&(((type *)0)->member))
#define container_of(ptr, type, member) \
((type *) ((char *) (ptr) - offsetof(type, member)))
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
#define list_next_entry(pos, member) \
list_entry((pos)->member.next, typeof(*(pos)), member)
#define list_for_each_entry(pos, head, member) \
for (pos = list_first_entry(head, typeof(*pos), member); \
&pos->member != (head); \
pos = list_next_entry(pos, member))
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_first_entry(head, typeof(*pos), member), \
n = list_next_entry(pos, member); \
&pos->member != (head); \
pos = n, n = list_next_entry(n, member))
#define list_prev_entry(pos, member) \
list_entry((pos)->member.prev, typeof(*(pos)), member)
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
static void __list_add(struct list_head *node, struct list_head *prev, struct list_head *next)
{
node->next = next;
node->prev = prev;
prev->next = node;
next->prev = node;
}
static void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
static void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
static void list_del(struct list_head *node)
{
struct list_head *prev = node->prev;
struct list_head *next = node->next;
prev->next = next;
next->prev = prev;
}
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
#ifdef __cplusplus
}
#endif
#endif

76
main.c Normal file
View file

@ -0,0 +1,76 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sched.h>
#include "aimm.h"
#define TCM_BUF_SIZE (1024*128*4)
#define DRAM_BUF_SIZE (1024*1024*12)
int main(void)
{
aimm_init();
cpu_set_t mask;
CPU_ZERO(&mask);
// 绑定到四个AICPU核心
CPU_SET(0, &mask);
CPU_SET(1, &mask);
CPU_SET(2, &mask);
CPU_SET(3, &mask);
// 获取当前进程ID
pid_t pid = getpid();
// 设置CPU亲和性
if (sched_setaffinity(pid, sizeof(cpu_set_t), &mask) == -1) {
perror("sched_setaffinity");
return 1;
}
char *tcm = aimm_tcm_malloc(TCM_BUF_SIZE);
char *dram = malloc(DRAM_BUF_SIZE);//aimm_dram_malloc(DRAM_BUF_SIZE);
if (!tcm || !dram) {
printf("aimm malloc failed(tcm:%lx)(dram:%lx)\n", (size_t)tcm, (size_t)dram);
return -1;
}
printf("aimm malloc succfully(tcm:%lx)(dram:%lx)\n", (size_t)tcm, (size_t)dram);
memset(dram, 0xa5, DRAM_BUF_SIZE);
int loop = ((DRAM_BUF_SIZE + TCM_BUF_SIZE -1) / TCM_BUF_SIZE);
int cpy_size = TCM_BUF_SIZE;
int remain = DRAM_BUF_SIZE;
int offset = 0;
printf("aimm cpy dram ---> tcm: total(%lx) copy size(%lx) loop(%lx)\n", DRAM_BUF_SIZE, TCM_BUF_SIZE, loop);
for (int i =0; i < loop; i++) {
//aimm_memcpy(tcm, dram + offset, cpy_size);
memcpy(tcm, dram + offset, cpy_size);
//printf("memcpy tcm:%p, dram:%p, cpy_sz:%d\n", tcm, dram+offset, cpy_size);
if (memcmp(tcm, dram + offset, cpy_size) != 0) {
printf("aimm memcpy fail\n");
break;
}
memcpy(dram + offset, tcm, cpy_size);
if (memcmp(tcm, dram + offset, cpy_size) != 0) {
printf("aimm memcpy fail 1111\n");
break;
}
remain -= cpy_size;
if (remain <= 0) {
printf("aimm memcpy succfully\n");
break;
}
offset += cpy_size;
cpy_size = (remain > cpy_size) ? cpy_size : remain;
}
aimm_tcm_free(tcm);
//aimm_dram_free(dram);
free(dram);
return 0;
}

298
tcm/tcm.c Normal file
View file

@ -0,0 +1,298 @@
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <poll.h>
#include <sys/time.h>
#include <unistd.h>
#include "tcm.h"
#include "list.h"
#define TCM_NAME "tcm"
#define IOC_MAGIC 'c'
#define TCM_MEM_SHOW _IOR(IOC_MAGIC, 2, int)
#define TCM_VA_TO_PA _IOR(IOC_MAGIC, 4, int)
#define TCM_REQUEST_MEM _IOR(IOC_MAGIC, 5, int)
#define TCM_RELEASE_MEM _IOR(IOC_MAGIC, 6, int)
#define tcm_mutex_init() pthread_mutex_init(&tcm.mutex, NULL)
#define tcm_mutex_lock() pthread_mutex_lock(&tcm.mutex)
#define tcm_mutex_try_lock() pthread_mutex_trylock(&tcm.mutex)
#define tcm_mutex_unlock() pthread_mutex_unlock(&tcm.mutex)
#define tcm_mutex_deinit() pthread_mutex_destroy(&tcm.mutex)
#define tcm_check_return_val(X, ret) \
do { \
if (!(X)) { \
printf("tcm check param err--->fun:%s + line:%d", __func__, __LINE__); \
return ret; \
} \
} while (0)
#define tcm_check_return(X) \
do { \
if (!(X)) { \
printf("tcm check param err--->fun:%s + line:%d", __func__, __LINE__); \
return; \
} \
} while (0)
#define timeval_sub(a, b, res) \
do { \
(res)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(res)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((res)->tv_usec < 0) { \
(res)->tv_sec--; \
(res)->tv_usec += 1000000; \
} \
} while (0)
typedef struct {
struct list_head list;
void *ptr;
size_t size;
} mm_node_t;
typedef struct {
int inited;
int debug;
int fd;
int block_num;
pthread_mutex_t mutex;
struct list_head head;
} tcm_t;
typedef struct {
void *vaddr;
void *paddr;
} va_to_pa_msg_t;
static tcm_t tcm;
static void mem_show(void)
{
ioctl(tcm.fd, TCM_MEM_SHOW, NULL);
}
static int mem_open(void)
{
int fd = open("/dev/"TCM_NAME, (O_RDWR | O_SYNC));
if (fd < 0) {
printf("open failed(%d)\n", fd);
return -1;
}
tcm.fd = fd;
return 0;
}
static int mem_close(void)
{
close(tcm.fd);
return 0;
}
static int add_node(mm_node_t *node)
{
list_add(&node->list, &tcm.head);
return 0;
}
static int del_node(mm_node_t *node)
{
list_del(&node->list);
return 0;
}
static mm_node_t *get_node(void *ptr)
{
mm_node_t *node;
list_for_each_entry(node, &tcm.head, list) {
if (node->ptr == ptr) {
return node;
}
}
return NULL;
}
static mm_node_t *match_node(void *ptr)
{
mm_node_t *node;
list_for_each_entry(node, &tcm.head, list) {
if ((size_t)ptr >= (size_t)node->ptr &&
(size_t)ptr < ((size_t)node->ptr + node->size)) {
return node;
}
}
return NULL;
}
static void *alloc(size_t size)
{
mm_node_t *node = malloc(sizeof(mm_node_t));
if (!node) return NULL;
void *p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, tcm.fd, 0);
if (p == MAP_FAILED) {
free(node);
printf("%s failed(%ld)\n", __func__, size);
return NULL;
}
node->ptr = p;
node->size = size;
tcm_mutex_lock();
add_node(node);
tcm_mutex_unlock();
return p;
}
void *tcm_malloc_sync(size_t size, int timeout)
{
tcm_check_return_val(tcm.inited, NULL);
struct timeval now;
struct timeval end;
struct timeval sub;
int remain_wait = timeout;
gettimeofday(&now, NULL);
void *p = alloc(size);
while ((p == NULL) && (timeout != 0)) {
int ret;
struct pollfd events;
events.fd = tcm.fd;
events.events = POLLIN | POLLERR;
if (tcm.debug) printf("thread(%d) %s timeout:%d(ms)\n", getpid(), __func__, remain_wait);
tcm_mutex_lock();
if (ioctl(tcm.fd, TCM_REQUEST_MEM, &size) < 0) {
tcm_mutex_unlock();
return NULL;
}
ret = poll((struct pollfd *)&events, 1, remain_wait);
if(ret <= 0 && events.revents == POLLERR) {
tcm_mutex_unlock();
break;
}
if (ioctl(tcm.fd, TCM_RELEASE_MEM, &size) < 0) {
tcm_mutex_unlock();
return NULL;
}
tcm_mutex_unlock();
if (tcm.debug) printf("thread(%d) %s wait\n", getpid(), __func__);
p = alloc(size);
if (p) {
break;
}
if (tcm.debug) printf("thread(%d) %s failed\n", getpid(), __func__);
if (timeout != -1) {
gettimeofday(&end, NULL);
timeval_sub(&end, &now, &sub);
long elapsed = end.tv_sec * 1000 + end.tv_usec / 1000;
if (elapsed > timeout) {
if (tcm.debug) printf("thread(%d) %s timeout\n", getpid(), __func__);
break;
} else {
remain_wait = (timeout - elapsed);
}
}
}
return p;
}
void *tcm_malloc(size_t size)
{
tcm_check_return_val(tcm.inited, NULL);
return alloc(size);
}
void *tcm_calloc(size_t nmemb, size_t size)
{
tcm_check_return_val(tcm.inited, NULL);
return alloc(size * nmemb);
}
void tcm_free(void *ptr)
{
tcm_check_return(tcm.inited);
mm_node_t *node = get_node(ptr);
if(!node) return;
munmap(ptr, node->size);
tcm_mutex_lock();
del_node(node);
tcm_mutex_unlock();
free(node);
}
int is_tcm_mm(void *p)
{
mm_node_t *node = match_node(p);
return node ? 0 : -1;
}
void *tcm_va_to_pa(void *va)
{
va_to_pa_msg_t msg;
msg.vaddr = va;
if (ioctl(tcm.fd, TCM_VA_TO_PA, &msg) < 0) {
return NULL;
}
return msg.paddr;
}
void tcm_mm_show(void)
{
mem_show();
}
int tcm_init(void)
{
int ret = 0;
if (!tcm.inited) {
ret = mem_open();
if ( ret == 0) {
INIT_LIST_HEAD(&tcm.head);
tcm_mutex_init();
tcm.inited = 1;
tcm.debug = 1;
}
}
return ret;
}
int tcm_deinit(void)
{
if (tcm.inited) {
mem_close();
tcm_mutex_deinit();
tcm.inited = 0;
return 0;
}
return -1;
}

81
tcm/tcm.h Normal file
View file

@ -0,0 +1,81 @@
#ifndef __TCM_MM_H__
#define __TCM_MM_H__
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
\brief Initialize Tcm Interface.
\param[in] None
\return Error code
*/
int tcm_init(void);
/**
\brief De-initialize Tcm Interface.
\param[in] None
\return Error code
*/
int tcm_deinit(void);
/**
\brief Allocates size bytes and returns a pointer to the allocated memory
\param[in] size allocated memory size(bytes)
\return a pointer to the allocated memory
*/
void *tcm_malloc(size_t size);
/**
\brief Sync allocates size bytes and returns a pointer to the allocated memory
\param[in] size allocated memory size(bytes)
\param[in] timeout allocated wait time(ms)
\return a pointer to the allocated memory
*/
void *tcm_malloc_sync(size_t size, int timeout);
/**
\brief Changes the size of the memory block pointed to by ptr to size bytes
\param[in] ptr an old pointer to the allocated memory
\param[in] size allocated memory size(bytes)
\return a new pointer to the allocated memoryError code
*/
void *tcm_realloc(void *ptr, size_t size);
/**
\brief Allocates memory for an array of nmemb elements of size bytes each and returns a pointer to the allocated memory
\param[in] nmenb nmemb elements
\param[in] size allocated memory size(bytes)
\return a pointer to the allocated memoryError code
*/
void *tcm_calloc(size_t nmemb, size_t size);
/**
\brief Frees the memory space pointed to by ptr
\param[in] ptr a pointer to the allocated memoryError code
\return None
*/
void tcm_free(void *ptr);
/**
\brief va to pa
\param[in] va
\return pa
*/
void *tcm_va_to_pa(void *va);
/**
\brief tcm memory shwo
\param[in] None
\return None
*/
void tcm_mm_show(void);
int is_tcm_mm(void *p);
#ifdef __cplusplus
}
#endif
#endif

108
tests/mem/memtester.c Normal file
View file

@ -0,0 +1,108 @@
/*
* memtester version 4
*
* Very simple but very effective user-space memory tester.
* Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
* Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
* Version 3 not publicly released.
* Version 4 rewrite:
* Copyright (C) 2004-2012 Charles Cazabon <charlesc-memtester@pyropus.ca>
* Licensed under the terms of the GNU General Public License version 2 (only).
* See the file COPYING for details.
*
*/
#define __version__ "4.3.0"
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
//#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include "types.h"
#include "sizes.h"
#include "tests.h"
#define TEST_NARROW_WRITES
#define EXIT_FAIL_NONSTARTER 0x01
#define EXIT_FAIL_ADDRESSLINES 0x02
#define EXIT_FAIL_OTHERTEST 0x04
#define TEST_LOOPS 1
struct test tests[] = {
{ "Random Value", test_random_value },
{ "Compare XOR", test_xor_comparison },
{ "Compare SUB", test_sub_comparison },
{ "Compare MUL", test_mul_comparison },
{ "Compare DIV", test_div_comparison },
{ "Compare OR", test_or_comparison },
{ "Compare AND", test_and_comparison },
{ "Sequential Increment", test_seqinc_comparison },
{ "Solid Bits", test_solidbits_comparison },
{ "Block Sequential", test_blockseq_comparison },
{ "Checkerboard", test_checkerboard_comparison },
{ "Bit Spread", test_bitspread_comparison },
{ "Bit Flip", test_bitflip_comparison },
{ "Walking Ones", test_walkbits1_comparison },
{ "Walking Zeroes", test_walkbits0_comparison },
#ifdef TEST_NARROW_WRITES
{ "8-bit Writes", test_8bit_wide_random },
{ "16-bit Writes", test_16bit_wide_random },
#endif
{ NULL, NULL }
};
int memtester_main(void *ram_start, void *ram_end)
{
uint32_t loop, i, size, count;
ulv *bufa = NULL, *bufb = NULL;
int32_t ret = 0;
size = (size_t)ram_end - (size_t)ram_start;
size &= 0xFFFFFFFFFFFFFFF0;
count = size / sizeof(ulv) / 2;
bufa = (ulv *)(ram_start);
bufb = (ulv *)((size_t)ram_start + size / 2);
printf("Start Test RAM\n");
printf("Test BUF A: 0x%p, Size = %d Bytes\n", bufa, size / 2);
printf("Test BUF B: 0x%p, Size = %d Bytes\n", bufb, size / 2);
for (loop = 0; loop < TEST_LOOPS; loop++) {
printf("Loop %u", loop);
printf(":\n");
printf(" %-20s: ", "Stuck Address");
for (i = 0;; i++) {
if (!tests[i].name) {
break;
}
printf(" %-20s: ", tests[i].name);
if (!tests[i].fp(bufa, bufb, count)) {
ret = 0;
printf("ok\n");
} else {
ret = -1;
printf("failed\n");
}
}
printf("\n");
}
printf("Done.\n");
return ret;
}

24
tests/mem/memtester.h Normal file
View file

@ -0,0 +1,24 @@
/*
* Very simple (yet, for some reason, very effective) memory tester.
* Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
* Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
* Version 3 not publicly released.
* Version 4 rewrite:
* Copyright (C) 2004-2012 Charles Cazabon <charlesc-memtester@pyropus.ca>
* Licensed under the terms of the GNU General Public License version 2 (only).
* See the file COPYING for details.
*
* This file contains the declarations for external variables from the main file.
* See other comments in that file.
*
*/
#include <sys/types.h>
/* extern declarations. */
// typedef long unsigned int off_t;
extern int use_phys;
extern off_t physaddrbase;

46
tests/mem/sizes.h Normal file
View file

@ -0,0 +1,46 @@
/*
* Very simple but very effective user-space memory tester.
* Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
* Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
* Version 3 not publicly released.
* Version 4 rewrite:
* Copyright (C) 2004-2012 Charles Cazabon <charlesc-memtester@pyropus.ca>
* Licensed under the terms of the GNU General Public License version 2 (only).
* See the file COPYING for details.
*
* This file contains some macro definitions for handling 32/64 bit platforms.
*
*/
#include <limits.h>
#ifdef __cplusplus
extern "C" {
#endif
#define rand32() ((unsigned int) rand() | ( (unsigned int) rand() << 16))
#if (ULONG_MAX == 4294967295UL)
#define rand_ul() rand32()
#define UL_ONEBITS 0xffffffff
#define UL_LEN 32
#define CHECKERBOARD1 0x55555555
#define CHECKERBOARD2 0xaaaaaaaa
#define UL_BYTE(x) ((x | x << 8 | x << 16 | x << 24))
#elif (ULONG_MAX == 18446744073709551615ULL)
#define rand64() (((ul) rand32()) << 32 | ((ul) rand32()))
#define rand_ul() rand64()
#define UL_ONEBITS 0xffffffffffffffffUL
#define UL_LEN 64
#define CHECKERBOARD1 0x5555555555555555
#define CHECKERBOARD2 0xaaaaaaaaaaaaaaaa
#define UL_BYTE(x) (((ul)x | (ul)x<<8 | (ul)x<<16 | (ul)x<<24 | (ul)x<<32 | (ul)x<<40 | (ul)x<<48 | (ul)x<<56))
#else
#error long on this platform is not 32 or 64 bits
#ifdef __cplusplus
}
#endif
#endif

610
tests/mem/tests.c Normal file
View file

@ -0,0 +1,610 @@
/*
* Very simple but very effective user-space memory tester.
* Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
* Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
* Version 3 not publicly released.
* Version 4 rewrite:
* Copyright (C) 2004-2012 Charles Cazabon <charlesc-memtester@pyropus.ca>
* Licensed under the terms of the GNU General Public License version 2 (only).
* See the file COPYING for details.
*
* This file contains the functions for the actual tests, called from the
* main routine in memtester.c. See other comments in that file.
*
*/
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include "memtester.h"
#include "sizes.h"
#include "types.h"
#define TEST_NARROW_WRITES
char progress[] = "-\\|/";
#define PROGRESSLEN 4
#define PROGRESSOFTEN 2500
#define ONE 0x00000001L
/* Function definitions. */
union {
unsigned char bytes[UL_LEN / 8];
ul val;
} mword8;
union {
unsigned short u16s[UL_LEN / 16];
ul val;
} mword16;
int compare_regions(ulv *bufa, ulv *bufb, size_t count)
{
int r = 0;
size_t i;
ulv *p1 = bufa;
ulv *p2 = bufb;
for (i = 0; i < count; i++, p1++, p2++) {
if (*p1 != *p2) {
printf("FAILURE: 0x%08lx != 0x%08lx at offset 0x%08lx.\n", (ul)*p1, (ul)*p2,
(ul)(i * sizeof(ul)));
/* printf("Skipping to next test..."); */
r = -1;
}
}
return r;
}
int test_stuck_address(ulv *bufa, size_t count)
{
ulv *p1 = bufa;
unsigned int j;
size_t i;
printf(" ");
fflush(stdout);
for (j = 0; j < 16; j++) {
printf("\b\b\b\b\b\b\b\b\b\b\b");
p1 = (ulv *)bufa;
printf("setting %3u", j);
fflush(stdout);
for (i = 0; i < count; i++) {
*p1 = ((j + i) % 2) == 0 ? (ul)p1 : ~((ul)p1);
*p1++;
}
printf("\b\b\b\b\b\b\b\b\b\b\b");
printf("testing %3u", j);
fflush(stdout);
p1 = (ulv *)bufa;
for (i = 0; i < count; i++, p1++) {
if (*p1 != (((j + i) % 2) == 0 ? (ul)p1 : ~((ul)p1))) {
printf(
"FAILURE: possible bad address line at offset "
"0x%08lx.\n",
(ul)(i * sizeof(ul)));
printf("Skipping to next test...\n");
fflush(stdout);
return -1;
}
}
}
printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
fflush(stdout);
return 0;
}
int test_random_value(ulv *bufa, ulv *bufb, size_t count)
{
ulv *p1 = bufa;
ulv *p2 = bufb;
ul j = 0;
size_t i;
putchar(' ');
fflush(stdout);
for (i = 0; i < count; i++) {
ulv val = rand_ul();
*p1 = val;
*p2 = val;
*p1++;
*p2++;
// *p1++ = val;
// *p2++ = val;
// *p1++ = *p2++ = rand_ul();
if (!(i % PROGRESSOFTEN)) {
putchar('\b');
putchar(progress[++j % PROGRESSLEN]);
fflush(stdout);
}
}
printf("\b \b");
fflush(stdout);
return compare_regions(bufa, bufb, count);
}
int test_xor_comparison(ulv *bufa, ulv *bufb, size_t count)
{
ulv *p1 = bufa;
ulv *p2 = bufb;
size_t i;
ul q = rand_ul();
for (i = 0; i < count; i++) {
*p1++ ^= q;
*p2++ ^= q;
}
return compare_regions(bufa, bufb, count);
}
int test_sub_comparison(ulv *bufa, ulv *bufb, size_t count)
{
ulv *p1 = bufa;
ulv *p2 = bufb;
size_t i;
ul q = rand_ul();
for (i = 0; i < count; i++) {
*p1++ -= q;
*p2++ -= q;
}
return compare_regions(bufa, bufb, count);
}
int test_mul_comparison(ulv *bufa, ulv *bufb, size_t count)
{
ulv *p1 = bufa;
ulv *p2 = bufb;
size_t i;
ul q = rand_ul();
for (i = 0; i < count; i++) {
*p1++ *= q;
*p2++ *= q;
}
return compare_regions(bufa, bufb, count);
}
int test_div_comparison(ulv *bufa, ulv *bufb, size_t count)
{
ulv *p1 = bufa;
ulv *p2 = bufb;
size_t i;
ul q = rand_ul();
for (i = 0; i < count; i++) {
if (!q) {
q++;
}
*p1++ /= q;
*p2++ /= q;
}
return compare_regions(bufa, bufb, count);
}
int test_or_comparison(ulv *bufa, ulv *bufb, size_t count)
{
ulv *p1 = bufa;
ulv *p2 = bufb;
size_t i;
ul q = rand_ul();
for (i = 0; i < count; i++) {
*p1++ |= q;
*p2++ |= q;
}
return compare_regions(bufa, bufb, count);
}
int test_and_comparison(ulv *bufa, ulv *bufb, size_t count)
{
ulv *p1 = bufa;
ulv *p2 = bufb;
size_t i;
ul q = rand_ul();
for (i = 0; i < count; i++) {
*p1++ &= q;
*p2++ &= q;
}
return compare_regions(bufa, bufb, count);
}
int test_seqinc_comparison(ulv *bufa, ulv *bufb, size_t count)
{
ulv *p1 = bufa;
ulv *p2 = bufb;
size_t i;
ul q = rand_ul();
for (i = 0; i < count; i++) {
*p1++ = *p2++ = (i + q);
}
return compare_regions(bufa, bufb, count);
}
int test_solidbits_comparison(ulv *bufa, ulv *bufb, size_t count)
{
ulv *p1 = bufa;
ulv *p2 = bufb;
unsigned int j;
ul q;
size_t i;
printf(" ");
fflush(stdout);
for (j = 0; j < 64; j++) {
printf("\b\b\b\b\b\b\b\b\b\b\b");
q = (j % 2) == 0 ? UL_ONEBITS : 0;
printf("setting %3u", j);
fflush(stdout);
p1 = (ulv *)bufa;
p2 = (ulv *)bufb;
for (i = 0; i < count; i++) {
*p1++ = *p2++ = (i % 2) == 0 ? q : ~q;
}
printf("\b\b\b\b\b\b\b\b\b\b\b");
printf("testing %3u", j);
fflush(stdout);
if (compare_regions(bufa, bufb, count)) {
return -1;
}
}
printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
fflush(stdout);
return 0;
}
int test_checkerboard_comparison(ulv *bufa, ulv *bufb, size_t count)
{
ulv *p1 = bufa;
ulv *p2 = bufb;
unsigned int j;
ul q;
size_t i;
printf(" ");
fflush(stdout);
for (j = 0; j < 64; j++) {
printf("\b\b\b\b\b\b\b\b\b\b\b");
q = (j % 2) == 0 ? CHECKERBOARD1 : CHECKERBOARD2;
printf("setting %3u", j);
fflush(stdout);
p1 = (ulv *)bufa;
p2 = (ulv *)bufb;
for (i = 0; i < count; i++) {
*p1++ = *p2++ = (i % 2) == 0 ? q : ~q;
}
printf("\b\b\b\b\b\b\b\b\b\b\b");
printf("testing %3u", j);
fflush(stdout);
if (compare_regions(bufa, bufb, count)) {
return -1;
}
}
printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
fflush(stdout);
return 0;
}
int test_blockseq_comparison(ulv *bufa, ulv *bufb, size_t count)
{
ulv *p1 = bufa;
ulv *p2 = bufb;
unsigned int j;
size_t i;
printf(" ");
fflush(stdout);
for (j = 0; j < 256; j++) {
printf("\b\b\b\b\b\b\b\b\b\b\b");
p1 = (ulv *)bufa;
p2 = (ulv *)bufb;
printf("setting %3u", j);
fflush(stdout);
for (i = 0; i < count; i++) {
*p1++ = *p2++ = (ul)UL_BYTE(j);
}
printf("\b\b\b\b\b\b\b\b\b\b\b");
printf("testing %3u", j);
fflush(stdout);
if (compare_regions(bufa, bufb, count)) {
return -1;
}
}
printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
fflush(stdout);
return 0;
}
int test_walkbits0_comparison(ulv *bufa, ulv *bufb, size_t count)
{
ulv *p1 = bufa;
ulv *p2 = bufb;
unsigned int j;
size_t i;
printf(" ");
fflush(stdout);
for (j = 0; j < UL_LEN * 2; j++) {
printf("\b\b\b\b\b\b\b\b\b\b\b");
p1 = (ulv *)bufa;
p2 = (ulv *)bufb;
printf("setting %3u", j);
fflush(stdout);
for (i = 0; i < count; i++) {
if (j < UL_LEN) { /* Walk it up. */
*p1++ = *p2++ = ONE << j;
} else { /* Walk it back down. */
*p1++ = *p2++ = ONE << (UL_LEN * 2 - j - 1);
}
}
printf("\b\b\b\b\b\b\b\b\b\b\b");
printf("testing %3u", j);
fflush(stdout);
if (compare_regions(bufa, bufb, count)) {
return -1;
}
}
printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
fflush(stdout);
return 0;
}
int test_walkbits1_comparison(ulv *bufa, ulv *bufb, size_t count)
{
ulv *p1 = bufa;
ulv *p2 = bufb;
unsigned int j;
size_t i;
printf(" ");
fflush(stdout);
for (j = 0; j < UL_LEN * 2; j++) {
printf("\b\b\b\b\b\b\b\b\b\b\b");
p1 = (ulv *)bufa;
p2 = (ulv *)bufb;
printf("setting %3u", j);
fflush(stdout);
for (i = 0; i < count; i++) {
if (j < UL_LEN) { /* Walk it up. */
*p1++ = *p2++ = UL_ONEBITS ^ (ONE << j);
} else { /* Walk it back down. */
*p1++ = *p2++ = UL_ONEBITS ^ (ONE << (UL_LEN * 2 - j - 1));
}
}
printf("\b\b\b\b\b\b\b\b\b\b\b");
printf("testing %3u", j);
fflush(stdout);
if (compare_regions(bufa, bufb, count)) {
return -1;
}
}
printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
fflush(stdout);
return 0;
}
int test_bitspread_comparison(ulv *bufa, ulv *bufb, size_t count)
{
ulv *p1 = bufa;
ulv *p2 = bufb;
unsigned int j;
size_t i;
printf(" ");
fflush(stdout);
for (j = 0; j < UL_LEN * 2; j++) {
printf("\b\b\b\b\b\b\b\b\b\b\b");
p1 = (ulv *)bufa;
p2 = (ulv *)bufb;
printf("setting %3u", j);
fflush(stdout);
for (i = 0; i < count; i++) {
if (j < UL_LEN) { /* Walk it up. */
*p1++ = *p2++ = (i % 2 == 0) ? (ONE << j) | (ONE << (j + 2))
: UL_ONEBITS ^ ((ONE << j) | (ONE << (j + 2)));
} else { /* Walk it back down. */
*p1++ = *p2++ =
(i % 2 == 0)
? (ONE << (UL_LEN * 2 - 1 - j)) | (ONE << (UL_LEN * 2 + 1 - j))
: UL_ONEBITS ^ (ONE << (UL_LEN * 2 - 1 - j) | (ONE << (UL_LEN * 2 + 1 - j)));
}
}
printf("\b\b\b\b\b\b\b\b\b\b\b");
printf("testing %3u", j);
fflush(stdout);
if (compare_regions(bufa, bufb, count)) {
return -1;
}
}
printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
fflush(stdout);
return 0;
}
int test_bitflip_comparison(ulv *bufa, ulv *bufb, size_t count)
{
ulv *p1 = bufa;
ulv *p2 = bufb;
unsigned int j, k;
ul q;
size_t i;
printf(" ");
fflush(stdout);
for (k = 0; k < UL_LEN; k++) {
q = ONE << k;
for (j = 0; j < 8; j++) {
printf("\b\b\b\b\b\b\b\b\b\b\b");
q = ~q;
printf("setting %3u", k * 8 + j);
fflush(stdout);
p1 = (ulv *)bufa;
p2 = (ulv *)bufb;
for (i = 0; i < count; i++) {
*p1++ = *p2++ = (i % 2) == 0 ? q : ~q;
}
printf("\b\b\b\b\b\b\b\b\b\b\b");
printf("testing %3u", k * 8 + j);
fflush(stdout);
if (compare_regions(bufa, bufb, count)) {
return -1;
}
}
}
printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
fflush(stdout);
return 0;
}
#ifdef TEST_NARROW_WRITES
int test_8bit_wide_random(ulv *bufa, ulv *bufb, size_t count)
{
u8v *p1, *t;
ulv *p2;
int attempt;
unsigned int b, j = 0;
size_t i;
putchar(' ');
fflush(stdout);
for (attempt = 0; attempt < 2; attempt++) {
if (attempt & 1) {
p1 = (u8v *)bufa;
p2 = bufb;
} else {
p1 = (u8v *)bufb;
p2 = bufa;
}
for (i = 0; i < count; i++) {
t = mword8.bytes;
*p2++ = mword8.val = rand_ul();
for (b = 0; b < UL_LEN / 8; b++) {
*p1++ = *t++;
}
if (!(i % PROGRESSOFTEN)) {
putchar('\b');
putchar(progress[++j % PROGRESSLEN]);
fflush(stdout);
}
}
if (compare_regions(bufa, bufb, count)) {
return -1;
}
}
printf("\b \b");
fflush(stdout);
return 0;
}
int test_16bit_wide_random(ulv *bufa, ulv *bufb, size_t count)
{
u16v *p1, *t;
ulv *p2;
int attempt;
unsigned int b, j = 0;
size_t i;
putchar(' ');
fflush(stdout);
for (attempt = 0; attempt < 2; attempt++) {
if (attempt & 1) {
p1 = (u16v *)bufa;
p2 = bufb;
} else {
p1 = (u16v *)bufb;
p2 = bufa;
}
for (i = 0; i < count; i++) {
t = mword16.u16s;
*p2++ = mword16.val = rand_ul();
for (b = 0; b < UL_LEN / 16; b++) {
*p1++ = *t++;
}
if (!(i % PROGRESSOFTEN)) {
putchar('\b');
putchar(progress[++j % PROGRESSLEN]);
fflush(stdout);
}
}
if (compare_regions(bufa, bufb, count)) {
return -1;
}
}
printf("\b \b");
fflush(stdout);
return 0;
}
#endif

40
tests/mem/tests.h Normal file
View file

@ -0,0 +1,40 @@
/*
* Very simple yet very effective memory tester.
* Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
* Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
* Version 3 not publicly released.
* Version 4 rewrite:
* Copyright (C) 2004-2012 Charles Cazabon <charlesc-memtester@pyropus.ca>
* Licensed under the terms of the GNU General Public License version 2 (only).
* See the file COPYING for details.
*
* This file contains the declarations for the functions for the actual tests,
* called from the main routine in memtester.c. See other comments in that
* file.
*
*/
/* Function declaration. */
#define TEST_NARROW_WRITES
int test_stuck_address(unsigned long volatile *bufa, size_t count);
int test_random_value(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
int test_xor_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
int test_sub_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
int test_mul_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
int test_div_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
int test_or_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
int test_and_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
int test_seqinc_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
int test_solidbits_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
int test_checkerboard_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
int test_blockseq_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
int test_walkbits0_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
int test_walkbits1_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
int test_bitspread_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
int test_bitflip_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
#ifdef TEST_NARROW_WRITES
int test_8bit_wide_random(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
int test_16bit_wide_random(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
#endif

31
tests/mem/types.h Normal file
View file

@ -0,0 +1,31 @@
/*
* Very simple but very effective user-space memory tester.
* Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
* Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
* Version 3 not publicly released.
* Version 4 rewrite:
* Copyright (C) 2004-2010 Charles Cazabon <charlesc-memtester@pyropus.ca>
* Licensed under the terms of the GNU General Public License version 2 (only).
* See the file COPYING for details.
*
* This file contains typedefs, structure, and union definitions.
*
*/
#ifndef __MY_TYPES_H__
#define __MY_TYPES_H__
#include "sizes.h"
typedef unsigned long ul;
typedef unsigned long long ull;
typedef unsigned long volatile ulv;
typedef unsigned char volatile u8v;
typedef unsigned short volatile u16v;
struct test {
char *name;
int (*fp)();
};
#endif

72
tests/tcm_malloc.c Normal file
View file

@ -0,0 +1,72 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include "tcm.h"
void tcm_malloc_test(void)
{
#define TCM_MALLOC_CASE_LEN 1024
printf("------------------%s case start-------------\n", __func__);
char *p;
char *s = malloc(TCM_MALLOC_CASE_LEN);
if (!s) {
printf("malloc failed, case return\n");
return;
}
memset(s, 0xa5, TCM_MALLOC_CASE_LEN);
p = tcm_aligned_alloc(2, TCM_MALLOC_CASE_LEN);
if (!p) {
printf("aligned alloc failed size: %d\n", TCM_MALLOC_CASE_LEN);
}
memset(p, 0xa5, TCM_MALLOC_CASE_LEN);
if (memcmp(p, s, TCM_MALLOC_CASE_LEN) != 0) {
printf("aligned alloc set failed\n");
return;
}
printf("aligned alloc(%d) successfully\n", TCM_MALLOC_CASE_LEN);
tcm_free(p);
p = tcm_aligned_alloc(3, TCM_MALLOC_CASE_LEN);
if (!p) {
printf("aligned alloc: %d\n", 3);
}
p = tcm_malloc(TCM_MALLOC_CASE_LEN);
if (!p) {
printf("malloc failed size: %d\n", TCM_MALLOC_CASE_LEN);
}
memset(s, 0xa6, TCM_MALLOC_CASE_LEN);
memset(p, 0xa6, TCM_MALLOC_CASE_LEN);
if (memcmp(p, s, TCM_MALLOC_CASE_LEN) != 0) {
printf("malloc alloc set failed\n");
return;
}
printf("malloc(%d) successfully\n", TCM_MALLOC_CASE_LEN);
tcm_free(p);
p = tcm_calloc(1, TCM_MALLOC_CASE_LEN);
if (!p) {
printf("calloc failed size: %d\n", TCM_MALLOC_CASE_LEN);
}
memset(s, 0xa7, TCM_MALLOC_CASE_LEN);
memset(p, 0xa7, TCM_MALLOC_CASE_LEN);
if (memcmp(p, s, TCM_MALLOC_CASE_LEN) != 0) {
printf("calloc set failed\n");
return;
}
printf("calloc(%d) successfully\n", TCM_MALLOC_CASE_LEN);
tcm_free(p);
printf("------------------%s case end-------------\n", __func__);
}

61
tests/tcm_mmap.c Normal file
View file

@ -0,0 +1,61 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include "tcm.h"
void tcm_mmap(void)
{
printf("------------------%s case start-------------\n", __func__);
void *tcm_p = tcm_malloc(1024);
if (tcm_p) {
printf("tcm alloc successfully!(%p)\n", tcm_p);
} else {
printf("tcm alloc failed!\n");
}
char buf[] = "hello tcm";
int len = strlen(buf) + 1;
memcpy(tcm_p, buf, len);
tcm_info_t info;
tcm_block_info_t b_info;
tcm_get_info(&info);
tcm_block_info_get(&b_info, 0);
int fd = open("/dev/mem", (O_RDWR | O_SYNC));
if (fd < 0) {
printf("Unable to open /dev/mem: %d\n", fd);
return;
}
void *map_base = mmap(NULL,
b_info.size,
(PROT_READ | PROT_WRITE),
MAP_SHARED,
fd,
(off_t)(b_info.paddr));
char *show = (char *)((size_t)(tcm_p) - (size_t)b_info.vaddr + (size_t)map_base);
if (memcmp(tcm_p, show, len) != 0) {
printf("/dev/mem check failed\n");
} else {
printf("/dev/mem check successfully\n");
}
munmap(b_info.paddr, b_info.size);
free(buf1);
tcm_free(tcm_p);
printf("------------------%s case end-------------\n", __func__);
}

74
tests/tcm_rand_access.c Normal file
View file

@ -0,0 +1,74 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include "tcm.h"
static int count = 0;
void tcm_rand_access(int total_cnt)
{
printf("------------------%s case start-------------\n", __func__);
tcm_info_t info;
block_info_t *b_info;
off_t base;
size_t size = 0;;
tcm_get_info(&info);
b_info = calloc(sizeof(block_info_t), info.block_num);
for (int i = 0; i < info.block_num; i++) {
tcm_block_info_get(b_info + i, i);
if (i == 0) {
base = (off_t)b_info[i].paddr;
}
size += b_info[i].size;
}
printf("-----(%x)(%x)\n", base, size);
int fd = open("/dev/mem", (O_RDWR | O_SYNC));
if (fd < 0) {
printf("Unable to open /dev/mem: %d\n", fd);
return;
}
void *map_base = mmap(NULL,
size,
(PROT_READ | PROT_WRITE),
MAP_SHARED,
fd,
(off_t)(base));
char *start = (char *)map_base;
size_t loop = size;
int flag = 0;
printf("start: %p, len:0x%x\n", start, size);
while (loop --) {
int offset = rand();
char *val = start + offset % size;
for (int i = 0; i < 4; i++) {
memcpy(val, &offset, i);
if (memcmp(val, &offset, i) != 0) {
flag = 1;
printf("rcm access failed(%p) len:%d (%x) (%x)\n", val, i, *val);
}
}
}
if (flag == 0) {
printf("total:%d ,succfully rand access(%d)\n", total_cnt, ++count);
}
munmap((void *)base, size);
close(fd);
printf("------------------%s case end-------------\n", __func__);
}

49
tests/tcm_test.c Normal file
View file

@ -0,0 +1,49 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include "tcm.h"
void tcm_test(void)
{
printf("------------------%s case start-------------\n", __func__);
void *tcm_p = tcm_malloc(1024);
if (tcm_p) {
printf("tcm alloc successfully!(%p)\n", tcm_p);
} else {
printf("tcm alloc failed!\n");
}
char buf[] = "hello tcm";
int len = strlen(buf) + 1;
memcpy(tcm_p, buf, len);
if (memcmp(tcm_p, buf, len) != 0) {
printf("write ddr --> tcm failed\n");
} else {
printf("write ddr --> tcm successfully\n");
}
char *buf1 = malloc(len);
if (!buf1) {
printf("%s_%d malloc failed\n", __func__, __LINE__);
}
memcpy(buf1, tcm_p, len);
if (memcmp(tcm_p, buf1, len) != 0) {
printf("write tcm --> ddr failed\n");
} else {
printf("write tcm --> ddr successfully\n");
}
printf("------------------%s case end-------------\n", __func__);
}

54
tests/tcm_thread.c Normal file
View file

@ -0,0 +1,54 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include "tcm.h"
static void *thread_func1(void *args)
{
int id = tcm_block_cur();
void *p = tcm_malloc(1024);
printf("thread:%s id[%d] p(%p)\n", __func__, id, p);
tcm_free(p);
tcm_block_bind_thread(1);
id = tcm_block_cur();
p = tcm_malloc(1024);
printf("thread:%s id[%d] p(%p)\n", __func__, id, p);
tcm_free(p);
}
static void *thread_func2(void *args)
{
int id = tcm_block_cur();
void *p = tcm_malloc(1024);
printf("thread:%s id[%d] p(%p)\n", __func__, id, p);
tcm_free(p);
tcm_block_bind_thread(1);
id = tcm_block_cur();
p = tcm_malloc(1024);
printf("thread:%s id[%d] p(%p)\n", __func__, id, p);
tcm_free(p);
}
void tcm_mul_thread(void)
{
printf("------------------%s case start-------------\n", __func__);
pthread_t pa, pb;
pthread_create(&pa, NULL, thread_func1, NULL);
pthread_create(&pb, NULL, thread_func2, NULL);
pthread_join(pa, NULL);
pthread_join(pb, NULL);
printf("------------------%s case end-------------\n", __func__);
}

14
time_us.c Normal file
View file

@ -0,0 +1,14 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
long long getus(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return ((long long)tv.tv_sec * 1000000 + tv.tv_usec);
}

141
udma/udma.c Normal file
View file

@ -0,0 +1,141 @@
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include "list.h"
#define IOC_MAGIC 'c'
#define UDMA_MEMCPY_CMD _IOR(IOC_MAGIC, 0, int)
typedef struct {
void *src;
void *dst;
size_t size;
} memcpy_msg_t;
typedef struct {
struct list_head list;
void *ptr;
size_t size;
} mm_node_t;
typedef struct {
int fd;
struct list_head head;
} udma_t;
static udma_t udma;
static int add_node(mm_node_t *node)
{
list_add(&node->list, &udma.head);
return 0;
}
static int del_node(mm_node_t *node)
{
list_del(&node->list);
return 0;
}
static mm_node_t *get_node(void *ptr)
{
mm_node_t *node;
list_for_each_entry(node, &udma.head, list) {
if (node->ptr == ptr) {
return node;
}
}
return NULL;
}
static mm_node_t *match_node(void *ptr)
{
mm_node_t *node;
list_for_each_entry(node, &udma.head, list) {
if ((size_t)ptr >= (size_t)node->ptr &&
(size_t)ptr < ((size_t)node->ptr + node->size)) {
return node;
}
}
return NULL;
}
int udma_init(void)
{
int fd = open("/dev/udma", (O_RDWR | O_SYNC));
if (fd < 0) {
return -1;
}
udma.fd = fd;
INIT_LIST_HEAD(&udma.head);
return 0;
}
int udma_deinit(void)
{
close(udma.fd);
return 0;
}
void *udma_malloc(size_t size)
{
mm_node_t *node = malloc(sizeof(mm_node_t));
if (!node) return NULL;
void *p = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, udma.fd, 0);
if (p == MAP_FAILED) {
perror("Failed to malloc the DMA memory mapped region");
return NULL;
}
node->ptr = p;
node->size = size;
add_node(node);
return p;
}
void udma_free(void *ptr)
{
mm_node_t *node = get_node(ptr);
if(!node) return;
if (munmap(ptr, node->size) < 0) {
perror("Failed to free the DMA memory mapped region");
}
del_node(node);
free(node);
}
void *udma_memcpy(void *dest, void *src, size_t n)
{
memcpy_msg_t msg;
msg.size = n;
msg.dst = dest;
msg.src = src;
if (ioctl(udma.fd, UDMA_MEMCPY_CMD, &msg) < 0) {
return NULL;
}
return dest;
}
int is_udma_mm(void *p)
{
mm_node_t *node = match_node(p);
return node ? 0 : -1;
}

20
udma/udma.h Normal file
View file

@ -0,0 +1,20 @@
#ifndef __UDMA_H__
#define __UDMA_H__
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
int udma_init(void);
int udma_deinit(void);
void *udma_malloc(size_t size);
void udma_free(void *ptr);
void *udma_memcpy(void *dest, const void *src, size_t n);
int is_udma_mm(void *p);
#ifdef __cplusplus
}
#endif
#endif