diff --git a/apps/Makefile b/apps/Makefile index 94912228..e45d1a38 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -1,4 +1,4 @@ -C_source := tests.c echo.c netio.c +C_source := tests.c echo.c netio.c laplace.c gfx_client.c gfx_generic.c MODULE := apps include $(TOPDIR)/Makefile.inc diff --git a/apps/gfx_client.c b/apps/gfx_client.c new file mode 100644 index 00000000..5614849d --- /dev/null +++ b/apps/gfx_client.c @@ -0,0 +1,146 @@ +/* + * Copyright 2011 Sarah Fischer, Nicolas Berr, Pablo Reble + * Chair for Operating Systems, RWTH Aachen University + * + * 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. + * + * This file is part of MetalSVM. + */ + +#include + +#ifdef CONFIG_LWIP + +#include "gfx_client.h" +#include + +static int myrank; +static int sockfd; + +#ifndef SINGLE_CONNECT +#define SINGLE_CONNECT 1 +#endif +#define SINGLE_CONNECT_RANK 0 +#define USE_GETHOSTBYNAME 0 + +//int gfx_init(int* pargc, char*** pargv, int rank){ +int gfx_init(char* ip_str, char* port_str, int rank) { + char* hostname; + int port; + struct sockaddr_in serveraddr; + struct hostent *server; + + //*pargc -=2; + myrank = rank; + +#if SINGLE_CONNECT + // currently only rank 0 will connect to the gfx-server + if (rank != SINGLE_CONNECT_RANK) { + return 0; + } +#endif + + /* hostname und port aus den parametern ermitteln) */ + //kprintf("pargc: %d\n", *pargc); + + hostname = ip_str; //(*pargv)[(*pargc)]; + port = atoi(port_str); //atoi((*pargv)[(*pargc)+1]); + + kprintf("gfx-client connecting to host: %s, port: %d\n", hostname, port); + + /* socket erzeugen */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + return -1; + +#if 1 + /* Disable the Nagle (TCP No Delay) algorithm */ + int flag = 1; + if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag)) < 0) { + kprintf("Couldn't setsockopt(TCP_NODELAY)\n"); + return -1; + } +#endif + +#if USE_GETHOSTBYNAME + /* dns eintrag vom server ermitteln */ + serveraddr = gethostbyname(hostname); + if (server == NULL){ + fprintf(stderr, "%s: no such host\n", hostname); + return -2; + } +#endif + + /* adresse vom server ermitteln */ + memset((char *) &serveraddr, 0x00, sizeof(serveraddr)); + serveraddr.sin_family = AF_INET; +#if USE_GETHOSTBYNAME + bcopy((char *)server->h_addr, (char *)&serveraddr.sin_addr.s_addr, server->h_length); +#else + serveraddr.sin_addr.s_addr = inet_addr(hostname); +#endif + serveraddr.sin_port = htons(port); + + /* verbindung herstellen */ + if (connect(sockfd, (const struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0) + return -3; + + return 0; +} + +int gfx_send(char* buf, int size, int tag){ + int ret, pos = 0; + uint32_t u32size, u32tag; + +#if SINGLE_CONNECT + if (myrank != SINGLE_CONNECT_RANK) + return 0; +#endif + + u32size = size; + u32tag = tag; + +// printf("sending stuff...."); +// printf("tag: %d, size: %d\n", tag, size); +// fflush(stdout); + + ret = write(sockfd, &u32tag, sizeof(u32tag)); + if (ret != sizeof(tag)) + return -1; + ret = write(sockfd, &u32size, sizeof(u32size)); + if (ret != sizeof(size)) + return -2; + + + do{ + ret = write(sockfd, &buf[pos], size-pos); + pos += ret; + } while (pos < size); + + + return 0; +} + +int gfx_finalize(){ + // uint32_t u32tag = (uint32_t)(-1); + uint32_t u32tag = 1111; +#if SINGLE_CONNECT + if (myrank == SINGLE_CONNECT_RANK) { + write(sockfd, &u32tag, sizeof(u32tag)); + close(sockfd); + } +#endif + return 0; +} + +#endif diff --git a/apps/gfx_client.h b/apps/gfx_client.h new file mode 100644 index 00000000..c36743c7 --- /dev/null +++ b/apps/gfx_client.h @@ -0,0 +1,50 @@ +/* + * Copyright 2011 Sarah Fischer, Nicolas Berr, Pablo Reble + * Chair for Operating Systems, RWTH Aachen University + * + * 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. + * + * This file is part of MetalSVM. + */ + +#ifndef __GFX_CLIENT_H__ +#define __GFX_CLIENT_H__ + +#include +#include +#include + +#ifdef CONFIG_LWIP + +#define BUFSIZE 1024 + +/* + * grafik initialisieren, letzte beide argumente, ip und port, werden entfernt + * verbindung zu server aufbauen, kollektiver aufruf, erstmal nur rank 0 connecten +*/ +//int gfx_init(int* pargc, char*** pargv, int rank); +int gfx_init(char* ip_str, char* port_str, int rank); + +/* + * paket mit der geg. laenge wird an den server gesehendet, das tag soll auch uebertragen werden +*/ +int gfx_send(char* buf, int size, int tag); + +/* + * kollektiver aufruf, vorhandene verbindungen kontrolliert beenden +*/ +int gfx_finalize(); + +#endif + +#endif diff --git a/apps/gfx_generic.c b/apps/gfx_generic.c new file mode 100644 index 00000000..63b6e570 --- /dev/null +++ b/apps/gfx_generic.c @@ -0,0 +1,138 @@ +/* + * Copyright 2011 Sarah Fischer, Nicolas Berr, Pablo Reble + * Chair for Operating Systems, RWTH Aachen University + * + * 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. + * + * This file is part of MetalSVM. + */ + +#include "gfx_client.h" +#include "gfx_generic.h" + +#ifdef CONFIG_LWIP + +int GFX_init(int* pargc, char*** pargv, int rank) +{ + return gfx_init(pargc, pargv, rank); +} + +int GFX_send(char* buf, int size, int tag) +{ + return gfx_send(buf, size, tag); +} + +int GFX_finalize() +{ + return gfx_finalize(); +} + +int GFX_update() +{ + return gfx_send(NULL, 0, GFX_UPDATE); +} + +int GFX_usleep(int sleep_time) +{ + int buf[1]; + buf[0] = sleep_time; + return gfx_send((char*)buf, sizeof(int), GFX_USLEEP); +} + +int GFX_set_rgb(int index, int r, int g, int b) +{ + int buf[4]; + buf[0] = index; + buf[1] = r; + buf[2] = g; + buf[3] = b; + return gfx_send((char*)buf, 4*sizeof(int), GFX_SET_RGB); +} + +int GFX_set_xy(int x, int y) +{ + int buf[2]; + buf[0] = x; + buf[1] = y; + return gfx_send((char*)buf, 2*sizeof(int), GFX_SET_XY); +} + +int GFX_set_hd(int height, int direction) +{ + int buf[2]; + buf[0] = height; + buf[1] = direction; + return gfx_send((char*)buf, 2*sizeof(int), GFX_SET_HD); +} + + +int GFX_draw_data(char *buf, int len) +{ + return gfx_send(buf, len, GFX_DRAW_DATA); +} + +int GFX_draw_pixel(int x, int y, int color) +{ + int buf[3]; + buf[0] = x; + buf[1] = y; + buf[2] = color; + return gfx_send((char*)buf, 3*sizeof(int), GFX_DRAW_PIXEL); +} + +int GFX_draw_line(int x1, int y1, int x2, int y2, int color) +{ + int buf[5]; + buf[0] = x1; + buf[1] = y1; + buf[2] = x2; + buf[3] = y2; + buf[4] = color; + return gfx_send((char*)buf, 5*sizeof(int), GFX_DRAW_LINE); +} + +int GFX_draw_box(int x, int y, int height, int width, int color) +{ + int buf[5]; + buf[0] = x; + buf[1] = y; + buf[2] = height; + buf[3] = width; + buf[4] = color; + return gfx_send((char*)buf, 5*sizeof(int), GFX_DRAW_BOX); +} + +int GFX_draw_text(int x, int y, int color, char *text) +{ + int buf[32]; + buf[0] = x; + buf[1] = y; + buf[2] = color; + strcpy((char*)&(buf[3]), text); + + return gfx_send((char*)buf, 32*sizeof(int), GFX_DRAW_TEXT); +} + +int GFX_draw_points(int* points, int num) +{ + return gfx_send((char*)points, num*3*sizeof(int), GFX_DRAW_POINTS); +} + +int GFX_draw_poly(int* points, int num, int color) +{ + int i; + for(i=0; i +#include +#include +#include + +#ifdef CONFIG_ROCKCREEK + +#include +#include + +#define _LAPLACE_SHMEM_ +//#define _USE_GFX + +#ifdef _LAPLACE_SHMEM_ +#define SINGLE_CONNECT 1 +#else +#define SINGLE_CONNECT 0 +#endif + +#ifdef _USE_GFX +#include "gfx_generic.h" +#include "gfx_client.h" +#endif + +#define ABS(a) (((a) < 0) ? -(a) : (a)) +#define MAX(a,b) (((a) < (b)) ? (b) : (a)) + +#define N 512 +#define M 512 + +#define TMAX 100*50 + +//#define DATA unsigned int +#define DATA double +//#define FIX 1024 +#define FIX 1 + +#define USE_SVM 0 +#define MEMTYPE SVM_STRONG +//#define MEMTYPE SVM_LAZYRELEASE + +static inline double pow(double a, int b) +{ + double base = a; + int i; + + for (i = 1; i < b; ++i) + a *= base; + + return a; +} + +int laplace(void *arg) +{ + //char* argv[] = {"/bin/laplace", "192.168.4.254", "12301", NULL}; + //int argc = 3; + uint32_t flags; +#ifdef _USE_GFX + uint32_t ret; +#endif + int t; + + int i, I, j, J; + int my_rank; + int num_ranks; + + int n; + int m; + + volatile DATA **NewValues; + volatile DATA **OldValues; + + volatile DATA **tmp; + + volatile char **BufValues; + + uint64_t start, end; + + flags = irq_nested_disable(); + my_rank = RCCE_ue(); + num_ranks = RCCE_num_ues(); + irq_nested_enable(flags); + +#ifdef _USE_GFX + kprintf("Laplace calls gfx_init\n"); + ret = gfx_init("192.168.4.254" /*&argc */ , "5000" /*&argv */ , my_rank); + kprintf("gfx_init: %d\n", ret); +#endif + + m = M; + J = 0; + + n = N / num_ranks; + + if (my_rank == num_ranks - 1) + n += N % num_ranks; + I = n * my_rank; + + kprintf("(%d) %d x %d / offsets: %d, %d / (%d x %d)\n", my_rank, N, M, I, J, n, m); + +#ifdef _USE_GFX + if (my_rank == 0) { + for (i = 0; i < 256; i++) { +//set color index, r, g, b + if (i < 64) + GFX_set_rgb(i, 0, i * 256 / 64, 255); + else if (i < 128) + GFX_set_rgb(i, 0, 255, 255 - ((i - 64) * 256 / 64)); + else if (i < 192) + GFX_set_rgb(i, (i - 128) * 256 / 64, 255, 0); + else if (i < 256) + GFX_set_rgb(i, 255, 255 - ((i - 192) * 256 / 64), 0); + } +// TODO: move draw area to center + //GFX_set_xy(150, 150); + GFX_set_hd(N, 0); + } +#endif + + NewValues = (volatile DATA **)kmalloc((N + 2) * sizeof(DATA *)); +#if USE_SVM + NewValues[0] = (DATA *) svmmalloc((N + 2) * (M + 2) * sizeof(DATA), MEMTYPE); +#else + NewValues[0] = (DATA *) kmalloc((N + 2) * (M + 2) * sizeof(DATA)); +#endif + + OldValues = (volatile DATA **)kmalloc((N + 2) * sizeof(DATA *)); +#if USE_SVM + OldValues[0] = (DATA *) svmmalloc((N + 2) * (M + 2) * sizeof(DATA), MEMTYPE); +#else + OldValues[0] = (DATA *) kmalloc((N + 2) * (M + 2) * sizeof(DATA)); +#endif + + for (i = 1; i < N + 2; i++) { + NewValues[i] = NewValues[i - 1] + (M + 2); + OldValues[i] = OldValues[i - 1] + (M + 2); + } + + BufValues = (volatile char **)kmalloc((N) * sizeof(char *)); + BufValues[0] = (char *)kmalloc((N) * (M) * sizeof(char)); + + for (i = 1; i < N; i++) { + BufValues[i] = BufValues[i - 1] + (M); + } + + RCCE_barrier(&RCCE_COMM_WORLD); + + kprintf("(%d) Memory allocated!\n", my_rank); + + //while (1) + { + int height = N + 2; + int width = M + 2; + + if (my_rank == 0) { + for (i = 0; i < N + 2; i++) { + for (j = 0; j < M + 2; j++) { + + double X = (((double)j / (double)width) * 5.0) - 2.5; + double Y = (((double)i / (double)height) * 5.0) - 2.5; + double Z = 0.0; + + Z = pow((4 - (X + 1) * (X + 1) - 4 * Y * Y), 2) + pow(1.2 * (1 - X), 3) - 10; + + if (Z < 0.0) + Z = 1.0; + else if (Z > 0.0) + Z = 0.0; + + NewValues[i][j] = (DATA) ((Z) * 255.0) * FIX; + + //if(NewValues[i][j] < 0) NewValues[i][j] = 0; + } + } + + for (i = 0; i < N + 2; i++) { + for (j = 0; j < M + 2; j++) { + OldValues[i][j] = NewValues[i][j]; + } + } + } + + svm_flush(); + svm_invalidate(); + RCCE_barrier(&RCCE_COMM_WORLD); + + kprintf("(%d) Arrays initialized!\n", my_rank); + + start = rdtsc(); + start = rdtsc(); + +// START ITERATIONS LOOP + for (t = 0; t < TMAX; t++) { + + //kprintf("(%d): o:%u n:%u \n",my_rank,(unsigned int)(OldValues[I+1][J+1]), (unsigned int)(NewValues[I+1][J+1]) ); + +// over all collumns + for (i = 1; i < n + 1; i++) { +// over all rows + for (j = 1; j < m + 1; j++) { +#if 1 + NewValues[I + i][J + j] = + (OldValues[I + i - 1][J + j] + + OldValues[I + i + 1][J + j] + + OldValues[I + i][J + j - 1] + + OldValues[I + i][J + j + 1]) / 4; + //if ( NewValues[I+i][J+j] < 0.0 ) NewValues[I+i][J+j] = 0.0 * FIX; + //else if ( NewValues[I+i][J+j] > 255.0 ) NewValues[I+i][J+j] = 255.0 * FIX; +#else + NewValues[I + i][J + j] = 25 * (DATA) (my_rank + 1); +#endif + } + } + + svm_flush(); + svm_invalidate(); + + tmp = NewValues; + NewValues = OldValues; + OldValues = tmp; + + RCCE_barrier(&RCCE_COMM_WORLD); + +#ifdef _USE_GFX + if ((my_rank == 0) && (t % 50 == 0)) { + int diff, res = 0; + + for (i = 1; i < N + 1; i++) { + for (j = 1; j < M + 1; j++) { + + diff = ABS(NewValues[i][j] - OldValues[i][j]); + if (diff > res) + res = diff; + + BufValues[i - 1][j - 1] = (unsigned char)(NewValues[i][j] / FIX); + //GFX_draw_pixel(150+j, 150+my_rank*n+i, (unsigned char)NewValues[i+1][j+1]); + //GFX_update(); + } + } + + kprintf("Graphic UPDATE! (t=%d) residual:%u \n", t, res); + GFX_draw_data((char *)(BufValues[0]), (N) * (M)); + GFX_update(); + } +#endif +// END ITERATIONS LOOP + } + + RCCE_barrier(&RCCE_COMM_WORLD); + + end = rdtsc(); + + kprintf("Calculation time: %llu ms (%llu ticks)\n", (end-start)/(1000ULL*get_cpu_frequency()), end-start); + + svm_statistics(); + } + + kprintf("(%d) Algorithm completed!\n", my_rank); + + // TODO: Freeing memory regions + +#ifdef _USE_GFX + gfx_finalize(); +#endif + + return 0; +} + +#endif