mirror of
https://gitee.com/bianbu-linux/tcm
synced 2025-04-18 19:34:45 -04:00
initial commit
This commit is contained in:
commit
fe6046f6ee
22 changed files with 2092 additions and 0 deletions
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
*.a
|
||||
*.so
|
||||
*.o
|
||||
*.o.*
|
||||
*.elf
|
||||
tags
|
||||
TAGS
|
42
Makefile
Normal file
42
Makefile
Normal 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
90
aimm.c
Normal 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
65
aimm.h
Normal 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
89
list.h
Normal 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
76
main.c
Normal 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
298
tcm/tcm.c
Normal 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
81
tcm/tcm.h
Normal 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
108
tests/mem/memtester.c
Normal 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
24
tests/mem/memtester.h
Normal 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
46
tests/mem/sizes.h
Normal 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
610
tests/mem/tests.c
Normal 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
40
tests/mem/tests.h
Normal 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
31
tests/mem/types.h
Normal 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
72
tests/tcm_malloc.c
Normal 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
61
tests/tcm_mmap.c
Normal 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
74
tests/tcm_rand_access.c
Normal 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
49
tests/tcm_test.c
Normal 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
54
tests/tcm_thread.c
Normal 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
14
time_us.c
Normal 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
141
udma/udma.c
Normal 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
20
udma/udma.h
Normal 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
|
Loading…
Add table
Reference in a new issue