forked from Github_Repos/cvw
		
	Coremark Diretory cleanup, removed syscall warning about noreturn, rresults are good.
This commit is contained in:
		
							parent
							
								
									82cfebfb83
								
							
						
					
					
						commit
						4d1bb3cdd8
					
				| @ -5,10 +5,10 @@ work/coremark.bare.riscv.objdump: work/coremark.bare.riscv | ||||
| 	riscv64-unknown-elf-objdump -D work/coremark.bare.riscv > work/coremark.bare.riscv.objdump  | ||||
| 
 | ||||
| work/coremark.bare.riscv: | ||||
| 	#make -C coremark PORT_DIR=/home/harris/riscv-wally/benchmarks/riscv-coremark/riscv64-baremetal compile RISCV=/courses/e190ax/riscvcompiler XCFLAGS="-march=rv64im" | ||||
| 	#mv coremark/coremark.bare.riscv work | ||||
| 	make -C ../../addins/coremark PORT_DIR=/home/harris/riscv-wally/benchmarks/riscv-coremark/riscv64-baremetal compile RISCV=/courses/e190ax/riscvcompiler XCFLAGS="-march=rv64im" | ||||
| 	mv ../../addins/coremark/coremark.bare.riscv work | ||||
| 	make -C coremark PORT_DIR=/home/harris/riscv-wally/benchmarks/riscv-coremark/riscv64-baremetal compile RISCV=/courses/e190ax/riscvcompiler XCFLAGS="-march=rv64im" | ||||
| 	mv coremark/coremark.bare.riscv work | ||||
| 	#make -C ../../addins/coremark PORT_DIR=/home/harris/riscv-wally/benchmarks/riscv-coremark/riscv64-baremetal compile RISCV=/courses/e190ax/riscvcompiler XCFLAGS="-march=rv64im" | ||||
| 	#mv ../../addins/coremark/coremark.bare.riscv work | ||||
| 
 | ||||
| .PHONY: clean | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										23
									
								
								benchmarks/riscv-coremark/old/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								benchmarks/riscv-coremark/old/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| Coremark EEMBC Wrapper | ||||
| ====================== | ||||
| 
 | ||||
| This repository provides the utility files to port [CoreMark EEMBC](https://www.eembc.org/coremark/) to RISC-V. | ||||
| 
 | ||||
| ### Requirements | ||||
| 
 | ||||
|   - You must have installed the RISC-V tools | ||||
| 
 | ||||
| ### Setup | ||||
| 
 | ||||
|   - `git submodule update --init` | ||||
|   - Run the `./build-coremark.sh` script that does the following | ||||
|     - Builds a version of Coremark for Linux or pk (coremark.riscv) | ||||
|     - Builds a version of Coremark for bare-metal (coremark.bare.riscv) | ||||
|     - Copies the output binaries into this directory | ||||
| 
 | ||||
| ### Default Files | ||||
| 
 | ||||
| The default files target **RV64GC** and use minimal amount of compilation flags. Additionally, the `*.mak` file in the `riscv64` | ||||
| folder setups `spike pk` as the default `run` rule. | ||||
| 
 | ||||
| Feel free to change these to suit your needs. | ||||
							
								
								
									
										346
									
								
								benchmarks/riscv-coremark/old/riscv64/core_portme.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										346
									
								
								benchmarks/riscv-coremark/old/riscv64/core_portme.c
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,346 @@ | ||||
| /*
 | ||||
| Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) | ||||
| 
 | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
| 
 | ||||
|     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| 
 | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| 
 | ||||
| Original Author: Shay Gal-on | ||||
| */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include "coremark.h" | ||||
| #if CALLGRIND_RUN | ||||
| #include <valgrind/callgrind.h> | ||||
| #endif | ||||
| 
 | ||||
| #if (MEM_METHOD==MEM_MALLOC) | ||||
| #include <malloc.h> | ||||
| /* Function: portable_malloc
 | ||||
| 	Provide malloc() functionality in a platform specific way. | ||||
| */ | ||||
| void *portable_malloc(size_t size) { | ||||
| 	return malloc(size); | ||||
| } | ||||
| /* Function: portable_free
 | ||||
| 	Provide free() functionality in a platform specific way. | ||||
| */ | ||||
| void portable_free(void *p) { | ||||
| 	free(p); | ||||
| } | ||||
| #else | ||||
| void *portable_malloc(size_t size) { | ||||
| 	return NULL; | ||||
| } | ||||
| void portable_free(void *p) { | ||||
| 	p=NULL; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #if (SEED_METHOD==SEED_VOLATILE) | ||||
| #if VALIDATION_RUN | ||||
| 	volatile ee_s32 seed1_volatile=0x3415; | ||||
| 	volatile ee_s32 seed2_volatile=0x3415; | ||||
| 	volatile ee_s32 seed3_volatile=0x66; | ||||
| #endif | ||||
| #if PERFORMANCE_RUN | ||||
| 	volatile ee_s32 seed1_volatile=0x0; | ||||
| 	volatile ee_s32 seed2_volatile=0x0; | ||||
| 	volatile ee_s32 seed3_volatile=0x66; | ||||
| #endif | ||||
| #if PROFILE_RUN | ||||
| 	volatile ee_s32 seed1_volatile=0x8; | ||||
| 	volatile ee_s32 seed2_volatile=0x8; | ||||
| 	volatile ee_s32 seed3_volatile=0x8; | ||||
| #endif | ||||
| 	volatile ee_s32 seed4_volatile=ITERATIONS; | ||||
| 	volatile ee_s32 seed5_volatile=0; | ||||
| #endif | ||||
| /* Porting: Timing functions
 | ||||
| 	How to capture time and convert to seconds must be ported to whatever is supported by the platform. | ||||
| 	e.g. Read value from on board RTC, read value from cpu clock cycles performance counter etc. | ||||
| 	Sample implementation for standard time.h and windows.h definitions included. | ||||
| */ | ||||
| /* Define: TIMER_RES_DIVIDER
 | ||||
| 	Divider to trade off timer resolution and total time that can be measured. | ||||
| 
 | ||||
| 	Use lower values to increase resolution, but make sure that overflow does not occur. | ||||
| 	If there are issues with the return value overflowing, increase this value. | ||||
| 	*/ | ||||
| #if USE_CLOCK | ||||
| 	#define NSECS_PER_SEC CLOCKS_PER_SEC | ||||
| 	#define EE_TIMER_TICKER_RATE 1000 | ||||
| 	#define CORETIMETYPE clock_t | ||||
| 	#define GETMYTIME(_t) (*_t=clock()) | ||||
| 	#define MYTIMEDIFF(fin,ini) ((fin)-(ini)) | ||||
| 	#define TIMER_RES_DIVIDER 1 | ||||
| 	#define SAMPLE_TIME_IMPLEMENTATION 1 | ||||
| #elif defined(_MSC_VER) | ||||
| 	#define NSECS_PER_SEC 10000000 | ||||
| 	#define EE_TIMER_TICKER_RATE 1000 | ||||
| 	#define CORETIMETYPE FILETIME | ||||
| 	#define GETMYTIME(_t) GetSystemTimeAsFileTime(_t) | ||||
| 	#define MYTIMEDIFF(fin,ini) (((*(__int64*)&fin)-(*(__int64*)&ini))/TIMER_RES_DIVIDER) | ||||
| 	/* setting to millisces resolution by default with MSDEV */ | ||||
| 	#ifndef TIMER_RES_DIVIDER | ||||
| 	#define TIMER_RES_DIVIDER 1000 | ||||
| 	#endif | ||||
| 	#define SAMPLE_TIME_IMPLEMENTATION 1 | ||||
| #elif HAS_TIME_H | ||||
| 	#define NSECS_PER_SEC 1000000000 | ||||
| 	#define EE_TIMER_TICKER_RATE 1000 | ||||
| 	#define CORETIMETYPE struct timespec | ||||
| 	#define GETMYTIME(_t) clock_gettime(CLOCK_REALTIME,_t) | ||||
| 	#define MYTIMEDIFF(fin,ini) ((fin.tv_sec-ini.tv_sec)*(NSECS_PER_SEC/TIMER_RES_DIVIDER)+(fin.tv_nsec-ini.tv_nsec)/TIMER_RES_DIVIDER) | ||||
| 	/* setting to 1/1000 of a second resolution by default with linux */ | ||||
| 	#ifndef TIMER_RES_DIVIDER | ||||
| 	#define TIMER_RES_DIVIDER 1000000 | ||||
| 	#endif | ||||
| 	#define SAMPLE_TIME_IMPLEMENTATION 1 | ||||
| #else | ||||
|     // Defined for RISCV
 | ||||
|     #define NSECS_PER_SEC 1000000000 // TODO: What freq are we assuming?
 | ||||
| 	#define EE_TIMER_TICKER_RATE 1000 // TODO: What is this?
 | ||||
| 	#define CORETIMETYPE clock_t | ||||
|     #define read_csr(reg) ({ unsigned long __tmp; \ | ||||
|        asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ | ||||
|        __tmp; }) | ||||
|     #define GETMYTIME(_t) (*_t=read_csr(cycle)) | ||||
| 	#define MYTIMEDIFF(fin,ini) ((fin)-(ini)) | ||||
| 	#define TIMER_RES_DIVIDER 1 | ||||
| 	#define SAMPLE_TIME_IMPLEMENTATION 1 | ||||
| #endif | ||||
| #define EE_TICKS_PER_SEC (NSECS_PER_SEC / TIMER_RES_DIVIDER) | ||||
| 
 | ||||
| #if SAMPLE_TIME_IMPLEMENTATION | ||||
| /** Define Host specific (POSIX), or target specific global time variables. */ | ||||
| static CORETIMETYPE start_time_val, stop_time_val; | ||||
| 
 | ||||
| /* Function: start_time
 | ||||
| 	This function will be called right before starting the timed portion of the benchmark. | ||||
| 
 | ||||
| 	Implementation may be capturing a system timer (as implemented in the example code) | ||||
| 	or zeroing some system parameters - e.g. setting the cpu clocks cycles to 0. | ||||
| */ | ||||
| void start_time(void) { | ||||
| 	GETMYTIME(&start_time_val ); | ||||
| #if CALLGRIND_RUN | ||||
| 	CALLGRIND_START_INSTRUMENTATION | ||||
| #endif | ||||
| #if MICA | ||||
|     asm volatile("int3");/*1 */ | ||||
| #endif | ||||
| } | ||||
| /* Function: stop_time
 | ||||
| 	This function will be called right after ending the timed portion of the benchmark. | ||||
| 
 | ||||
| 	Implementation may be capturing a system timer (as implemented in the example code) | ||||
| 	or other system parameters - e.g. reading the current value of cpu cycles counter. | ||||
| */ | ||||
| void stop_time(void) { | ||||
| #if CALLGRIND_RUN | ||||
| 	 CALLGRIND_STOP_INSTRUMENTATION | ||||
| #endif | ||||
| #if MICA | ||||
|     asm volatile("int3");/*1 */ | ||||
| #endif | ||||
| 	GETMYTIME(&stop_time_val ); | ||||
| } | ||||
| /* Function: get_time
 | ||||
| 	Return an abstract "ticks" number that signifies time on the system. | ||||
| 
 | ||||
| 	Actual value returned may be cpu cycles, milliseconds or any other value, | ||||
| 	as long as it can be converted to seconds by <time_in_secs>. | ||||
| 	This methodology is taken to accomodate any hardware or simulated platform. | ||||
| 	The sample implementation returns millisecs by default, | ||||
| 	and the resolution is controlled by <TIMER_RES_DIVIDER> | ||||
| */ | ||||
| CORE_TICKS get_time(void) { | ||||
| 	CORE_TICKS elapsed=(CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val)); | ||||
| 	return elapsed; | ||||
| } | ||||
| /* Function: time_in_secs
 | ||||
| 	Convert the value returned by get_time to seconds. | ||||
| 
 | ||||
| 	The <secs_ret> type is used to accomodate systems with no support for floating point. | ||||
| 	Default implementation implemented by the EE_TICKS_PER_SEC macro above. | ||||
| */ | ||||
| secs_ret time_in_secs(CORE_TICKS ticks) { | ||||
| 	secs_ret retval=((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC; | ||||
| 	return retval; | ||||
| } | ||||
| #else | ||||
| #error "Please implement timing functionality in core_portme.c" | ||||
| #endif /* SAMPLE_TIME_IMPLEMENTATION */ | ||||
| 
 | ||||
| ee_u32 default_num_contexts=MULTITHREAD; | ||||
| 
 | ||||
| /* Function: portable_init
 | ||||
| 	Target specific initialization code | ||||
| 	Test for some common mistakes. | ||||
| */ | ||||
| void portable_init(core_portable *p, int *argc, char *argv[]) | ||||
| { | ||||
| #if PRINT_ARGS | ||||
| 	int i; | ||||
| 	for (i=0; i<*argc; i++) { | ||||
| 		ee_printf("Arg[%d]=%s\n",i,argv[i]); | ||||
| 	} | ||||
| #endif | ||||
| 	if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) { | ||||
| 		ee_printf("ERROR! Please define ee_ptr_int to a type that holds a pointer!\n"); | ||||
| 	} | ||||
| 	if (sizeof(ee_u32) != 4) { | ||||
| 		ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n"); | ||||
| 	} | ||||
| #if (MAIN_HAS_NOARGC && (SEED_METHOD==SEED_ARG)) | ||||
| 	ee_printf("ERROR! Main has no argc, but SEED_METHOD defined to SEED_ARG!\n"); | ||||
| #endif | ||||
| 
 | ||||
| #if (MULTITHREAD>1) && (SEED_METHOD==SEED_ARG) | ||||
| 	int nargs=*argc,i; | ||||
| 	if ((nargs>1) && (*argv[1]=='M')) { | ||||
| 		default_num_contexts=parseval(argv[1]+1); | ||||
| 		if (default_num_contexts>MULTITHREAD) | ||||
| 			default_num_contexts=MULTITHREAD; | ||||
| 		/* Shift args since first arg is directed to the portable part and not to coremark main */ | ||||
| 		--nargs; | ||||
| 		for (i=1; i<nargs; i++) | ||||
| 			argv[i]=argv[i+1]; | ||||
| 		*argc=nargs; | ||||
| 	} | ||||
| #endif /* sample of potential platform specific init via command line, reset the number of contexts being used if first argument is M<n>*/ | ||||
| 	p->portable_id=1; | ||||
| } | ||||
| /* Function: portable_fini
 | ||||
| 	Target specific final code | ||||
| */ | ||||
| void portable_fini(core_portable *p) | ||||
| { | ||||
| 	p->portable_id=0; | ||||
| } | ||||
| 
 | ||||
| #if (MULTITHREAD>1) | ||||
| 
 | ||||
| /* Function: core_start_parallel
 | ||||
| 	Start benchmarking in a parallel context. | ||||
| 
 | ||||
| 	Three implementations are provided, one using pthreads, one using fork and shared mem, and one using fork and sockets. | ||||
| 	Other implementations using MCAPI or other standards can easily be devised. | ||||
| */ | ||||
| /* Function: core_stop_parallel
 | ||||
| 	Stop a parallel context execution of coremark, and gather the results. | ||||
| 
 | ||||
| 	Three implementations are provided, one using pthreads, one using fork and shared mem, and one using fork and sockets. | ||||
| 	Other implementations using MCAPI or other standards can easily be devised. | ||||
| */ | ||||
| #if USE_PTHREAD | ||||
| ee_u8 core_start_parallel(core_results *res) { | ||||
| 	return (ee_u8)pthread_create(&(res->port.thread),NULL,iterate,(void *)res); | ||||
| } | ||||
| ee_u8 core_stop_parallel(core_results *res) { | ||||
| 	void *retval; | ||||
| 	return (ee_u8)pthread_join(res->port.thread,&retval); | ||||
| } | ||||
| #elif USE_FORK | ||||
| static int key_id=0; | ||||
| ee_u8 core_start_parallel(core_results *res) { | ||||
| 	key_t key=4321+key_id; | ||||
| 	key_id++; | ||||
| 	res->port.pid=fork(); | ||||
| 	res->port.shmid=shmget(key, 8, IPC_CREAT | 0666); | ||||
| 	if (res->port.shmid<0) { | ||||
| 		ee_printf("ERROR in shmget!\n"); | ||||
| 	} | ||||
| 	if (res->port.pid==0) { | ||||
| 		iterate(res); | ||||
| 		res->port.shm=shmat(res->port.shmid, NULL, 0); | ||||
| 		/* copy the validation values to the shared memory area  and quit*/ | ||||
| 		if (res->port.shm == (char *) -1) { | ||||
| 			ee_printf("ERROR in child shmat!\n"); | ||||
| 		} else { | ||||
| 			memcpy(res->port.shm,&(res->crc),8); | ||||
| 			shmdt(res->port.shm); | ||||
| 		} | ||||
| 		exit(0); | ||||
| 	} | ||||
| 	return 1; | ||||
| } | ||||
| ee_u8 core_stop_parallel(core_results *res) { | ||||
| 	int status; | ||||
| 	pid_t wpid = waitpid(res->port.pid,&status,WUNTRACED); | ||||
| 	if (wpid != res->port.pid) { | ||||
| 		ee_printf("ERROR waiting for child.\n"); | ||||
| 		if (errno == ECHILD) ee_printf("errno=No such child %d\n",res->port.pid); | ||||
| 		if (errno == EINTR) ee_printf("errno=Interrupted\n"); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	/* after process is done, get the values from the shared memory area */ | ||||
| 	res->port.shm=shmat(res->port.shmid, NULL, 0); | ||||
| 	if (res->port.shm == (char *) -1) { | ||||
| 		ee_printf("ERROR in parent shmat!\n"); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	memcpy(&(res->crc),res->port.shm,8); | ||||
| 	shmdt(res->port.shm); | ||||
| 	return 1; | ||||
| } | ||||
| #elif USE_SOCKET | ||||
| static int key_id=0; | ||||
| ee_u8 core_start_parallel(core_results *res) { | ||||
| 	int bound, buffer_length=8; | ||||
| 	res->port.sa.sin_family = AF_INET; | ||||
| 	res->port.sa.sin_addr.s_addr = htonl(0x7F000001); | ||||
| 	res->port.sa.sin_port = htons(7654+key_id); | ||||
| 	key_id++; | ||||
| 	res->port.pid=fork(); | ||||
| 	if (res->port.pid==0) { /* benchmark child */ | ||||
| 		iterate(res); | ||||
| 		res->port.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); | ||||
| 		if (-1 == res->port.sock) /* if socket failed to initialize, exit */   { | ||||
| 			ee_printf("Error Creating Socket"); | ||||
| 		} else { | ||||
| 			int bytes_sent = sendto(res->port.sock, &(res->crc), buffer_length, 0,(struct sockaddr*)&(res->port.sa), sizeof (struct sockaddr_in)); | ||||
| 			if (bytes_sent < 0) | ||||
| 				ee_printf("Error sending packet: %s\n", strerror(errno)); | ||||
| 			close(res->port.sock); /* close the socket */ | ||||
| 		} | ||||
| 		exit(0); | ||||
| 	} | ||||
| 	/* parent process, open the socket */ | ||||
| 	res->port.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); | ||||
| 	bound = bind(res->port.sock,(struct sockaddr*)&(res->port.sa), sizeof(struct sockaddr)); | ||||
| 	if (bound < 0) | ||||
| 		ee_printf("bind(): %s\n",strerror(errno)); | ||||
| 	return 1; | ||||
| } | ||||
| ee_u8 core_stop_parallel(core_results *res) { | ||||
| 	int status; | ||||
| 	int fromlen=sizeof(struct sockaddr); | ||||
| 	int recsize = recvfrom(res->port.sock, &(res->crc), 8, 0, (struct sockaddr*)&(res->port.sa), &fromlen); | ||||
| 	if (recsize < 0) { | ||||
| 		ee_printf("Error in receive: %s\n", strerror(errno)); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	pid_t wpid = waitpid(res->port.pid,&status,WUNTRACED); | ||||
| 	if (wpid != res->port.pid) { | ||||
| 		ee_printf("ERROR waiting for child.\n"); | ||||
| 		if (errno == ECHILD) ee_printf("errno=No such child %d\n",res->port.pid); | ||||
| 		if (errno == EINTR) ee_printf("errno=Interrupted\n"); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	return 1; | ||||
| } | ||||
| #else /* no standard multicore implementation */ | ||||
| #error "Please implement multicore functionality in core_portme.c to use multiple contexts." | ||||
| #endif /* multithread implementations */ | ||||
| #endif | ||||
							
								
								
									
										296
									
								
								benchmarks/riscv-coremark/old/riscv64/core_portme.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										296
									
								
								benchmarks/riscv-coremark/old/riscv64/core_portme.h
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,296 @@ | ||||
| /*
 | ||||
| Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) | ||||
| 
 | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
| 
 | ||||
|     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| 
 | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| 
 | ||||
| Original Author: Shay Gal-on | ||||
| */ | ||||
| 
 | ||||
| /* Topic: Description
 | ||||
| 	This file contains configuration constants required to execute on different platforms | ||||
| */ | ||||
| #ifndef CORE_PORTME_H | ||||
| #define CORE_PORTME_H | ||||
| /************************/ | ||||
| /* Data types and settings */ | ||||
| /************************/ | ||||
| /* Configuration: HAS_FLOAT
 | ||||
| 	Define to 1 if the platform supports floating point. | ||||
| */ | ||||
| #ifndef HAS_FLOAT | ||||
| #define HAS_FLOAT 1 | ||||
| #endif | ||||
| /* Configuration: HAS_TIME_H
 | ||||
| 	Define to 1 if platform has the time.h header file, | ||||
| 	and implementation of functions thereof. | ||||
| */ | ||||
| #ifndef HAS_TIME_H | ||||
| #define HAS_TIME_H 0 | ||||
| #endif | ||||
| /* Configuration: USE_CLOCK
 | ||||
| 	Define to 1 if platform has the time.h header file, | ||||
| 	and implementation of functions thereof. | ||||
| */ | ||||
| #ifndef USE_CLOCK | ||||
| #define USE_CLOCK 0 | ||||
| #endif | ||||
| /* Configuration: HAS_STDIO
 | ||||
| 	Define to 1 if the platform has stdio.h. | ||||
| */ | ||||
| #ifndef HAS_STDIO | ||||
| #define HAS_STDIO 1 | ||||
| #endif | ||||
| /* Configuration: HAS_PRINTF
 | ||||
| 	Define to 1 if the platform has stdio.h and implements the printf function. | ||||
| */ | ||||
| #ifndef HAS_PRINTF | ||||
| #define HAS_PRINTF 1 | ||||
| #endif | ||||
| 
 | ||||
| /* Configuration: CORE_TICKS
 | ||||
| 	Define type of return from the timing functions. | ||||
|  */ | ||||
| #if defined(_MSC_VER) | ||||
| #include <windows.h> | ||||
| typedef size_t CORE_TICKS; | ||||
| #elif HAS_TIME_H | ||||
| #include <time.h> | ||||
| typedef clock_t CORE_TICKS; | ||||
| #else | ||||
| /* Configuration: size_t and clock_t
 | ||||
|      Note these need to match the size of the clock output and the xLen the processor supports | ||||
|  */ | ||||
| typedef unsigned long int size_t; | ||||
| typedef unsigned long int clock_t; | ||||
| typedef clock_t CORE_TICKS; | ||||
| #endif | ||||
| 
 | ||||
| /* Definitions: COMPILER_VERSION, COMPILER_FLAGS, MEM_LOCATION
 | ||||
| 	Initialize these strings per platform | ||||
| */ | ||||
| #ifndef COMPILER_VERSION | ||||
|  #ifdef __GNUC__ | ||||
|  #define COMPILER_VERSION "GCC"__VERSION__ | ||||
|  #else | ||||
|  #define COMPILER_VERSION "Please put compiler version here (e.g. gcc 4.1)" | ||||
|  #endif | ||||
| #endif | ||||
| #ifndef COMPILER_FLAGS | ||||
|  #define COMPILER_FLAGS FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */ | ||||
| #endif | ||||
| #ifndef MEM_LOCATION | ||||
|  #define MEM_LOCATION "Please put data memory location here\n\t\t\t(e.g. code in flash, data on heap etc)" | ||||
|  #define MEM_LOCATION_UNSPEC 1 | ||||
| #endif | ||||
| 
 | ||||
| /* Data Types:
 | ||||
| 	To avoid compiler issues, define the data types that need ot be used for 8b, 16b and 32b in <core_portme.h>. | ||||
| 
 | ||||
| 	*Imprtant*: | ||||
| 	ee_ptr_int needs to be the data type used to hold pointers, otherwise coremark may fail!!! | ||||
| */ | ||||
| typedef signed short ee_s16; | ||||
| typedef unsigned short ee_u16; | ||||
| typedef signed int ee_s32; | ||||
| typedef double ee_f32; | ||||
| typedef unsigned char ee_u8; | ||||
| typedef unsigned int ee_u32; | ||||
| typedef unsigned long long ee_ptr_int; | ||||
| typedef size_t ee_size_t; | ||||
| /* align an offset to point to a 32b value */ | ||||
| #define align_mem(x) (void *)(4 + (((ee_ptr_int)(x) - 1) & ~3)) | ||||
| 
 | ||||
| /* Configuration: SEED_METHOD
 | ||||
| 	Defines method to get seed values that cannot be computed at compile time. | ||||
| 
 | ||||
| 	Valid values: | ||||
| 	SEED_ARG - from command line. | ||||
| 	SEED_FUNC - from a system function. | ||||
| 	SEED_VOLATILE - from volatile variables. | ||||
| */ | ||||
| #ifndef SEED_METHOD | ||||
| #define SEED_METHOD SEED_ARG | ||||
| #endif | ||||
| 
 | ||||
| /* Configuration: MEM_METHOD
 | ||||
| 	Defines method to get a block of memry. | ||||
| 
 | ||||
| 	Valid values: | ||||
| 	MEM_MALLOC - for platforms that implement malloc and have malloc.h. | ||||
| 	MEM_STATIC - to use a static memory array. | ||||
| 	MEM_STACK - to allocate the data block on the stack (NYI). | ||||
| */ | ||||
| #ifndef MEM_METHOD | ||||
| #define MEM_METHOD MEM_MALLOC | ||||
| #endif | ||||
| 
 | ||||
| /* Configuration: MULTITHREAD
 | ||||
| 	Define for parallel execution | ||||
| 
 | ||||
| 	Valid values: | ||||
| 	1 - only one context (default). | ||||
| 	N>1 - will execute N copies in parallel. | ||||
| 
 | ||||
| 	Note: | ||||
| 	If this flag is defined to more then 1, an implementation for launching parallel contexts must be defined. | ||||
| 
 | ||||
| 	Two sample implementations are provided. Use <USE_PTHREAD> or <USE_FORK> to enable them. | ||||
| 
 | ||||
| 	It is valid to have a different implementation of <core_start_parallel> and <core_end_parallel> in <core_portme.c>, | ||||
| 	to fit a particular architecture. | ||||
| */ | ||||
| #ifndef MULTITHREAD | ||||
| #define MULTITHREAD 1 | ||||
| #endif | ||||
| 
 | ||||
| /* Configuration: USE_PTHREAD
 | ||||
| 	Sample implementation for launching parallel contexts | ||||
| 	This implementation uses pthread_thread_create and pthread_join. | ||||
| 
 | ||||
| 	Valid values: | ||||
| 	0 - Do not use pthreads API. | ||||
| 	1 - Use pthreads API | ||||
| 
 | ||||
| 	Note: | ||||
| 	This flag only matters if MULTITHREAD has been defined to a value greater then 1. | ||||
| */ | ||||
| #ifndef USE_PTHREAD | ||||
| #define USE_PTHREAD 0 | ||||
| #endif | ||||
| 
 | ||||
| /* Configuration: USE_FORK
 | ||||
| 	Sample implementation for launching parallel contexts | ||||
| 	This implementation uses fork, waitpid, shmget,shmat and shmdt. | ||||
| 
 | ||||
| 	Valid values: | ||||
| 	0 - Do not use fork API. | ||||
| 	1 - Use fork API | ||||
| 
 | ||||
| 	Note: | ||||
| 	This flag only matters if MULTITHREAD has been defined to a value greater then 1. | ||||
| */ | ||||
| #ifndef USE_FORK | ||||
| #define USE_FORK 0 | ||||
| #endif | ||||
| 
 | ||||
| /* Configuration: USE_SOCKET
 | ||||
| 	Sample implementation for launching parallel contexts | ||||
| 	This implementation uses fork, socket, sendto and recvfrom | ||||
| 
 | ||||
| 	Valid values: | ||||
| 	0 - Do not use fork and sockets API. | ||||
| 	1 - Use fork and sockets API | ||||
| 
 | ||||
| 	Note: | ||||
| 	This flag only matters if MULTITHREAD has been defined to a value greater then 1. | ||||
| */ | ||||
| #ifndef USE_SOCKET | ||||
| #define USE_SOCKET 0 | ||||
| #endif | ||||
| 
 | ||||
| /* Configuration: MAIN_HAS_NOARGC
 | ||||
| 	Needed if platform does not support getting arguments to main. | ||||
| 
 | ||||
| 	Valid values: | ||||
| 	0 - argc/argv to main is supported | ||||
| 	1 - argc/argv to main is not supported | ||||
| */ | ||||
| #ifndef MAIN_HAS_NOARGC | ||||
| #define MAIN_HAS_NOARGC 0 | ||||
| #endif | ||||
| 
 | ||||
| /* Configuration: MAIN_HAS_NORETURN
 | ||||
| 	Needed if platform does not support returning a value from main. | ||||
| 
 | ||||
| 	Valid values: | ||||
| 	0 - main returns an int, and return value will be 0. | ||||
| 	1 - platform does not support returning a value from main | ||||
| */ | ||||
| #ifndef MAIN_HAS_NORETURN | ||||
| #define MAIN_HAS_NORETURN 0 | ||||
| #endif | ||||
| 
 | ||||
| /* Variable: default_num_contexts
 | ||||
| 	Number of contexts to spawn in multicore context. | ||||
| 	Override this global value to change number of contexts used. | ||||
| 
 | ||||
| 	Note: | ||||
| 	This value may not be set higher then the <MULTITHREAD> define. | ||||
| 
 | ||||
| 	To experiment, you can set the <MULTITHREAD> define to the highest value expected, and use argc/argv in the <portable_init> to set this value from the command line. | ||||
| */ | ||||
| extern ee_u32 default_num_contexts; | ||||
| 
 | ||||
| #if (MULTITHREAD>1) | ||||
| #if USE_PTHREAD | ||||
| 	#include <pthread.h> | ||||
| 	#define PARALLEL_METHOD "PThreads" | ||||
| #elif USE_FORK | ||||
| 	#include <unistd.h> | ||||
| 	#include <errno.h> | ||||
| 	#include <sys/wait.h> | ||||
| 	#include <sys/shm.h> | ||||
| 	#include <string.h> /* for memcpy */ | ||||
| 	#define PARALLEL_METHOD "Fork" | ||||
| #elif USE_SOCKET | ||||
| 	#include <sys/types.h> | ||||
| 	#include <sys/socket.h> | ||||
| 	#include <netinet/in.h> | ||||
| 	#include <arpa/inet.h> | ||||
| 	#include <sys/wait.h> | ||||
| 	#include <stdio.h> | ||||
| 	#include <stdlib.h> | ||||
| 	#include <string.h> | ||||
| 	#include <unistd.h> | ||||
| 	#include <errno.h> | ||||
| 	#define PARALLEL_METHOD "Sockets" | ||||
| #else | ||||
| 	#define PARALLEL_METHOD "Proprietary" | ||||
| 	#error "Please implement multicore functionality in core_portme.c to use multiple contexts." | ||||
| #endif /* Method for multithreading */ | ||||
| #endif /* MULTITHREAD > 1 */ | ||||
| 
 | ||||
| typedef struct CORE_PORTABLE_S { | ||||
| #if (MULTITHREAD>1) | ||||
| 	#if USE_PTHREAD | ||||
| 	pthread_t thread; | ||||
| 	#elif USE_FORK | ||||
| 	pid_t pid; | ||||
| 	int shmid; | ||||
| 	void *shm; | ||||
| 	#elif USE_SOCKET | ||||
| 	pid_t pid; | ||||
| 	int sock; | ||||
| 	struct sockaddr_in sa; | ||||
| 	#endif /* Method for multithreading */ | ||||
| #endif /* MULTITHREAD>1 */ | ||||
| 	ee_u8	portable_id; | ||||
| } core_portable; | ||||
| 
 | ||||
| /* target specific init/fini */ | ||||
| void portable_init(core_portable *p, int *argc, char *argv[]); | ||||
| void portable_fini(core_portable *p); | ||||
| 
 | ||||
| #if (SEED_METHOD==SEED_VOLATILE) | ||||
|  #if (VALIDATION_RUN || PERFORMANCE_RUN || PROFILE_RUN) | ||||
|   #define RUN_TYPE_FLAG 1 | ||||
|  #else | ||||
|   #if (TOTAL_DATA_SIZE==1200) | ||||
|    #define PROFILE_RUN 1 | ||||
|   #else | ||||
|    #define PERFORMANCE_RUN 1 | ||||
|   #endif | ||||
|  #endif | ||||
| #endif /* SEED_METHOD==SEED_VOLATILE */ | ||||
| 
 | ||||
| #endif /* CORE_PORTME_H */ | ||||
							
								
								
									
										147
									
								
								benchmarks/riscv-coremark/old/riscv64/core_portme.mak
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										147
									
								
								benchmarks/riscv-coremark/old/riscv64/core_portme.mak
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,147 @@ | ||||
| # Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
 | ||||
| #
 | ||||
| # Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| # you may not use this file except in compliance with the License.
 | ||||
| # You may obtain a copy of the License at
 | ||||
| #
 | ||||
| #    http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| #
 | ||||
| # Unless required by applicable law or agreed to in writing, software
 | ||||
| # distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| # See the License for the specific language governing permissions and
 | ||||
| # limitations under the License.
 | ||||
| #
 | ||||
| # Original Author: Shay Gal-on
 | ||||
| 
 | ||||
| #File: core_portme.mak
 | ||||
| 
 | ||||
| # Flag: RISCVTOOLS
 | ||||
| #	Use this flag to point to your RISCV tools
 | ||||
| RISCVTOOLS=$(RISCV) | ||||
| # Flag: RISCVTYPE
 | ||||
| #   Type of toolchain to use
 | ||||
| RISCVTYPE=riscv64-unknown-elf | ||||
| # Flag: OUTFLAG
 | ||||
| #	Use this flag to define how to to get an executable (e.g -o)
 | ||||
| OUTFLAG= -o | ||||
| # Flag: CC
 | ||||
| #	Use this flag to define compiler to use
 | ||||
| CC = $(RISCVTOOLS)/bin/$(RISCVTYPE)-gcc | ||||
| # Flag: CFLAGS
 | ||||
| #	Use this flag to define compiler options. Note, you can add compiler options from the command line using XCFLAGS="other flags"
 | ||||
| #PORT_CFLAGS = -O2 -static -std=gnu99
 | ||||
| PORT_CFLAGS = -O2 | ||||
| FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)" | ||||
| CFLAGS = $(PORT_CFLAGS) -I$(PORT_DIR) -I. -DFLAGS_STR=\"$(FLAGS_STR)\" | ||||
| #Flag: LFLAGS_END
 | ||||
| #	Define any libraries needed for linking or other flags that should come at the end of the link line (e.g. linker scripts).
 | ||||
| #	Note: On certain platforms, the default clock_gettime implementation is supported but requires linking of librt.
 | ||||
| LFLAGS_END += | ||||
| # Flag: PORT_SRCS
 | ||||
| # Port specific source files can be added here
 | ||||
| PORT_SRCS = $(PORT_DIR)/core_portme.c | ||||
| # Flag: LOAD
 | ||||
| #	Define this flag if you need to load to a target, as in a cross compile environment.
 | ||||
| 
 | ||||
| # Flag: RUN
 | ||||
| #	Define this flag if running does not consist of simple invocation of the binary.
 | ||||
| #	In a cross compile environment, you need to define this.
 | ||||
| 
 | ||||
| #For flashing and using a tera term macro, you could use
 | ||||
| #LOAD = flash ADDR
 | ||||
| #RUN =  ttpmacro coremark.ttl
 | ||||
| 
 | ||||
| #For copying to target and executing via SSH connection, you could use
 | ||||
| #LOAD = scp $(OUTFILE)  user@target:~
 | ||||
| #RUN = ssh user@target -c
 | ||||
| 
 | ||||
| #For native compilation and execution
 | ||||
| LOAD = echo Loading done | ||||
| RUN = spike pk | ||||
| 
 | ||||
| OEXT = .o | ||||
| EXE = .riscv | ||||
| 
 | ||||
| # Flag: SEPARATE_COMPILE
 | ||||
| # Define if you need to separate compilation from link stage.
 | ||||
| # In this case, you also need to define below how to create an object file, and how to link.
 | ||||
| ifdef SEPARATE_COMPILE | ||||
| 
 | ||||
| LD		= $(RISCVTOOLS)/bin/$(RISCVTYPE)-gcc | ||||
| OBJOUT 	= -o | ||||
| LFLAGS 	= | ||||
| OFLAG 	= -o | ||||
| COUT 	= -c | ||||
| # Flag: PORT_OBJS
 | ||||
| # Port specific object files can be added here
 | ||||
| PORT_OBJS = $(PORT_DIR)/core_portme$(OEXT) | ||||
| PORT_CLEAN = *$(OEXT) | ||||
| 
 | ||||
| $(OPATH)%$(OEXT) : %.c | ||||
| 	$(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@ | ||||
| 
 | ||||
| endif | ||||
| 
 | ||||
| # Target: port_prebuild
 | ||||
| # Generate any files that are needed before actual build starts.
 | ||||
| # E.g. generate profile guidance files. Sample PGO generation for gcc enabled with PGO=1
 | ||||
| #  - First, check if PGO was defined on the command line, if so, need to add -fprofile-use to compile line.
 | ||||
| #  - Second, if PGO reference has not yet been generated, add a step to the prebuild that will build a profile-generate version and run it.
 | ||||
| #  Note - Using REBUILD=1
 | ||||
| #
 | ||||
| # Use make PGO=1 to invoke this sample processing.
 | ||||
| 
 | ||||
| ifdef PGO | ||||
|  ifeq (,$(findstring $(PGO),gen)) | ||||
|   PGO_STAGE=build_pgo_gcc | ||||
|   CFLAGS+=-fprofile-use | ||||
|  endif | ||||
|  PORT_CLEAN+=*.gcda *.gcno gmon.out | ||||
| endif | ||||
| 
 | ||||
| .PHONY: port_prebuild | ||||
| port_prebuild: $(PGO_STAGE) | ||||
| 
 | ||||
| .PHONY: build_pgo_gcc | ||||
| build_pgo_gcc: | ||||
| 	$(MAKE) PGO=gen XCFLAGS="$(XCFLAGS) -fprofile-generate -DTOTAL_DATA_SIZE=1200" ITERATIONS=10 gen_pgo_data REBUILD=1 | ||||
| 
 | ||||
| # Target: port_postbuild
 | ||||
| # Generate any files that are needed after actual build end.
 | ||||
| # E.g. change format to srec, bin, zip in order to be able to load into flash
 | ||||
| .PHONY: port_postbuild | ||||
| port_postbuild: | ||||
| 
 | ||||
| # Target: port_postrun
 | ||||
| # 	Do platform specific after run stuff.
 | ||||
| #	E.g. reset the board, backup the logfiles etc.
 | ||||
| .PHONY: port_postrun | ||||
| port_postrun: | ||||
| 
 | ||||
| # Target: port_prerun
 | ||||
| # 	Do platform specific after run stuff.
 | ||||
| #	E.g. reset the board, backup the logfiles etc.
 | ||||
| .PHONY: port_prerun | ||||
| port_prerun: | ||||
| 
 | ||||
| # Target: port_postload
 | ||||
| # 	Do platform specific after load stuff.
 | ||||
| #	E.g. reset the reset power to the flash eraser
 | ||||
| .PHONY: port_postload | ||||
| port_postload: | ||||
| 
 | ||||
| # Target: port_preload
 | ||||
| # 	Do platform specific before load stuff.
 | ||||
| #	E.g. reset the reset power to the flash eraser
 | ||||
| .PHONY: port_preload | ||||
| port_preload: | ||||
| 
 | ||||
| # FLAG: OPATH
 | ||||
| # Path to the output folder. Default - current folder.
 | ||||
| OPATH = ./ | ||||
| MKDIR = mkdir -p | ||||
| 
 | ||||
| # FLAG: PERL
 | ||||
| # Define perl executable to calculate the geomean if running separate.
 | ||||
| PERL=/usr/bin/perl | ||||
							
								
								
									
										48
									
								
								benchmarks/riscv-coremark/old/trace
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								benchmarks/riscv-coremark/old/trace
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | ||||
| Imperas riscvOVPsimPlus | ||||
| 
 | ||||
| 
 | ||||
| riscvOVPsimPlus (64-Bit) v20210329.0 Open Virtual Platform simulator from www.IMPERAS.com. | ||||
| Copyright (c) 2005-2021 Imperas Software Ltd.  Contains Imperas Proprietary Information. | ||||
| Licensed Software, All Rights Reserved. | ||||
| Visit www.IMPERAS.com for multicore debug, verification and analysis solutions. | ||||
| 
 | ||||
| riscvOVPsimPlus started: Wed May 12 17:55:33 2021 | ||||
| 
 | ||||
| 
 | ||||
| Info (GDBT_PORT) Host: Tera.Eng.HMC.Edu, Port: 55460 | ||||
| Info (DBC_LGDB) Starting Debugger /cad/riscv/imperas-riscv-tests/riscv-ovpsim-plus/bin/Linux64/riscv-none-embed-gdb | ||||
| Info (GDBT_WAIT) Waiting for remote debugger to connect... | ||||
| Info (OR_OF) Target 'riscvOVPsim/cpu' has object file read from 'coremark.bare.riscv' | ||||
| Info (OR_PH) Program Headers: | ||||
| Info (OR_PH) Type           Offset             VirtAddr           PhysAddr | ||||
| Info (OR_PH)                FileSiz            MemSiz             Flags  Align | ||||
| Info (OR_PD) LOAD           0x0000000000001000 0x0000000080000000 0x0000000080000000 | ||||
| Info (OR_PD)                0x0000000000000204 0x0000000000000204 R-E    1000 | ||||
| Info (OR_PD) LOAD           0x0000000000002000 0x0000000080001000 0x0000000080001000 | ||||
| Info (OR_PD)                0x00000000000047e0 0x0000000000004ff0 RWE    1000 | ||||
| Info (GDBT_CONNECTED) Client connected | ||||
| Info (GDBT_GON) Client disappeared 'riscvOVPsim/cpu' | ||||
| Info  | ||||
| Info --------------------------------------------------- | ||||
| Info CPU 'riscvOVPsim/cpu' STATISTICS | ||||
| Info   Type                  : riscv (RV64GC) | ||||
| Info   Nominal MIPS          : 100 | ||||
| Info   Final program counter : 0x80003558 | ||||
| Info   Simulated instructions: 1,455,608 | ||||
| Info   Simulated MIPS        : 0.0 | ||||
| Info --------------------------------------------------- | ||||
| Info  | ||||
| Info --------------------------------------------------- | ||||
| Info SIMULATION TIME STATISTICS | ||||
| Info   Simulated time        : 0.02 seconds | ||||
| Info   User time             : 99.23 seconds | ||||
| Info   System time           : 254.08 seconds | ||||
| Info   Elapsed time          : 1107.49 seconds | ||||
| Info --------------------------------------------------- | ||||
| 
 | ||||
| riscvOVPsimPlus finished: Wed May 12 18:14:04 2021 | ||||
| 
 | ||||
| 
 | ||||
| riscvOVPsimPlus (64-Bit) v20210329.0 Open Virtual Platform simulator from www.IMPERAS.com. | ||||
| Visit www.IMPERAS.com for multicore debug, verification and analysis solutions. | ||||
| 
 | ||||
							
								
								
									
										8
									
								
								benchmarks/riscv-coremark/old/transferobjdump.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										8
									
								
								benchmarks/riscv-coremark/old/transferobjdump.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,8 @@ | ||||
| #!/usr/bin/env bash | ||||
| ./build-coremark.sh | ||||
| 
 | ||||
| riscv64-unknown-elf-objdump -D coremark.bare.riscv > coremarkcodemod.bare.riscv.objdump  | ||||
| cp coremarkcodemod.bare.riscv.objdump ~/riscv-wally/tests/imperas-riscv-tests/riscv-ovpsim-plus/examples/CoreMark/. | ||||
| pushd ~/riscv-wally/tests/imperas-riscv-tests/riscv-ovpsim-plus/examples/CoreMark | ||||
| ./exe2memfile.pl coremarkcodemod.bare.riscv | ||||
| popd | ||||
| @ -7,6 +7,7 @@ | ||||
| #include <limits.h> | ||||
| #include <sys/signal.h> | ||||
| #include "util.h" | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #define SYS_write 64 | ||||
| 
 | ||||
| @ -80,6 +81,7 @@ void __attribute__((noreturn)) tohost_exit(uintptr_t code) | ||||
| { | ||||
|   tohost = (code << 1) | 1; | ||||
|   asm ("ecall"); | ||||
|   exit(0); | ||||
| } | ||||
| 
 | ||||
| uintptr_t __attribute__((weak)) handle_trap(uintptr_t cause, uintptr_t epc, uintptr_t regs[32]) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user