ported matrix mul and richards

This commit is contained in:
2026-04-15 17:27:30 +01:00
parent 365a35e61b
commit b14264eb45
22 changed files with 3839 additions and 40 deletions

View File

@@ -0,0 +1,58 @@
# scp ../../encoding.h home-1:/home/akilan/
# scp ../../entry.S home-1:/home/akilan/
# scp ../../link.ld home-1:/home/akilan/
# scp ../../riscv_test_p.h home-1:/home/akilan/
# scp ../../riscv_test.h home-1:/home/akilan/
# scp ../../string.c home-1:/home/akilan/
# scp ../../vm.c home-1:/home/akilan/
# scp ../../test.S home-1:/home/akilan/
# scp ../../test_macros.h home-1:/home/akilan/
# scp ../../malloc.c home-1:/home/akilan/
# # scp ../../test.c home-1:/home/akilan/
# # scp glibc.c home-1:/home/akilan/
# scp code_io.c home-1:/home/akilan/
# scp code.c home-1:/home/akilan/
# scp code.h home-1:/home/akilan/
# scp defs.h home-1:/home/akilan/
# scp getparam.c home-1:/home/akilan/
# scp grav.c home-1:/home/akilan/
scp load.c home-1:/home/akilan/
# scp stdinc.h home-1:/home/akilan/
# scp util.c home-1:/home/akilan/
# scp vectmath.h home-1:/home/akilan/
# GCC compile
# ssh home-1 'cd /home/akilan/ && export PATH=/opt/riscv/bin:$PATH && riscv64-unknown-elf-gcc -DENTROPY=0xf21e02b -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -mabi=lp64 -T link.ld vm.c string.c entry.S test.S -o testC'
# Clang compile (architecture Regular RISCV)
ssh home-1 'clang --target=riscv64-unknown-elf -DENTROPY=0xf21e02b -DDEFINE_MALLOC -DDEFINE_FREE --gcc-toolchain=/opt/riscv -std=gnu89 -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -fno-builtin-malloc -mabi=lp64 -lm -T link.ld vm.c string.c malloc.c entry.S test.S code_io.c code.c getparam.c grav.c load.c util.c -o testC'
# Clang using the cheri clang compiler
# ssh home-1 'cd cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-freebsd -DENTROPY=0xf21e02b --sysroot=cheribsd-riscv64-for-purecap-rootfs.cfg -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -march=rv64imafdcxcheri -mabi=lp64d -T link.ld vm.c string.c entry.S test.S -o testC'
scp home-1:/home/akilan/testC ../../../
# scp home-1:/home/akilan/cheri/output/sdk/bin/testC .
# riscv64-unknown-elf-gcc \
# -march=rv64imac \
# -mabi=lp64 \
# -nostartfiles \
# -fno-builtin \
# -T link.ld \
# entry.S vm.c string.c \
# clang \
# --target=riscv64-unknown-elf \
# -march=rv64imac \
# -mabi=lp64 \
# -nostdlib \
# -nostartfiles \
# -fuse-ld=lld \
# -T link.ld \
# entry.S vm.c string.c \
# -I. \
# -o output.elf%

View File

@@ -0,0 +1,841 @@
#line 95 "./null_macros/c.m4.null"
#line 1 "code.C"
/*************************************************************************/
/* */
/* Copyright (c) 1994 Stanford University */
/* */
/* All rights reserved. */
/* */
/* Permission is given to use, copy, and modify this software for any */
/* non-commercial purpose as long as this copyright notice is not */
/* removed. All other uses, including redistribution in whole or in */
/* part, are forbidden without prior written permission. */
/* */
/* This software is provided with absolutely no warranty and no */
/* support. */
/* */
/*************************************************************************/
/*
Usage: BARNES <options> < inputfile
Command line options:
-h : Print out input file description
Input parameters should be placed in a file and redirected through
standard input. There are a total of twelve parameters, and all of
them have default values.
1) infile (char*) : The name of an input file that contains particle
data.
The format of the file is:
a) An int representing the number of particles in the distribution
b) An int representing the dimensionality of the problem (3-D)
c) A double representing the current time of the simulation
d) Doubles representing the masses of all the particles
e) A vector (length equal to the dimensionality) of doubles
representing the positions of all the particles
f) A vector (length equal to the dimensionality) of doubles
representing the velocities of all the particles
Each of these numbers can be separated by any amount of whitespace.
2) nbody (int) : If no input file is specified (the first line is
blank), this number specifies the number of particles to generate
under a plummer model. Default is 16384.
3) seed (int) : The seed used by the random number generator.
Default is 123.
4) outfile (char*) : The name of the file that snapshots will be
printed to. This feature has been disabled in the SPLASH release.
Default is NULL.
5) dtime (double) : The integration time-step.
Default is 0.025.
6) eps (double) : The usual potential softening
Default is 0.05.
7) tol (double) : The cell subdivision tolerance.
Default is 1.0.
8) fcells (double) : Number of cells created = fcells * number of
leaves.
Default is 2.0.
9) fleaves (double) : Number of leaves created = fleaves * nbody.
Default is 0.5.
10) tstop (double) : The time to stop integration.
Default is 0.075.
11) dtout (double) : The data-output interval.
Default is 0.25.
12) NPROC (int) : The number of processors.
Default is 1.
*/
#define global /* nada */
#include "code.h"
#include "defs.h"
#include <math.h>
#include <time.h>
#include "malloc.h"
// #define malloc MALLOCCHERI
// #define free FREECHERI
string defv[] = { /* DEFAULT PARAMETER VALUES */
/* file names for input/output */
"in=", /* snapshot of initial conditions */
"out=", /* stream of output snapshots */
/* params, used if no input specified, to make a Plummer Model */
"nbody=16384", /* number of particles to generate */
"seed=123", /* random number generator seed */
/* params to control N-body integration */
"dtime=0.025", /* integration time-step */
"eps=0.05", /* usual potential softening */
"tol=1.0", /* cell subdivision tolerence */
"fcells=2.0", /* cell allocation parameter */
"fleaves=0.5", /* leaf allocation parameter */
"tstop=0.075", /* time to stop integration */
"dtout=0.25", /* data-output interval */
"NPROC=1", /* number of processors */
};
void SlaveStart ();
void stepsystem (unsigned int ProcessId);
void ComputeForces ();
void Help();
FILE *fopen();
void* malloc(size_t);
void free(void*);
main(argc, argv)
int argc;
string argv[];
{
// INITREGULARALLOC(0);
unsigned ProcessId = 0;
int c;
// printf("Run this as\n BARNES < input \n for default values\n");
while ((c = getopt(argc, argv, "h")) != -1) {
switch(c) {
case 'h':
Help();
exit(-1);
break;
default:
// fprintf(stderr, "Only valid option is \"-h\".\n");
exit(-1);
break;
}
}
ANLinit();
initparam(argv, defv);
startrun();
initoutput();
tab_init();
Global->tracktime = 0;
Global->partitiontime = 0;
Global->treebuildtime = 0;
Global->forcecalctime = 0;
/* Create the slave processes: number of processors less one,
since the master will do work as well */
Global->current_id = 0;
// for(ProcessId = 1; ProcessId < NPROC; ProcessId++) {
// {fprintf(stderr, "No more processors -- this is a uniprocessor version!\n"); exit(-1);};
// }
/* Make the master do slave work so we don't waste the processor */
{long time(); (Global->computestart) = time(0);};
// printf("COMPUTESTART = %12u\n",Global->computestart);
SlaveStart();
{long time(); (Global->computeend) = time(0);};
{;};
// printf("COMPUTEEND = %12u\n",Global->computeend);
// printf("COMPUTETIME = %12u\n",Global->computeend - Global->computestart);
// printf("TRACKTIME = %12u\n",Global->tracktime);
// printf("PARTITIONTIME = %12u\t%5.2f\n",Global->partitiontime,
// ((float)Global->partitiontime)/Global->tracktime);
// printf("TREEBUILDTIME = %12u\t%5.2f\n",Global->treebuildtime,
// ((float)Global->treebuildtime)/Global->tracktime);
// printf("FORCECALCTIME = %12u\t%5.2f\n",Global->forcecalctime,
// ((float)Global->forcecalctime)/Global->tracktime);
// printf("RESTTIME = %12u\t%5.2f\n",
// Global->tracktime - Global->partitiontime -
// Global->treebuildtime - Global->forcecalctime,
// ((float)(Global->tracktime-Global->partitiontime-
// Global->treebuildtime-Global->forcecalctime))/
// Global->tracktime);
{exit(0);};
}
/*
* ANLINIT : initialize ANL macros
*/
ANLinit()
{
{;};
/* Allocate global, shared memory */
Global = (struct GlobalMemory *) malloc(sizeof(struct GlobalMemory));;
if (Global==NULL) error("No initialization for Global\n");
{;};
{;};
{;};
{;};
{;};
{;};
{;};
{;};
}
/*
* INIT_ROOT: Processor 0 reinitialize the global root at each time step
*/
init_root (ProcessId)
unsigned int ProcessId;
{
int i;
Global->G_root=Local[0].ctab;
Type(Global->G_root) = CELL;
Done(Global->G_root) = FALSE;
Level(Global->G_root) = IMAX >> 1;
for (i = 0; i < NSUB; i++) {
Subp(Global->G_root)[i] = NULL;
}
Local[0].mynumcell=1;
}
int Log_base_2(number)
int number;
{
int cumulative;
int out;
cumulative = 1;
for (out = 0; out < 20; out++) {
if (cumulative == number) {
return(out);
}
else {
cumulative = cumulative * 2;
}
}
// fprintf(stderr,"Log_base_2: couldn't find log2 of %d\n", number);
exit(-1);
}
/*
* TAB_INIT : allocate body and cell data space
*/
tab_init()
{
cellptr pc;
int i;
char *starting_address, *ending_address;
/*allocate leaf/cell space */
maxleaf = (int) ((double) fleaves * nbody);
maxcell = fcells * maxleaf;
for (i = 0; i < NPROC; ++i) {
Local[i].ctab = (cellptr) malloc((maxcell / NPROC) * sizeof(cell));;
Local[i].ltab = (leafptr) malloc((maxleaf / NPROC) * sizeof(leaf));;
}
/*allocate space for personal lists of body pointers */
maxmybody = (nbody+maxleaf*MAX_BODIES_PER_LEAF)/NPROC;
Local[0].mybodytab = (bodyptr*) malloc(NPROC*maxmybody*sizeof(bodyptr));;
/* space is allocated so that every */
/* process can have a maximum of maxmybody pointers to bodies */
/* then there is an array of bodies called bodytab which is */
/* allocated in the distribution generation or when the distr. */
/* file is read */
maxmycell = maxcell / NPROC;
maxmyleaf = maxleaf / NPROC;
Local[0].mycelltab = (cellptr*) malloc(NPROC*maxmycell*sizeof(cellptr));;
Local[0].myleaftab = (leafptr*) malloc(NPROC*maxmyleaf*sizeof(leafptr));;
CellLock = (struct CellLockType *) malloc(sizeof(struct CellLockType));;
{;};
}
/*
* SLAVESTART: main task for each processor
*/
void SlaveStart()
{
unsigned int ProcessId;
/* Get unique ProcessId */
{;};
ProcessId = Global->current_id++;
{;};
/* POSSIBLE ENHANCEMENT: Here is where one might pin processes to
processors to avoid migration */
/* initialize mybodytabs */
Local[ProcessId].mybodytab = Local[0].mybodytab + (maxmybody * ProcessId);
/* note that every process has its own copy */
/* of mybodytab, which was initialized to the */
/* beginning of the whole array by proc. 0 */
/* before create */
Local[ProcessId].mycelltab = Local[0].mycelltab + (maxmycell * ProcessId);
Local[ProcessId].myleaftab = Local[0].myleaftab + (maxmyleaf * ProcessId);
/* POSSIBLE ENHANCEMENT: Here is where one might distribute the
data across physically distributed memories as desired.
One way to do this is as follows:
int i;
if (ProcessId == 0) {
for (i=0;i<NPROC;i++) {
Place all addresses x such that
&(Local[i]) <= x < &(Local[i])+
sizeof(struct local_memory) on node i
Place all addresses x such that
&(Local[i].mybodytab) <= x < &(Local[i].mybodytab)+
maxmybody * sizeof(bodyptr) - 1 on node i
Place all addresses x such that
&(Local[i].mycelltab) <= x < &(Local[i].mycelltab)+
maxmycell * sizeof(cellptr) - 1 on node i
Place all addresses x such that
&(Local[i].myleaftab) <= x < &(Local[i].myleaftab)+
maxmyleaf * sizeof(leafptr) - 1 on node i
}
}
barrier(Global->Barstart,NPROC);
*/
Local[ProcessId].tout = Local[0].tout;
Local[ProcessId].tnow = Local[0].tnow;
Local[ProcessId].nstep = Local[0].nstep;
find_my_initial_bodies(bodytab, nbody, ProcessId);
/* main loop */
while (Local[ProcessId].tnow < tstop + 0.1 * dtime) {
stepsystem(ProcessId);
}
}
/*
* STARTRUN: startup hierarchical N-body code.
*/
startrun()
{
string getparam();
int getiparam();
bool getbparam();
double getdparam();
int seed;
infile = getparam("in");
if (*infile != NULL) {
inputdata();
}
else {
nbody = getiparam("nbody");
if (nbody < 1) {
error("startrun: absurd nbody\n");
}
seed = getiparam("seed");
}
outfile = getparam("out");
dtime = getdparam("dtime");
dthf = 0.5 * dtime;
eps = getdparam("eps");
epssq = eps*eps;
tol = getdparam("tol");
tolsq = tol*tol;
fcells = getdparam("fcells");
fleaves = getdparam("fleaves");
tstop = getdparam("tstop");
dtout = getdparam("dtout");
NPROC = getiparam("NPROC");
Local[0].nstep = 0;
pranset(seed);
testdata();
setbound();
Local[0].tout = Local[0].tnow + dtout;
}
/*
* TESTDATA: generate Plummer model initial conditions for test runs,
* scaled to units such that M = -4E = G = 1 (Henon, Hegge, etc).
* See Aarseth, SJ, Henon, M, & Wielen, R (1974) Astr & Ap, 37, 183.
*/
#define MFRAC 0.999 /* mass cut off at MFRAC of total */
testdata()
{
real rsc, vsc, sqrt(), xrand(), pow(), rsq, r, v, x, y;
vector cmr, cmv;
register bodyptr p;
int rejects = 0;
int k;
int halfnbody, i;
float offset;
register bodyptr cp;
double tmp;
headline = "Hack code: Plummer model";
Local[0].tnow = 0.0;
bodytab = (bodyptr) malloc(nbody * sizeof(body));;
if (bodytab == NULL) {
error("testdata: not enuf memory\n");
}
rsc = 9 * PI / 16;
vsc = sqrt(1.0 / rsc);
CLRV(cmr);
CLRV(cmv);
halfnbody = nbody / 2;
if (nbody % 2 != 0) halfnbody++;
for (p = bodytab; p < bodytab+halfnbody; p++) {
Type(p) = BODY;
Mass(p) = 1.0 / nbody;
Cost(p) = 1;
r = 1 / sqrt(pow(xrand(0.0, MFRAC), -2.0/3.0) - 1);
/* reject radii greater than 10 */
while (r > 9.0) {
rejects++;
r = 1 / sqrt(pow(xrand(0.0, MFRAC), -2.0/3.0) - 1);
}
pickshell(Pos(p), rsc * r);
ADDV(cmr, cmr, Pos(p));
do {
x = xrand(0.0, 1.0);
y = xrand(0.0, 0.1);
} while (y > x*x * pow(1 - x*x, 3.5));
v = sqrt(2.0) * x / pow(1 + r*r, 0.25);
pickshell(Vel(p), vsc * v);
ADDV(cmv, cmv, Vel(p));
}
offset = 4.0;
for (p = bodytab + halfnbody; p < bodytab+nbody; p++) {
Type(p) = BODY;
Mass(p) = 1.0 / nbody;
Cost(p) = 1;
cp = p - halfnbody;
for (i = 0; i < NDIM; i++){
Pos(p)[i] = Pos(cp)[i] + offset;
ADDV(cmr, cmr, Pos(p));
Vel(p)[i] = Vel(cp)[i];
ADDV(cmv, cmv, Vel(p));
}
}
DIVVS(cmr, cmr, (real) nbody);
DIVVS(cmv, cmv, (real) nbody);
for (p = bodytab; p < bodytab+nbody; p++) {
SUBV(Pos(p), Pos(p), cmr);
SUBV(Vel(p), Vel(p), cmv);
}
}
/*
* PICKSHELL: pick a random point on a sphere of specified radius.
*/
pickshell(vec, rad)
real vec[]; /* coordinate vector chosen */
real rad; /* radius of chosen point */
{
register int k;
double rsq, xrand(), sqrt(), rsc;
do {
for (k = 0; k < NDIM; k++) {
vec[k] = xrand(-1.0, 1.0);
}
DOTVP(rsq, vec, vec);
} while (rsq > 1.0);
rsc = rad / sqrt(rsq);
MULVS(vec, vec, rsc);
}
int intpow(i,j)
int i,j;
{
int k;
int temp = 1;
for (k = 0; k < j; k++)
temp = temp*i;
return temp;
}
/*
* STEPSYSTEM: advance N-body system one time-step.
*/
void
stepsystem (ProcessId)
unsigned int ProcessId;
{
int i;
real Cavg;
bodyptr p,*pp;
vector acc1, dacc, dvel, vel1, dpos;
int intpow();
unsigned int time;
unsigned int trackstart, trackend;
unsigned int partitionstart, partitionend;
unsigned int treebuildstart, treebuildend;
unsigned int forcecalcstart, forcecalcend;
if (Local[ProcessId].nstep == 2) {
/* POSSIBLE ENHANCEMENT: Here is where one might reset the
statistics that one is measuring about the parallel execution */
}
if ((ProcessId == 0) && (Local[ProcessId].nstep >= 2)) {
{long time(); (trackstart) = time(0);};
}
if (ProcessId == 0) {
init_root(ProcessId);
}
else {
Local[ProcessId].mynumcell = 0;
Local[ProcessId].mynumleaf = 0;
}
/* start at same time */
{;};
if ((ProcessId == 0) && (Local[ProcessId].nstep >= 2)) {
{long time(); (treebuildstart) = time(0);};
}
/* load bodies into tree */
maketree(ProcessId);
if ((ProcessId == 0) && (Local[ProcessId].nstep >= 2)) {
{long time(); (treebuildend) = time(0);};
Global->treebuildtime += treebuildend - treebuildstart;
}
Housekeep(ProcessId);
Cavg = (real) Cost(Global->G_root) / (real)NPROC ;
Local[ProcessId].workMin = (int) (Cavg * ProcessId);
Local[ProcessId].workMax = (int) (Cavg * (ProcessId + 1)
+ (ProcessId == (NPROC - 1)));
if ((ProcessId == 0) && (Local[ProcessId].nstep >= 2)) {
{long time(); (partitionstart) = time(0);};
}
Local[ProcessId].mynbody = 0;
find_my_bodies(Global->G_root, 0, BRC_FUC, ProcessId );
/* B*RRIER(Global->Barcom,NPROC); */
if ((ProcessId == 0) && (Local[ProcessId].nstep >= 2)) {
{long time(); (partitionend) = time(0);};
Global->partitiontime += partitionend - partitionstart;
}
if ((ProcessId == 0) && (Local[ProcessId].nstep >= 2)) {
{long time(); (forcecalcstart) = time(0);};
}
ComputeForces(ProcessId);
if ((ProcessId == 0) && (Local[ProcessId].nstep >= 2)) {
{long time(); (forcecalcend) = time(0);};
Global->forcecalctime += forcecalcend - forcecalcstart;
}
/* advance my bodies */
for (pp = Local[ProcessId].mybodytab;
pp < Local[ProcessId].mybodytab+Local[ProcessId].mynbody; pp++) {
p = *pp;
MULVS(dvel, Acc(p), dthf);
ADDV(vel1, Vel(p), dvel);
MULVS(dpos, vel1, dtime);
ADDV(Pos(p), Pos(p), dpos);
ADDV(Vel(p), vel1, dvel);
for (i = 0; i < NDIM; i++) {
if (Pos(p)[i]<Local[ProcessId].min[i]) {
Local[ProcessId].min[i]=Pos(p)[i];
}
if (Pos(p)[i]>Local[ProcessId].max[i]) {
Local[ProcessId].max[i]=Pos(p)[i] ;
}
}
}
{;};
for (i = 0; i < NDIM; i++) {
if (Global->min[i] > Local[ProcessId].min[i]) {
Global->min[i] = Local[ProcessId].min[i];
}
if (Global->max[i] < Local[ProcessId].max[i]) {
Global->max[i] = Local[ProcessId].max[i];
}
}
{;};
/* bar needed to make sure that every process has computed its min */
/* and max coordinates, and has accumulated them into the global */
/* min and max, before the new dimensions are computed */
{;};
if ((ProcessId == 0) && (Local[ProcessId].nstep >= 2)) {
{long time(); (trackend) = time(0);};
Global->tracktime += trackend - trackstart;
}
if (ProcessId==0) {
Global->rsize=0;
SUBV(Global->max,Global->max,Global->min);
for (i = 0; i < NDIM; i++) {
if (Global->rsize < Global->max[i]) {
Global->rsize = Global->max[i];
}
}
ADDVS(Global->rmin,Global->min,-Global->rsize/100000.0);
Global->rsize = 1.00002*Global->rsize;
SETVS(Global->min,1E99);
SETVS(Global->max,-1E99);
}
Local[ProcessId].nstep++;
Local[ProcessId].tnow = Local[ProcessId].tnow + dtime;
}
void
ComputeForces (ProcessId)
unsigned int ProcessId;
{
bodyptr p,*pp;
vector acc1, dacc, dvel, vel1, dpos;
for (pp = Local[ProcessId].mybodytab;
pp < Local[ProcessId].mybodytab+Local[ProcessId].mynbody;pp++) {
p = *pp;
SETV(acc1, Acc(p));
Cost(p)=0;
hackgrav(p,ProcessId);
Local[ProcessId].myn2bcalc += Local[ProcessId].myn2bterm;
Local[ProcessId].mynbccalc += Local[ProcessId].mynbcterm;
if (!Local[ProcessId].skipself) { /* did we miss self-int? */
Local[ProcessId].myselfint++; /* count another goofup */
}
if (Local[ProcessId].nstep > 0) {
/* use change in accel to make 2nd order correction to vel */
SUBV(dacc, Acc(p), acc1);
MULVS(dvel, dacc, dthf);
ADDV(Vel(p), Vel(p), dvel);
}
}
}
/*
* FIND_MY_INITIAL_BODIES: puts into mybodytab the initial list of bodies
* assigned to the processor.
*/
find_my_initial_bodies(btab, nbody, ProcessId)
bodyptr btab;
int nbody;
unsigned int ProcessId;
{
int Myindex;
int intpow();
int equalbodies;
int extra,offset,i;
Local[ProcessId].mynbody = nbody / NPROC;
extra = nbody % NPROC;
if (ProcessId < extra) {
Local[ProcessId].mynbody++;
offset = Local[ProcessId].mynbody * ProcessId;
}
if (ProcessId >= extra) {
offset = (Local[ProcessId].mynbody+1) * extra + (ProcessId - extra)
* Local[ProcessId].mynbody;
}
for (i=0; i < Local[ProcessId].mynbody; i++) {
Local[ProcessId].mybodytab[i] = &(btab[offset+i]);
}
{;};
}
find_my_bodies(mycell, work, direction, ProcessId)
nodeptr mycell;
int work;
int direction;
unsigned ProcessId;
{
int i;
leafptr l;
nodeptr qptr;
if (Type(mycell) == LEAF) {
l = (leafptr) mycell;
for (i = 0; i < l->num_bodies; i++) {
if (work >= Local[ProcessId].workMin - .1) {
if((Local[ProcessId].mynbody+2) > maxmybody) {
error("find_my_bodies: Processor %d needs more than %d bodies; increase fleaves\n",ProcessId, maxmybody);
}
Local[ProcessId].mybodytab[Local[ProcessId].mynbody++] =
Bodyp(l)[i];
}
work += Cost(Bodyp(l)[i]);
if (work >= Local[ProcessId].workMax-.1) {
break;
}
}
}
else {
for(i = 0; (i < NSUB) && (work < (Local[ProcessId].workMax - .1)); i++){
qptr = Subp(mycell)[Child_Sequence[direction][i]];
if (qptr!=NULL) {
if ((work+Cost(qptr)) >= (Local[ProcessId].workMin -.1)) {
find_my_bodies(qptr,work, Direction_Sequence[direction][i],
ProcessId);
}
work += Cost(qptr);
}
}
}
}
/*
* HOUSEKEEP: reinitialize the different variables (in particular global
* variables) between each time step.
*/
Housekeep(ProcessId)
unsigned ProcessId;
{
Local[ProcessId].myn2bcalc = Local[ProcessId].mynbccalc
= Local[ProcessId].myselfint = 0;
SETVS(Local[ProcessId].min,1E99);
SETVS(Local[ProcessId].max,-1E99);
}
/*
* SETBOUND: Compute the initial size of the root of the tree; only done
* before first time step, and only processor 0 does it
*/
setbound()
{
int i;
real side ;
bodyptr p;
SETVS(Local[0].min,1E99);
SETVS(Local[0].max,-1E99);
side=0;
for (p = bodytab; p < bodytab+nbody; p++) {
for (i=0; i<NDIM;i++) {
if (Pos(p)[i]<Local[0].min[i]) Local[0].min[i]=Pos(p)[i] ;
if (Pos(p)[i]>Local[0].max[i]) Local[0].max[i]=Pos(p)[i] ;
}
}
SUBV(Local[0].max,Local[0].max,Local[0].min);
for (i=0; i<NDIM;i++) if (side<Local[0].max[i]) side=Local[0].max[i];
ADDVS(Global->rmin,Local[0].min,-side/100000.0);
Global->rsize = 1.00002*side;
SETVS(Global->max,-1E99);
SETVS(Global->min,1E99);
}
// void
// Help ()
// {
// printf("There are a total of twelve parameters, and all of them have default values.\n");
// printf("\n");
// printf("1) infile (char*) : The name of an input file that contains particle data. \n");
// printf(" The format of the file is:\n");
// printf("\ta) An int representing the number of particles in the distribution\n");
// printf("\tb) An int representing the dimensionality of the problem (3-D)\n");
// printf("\tc) A double representing the current time of the simulation\n");
// printf("\td) Doubles representing the masses of all the particles\n");
// printf("\te) A vector (length equal to the dimensionality) of doubles\n");
// printf("\t representing the positions of all the particles\n");
// printf("\tf) A vector (length equal to the dimensionality) of doubles\n");
// printf("\t representing the velocities of all the particles\n");
// printf("\n");
// printf(" Each of these numbers can be separated by any amount of whitespace.\n");
// printf("\n");
// printf("2) nbody (int) : If no input file is specified (the first line is blank), this\n");
// printf(" number specifies the number of particles to generate under a plummer model.\n");
// printf(" Default is 16384.\n");
// printf("\n");
// printf("3) seed (int) : The seed used by the random number generator.\n");
// printf(" Default is 123.\n");
// printf("\n");
// printf("4) outfile (char*) : The name of the file that snapshots will be printed to. \n");
// printf(" This feature has been disabled in the SPLASH release.\n");
// printf(" Default is NULL.\n");
// printf("\n");
// printf("5) dtime (double) : The integration time-step.\n");
// printf(" Default is 0.025.\n");
// printf("\n");
// printf("6) eps (double) : The usual potential softening\n");
// printf(" Default is 0.05.\n");
// printf("\n");
// printf("7) tol (double) : The cell subdivision tolerance.\n");
// printf(" Default is 1.0.\n");
// printf("\n");
// printf("8) fcells (double) : The total number of cells created is equal to \n");
// printf(" fcells * number of leaves.\n");
// printf(" Default is 2.0.\n");
// printf("\n");
// printf("9) fleaves (double) : The total number of leaves created is equal to \n");
// printf(" fleaves * nbody.\n");
// printf(" Default is 0.5.\n");
// printf("\n");
// printf("10) tstop (double) : The time to stop integration.\n");
// printf(" Default is 0.075.\n");
// printf("\n");
// printf("11) dtout (double) : The data-output interval.\n");
// printf(" Default is 0.25.\n");
// printf("\n");
// printf("12) NPROC (int) : The number of processors.\n");
// printf(" Default is 1.\n");
// }

View File

@@ -0,0 +1,150 @@
#line 95 "./null_macros/c.m4.null"
#line 1 "code.H"
/*************************************************************************/
/* */
/* Copyright (c) 1994 Stanford University */
/* */
/* All rights reserved. */
/* */
/* Permission is given to use, copy, and modify this software for any */
/* non-commercial purpose as long as this copyright notice is not */
/* removed. All other uses, including redistribution in whole or in */
/* part, are forbidden without prior written permission. */
/* */
/* This software is provided with absolutely no warranty and no */
/* support. */
/* */
/*************************************************************************/
/*
* CODE.H: define various global things for CODE.C.
*/
#ifndef _CODE_H_
#define _CODE_H_
#include "defs.h"
#define PAD_SIZE (PAGE_SIZE / (sizeof(int)))
/* Defined by the input file */
global string headline; /* message describing calculation */
global string infile; /* file name for snapshot input */
global string outfile; /* file name for snapshot output */
global real dtime; /* timestep for leapfrog integrator */
global real dtout; /* time between data outputs */
global real tstop; /* time to stop calculation */
global int nbody; /* number of bodies in system */
global real fcells; /* ratio of cells/leaves allocated */
global real fleaves; /* ratio of leaves/bodies allocated */
global real tol; /* accuracy parameter: 0.0 => exact */
global real tolsq; /* square of previous */
global real eps; /* potential softening parameter */
global real epssq; /* square of previous */
global real dthf; /* half time step */
global int NPROC; /* Number of Processors */
global int maxcell; /* max number of cells allocated */
global int maxleaf; /* max number of leaves allocated */
global int maxmybody; /* max no. of bodies allocated per processor */
global int maxmycell; /* max num. of cells to be allocated */
global int maxmyleaf; /* max num. of leaves to be allocated */
global bodyptr bodytab; /* array size is exactly nbody bodies */
global struct CellLockType {
int (CL); /* locks on the cells*/
} *CellLock;
struct GlobalMemory { /* all this info is for the whole system */
int n2bcalc; /* total number of body/cell interactions */
int nbccalc; /* total number of body/body interactions */
int selfint; /* number of self interactions */
real mtot; /* total mass of N-body system */
real etot[3]; /* binding, kinetic, potential energy */
matrix keten; /* kinetic energy tensor */
matrix peten; /* potential energy tensor */
vector cmphase[2]; /* center of mass coordinates and velocity */
vector amvec; /* angular momentum vector */
cellptr G_root; /* root of the whole tree */
vector rmin; /* lower-left corner of coordinate box */
vector min; /* temporary lower-left corner of the box */
vector max; /* temporary upper right corner of the box */
real rsize; /* side-length of integer coordinate box */
int (Barstart); /* barrier at the beginning of stepsystem */
int (Bartree); /* barrier after loading the tree */
int (Barcom); /* barrier after computing the c. of m. */
int (Barload);
int (Baraccel); /* barrier after accel and before output */
int (Barpos); /* barrier after computing the new pos */
int (CountLock); /* Lock on the shared variables */
int (NcellLock); /* Lock on the counter of array of cells for loadtree */
int (NleafLock);/* Lock on the counter of array of leaves for loadtree */
int (io_lock);
unsigned int createstart,createend,computestart,computeend;
unsigned int trackstart, trackend, tracktime;
unsigned int partitionstart, partitionend, partitiontime;
unsigned int treebuildstart, treebuildend, treebuildtime;
unsigned int forcecalcstart, forcecalcend, forcecalctime;
unsigned int current_id;
volatile int k; /*for memory allocation in code.C */
};
global struct GlobalMemory *Global;
/* This structure is needed because under the sproc model there is no
* per processor private address space.
*/
struct local_memory {
/* Use padding so that each processor's variables are on their own page */
int pad_begin[PAD_SIZE];
real tnow; /* current value of simulation time */
real tout; /* time next output is due */
int nstep; /* number of integration steps so far */
int workMin, workMax;/* interval of cost to be treated by a proc */
vector min, max; /* min and max of coordinates for each Proc. */
int mynumcell; /* num. of cells used for this proc in ctab */
int mynumleaf; /* num. of leaves used for this proc in ctab */
int mynbody; /* num bodies allocated to the processor */
bodyptr* mybodytab; /* array of bodies allocated / processor */
int myncell; /* num cells allocated to the processor */
cellptr* mycelltab; /* array of cellptrs allocated to the processor */
int mynleaf; /* number of leaves allocated to the processor */
leafptr* myleaftab; /* array of leafptrs allocated to the processor */
cellptr ctab; /* array of cells used for the tree. */
leafptr ltab; /* array of cells used for the tree. */
int myn2bcalc; /* body-body force calculations for each processor */
int mynbccalc; /* body-cell force calculations for each processor */
int myselfint; /* count self-interactions for each processor */
int myn2bterm; /* count body-body terms for a body */
int mynbcterm; /* count body-cell terms for a body */
bool skipself; /* true if self-interaction skipped OK */
bodyptr pskip; /* body to skip in force evaluation */
vector pos0; /* point at which to evaluate field */
real phi0; /* computed potential at pos0 */
vector acc0; /* computed acceleration at pos0 */
vector dr; /* data to be shared */
real drsq; /* between gravsub and subdivp */
nodeptr pmem; /* remember particle data */
nodeptr Current_Root;
int Root_Coords[NDIM];
real mymtot; /* total mass of N-body system */
real myetot[3]; /* binding, kinetic, potential energy */
matrix myketen; /* kinetic energy tensor */
matrix mypeten; /* potential energy tensor */
vector mycmphase[2]; /* center of mass coordinates */
vector myamvec; /* angular momentum vector */
int pad_end[PAD_SIZE];
};
global struct local_memory Local[MAX_PROC];
#endif

View File

@@ -0,0 +1,262 @@
#line 95 "./null_macros/c.m4.null"
#line 1 "code_io.C"
/*************************************************************************/
/* */
/* Copyright (c) 1994 Stanford University */
/* */
/* All rights reserved. */
/* */
/* Permission is given to use, copy, and modify this software for any */
/* non-commercial purpose as long as this copyright notice is not */
/* removed. All other uses, including redistribution in whole or in */
/* part, are forbidden without prior written permission. */
/* */
/* This software is provided with absolutely no warranty and no */
/* support. */
/* */
/*************************************************************************/
/*
* CODE_IO.C:
*/
#define global extern
#include "code.h"
void* malloc(size_t);
void free(void*);
void in_int (), in_real (), in_vector ();
void out_int (), out_real (), out_vector ();
void diagnostics (unsigned int ProcessId);
/*
* INPUTDATA: read initial conditions from input file.
*/
inputdata ()
{
stream instr;
permanent char headbuf[128];
int ndim,counter=0;
real tnow;
bodyptr p;
int i;
// fprintf(stderr,"reading input file : %s\n",infile);
fflush(stderr);
instr = fopen(infile, "r");
if (instr == NULL)
error("inputdata: cannot find file %s\n", infile);
// sprintf(headbuf, "Hack code: input file %s\n", infile);
headline = headbuf;
in_int(instr, &nbody);
if (nbody < 1)
error("inputdata: nbody = %d is absurd\n", nbody);
in_int(instr, &ndim);
if (ndim != NDIM)
error("inputdata: NDIM = %d ndim = %d is absurd\n", NDIM,ndim);
in_real(instr, &tnow);
for (i = 0; i < MAX_PROC; i++) {
Local[i].tnow = tnow;
}
bodytab = (bodyptr) malloc(nbody * sizeof(body));;
if (bodytab == NULL)
error("inputdata: not enuf memory\n");
for (p = bodytab; p < bodytab+nbody; p++) {
Type(p) = BODY;
Cost(p) = 1;
Phi(p) = 0.0;
CLRV(Acc(p));
}
for (p = bodytab; p < bodytab+nbody; p++)
in_real(instr, &Mass(p));
for (p = bodytab; p < bodytab+nbody; p++)
in_vector(instr, Pos(p));
for (p = bodytab; p < bodytab+nbody; p++)
in_vector(instr, Vel(p));
fclose(instr);
}
/*
* INITOUTPUT: initialize output routines.
*/
// initoutput()
// {
// printf("\n\t\t%s\n\n", headline);
// printf("%10s%10s%10s%10s%10s%10s%10s%10s\n",
// "nbody", "dtime", "eps", "tol", "dtout", "tstop","fcells","NPROC");
// printf("%10d%10.5f%10.4f%10.2f%10.3f%10.3f%10.2f%10d\n\n",
// nbody, dtime, eps, tol, dtout, tstop, fcells, NPROC);
// }
/*
* STOPOUTPUT: finish up after a run.
*/
/*
* OUTPUT: compute diagnostics and output data.
*/
void
output (ProcessId)
unsigned int ProcessId;
{
int nttot, nbavg, ncavg,k;
double cputime();
bodyptr p, *pp;
vector tempv1,tempv2;
if ((Local[ProcessId].tout - 0.01 * dtime) <= Local[ProcessId].tnow) {
Local[ProcessId].tout += dtout;
}
diagnostics(ProcessId);
if (Local[ProcessId].mymtot!=0) {
{;};
Global->n2bcalc += Local[ProcessId].myn2bcalc;
Global->nbccalc += Local[ProcessId].mynbccalc;
Global->selfint += Local[ProcessId].myselfint;
ADDM(Global->keten, Global-> keten, Local[ProcessId].myketen);
ADDM(Global->peten, Global-> peten, Local[ProcessId].mypeten);
for (k=0;k<3;k++) Global->etot[k] += Local[ProcessId].myetot[k];
ADDV(Global->amvec, Global-> amvec, Local[ProcessId].myamvec);
MULVS(tempv1, Global->cmphase[0],Global->mtot);
MULVS(tempv2, Local[ProcessId].mycmphase[0], Local[ProcessId].mymtot);
ADDV(tempv1, tempv1, tempv2);
DIVVS(Global->cmphase[0], tempv1, Global->mtot+Local[ProcessId].mymtot);
MULVS(tempv1, Global->cmphase[1],Global->mtot);
MULVS(tempv2, Local[ProcessId].mycmphase[1], Local[ProcessId].mymtot);
ADDV(tempv1, tempv1, tempv2);
DIVVS(Global->cmphase[1], tempv1, Global->mtot+Local[ProcessId].mymtot);
Global->mtot +=Local[ProcessId].mymtot;
{;};
}
{;};
if (ProcessId==0) {
nttot = Global->n2bcalc + Global->nbccalc;
nbavg = (int) ((real) Global->n2bcalc / (real) nbody);
ncavg = (int) ((real) Global->nbccalc / (real) nbody);
}
}
/*
* DIAGNOSTICS: compute set of dynamical diagnostics.
*/
void
diagnostics (ProcessId)
unsigned int ProcessId;
{
register bodyptr p,*pp;
real velsq;
vector tmpv;
matrix tmpt;
Local[ProcessId].mymtot = 0.0;
Local[ProcessId].myetot[1] = Local[ProcessId].myetot[2] = 0.0;
CLRM(Local[ProcessId].myketen);
CLRM(Local[ProcessId].mypeten);
CLRV(Local[ProcessId].mycmphase[0]);
CLRV(Local[ProcessId].mycmphase[1]);
CLRV(Local[ProcessId].myamvec);
for (pp = Local[ProcessId].mybodytab+Local[ProcessId].mynbody -1;
pp >= Local[ProcessId].mybodytab; pp--) {
p= *pp;
Local[ProcessId].mymtot += Mass(p);
DOTVP(velsq, Vel(p), Vel(p));
Local[ProcessId].myetot[1] += 0.5 * Mass(p) * velsq;
Local[ProcessId].myetot[2] += 0.5 * Mass(p) * Phi(p);
MULVS(tmpv, Vel(p), 0.5 * Mass(p));
OUTVP(tmpt, tmpv, Vel(p));
ADDM(Local[ProcessId].myketen, Local[ProcessId].myketen, tmpt);
MULVS(tmpv, Pos(p), Mass(p));
OUTVP(tmpt, tmpv, Acc(p));
ADDM(Local[ProcessId].mypeten, Local[ProcessId].mypeten, tmpt);
MULVS(tmpv, Pos(p), Mass(p));
ADDV(Local[ProcessId].mycmphase[0], Local[ProcessId].mycmphase[0], tmpv);
MULVS(tmpv, Vel(p), Mass(p));
ADDV(Local[ProcessId].mycmphase[1], Local[ProcessId].mycmphase[1], tmpv);
CROSSVP(tmpv, Pos(p), Vel(p));
MULVS(tmpv, tmpv, Mass(p));
ADDV(Local[ProcessId].myamvec, Local[ProcessId].myamvec, tmpv);
}
Local[ProcessId].myetot[0] = Local[ProcessId].myetot[1]
+ Local[ProcessId].myetot[2];
if (Local[ProcessId].mymtot!=0){
DIVVS(Local[ProcessId].mycmphase[0], Local[ProcessId].mycmphase[0],
Local[ProcessId].mymtot);
DIVVS(Local[ProcessId].mycmphase[1], Local[ProcessId].mycmphase[1],
Local[ProcessId].mymtot);
}
}
/*
* Low-level input and output operations.
*/
void in_int(str, iptr)
stream str;
int *iptr;
{
if (fscanf(str, "%d", iptr) != 1)
error("in_int: input conversion error\n");
}
void in_real(str, rptr)
stream str;
real *rptr;
{
double tmp;
if (fscanf(str, "%lf", &tmp) != 1)
error("in_real: input conversion error\n");
*rptr = tmp;
}
void in_vector(str, vec)
stream str;
vector vec;
{
double tmpx, tmpy, tmpz;
if (fscanf(str, "%lf%lf%lf", &tmpx, &tmpy, &tmpz) != 3)
error("in_vector: input conversion error\n");
vec[0] = tmpx; vec[1] = tmpy; vec[2] = tmpz;
}
// void out_int(str, ival)
// stream str;
// int ival;
// {
// fprintf(str, " %d\n", ival);
// }
// void out_real(str, rval)
// stream str;
// real rval;
// {
// fprintf(str, " %21.14E\n", rval);
// }
// void out_vector(str, vec)
// stream str;
// vector vec;
// {
// fprintf(str, " %21.14E %21.14E", vec[0], vec[1]);
// fprintf(str, " %21.14E\n",vec[2]);
// }

View File

@@ -0,0 +1,317 @@
#line 95 "./null_macros/c.m4.null"
#line 1 "defs.H"
/*************************************************************************/
/* */
/* Copyright (c) 1994 Stanford University */
/* */
/* All rights reserved. */
/* */
/* Permission is given to use, copy, and modify this software for any */
/* non-commercial purpose as long as this copyright notice is not */
/* removed. All other uses, including redistribution in whole or in */
/* part, are forbidden without prior written permission. */
/* */
/* This software is provided with absolutely no warranty and no */
/* support. */
/* */
/*************************************************************************/
#ifndef _DEFS_H_
#define _DEFS_H_
#include "stdinc.h"
#include <assert.h>
//#include <ulocks.h>
#include "vectmath.h"
#define MAX_PROC 128
#define MAX_BODIES_PER_LEAF 10
#define MAXLOCK 2048 /* maximum number of locks on DASH */
#define PAGE_SIZE 4096 /* in bytes */
#define NSUB (1 << NDIM) /* subcells per cell */
/* The more complicated 3D case */
#define NUM_DIRECTIONS 32
#define BRC_FUC 0
#define BRC_FRA 1
#define BRA_FDA 2
#define BRA_FRC 3
#define BLC_FDC 4
#define BLC_FLA 5
#define BLA_FUA 6
#define BLA_FLC 7
#define BUC_FUA 8
#define BUC_FLC 9
#define BUA_FUC 10
#define BUA_FRA 11
#define BDC_FDA 12
#define BDC_FRC 13
#define BDA_FDC 14
#define BDA_FLA 15
#define FRC_BUC 16
#define FRC_BRA 17
#define FRA_BDA 18
#define FRA_BRC 19
#define FLC_BDC 20
#define FLC_BLA 21
#define FLA_BUA 22
#define FLA_BLC 23
#define FUC_BUA 24
#define FUC_BLC 25
#define FUA_BUC 26
#define FUA_BRA 27
#define FDC_BDA 28
#define FDC_BRC 29
#define FDA_BDC 30
#define FDA_BLA 31
static int Child_Sequence[NUM_DIRECTIONS][NSUB] =
{
{ 2, 5, 6, 1, 0, 3, 4, 7}, /* BRC_FUC */
{ 2, 5, 6, 1, 0, 7, 4, 3}, /* BRC_FRA */
{ 1, 6, 5, 2, 3, 0, 7, 4}, /* BRA_FDA */
{ 1, 6, 5, 2, 3, 4, 7, 0}, /* BRA_FRC */
{ 6, 1, 2, 5, 4, 7, 0, 3}, /* BLC_FDC */
{ 6, 1, 2, 5, 4, 3, 0, 7}, /* BLC_FLA */
{ 5, 2, 1, 6, 7, 4, 3, 0}, /* BLA_FUA */
{ 5, 2, 1, 6, 7, 0, 3, 4}, /* BLA_FLC */
{ 1, 2, 5, 6, 7, 4, 3, 0}, /* BUC_FUA */
{ 1, 2, 5, 6, 7, 0, 3, 4}, /* BUC_FLC */
{ 6, 5, 2, 1, 0, 3, 4, 7}, /* BUA_FUC */
{ 6, 5, 2, 1, 0, 7, 4, 3}, /* BUA_FRA */
{ 5, 6, 1, 2, 3, 0, 7, 4}, /* BDC_FDA */
{ 5, 6, 1, 2, 3, 4, 7, 0}, /* BDC_FRC */
{ 2, 1, 6, 5, 4, 7, 0, 3}, /* BDA_FDC */
{ 2, 1, 6, 5, 4, 3, 0, 7}, /* BDA_FLA */
{ 3, 4, 7, 0, 1, 2, 5, 6}, /* FRC_BUC */
{ 3, 4, 7, 0, 1, 6, 5, 2}, /* FRC_BRA */
{ 0, 7, 4, 3, 2, 1, 6, 5}, /* FRA_BDA */
{ 0, 7, 4, 3, 2, 5, 6, 1}, /* FRA_BRC */
{ 7, 0, 3, 4, 5, 6, 1, 2}, /* FLC_BDC */
{ 7, 0, 3, 4, 5, 2, 1, 6}, /* FLC_BLA */
{ 4, 3, 0, 7, 6, 5, 2, 1}, /* FLA_BUA */
{ 4, 3, 0, 7, 6, 1, 2, 5}, /* FLA_BLC */
{ 0, 3, 4, 7, 6, 5, 2, 1}, /* FUC_BUA */
{ 0, 3, 4, 7, 6, 1, 2, 5}, /* FUC_BLC */
{ 7, 4, 3, 0, 1, 2, 5, 6}, /* FUA_BUC */
{ 7, 4, 3, 0, 1, 6, 5, 2}, /* FUA_BRA */
{ 4, 7, 0, 3, 2, 1, 6, 5}, /* FDC_BDA */
{ 4, 7, 0, 3, 2, 5, 6, 1}, /* FDC_BRC */
{ 3, 0, 7, 4, 5, 6, 1, 2}, /* FDA_BDC */
{ 3, 0, 7, 4, 5, 2, 1, 6}, /* FDA_BLA */
};
static int Direction_Sequence[NUM_DIRECTIONS][NSUB] =
{
{ FRC_BUC, BRA_FRC, FDA_BDC, BLA_FUA, BUC_FLC, FUA_BUC, BRA_FRC, FDA_BLA },
/* BRC_FUC */
{ FRC_BUC, BRA_FRC, FDA_BDC, BLA_FUA, BRA_FDA, FRC_BRA, BUC_FUA, FLC_BDC },
/* BRC_FRA */
{ FRA_BDA, BRC_FRA, FUC_BUA, BLC_FDC, BDA_FLA, FDC_BDA, BRC_FRA, FUC_BLC },
/* BRA_FDA */
{ FRA_BDA, BRC_FRA, FUC_BUA, BLC_FDC, BUC_FLC, FUA_BUC, BRA_FRC, FDA_BLA },
/* BRA_FRC */
{ FLC_BDC, BLA_FLC, FUA_BUC, BRA_FDA, BDC_FRC, FDA_BDC, BLA_FLC, FUA_BRA },
/* BLC_FDC */
{ FLC_BDC, BLA_FLC, FUA_BUC, BRA_FDA, BLA_FUA, FLC_BLA, BDC_FDA, FRC_BUC },
/* BLC_FLA */
{ FLA_BUA, BLC_FLA, FDC_BDA, BRC_FUC, BUA_FRA, FUC_BUA, BLC_FLA, FDC_BRC },
/* BLA_FUA */
{ FLA_BUA, BLC_FLA, FDC_BDA, BRC_FUC, BLC_FDC, FLA_BLC, BUA_FUC, FRA_BDA },
/* BLA_FLC */
{ FUC_BLC, BUA_FUC, FRA_BRC, BDA_FLA, BUA_FRA, FUC_BUA, BLC_FLA, FDC_BRC },
/* BUC_FUA */
{ FUC_BLC, BUA_FUC, FRA_BRC, BDA_FLA, BLC_FDC, FLA_BLC, BUA_FUC, FRA_BDA },
/* BUC_FLC */
{ FUA_BRA, BUC_FUA, FLC_BLA, BDC_FRC, BUC_FLC, FUA_BUC, BRA_FRC, FDA_BLA },
/* BUA_FUC */
{ FUA_BRA, BUC_FUA, FLC_BLA, BDC_FRC, BRA_FDA, FRC_BRA, BUC_FUA, FLC_BDC },
/* BUA_FRA */
{ FDC_BRC, BDA_FDC, FLA_BLC, BUA_FRA, BDA_FLA, FDC_BDA, BRC_FRA, FUC_BLC },
/* BDC_FDA */
{ FDC_BRC, BDA_FDC, FLA_BLC, BUA_FRA, BUC_FLC, FUA_BUC, BRA_FRC, FDA_BLA },
/* BDC_FRC */
{ FDA_BLA, BDC_FDA, FRC_BRA, BUC_FLC, BDC_FRC, FDA_BDC, BLA_FLC, FUA_BRA },
/* BDA_FDC */
{ FDA_BLA, BDC_FDA, FRC_BRA, BUC_FLC, BLA_FUA, FLC_BLA, BDC_FDA, FRC_BUC },
/* BDA_FLA */
{ BUC_FLC, FUA_BUC, BRA_FRC, FDA_BLA, FUC_BLC, BUA_FUC, FRA_BRC, BDA_FLA },
/* FRC_BUC */
{ BUC_FLC, FUA_BUC, BRA_FRC, FDA_BLA, FRA_BDA, BRC_FRA, FUC_BUA, BLC_FDC },
/* FRC_BRA */
{ BRA_FDA, FRC_BRA, BUC_FUA, FLC_BDC, FDA_BLA, BDC_FDA, FRC_BRA, BUC_FLC },
/* FRA_BDA */
{ BRA_FDA, FRC_BRA, BUC_FUA, FLC_BDC, FRC_BUC, BRA_FRC, FDA_BDC, BLA_FUA },
/* FRA_BRC */
{ BLC_FDC, FLA_BLC, BUA_FUC, FRA_BDA, FDC_BRC, BDA_FDC, FLA_BLC, BUA_FRA },
/* FLC_BDC */
{ BLC_FDC, FLA_BLC, BUA_FUC, FRA_BDA, FLA_BUA, BLC_FLA, FDC_BDA, BRC_FUC },
/* FLC_BLA */
{ BLA_FUA, FLC_BLA, BDC_FDA, FRC_BUC, FUA_BRA, BUC_FUA, FLC_BLA, BDC_FRC },
/* FLA_BUA */
{ BLA_FUA, FLC_BLA, BDC_FDA, FRC_BUC, FLC_BDC, BLA_FLC, FUA_BUC, BRA_FDA },
/* FLA_BLC */
{ BUC_FLC, FUA_BUC, BRA_FRC, FDA_BLA, FUA_BRA, BUC_FUA, FLC_BLA, BDC_FRC },
/* FUC_BUA */
{ BUC_FLC, FUA_BUC, BRA_FRC, FDA_BLA, FLC_BDC, BLA_FLC, FUA_BUC, BRA_FDA },
/* FUC_BLC */
{ BUA_FRA, FUC_BUA, BLC_FLA, FDC_BRC, FUC_BLC, BUA_FUC, FRA_BRC, BDA_FLA },
/* FUA_BUC */
{ BUA_FRA, FUC_BUA, BLC_FLA, FDC_BRC, FRA_BDA, BRC_FRA, FUC_BUA, BLC_FDC },
/* FUA_BRA */
{ BDC_FRC, FDA_BDC, BLA_FLC, FUA_BRA, FDA_BLA, BDC_FDA, FRC_BRA, BUC_FLC },
/* FDC_BDA */
{ BDC_FRC, FDA_BDC, BLA_FLC, FUA_BRA, FRC_BUC, BRA_FRC, FDA_BDC, BLA_FUA },
/* FDC_BRC */
{ BDA_FLA, FDC_BDA, BRC_FRA, FUC_BLC, FDC_BRC, BDA_FDC, FLA_BLC, BUA_FRA },
/* FDA_BDC */
{ BDA_FLA, FDC_BDA, BRC_FRA, FUC_BLC, FLA_BUA, BLC_FLA, FDC_BDA, BRC_FUC },
/* FDA_BLA */
};
/*
* BODY and CELL data structures are used to represent the tree:
*
* +-----------------------------------------------------------+
* root--> | CELL: mass, pos, cost, quad, /, o, /, /, /, /, o, /, done |
* +---------------------------------|--------------|----------+
* | |
* +--------------------------------------+ |
* | |
* | +--------------------------------------+ |
* +--> | BODY: mass, pos, cost, vel, acc, phi | |
* +--------------------------------------+ |
* |
* +-----------------------------------------------------+
* |
* | +-----------------------------------------------------------+
* +--> | CELL: mass, pos, cost, quad, o, /, /, o, /, /, o, /, done |
* +------------------------------|--------|--------|----------+
* etc etc etc
*/
/*
* NODE: data common to BODY and CELL structures.
*/
typedef struct _node {
short type; /* code for node type: body or cell */
real mass; /* total mass of node */
vector pos; /* position of node */
int cost; /* number of interactions computed */
int level;
struct _node *parent; /* ptr to parent of this node in tree */
int child_num; /* Index that this node should be put
at in parent cell */
} node;
typedef node* nodeptr;
#define Type(x) (((nodeptr) (x))->type)
#define Mass(x) (((nodeptr) (x))->mass)
#define Pos(x) (((nodeptr) (x))->pos)
#define Cost(x) (((nodeptr) (x))->cost)
#define Level(x) (((nodeptr) (x))->level)
#define Parent(x) (((nodeptr) (x))->parent)
#define ChildNum(x) (((nodeptr) (x))->child_num)
/*
* BODY: data structure used to represent particles.
*/
typedef struct _body* bodyptr;
typedef struct _leaf* leafptr;
typedef struct _cell* cellptr;
#define BODY 01 /* type code for bodies */
typedef struct _body {
short type;
real mass; /* mass of body */
vector pos; /* position of body */
int cost; /* number of interactions computed */
int level;
leafptr parent;
int child_num; /* Index that this node should be put */
vector vel; /* velocity of body */
vector acc; /* acceleration of body */
real phi; /* potential at body */
} body;
#define Vel(x) (((bodyptr) (x))->vel)
#define Acc(x) (((bodyptr) (x))->acc)
#define Phi(x) (((bodyptr) (x))->phi)
/*
* CELL: structure used to represent internal nodes of tree.
*/
#define CELL 02 /* type code for cells */
typedef struct _cell {
short type;
real mass; /* total mass of cell */
vector pos; /* cm. position of cell */
int cost; /* number of interactions computed */
int level;
cellptr parent;
int child_num; /* Index [0..8] that this node should be put */
int processor; /* Used by partition code */
struct _cell *next, *prev; /* Used in the partition array */
unsigned long seqnum;
#ifdef QUADPOLE
matrix quad; /* quad. moment of cell */
#endif
volatile short int done; /* flag to tell when the c.of.m is ready */
nodeptr subp[NSUB]; /* descendents of cell */
} cell;
#define Subp(x) (((cellptr) (x))->subp)
/*
* LEAF: structure used to represent leaf nodes of tree.
*/
#define LEAF 03 /* type code for leaves */
typedef struct _leaf {
short type;
real mass; /* total mass of leaf */
vector pos; /* cm. position of leaf */
int cost; /* number of interactions computed */
int level;
cellptr parent;
int child_num; /* Index [0..8] that this node should be put */
int processor; /* Used by partition code */
struct _leaf *next, *prev; /* Used in the partition array */
unsigned long seqnum;
#ifdef QUADPOLE
matrix quad; /* quad. moment of leaf */
#endif
volatile short int done; /* flag to tell when the c.of.m is ready */
unsigned int num_bodies;
bodyptr bodyp[MAX_BODIES_PER_LEAF]; /* bodies of leaf */
} leaf;
#define Bodyp(x) (((leafptr) (x))->bodyp)
#ifdef QUADPOLE
#define Quad(x) (((cellptr) (x))->quad)
#endif
#define Done(x) (((cellptr) (x))->done)
/*
* Integerized coordinates: used to mantain body-tree.
*/
#define MAXLEVEL (8*sizeof(int)-2)
#define IMAX (1 << MAXLEVEL) /* highest bit of int coord */
#endif

View File

@@ -0,0 +1,176 @@
#line 95 "./null_macros/c.m4.null"
#line 1 "getparam.C"
/*************************************************************************/
/* */
/* Copyright (c) 1994 Stanford University */
/* */
/* All rights reserved. */
/* */
/* Permission is given to use, copy, and modify this software for any */
/* non-commercial purpose as long as this copyright notice is not */
/* removed. All other uses, including redistribution in whole or in */
/* part, are forbidden without prior written permission. */
/* */
/* This software is provided with absolutely no warranty and no */
/* support. */
/* */
/*************************************************************************/
/*
* GETPARAM.C:
*/
#include "stdinc.h"
void* malloc(size_t);
void free(void*);
local string *defaults = NULL; /* vector of "name=value" strings */
/*
* INITPARAM: ignore arg vector, remember defaults.
*/
initparam(argv, defv)
string *argv, *defv;
{
defaults = defv;
}
/*
* GETPARAM: export version prompts user for value.
*/
string getparam(name)
string name; /* name of parameter */
{
int scanbind(), i, strlen(), leng;
string extrvalue(), def;
char buf[128], *strcpy();
char* temp;
if (defaults == NULL)
error("getparam: called before initparam\n");
i = scanbind(defaults, name);
if (i < 0)
error("getparam: %s unknown\n", name);
def = extrvalue(defaults[i]);
gets_s(buf,100);
leng = strlen(buf) + 1;
if (leng > 1) {
return (strcpy(malloc(leng), buf));
}
else {
return (def);
}
}
/*
* GETIPARAM, ..., GETDPARAM: get int, long, bool, or double parameters.
*/
int getiparam(name)
string name; /* name of parameter */
{
string getparam(), val;
int atoi();
for (val = ""; *val == NULL;) {
val = getparam(name);
}
return (atoi(val));
}
long getlparam(name)
string name; /* name of parameter */
{
string getparam(), val;
long atol();
for (val = ""; *val == NULL; )
val = getparam(name);
return (atol(val));
}
bool getbparam(name)
string name; /* name of parameter */
{
string getparam(), val;
for (val = ""; *val == NULL; )
val = getparam(name);
if (strchr("tTyY1", *val) != NULL) {
return (TRUE);
}
if (strchr("fFnN0", *val) != NULL) {
return (FALSE);
}
error("getbparam: %s=%s not bool\n", name, val);
}
double getdparam(name)
string name; /* name of parameter */
{
string getparam(), val;
double atof();
for (val = ""; *val == NULL; ) {
val = getparam(name);
}
return (atof(val));
}
/*
* SCANBIND: scan binding vector for name, return index.
*/
int scanbind(bvec, name)
string bvec[];
string name;
{
int i;
bool matchname();
for (i = 0; bvec[i] != NULL; i++)
if (matchname(bvec[i], name))
return (i);
return (-1);
}
/*
* MATCHNAME: determine if "name=value" matches "name".
*/
bool matchname(bind, name)
string bind, name;
{
char *bp, *np;
bp = bind;
np = name;
while (*bp == *np) {
bp++;
np++;
}
return (*bp == '=' && *np == NULL);
}
/*
* EXTRVALUE: extract value from name=value string.
*/
string extrvalue(arg)
string arg; /* string of the form "name=value" */
{
char *ap;
ap = (char *) arg;
while (*ap != NULL)
if (*ap++ == '=')
return ((string) ap);
return (NULL);
}

View File

@@ -0,0 +1,172 @@
#line 95 "./null_macros/c.m4.null"
#line 1 "grav.C"
/*************************************************************************/
/* */
/* Copyright (c) 1994 Stanford University */
/* */
/* All rights reserved. */
/* */
/* Permission is given to use, copy, and modify this software for any */
/* non-commercial purpose as long as this copyright notice is not */
/* removed. All other uses, including redistribution in whole or in */
/* part, are forbidden without prior written permission. */
/* */
/* This software is provided with absolutely no warranty and no */
/* support. */
/* */
/*************************************************************************/
/*
* GRAV.C:
*/
#define global extern
#include "code.h"
/*
* HACKGRAV: evaluate grav field at a given particle.
*/
hackgrav(p,ProcessId)
bodyptr p;
unsigned ProcessId;
{
extern gravsub();
Local[ProcessId].pskip = p;
SETV(Local[ProcessId].pos0, Pos(p));
Local[ProcessId].phi0 = 0.0;
CLRV(Local[ProcessId].acc0);
Local[ProcessId].myn2bterm = 0;
Local[ProcessId].mynbcterm = 0;
Local[ProcessId].skipself = FALSE;
hackwalk(gravsub, ProcessId);
Phi(p) = Local[ProcessId].phi0;
SETV(Acc(p), Local[ProcessId].acc0);
#ifdef QUADPOLE
Cost(p) = Local[ProcessId].myn2bterm + NDIM * Local[ProcessId].mynbcterm;
#else
Cost(p) = Local[ProcessId].myn2bterm + Local[ProcessId].mynbcterm;
#endif
}
/*
* GRAVSUB: compute a single body-body or body-cell interaction.
*/
gravsub(p, ProcessId, level)
register nodeptr p; /* body or cell to interact with */
unsigned ProcessId;
int level;
{
double sqrt();
real drabs, phii, mor3;
vector ai, quaddr;
real dr5inv, phiquad, drquaddr;
if (p != Local[ProcessId].pmem) {
SUBV(Local[ProcessId].dr, Pos(p), Local[ProcessId].pos0);
DOTVP(Local[ProcessId].drsq, Local[ProcessId].dr, Local[ProcessId].dr);
}
Local[ProcessId].drsq += epssq;
drabs = sqrt((double) Local[ProcessId].drsq);
phii = Mass(p) / drabs;
Local[ProcessId].phi0 -= phii;
mor3 = phii / Local[ProcessId].drsq;
MULVS(ai, Local[ProcessId].dr, mor3);
ADDV(Local[ProcessId].acc0, Local[ProcessId].acc0, ai);
if(Type(p) != BODY) { /* a body-cell/leaf interaction? */
Local[ProcessId].mynbcterm++;
#ifdef QUADPOLE
dr5inv = 1.0/(Local[ProcessId].drsq * Local[ProcessId].drsq * drabs);
MULMV(quaddr, Quad(p), Local[ProcessId].dr);
DOTVP(drquaddr, Local[ProcessId].dr, quaddr);
phiquad = -0.5 * dr5inv * drquaddr;
Local[ProcessId].phi0 += phiquad;
phiquad = 5.0 * phiquad / Local[ProcessId].drsq;
MULVS(ai, Local[ProcessId].dr, phiquad);
SUBV(Local[ProcessId].acc0, Local[ProcessId].acc0, ai);
MULVS(quaddr, quaddr, dr5inv);
SUBV(Local[ProcessId].acc0, Local[ProcessId].acc0, quaddr);
#endif
}
else { /* a body-body interaction */
Local[ProcessId].myn2bterm++;
}
}
/*
* HACKWALK: walk the tree opening cells too close to a given point.
*/
local proced hacksub;
hackwalk(sub, ProcessId)
proced sub; /* routine to do calculation */
unsigned ProcessId;
{
walksub(Global->G_root, Global->rsize * Global->rsize, ProcessId);
}
/*
* WALKSUB: recursive routine to do hackwalk operation.
*/
walksub(n, dsq, ProcessId)
nodeptr n; /* pointer into body-tree */
real dsq; /* size of box squared */
unsigned ProcessId;
{
bool subdivp();
nodeptr* nn;
leafptr l;
bodyptr p;
int i;
if (subdivp(n, dsq, ProcessId)) {
if (Type(n) == CELL) {
for (nn = Subp(n); nn < Subp(n) + NSUB; nn++) {
if (*nn != NULL) {
walksub(*nn, dsq / 4.0, ProcessId);
}
}
}
else {
l = (leafptr) n;
for (i = 0; i < l->num_bodies; i++) {
p = Bodyp(l)[i];
if (p != Local[ProcessId].pskip) {
gravsub(p, ProcessId);
}
else {
Local[ProcessId].skipself = TRUE;
}
}
}
}
else {
gravsub(n, ProcessId);
}
}
/*
* SUBDIVP: decide if a node should be opened.
* Side effects: sets pmem,dr, and drsq.
*/
bool subdivp(p, dsq, ProcessId)
register nodeptr p; /* body/cell to be tested */
real dsq; /* size of cell squared */
unsigned ProcessId;
{
SUBV(Local[ProcessId].dr, Pos(p), Local[ProcessId].pos0);
DOTVP(Local[ProcessId].drsq, Local[ProcessId].dr, Local[ProcessId].dr);
Local[ProcessId].pmem = p;
return (tolsq * Local[ProcessId].drsq < dsq);
}

View File

@@ -0,0 +1,550 @@
#line 95 "./null_macros/c.m4.null"
#line 1 "load.C"
/*************************************************************************/
/* */
/* Copyright (c) 1994 Stanford University */
/* */
/* All rights reserved. */
/* */
/* Permission is given to use, copy, and modify this software for any */
/* non-commercial purpose as long as this copyright notice is not */
/* removed. All other uses, including redistribution in whole or in */
/* part, are forbidden without prior written permission. */
/* */
/* This software is provided with absolutely no warranty and no */
/* support. */
/* */
/*************************************************************************/
#define global extern
#include "code.h"
#include "defs.h"
#include <math.h>
bool intcoord();
cellptr makecell(unsigned int ProcessId);
leafptr makeleaf(unsigned int ProcessId);
cellptr SubdivideLeaf(leafptr le, cellptr parent, unsigned int l,
unsigned int ProcessId);
cellptr InitCell(cellptr parent, unsigned int ProcessId);
leafptr InitLeaf(cellptr parent, unsigned int ProcessId);
nodeptr loadtree(bodyptr p, cellptr root, unsigned int ProcessId);
void hackcofm(int nc, unsigned ProcessId);
/*
* MAKETREE: initialize tree structure for hack force calculation.
*/
maketree(unsigned ProcessId)
{
bodyptr p, *pp;
Local[ProcessId].myncell = 0;
Local[ProcessId].mynleaf = 0;
if (ProcessId == 0) {
Local[ProcessId].mycelltab[Local[ProcessId].myncell++] = Global->G_root;
}
Local[ProcessId].Current_Root = (nodeptr) Global->G_root;
for (pp = Local[ProcessId].mybodytab;
pp < Local[ProcessId].mybodytab+Local[ProcessId].mynbody; pp++) {
p = *pp;
if (Mass(p) != 0.0) {
Local[ProcessId].Current_Root
= (nodeptr) loadtree(p, (cellptr) Local[ProcessId].Current_Root,
ProcessId);
}
else {
{;};
// fprintf(stderr, "Process %d found body %d to have zero mass\n",
// ProcessId, (int) p);
{;};
}
}
{;};
hackcofm( 0, ProcessId );
{;};
}
cellptr InitCell(cellptr parent, unsigned ProcessId)
{
cellptr c;
int i, Mycell;
c = makecell(ProcessId);
c->processor = ProcessId;
c->next = NULL;
c->prev = NULL;
if (parent == NULL)
Level(c) = IMAX >> 1;
else
Level(c) = Level(parent) >> 1;
Parent(c) = (nodeptr) parent;
ChildNum(c) = 0;
return (c);
}
leafptr InitLeaf(cellptr parent,unsigned ProcessId)
{
leafptr l;
int i, Mycell;
l = makeleaf(ProcessId);
l->processor = ProcessId;
l->next = NULL;
l->prev = NULL;
if (parent==NULL)
Level(l) = IMAX >> 1;
else
Level(l) = Level(parent) >> 1;
Parent(l) = (nodeptr) parent;
ChildNum(l) = 0;
return (l);
}
// printtree (n)
// nodeptr n;
// {
// int k;
// cellptr c;
// leafptr l;
// bodyptr p;
// nodeptr tmp;
// unsigned long nseq;
// int xp[NDIM];
// switch (Type(n)) {
// case CELL:
// c = (cellptr) n;
// nseq = c->seqnum;
// // printf("Cell : Cost = %d, ", Cost(c));
// // PRTV("Pos", Pos(n));
// // printf("\n");
// for (k = 0; k < NSUB; k++) {
// // printf("Child #%d: ", k);
// if (Subp(c)[k] == NULL) {
// // printf("NONE");
// }
// else {
// if (Type(Subp(c)[k]) == CELL) {
// nseq = ((cellptr) Subp(c)[k])->seqnum;
// // printf("C: Cost = %d, ", Cost(Subp(c)[k]));
// }
// else {
// nseq = ((leafptr) Subp(c)[k])->seqnum;
// // printf("L: # Bodies = %2d, Cost = %d, ",
// // ((leafptr) Subp(c)[k])->num_bodies, Cost(Subp(c)[k]));
// }
// tmp = Subp(c)[k];
// // PRTV("Pos", Pos(tmp));
// }
// // printf("\n");
// }
// for (k=0;k<NSUB;k++) {
// if (Subp(c)[k] != NULL) {
// // printtree(Subp(c)[k]);
// }
// }
// break;
// case LEAF:
// l = (leafptr) n;
// nseq = l->seqnum;
// // printf("Leaf : # Bodies = %2d, Cost = %d, ", l->num_bodies, Cost(l));
// // PRTV("Pos", Pos(n));
// // printf("\n");
// for (k = 0; k < l->num_bodies; k++) {
// p = Bodyp(l)[k];
// // printf("Body #%2d: Num = %2d, Level = %o, ",
// // p - bodytab, k, Level(p));
// // PRTV("Pos",Pos(p));
// // printf("\n");
// }
// break;
// default:
// // fprintf(stderr, "Bad type\n");
// exit(-1);
// break;
// }
// fflush(stdout);
// }
/*
* LOADTREE: descend tree and insert particle.
*/
nodeptr
loadtree(bodyptr p, cellptr root,unsigned ProcessId)
{
int l, xq[NDIM], xp[NDIM], xor[NDIM], subindex(), flag;
int i, j, root_level;
bool valid_root;
int kidIndex;
volatile nodeptr *volatile qptr, mynode;
cellptr c;
leafptr le;
intcoord(xp, Pos(p));
valid_root = TRUE;
for (i = 0; i < NDIM; i++) {
xor[i] = xp[i] ^ Local[ProcessId].Root_Coords[i];
}
for (i = IMAX >> 1; i > Level(root); i >>= 1) {
for (j = 0; j < NDIM; j++) {
if (xor[j] & i) {
valid_root = FALSE;
break;
}
}
if (!valid_root) {
break;
}
}
if (!valid_root) {
if (root != Global->G_root) {
root_level = Level(root);
for (j = i; j > root_level; j >>= 1) {
root = (cellptr) Parent(root);
}
valid_root = TRUE;
for (i = IMAX >> 1; i > Level(root); i >>= 1) {
for (j = 0; j < NDIM; j++) {
if (xor[j] & i) {
valid_root = FALSE;
break;
}
}
if (!valid_root) {
// printf("P%d body %d\n", ProcessId, p - bodytab);
root = Global->G_root;
}
}
}
}
root = Global->G_root;
mynode = (nodeptr) root;
kidIndex = subindex(xp, Level(mynode));
qptr = &Subp(mynode)[kidIndex];
l = Level(mynode) >> 1;
flag = TRUE;
while (flag) { /* loop descending tree */
if (l == 0) {
// error("not enough levels in tree\n");
}
if (*qptr == NULL) {
/* lock the parent cell */
{;};
if (*qptr == NULL) {
le = InitLeaf((cellptr) mynode, ProcessId);
Parent(p) = (nodeptr) le;
Level(p) = l;
ChildNum(p) = le->num_bodies;
ChildNum(le) = kidIndex;
Bodyp(le)[le->num_bodies++] = p;
*qptr = (nodeptr) le;
flag = FALSE;
}
{;};
/* unlock the parent cell */
}
if (flag && *qptr && (Type(*qptr) == LEAF)) {
/* reached a "leaf"? */
{;};
/* lock the parent cell */
if (Type(*qptr) == LEAF) { /* still a "leaf"? */
le = (leafptr) *qptr;
if (le->num_bodies == MAX_BODIES_PER_LEAF) {
*qptr = (nodeptr) SubdivideLeaf(le, (cellptr) mynode, l,
ProcessId);
}
else {
Parent(p) = (nodeptr) le;
Level(p) = l;
ChildNum(p) = le->num_bodies;
Bodyp(le)[le->num_bodies++] = p;
flag = FALSE;
}
}
{;};
/* unlock the node */
}
if (flag) {
mynode = *qptr;
kidIndex = subindex(xp, l);
qptr = &Subp(*qptr)[kidIndex]; /* move down one level */
l = l >> 1; /* and test next bit */
}
}
SETV(Local[ProcessId].Root_Coords, xp);
return Parent((leafptr) *qptr);
}
/* * INTCOORD: compute integerized coordinates. * Returns: TRUE
unless rp was out of bounds. */
bool intcoord(xp, rp)
int xp[NDIM]; /* integerized coordinate vector [0,IMAX) */
vector rp; /* real coordinate vector (system coords) */
{
int k;
bool inb;
double xsc, floor();
inb = TRUE;
for (k = 0; k < NDIM; k++) {
xsc = (rp[k] - Global->rmin[k]) / Global->rsize;
if (0.0 <= xsc && xsc < 1.0) {
xp[k] = floor(IMAX * xsc);
}
else {
inb = FALSE;
}
}
return (inb);
}
/*
* SUBINDEX: determine which subcell to select.
*/
int subindex(x, l)
int x[NDIM]; /* integerized coordinates of particle */
int l; /* current level of tree */
{
int i, k;
int yes;
i = 0;
yes = FALSE;
if (x[0] & l) {
i += NSUB >> 1;
yes = TRUE;
}
for (k = 1; k < NDIM; k++) {
if (((x[k] & l) && !yes) || (!(x[k] & l) && yes)) {
i += NSUB >> (k + 1);
yes = TRUE;
}
else yes = FALSE;
}
return (i);
}
/*
* HACKCOFM: descend tree finding center-of-mass coordinates.
*/
void hackcofm(int nc,unsigned ProcessId)
{
int i,Myindex;
nodeptr r;
leafptr l;
leafptr* ll;
bodyptr p;
cellptr q;
cellptr *cc;
vector tmpv, dr;
real drsq;
matrix drdr, Idrsq, tmpm;
/* get a cell using get*sub. Cells are got in reverse of the order in */
/* the cell array; i.e. reverse of the order in which they were created */
/* this way, we look at child cells before parents */
for (ll = Local[ProcessId].myleaftab + Local[ProcessId].mynleaf - 1;
ll >= Local[ProcessId].myleaftab; ll--) {
l = *ll;
Mass(l) = 0.0;
Cost(l) = 0;
CLRV(Pos(l));
for (i = 0; i < l->num_bodies; i++) {
p = Bodyp(l)[i];
Mass(l) += Mass(p);
Cost(l) += Cost(p);
MULVS(tmpv, Pos(p), Mass(p));
ADDV(Pos(l), Pos(l), tmpv);
}
DIVVS(Pos(l), Pos(l), Mass(l));
#ifdef QUADPOLE
CLRM(Quad(l));
for (i = 0; i < l->num_bodies; i++) {
p = Bodyp(l)[i];
SUBV(dr, Pos(p), Pos(l));
OUTVP(drdr, dr, dr);
DOTVP(drsq, dr, dr);
SETMI(Idrsq);
MULMS(Idrsq, Idrsq, drsq);
MULMS(tmpm, drdr, 3.0);
SUBM(tmpm, tmpm, Idrsq);
MULMS(tmpm, tmpm, Mass(p));
ADDM(Quad(l), Quad(l), tmpm);
}
#endif
Done(l)=TRUE;
}
for (cc = Local[ProcessId].mycelltab+Local[ProcessId].myncell-1;
cc >= Local[ProcessId].mycelltab; cc--) {
q = *cc;
Mass(q) = 0.0;
Cost(q) = 0;
CLRV(Pos(q));
for (i = 0; i < NSUB; i++) {
r = Subp(q)[i];
if (r != NULL) {
while(!Done(r)) {
/* wait */
}
Mass(q) += Mass(r);
Cost(q) += Cost(r);
MULVS(tmpv, Pos(r), Mass(r));
ADDV(Pos(q), Pos(q), tmpv);
Done(r) = FALSE;
}
}
DIVVS(Pos(q), Pos(q), Mass(q));
#ifdef QUADPOLE
CLRM(Quad(q));
for (i = 0; i < NSUB; i++) {
r = Subp(q)[i];
if (r != NULL) {
SUBV(dr, Pos(r), Pos(q));
OUTVP(drdr, dr, dr);
DOTVP(drsq, dr, dr);
SETMI(Idrsq);
MULMS(Idrsq, Idrsq, drsq);
MULMS(tmpm, drdr, 3.0);
SUBM(tmpm, tmpm, Idrsq);
MULMS(tmpm, tmpm, Mass(r));
ADDM(tmpm, tmpm, Quad(r));
ADDM(Quad(q), Quad(q), tmpm);
}
}
#endif
Done(q)=TRUE;
}
}
cellptr
SubdivideLeaf (le, parent, l, ProcessId)
leafptr le;
cellptr parent;
unsigned int l;
unsigned int ProcessId;
{
cellptr c;
int i, index;
int xp[NDIM];
bodyptr bodies[MAX_BODIES_PER_LEAF];
int num_bodies;
bodyptr p;
/* first copy leaf's bodies to temp array, so we can reuse the leaf */
num_bodies = le->num_bodies;
for (i = 0; i < num_bodies; i++) {
bodies[i] = Bodyp(le)[i];
Bodyp(le)[i] = NULL;
}
le->num_bodies = 0;
/* create the parent cell for this subtree */
c = InitCell(parent, ProcessId);
ChildNum(c) = ChildNum(le);
/* do first particle separately, so we can reuse le */
p = bodies[0];
intcoord(xp, Pos(p));
index = subindex(xp, l);
Subp(c)[index] = (nodeptr) le;
ChildNum(le) = index;
Parent(le) = (nodeptr) c;
Level(le) = l >> 1;
/* set stuff for body */
Parent(p) = (nodeptr) le;
ChildNum(p) = le->num_bodies;
Level(p) = l >> 1;
/* insert the body */
Bodyp(le)[le->num_bodies++] = p;
/* now handle the rest */
for (i = 1; i < num_bodies; i++) {
p = bodies[i];
intcoord(xp, Pos(p));
index = subindex(xp, l);
if (!Subp(c)[index]) {
le = InitLeaf(c, ProcessId);
ChildNum(le) = index;
Subp(c)[index] = (nodeptr) le;
}
else {
le = (leafptr) Subp(c)[index];
}
Parent(p) = (nodeptr) le;
ChildNum(p) = le->num_bodies;
Level(p) = l >> 1;
Bodyp(le)[le->num_bodies++] = p;
}
return c;
}
/*
* MAKECELL: allocation routine for cells.
*/
cellptr makecell(ProcessId)
unsigned ProcessId;
{
cellptr c;
int i, Mycell;
if (Local[ProcessId].mynumcell == maxmycell) {
// error("makecell: Proc %d needs more than %d cells; increase fcells\n",
// ProcessId,maxmycell);
}
Mycell = Local[ProcessId].mynumcell++;
c = Local[ProcessId].ctab + Mycell;
c->seqnum = ProcessId*maxmycell+Mycell;
Type(c) = CELL;
Done(c) = FALSE;
Mass(c) = 0.0;
for (i = 0; i < NSUB; i++) {
Subp(c)[i] = NULL;
}
Local[ProcessId].mycelltab[Local[ProcessId].myncell++] = c;
return (c);
}
/*
* MAKELEAF: allocation routine for leaves.
*/
leafptr makeleaf(ProcessId)
unsigned ProcessId;
{
leafptr le;
int i, Myleaf;
if (Local[ProcessId].mynumleaf == maxmyleaf) {
// error("makeleaf: Proc %d needs more than %d leaves; increase fleaves\n",
// ProcessId,maxmyleaf);
}
Myleaf = Local[ProcessId].mynumleaf++;
le = Local[ProcessId].ltab + Myleaf;
le->seqnum = ProcessId * maxmyleaf + Myleaf;
Type(le) = LEAF;
Done(le) = FALSE;
Mass(le) = 0.0;
le->num_bodies = 0;
for (i = 0; i < MAX_BODIES_PER_LEAF; i++) {
Bodyp(le)[i] = NULL;
}
Local[ProcessId].myleaftab[Local[ProcessId].mynleaf++] = le;
return (le);
}

View File

@@ -0,0 +1,119 @@
#line 95 "./null_macros/c.m4.null"
#line 1 "stdinc.H"
/*************************************************************************/
/* */
/* Copyright (c) 1994 Stanford University */
/* */
/* All rights reserved. */
/* */
/* Permission is given to use, copy, and modify this software for any */
/* non-commercial purpose as long as this copyright notice is not */
/* removed. All other uses, including redistribution in whole or in */
/* part, are forbidden without prior written permission. */
/* */
/* This software is provided with absolutely no warranty and no */
/* support. */
/* */
/*************************************************************************/
/*
* STDINC.H: standard include file for C programs.
*/
#ifndef _STDINC_H_
#define _STDINC_H_
/*
* If not already loaded, include stdio.h.
*/
#include <stdio.h>
/*
* STREAM: a replacement for FILE *.
*/
typedef FILE *stream;
/*
* NULL: denotes a pointer to no object.
*/
#ifndef NULL
#define NULL 0
#endif
/*
* BOOL, TRUE and FALSE: standard names for logical values.
*/
typedef int bool;
#ifndef TRUE
#define FALSE 0
#define TRUE 1
#endif
/*
* BYTE: a short name for a handy chunk of bits.
*/
typedef unsigned char byte;
/*
* STRING: for null-terminated strings which are not taken apart.
*/
typedef char *string;
/*
* REAL: default type is double;
*/
typedef double real, *realptr;
/*
* PROC, IPROC, RPROC: pointers to procedures, integer functions, and
* real-valued functions, respectively.
*/
typedef void (*proced)();
typedef int (*iproc)();
typedef real (*rproc)();
/*
* LOCAL: declare something to be local to a file.
* PERMANENT: declare something to be permanent data within a function.
*/
#define local static
#define permanent static
/*
* STREQ: handy string-equality macro.
*/
#define streq(x,y) (strcmp((x), (y)) == 0)
/*
* PI, etc. -- mathematical constants
*/
#define PI 3.14159265358979323846
#define TWO_PI 6.28318530717958647693
#define FOUR_PI 12.56637061435917295385
#define HALF_PI 1.57079632679489661923
#define FRTHRD_PI 4.18879020478639098462
/*
* ABS: returns the absolute value of its argument
* MAX: returns the argument with the highest value
* MIN: returns the argument with the lowest value
*/
#define ABS(x) (((x) < 0) ? -(x) : (x))
#endif

View File

@@ -0,0 +1,102 @@
#line 95 "./null_macros/c.m4.null"
#line 1 "util.C"
/*************************************************************************/
/* */
/* Copyright (c) 1994 Stanford University */
/* */
/* All rights reserved. */
/* */
/* Permission is given to use, copy, and modify this software for any */
/* non-commercial purpose as long as this copyright notice is not */
/* removed. All other uses, including redistribution in whole or in */
/* part, are forbidden without prior written permission. */
/* */
/* This software is provided with absolutely no warranty and no */
/* support. */
/* */
/*************************************************************************/
#include <stdio.h>
#include <errno.h>
#include "stdinc.h"
#define HZ 60.0
#define MULT 1103515245
#define ADD 12345
#define MASK (0x7FFFFFFF)
#define TWOTO31 2147483648.0
local int A = 1;
local int B = 0;
local int randx = 1;
local int lastrand; /* the last random number */
/*
* XRAND: generate floating-point random number.
*/
double prand();
double xrand(xl, xh)
double xl, xh; /* lower, upper bounds on number */
{
long random ();
double x;
return (xl + (xh - xl) * prand());
}
void pranset(int seed)
{
int proc;
A = 1;
B = 0;
randx = (A*seed+B) & MASK;
A = (MULT * A) & MASK;
B = (MULT*B + ADD) & MASK;
}
double
prand()
/*
Return a random double in [0, 1.0)
*/
{
lastrand = randx;
randx = (A*randx+B) & MASK;
return((double)lastrand/TWOTO31);
}
/*
* CPUTIME: compute CPU time in min.
*/
// #include <sys/types.h>
// #include <sys/times.h>
// double cputime()
// {
// struct tms buffer;
// if (times(&buffer) == -1)
// error("times() call failed\n");
// return (buffer.tms_utime / (60.0 * HZ));
// }
/*
* ERROR: scream and die quickly.
*/
// error(msg, a1, a2, a3, a4)
// char *msg, *a1, *a2, *a3, *a4;
// {
// extern int errno;
// // fprintf(stderr, msg, a1, a2, a3, a4);
// // if (errno != 0)
// // perror("Error");
// // exit(0);
// }

View File

@@ -0,0 +1,307 @@
#line 95 "./null_macros/c.m4.null"
#line 1 "vectmath.H"
/*************************************************************************/
/* */
/* Copyright (c) 1994 Stanford University */
/* */
/* All rights reserved. */
/* */
/* Permission is given to use, copy, and modify this software for any */
/* non-commercial purpose as long as this copyright notice is not */
/* removed. All other uses, including redistribution in whole or in */
/* part, are forbidden without prior written permission. */
/* */
/* This software is provided with absolutely no warranty and no */
/* support. */
/* */
/*************************************************************************/
/*
* VECTMATH.H: include file for vector/matrix operations.
*/
#ifndef _VECMATH_H_
#define _VECMATH_H_
# define NDIM 3
typedef real vector[NDIM], matrix[NDIM][NDIM];
/*
* Vector operations.
*/
#define CLRV(v) /* CLeaR Vector */ \
{ \
register int _i; \
for (_i = 0; _i < NDIM; _i++) \
(v)[_i] = 0.0; \
}
#define UNITV(v,j) /* UNIT Vector */ \
{ \
register int _i; \
for (_i = 0; _i < NDIM; _i++) \
(v)[_i] = (_i == (j) ? 1.0 : 0.0); \
}
#define SETV(v,u) /* SET Vector */ \
{ \
register int _i; \
for (_i = 0; _i < NDIM; _i++) \
(v)[_i] = (u)[_i]; \
}
#define ADDV(v,u,w) /* ADD Vector */ \
{ \
register real *_vp = (v), *_up = (u), *_wp = (w); \
*_vp++ = (*_up++) + (*_wp++); \
*_vp++ = (*_up++) + (*_wp++); \
*_vp = (*_up ) + (*_wp ); \
}
#define SUBV(v,u,w) /* SUBtract Vector */ \
{ \
register real *_vp = (v), *_up = (u), *_wp = (w); \
*_vp++ = (*_up++) - (*_wp++); \
*_vp++ = (*_up++) - (*_wp++); \
*_vp = (*_up ) - (*_wp ); \
}
#define MULVS(v,u,s) /* MULtiply Vector by Scalar */ \
{ \
register real *_vp = (v), *_up = (u); \
*_vp++ = (*_up++) * (s); \
*_vp++ = (*_up++) * (s); \
*_vp = (*_up ) * (s); \
}
#define DIVVS(v,u,s) /* DIVide Vector by Scalar */ \
{ \
register int _i; \
for (_i = 0; _i < NDIM; _i++) \
(v)[_i] = (u)[_i] / (s); \
}
#define DOTVP(s,v,u) /* DOT Vector Product */ \
{ \
register real *_vp = (v), *_up = (u); \
(s) = (*_vp++) * (*_up++); \
(s) += (*_vp++) * (*_up++); \
(s) += (*_vp ) * (*_up ); \
}
#define ABSV(s,v) /* ABSolute value of a Vector */ \
{ \
double _tmp, sqrt(); \
register int _i; \
_tmp = 0.0; \
for (_i = 0; _i < NDIM; _i++) \
_tmp += (v)[_i] * (v)[_i]; \
(s) = sqrt(_tmp); \
}
#define DISTV(s,u,v) /* DISTance between Vectors */ \
{ \
double _tmp, sqrt(); \
register int _i; \
_tmp = 0.0; \
for (_i = 0; _i < NDIM; _i++) \
_tmp += ((u)[_i]-(v)[_i]) * ((u)[_i]-(v)[_i]); \
(s) = sqrt(_tmp); \
}
#define CROSSVP(v,u,w) /* CROSS Vector Product */ \
{ \
(v)[0] = (u)[1]*(w)[2] - (u)[2]*(w)[1]; \
(v)[1] = (u)[2]*(w)[0] - (u)[0]*(w)[2]; \
(v)[2] = (u)[0]*(w)[1] - (u)[1]*(w)[0]; \
}
#define INCADDV(v,u) /* INCrementally ADD Vector */ \
{ \
register int _i; \
for (_i = 0; _i < NDIM; _i++) \
(v)[_i] += (u)[_i]; \
}
#define INCSUBV(v,u) /* INCrementally SUBtract Vector */ \
{ \
register int _i; \
for (_i = 0; _i < NDIM; _i++) \
(v)[_i] -= (u)[_i]; \
}
#define INCMULVS(v,s) /* INCrementally MULtiply Vector by Scalar */ \
{ \
register int _i; \
for (_i = 0; _i < NDIM; _i++) \
(v)[_i] *= (s); \
}
#define INCDIVVS(v,s) /* INCrementally DIVide Vector by Scalar */ \
{ \
register int _i; \
for (_i = 0; _i < NDIM; _i++) \
(v)[_i] /= (s); \
}
/*
* Matrix operations.
*/
#define CLRM(p) /* CLeaR Matrix */ \
{ \
register int _i, _j; \
for (_i = 0; _i < NDIM; _i++) \
for (_j = 0; _j < NDIM; _j++) \
(p)[_i][_j] = 0.0; \
}
#define SETMI(p) /* SET Matrix to Identity */ \
{ \
register int _i, _j; \
for (_i = 0; _i < NDIM; _i++) \
for (_j = 0; _j < NDIM; _j++) \
(p)[_i][_j] = (_i == _j ? 1.0 : 0.0); \
}
#define SETM(p,q) /* SET Matrix */ \
{ \
register int _i, _j; \
for (_i = 0; _i < NDIM; _i++) \
for (_j = 0; _j < NDIM; _j++) \
(p)[_i][_j] = (q)[_i][_j]; \
}
#define TRANM(p,q) /* TRANspose Matrix */ \
{ \
register int _i, _j; \
for (_i = 0; _i < NDIM; _i++) \
for (_j = 0; _j < NDIM; _j++) \
(p)[_i][_j] = (q)[_j][_i]; \
}
#define ADDM(p,q,r) /* ADD Matrix */ \
{ \
register int _i, _j; \
for (_i = 0; _i < NDIM; _i++) \
for (_j = 0; _j < NDIM; _j++) \
(p)[_i][_j] = (q)[_i][_j] + (r)[_i][_j]; \
}
#define SUBM(p,q,r) /* SUBtract Matrix */ \
{ \
register int _i, _j; \
for (_i = 0; _i < NDIM; _i++) \
for (_j = 0; _j < NDIM; _j++) \
(p)[_i][_j] = (q)[_i][_j] - (r)[_i][_j]; \
}
#define MULM(p,q,r) /* Multiply Matrix */ \
{ \
register int _i, _j, _k; \
for (_i = 0; _i < NDIM; _i++) \
for (_j = 0; _j < NDIM; _j++) { \
(p)[_i][_j] = 0.0; \
for (_k = 0; _k < NDIM; _k++) \
(p)[_i][_j] += (q)[_i][_k] * (r)[_k][_j]; \
} \
}
#define MULMS(p,q,s) /* MULtiply Matrix by Scalar */ \
{ \
register int _i, _j; \
for (_i = 0; _i < NDIM; _i++) \
for (_j = 0; _j < NDIM; _j++) \
(p)[_i][_j] = (q)[_i][_j] * (s); \
}
#define DIVMS(p,q,s) /* DIVide Matrix by Scalar */ \
{ \
register int _i, _j; \
for (_i = 0; _i < NDIM; _i++) \
for (_j = 0; _j < NDIM; _j++) \
(p)[_i][_j] = (q)[_i][_j] / (s); \
}
#define MULMV(v,p,u) /* MULtiply Matrix by Vector */ \
{ \
register int _i, _j; \
for (_i = 0; _i < NDIM; _i++) { \
(v)[_i] = 0.0; \
for (_j = 0; _j < NDIM; _j++) \
(v)[_i] += (p)[_i][_j] * (u)[_j]; \
} \
}
#define OUTVP(p,v,u) /* OUTer Vector Product */ \
{ \
register int _i, _j; \
for (_i = 0; _i < NDIM; _i++) \
for (_j = 0; _j < NDIM; _j++) \
(p)[_i][_j] = (v)[_i] * (u)[_j]; \
}
#define TRACEM(s,p) /* TRACE of Matrix */ \
{ \
register int _i; \
(s) = 0.0; \
for (_i = 0.0; _i < NDIM; _i++) \
(s) += (p)[_i][_i]; \
}
/*
* Misc. impure operations.
*/
#define SETVS(v,s) /* SET Vector to Scalar */ \
{ \
register int _i; \
for (_i = 0; _i < NDIM; _i++) \
(v)[_i] = (s); \
}
#define ADDVS(v,u,s) /* ADD Vector and Scalar */ \
{ \
register int _i; \
for (_i = 0; _i < NDIM; _i++) \
(v)[_i] = (u)[_i] + (s); \
}
#define SETMS(p,s) /* SET Matrix to Scalar */ \
{ \
register int _i, _j; \
for (_i = 0; _i < NDIM; _i++) \
for (_j = 0; _j < NDIM; _j++) \
(p)[_i][_j] = (s); \
}
// #define PRTV(name, vec) /* PRinT Vector */ \
// { \
// fprintf(stdout,"%s = [%9.4f,%9.4f,%9.4f] ",name,vec[0],vec[1],vec[2]); \
// }
// #define PRIV(name, vec) /* PRint Integer Vector */ \
// { \
// fprintf(stdout,"%s = [%d,%d,%d] ",name,vec[0],vec[1],vec[2]); \
// }
// #define PROV(name, vec) /* PRint Integer Vector */ \
// { \
// fprintf(stdout,"%s = [%o,%o,%o] ",name,vec[0],vec[1],vec[2]); \
// }
// #define PRHV(name, vec) /* PRint Integer Vector */ \
// { \
// fprintf(stdout,"%s = [%x,%x,%x] ",name,vec[0],vec[1],vec[2]); \
// }
#endif

View File

@@ -218,7 +218,7 @@ int main (void)
// if (argc > 2 || size <= 0)
// usage (argv[0]);
// bench (size);
bench (size);
// bench (2*size);
// bench (4*size);
// bench (8*size);

View File

@@ -0,0 +1,45 @@
scp ../../encoding.h home-1:/home/akilan/
scp ../../entry.S home-1:/home/akilan/
scp ../../link.ld home-1:/home/akilan/
scp ../../riscv_test_p.h home-1:/home/akilan/
scp ../../riscv_test.h home-1:/home/akilan/
scp ../../string.c home-1:/home/akilan/
scp ../../vm.c home-1:/home/akilan/
scp ../../test.S home-1:/home/akilan/
scp ../../test_macros.h home-1:/home/akilan/
scp ../../malloc.c home-1:/home/akilan/
# scp ../../test.c home-1:/home/akilan/
scp matrixmul.c home-1:/home/akilan/
# GCC compile
# ssh home-1 'cd /home/akilan/ && export PATH=/opt/riscv/bin:$PATH && riscv64-unknown-elf-gcc -DENTROPY=0xf21e02b -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -mabi=lp64 -T link.ld vm.c string.c entry.S test.S -o testC'
# Clang compile (architecture Regular RISCV)
ssh home-1 'clang --target=riscv64-unknown-elf -DENTROPY=0xf21e02b -DDEFINE_MALLOC -DDEFINE_FREE --gcc-toolchain=/opt/riscv -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -fno-builtin-malloc -mabi=lp64 -T link.ld vm.c string.c malloc.c entry.S test.S matrixmul.c -o testC'
# Clang using the cheri clang compiler
# ssh home-1 'cd cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-freebsd -DENTROPY=0xf21e02b --sysroot=cheribsd-riscv64-for-purecap-rootfs.cfg -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -march=rv64imafdcxcheri -mabi=lp64d -T link.ld vm.c string.c entry.S test.S -o testC'
scp home-1:/home/akilan/testC ../../../
# scp home-1:/home/akilan/cheri/output/sdk/bin/testC .
# riscv64-unknown-elf-gcc \
# -march=rv64imac \
# -mabi=lp64 \
# -nostartfiles \
# -fno-builtin \
# -T link.ld \
# entry.S vm.c string.c \
# clang \
# --target=riscv64-unknown-elf \
# -march=rv64imac \
# -mabi=lp64 \
# -nostdlib \
# -nostartfiles \
# -fuse-ld=lld \
# -T link.ld \
# entry.S vm.c string.c \
# -I. \
# -o output.elf%

View File

@@ -0,0 +1,204 @@
#define MATMUL_1D
#ifdef MATMUL_1D
/* Matrices are represented as 1-D arrays in memory.
* That means they are contiguous in memory.
* Minimum dimension is 1, not 0, and internal dimensions must match. */
#include <math.h>
// #include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
void free(void *ptr);
void *malloc(size_t size);
/* Initializes vector or matrix, sequentially, with indices. */
void init_seq(double *a, const unsigned n_rows_a, const unsigned n_cols_a) {
for (size_t i = 0; i < n_rows_a; i++) {
for (size_t j = 0; j < n_cols_a; j++) {
a[i*n_cols_a + j] = i*n_cols_a + j;
}
}
}
// static unsigned int seed = 123456789; // must be initialized somehow
// unsigned int rand_test(void)
// {
// seed = (1103515245 * seed + 12345);
// return (seed >> 16) & 0x7FFF; // 15-bit result
// }
// /* Initializes vector or matrix, randomly. */
// void init_rand(double *a, const unsigned n_rows_a, const unsigned n_cols_a) {
// for (size_t i = 0; i < n_rows_a; i++) {
// for (size_t j = 0; j < n_cols_a; j++) {
// a[i*n_cols_a + j] = rand_test() / 32767.0;
// // rand_test() / (double)RAND_MAX;
// }
// }
// }
/* Takes and returns a new matrix, t, which is a transpose of the original one, m.
It's also flat in memory, i.e., 1-D, but it should be looked at as a transpose
of m, meaning, n_rows_t == n_cols_m, and n_cols_t == n_rows_m.
The original matrix m stays intact. */
double *transpose(const double *m, const unsigned n_rows_m, const unsigned n_cols_m, double *t) {
for (size_t i = 0; i < n_rows_m; i++) {
for (size_t j = 0; j < n_cols_m; j++) {
t[j*n_rows_m + i] = m[i*n_cols_m + j];
}
}
return t;
}
/* Dot product of two arrays, or matrix product
* Allocates and returns an array.
* This variant doesn't transpose matrix b, and it's a lot slower. */
double *dot_simple(const double *a, const unsigned n_rows_a, const unsigned n_cols_a,\
const double *b, const unsigned n_rows_b, const unsigned n_cols_b) {
if (n_cols_a != n_rows_b) {
// printf("#columns A must be equal to #rows B!\n");
// system("pause");
// exit(-2);
}
double *c = malloc(n_rows_a * n_cols_b * sizeof(*c));
if (c == NULL) {
// printf("Couldn't allocate memory!\n");
// system("pause");
// exit(-1);
}
for (size_t i = 0; i < n_rows_a; i++) {
for (size_t k = 0; k < n_cols_b; k++) {
double sum = 0.0;
for (size_t j = 0; j < n_cols_a; j++) {
sum += a[i*n_cols_a + j] * b[j*n_cols_b + k];
}
c[i*n_cols_b + k] = sum;
}
}
return c;
}
/* Dot product of two arrays, or matrix product
* Allocates and returns an array.
* This variant transposes matrix b, and it's a lot faster. */
double *dot(const double *a, const unsigned n_rows_a, const unsigned n_cols_a, \
const double *b, const unsigned n_rows_b, const unsigned n_cols_b) {
if (n_cols_a != n_rows_b) {
// printf("#columns A must be equal to #rows B!\n");
// system("pause");
// exit(-2);
}
double *bt = malloc(n_rows_b * n_cols_b * sizeof(*b));
double *c = malloc(n_rows_a * n_cols_b * sizeof(*c));
if ((c == NULL) || (bt == NULL)) {
// printf("Couldn't allocate memory!\n");
// system("pause");
// exit(-1);
}
bt = transpose(b, n_rows_b, n_cols_b, bt);
for (size_t i = 0; i < n_rows_a; i++) {
for (size_t k = 0; k < n_cols_b; k++) {
double sum = 0.0;
for (size_t j = 0; j < n_cols_a; j++) {
sum += a[i*n_cols_a + j] * bt[k*n_rows_b + j];
}
c[i*n_cols_b + k] = sum;
}
}
free(bt);
return c;
}
/* Prints vector, or matrix. */
// void print(const double *a, const unsigned n_rows_a, const unsigned n_cols_a) {
// for (size_t i = 0; i < n_rows_a; i++) {
// for (size_t j = 0; j < n_cols_a; j++) {
// printf("%8.3f ", a[i*n_cols_a + j]);
// }
// printf("\n");
// }
// printf("\n");
// }
int main(void) {
/* Intializes random number generator */
// time_t t;
// srand((unsigned)time(&t));
// srand(0);
/* For measuring time */
double t0, t1;
const unsigned scale = 1;
const unsigned n_rows_a = 4 * scale;
const unsigned n_cols_a = 3 * scale;
const unsigned n_rows_b = 3 * scale;
const unsigned n_cols_b = 2 * scale;
double *a = malloc(n_rows_a * n_cols_a * sizeof(*a));
double *b = malloc(n_rows_b * n_cols_b * sizeof(*b));
double *c = NULL;
double *d = NULL;
if (!a || !b) {
// printf("Couldn't allocate memory!\n");
// system("pause");
// exit(-1);
}
// init_rand(a, n_rows_a, n_cols_a);
// init_rand(b, n_rows_b, n_cols_b);
init_seq(a, n_rows_a, n_cols_a);
init_seq(b, n_rows_b, n_cols_b);
// t0 = omp_get_wtime();
c = dot_simple(a, n_rows_a, n_cols_a, b, n_rows_b, n_cols_b);
// t1 = omp_get_wtime();
// printf("Dot Simple: Elapsed time %.3f s\n", t1 - t0);
// t0 = omp_get_wtime();
d = dot(a, n_rows_a, n_cols_a, b, n_rows_b, n_cols_b);
// t1 = omp_get_wtime();
// printf("Dot: Elapsed time %.3f s\n", t1 - t0);
if (scale == 1) {
// printf("Matrix A:\n");
// print(a, n_rows_a, n_cols_a);
// // printf("Matrix B:\n");
// print(b, n_rows_b, n_cols_b);
// // printf("Matrix C:\n");
// print(c, n_rows_a, n_cols_b);
// // printf("Matrix D:\n");
// print(d, n_rows_a, n_cols_b);
}
free(a);
free(b);
free(c);
free(d);
// system("pause");
return(0);
}
#endif // MATMUL_1D

View File

@@ -27,7 +27,7 @@ All rights reserved.
#define NPAD 7
#define MIN_WSS sizeof(struct l)
#define MAX_WSS 10
#define MAX_WSS 32
void free(void *ptr);
void *malloc(size_t size);

View File

@@ -0,0 +1,46 @@
scp ../../encoding.h home-1:/home/akilan/
scp ../../entry.S home-1:/home/akilan/
scp ../../link.ld home-1:/home/akilan/
scp ../../riscv_test_p.h home-1:/home/akilan/
scp ../../riscv_test.h home-1:/home/akilan/
scp ../../string.c home-1:/home/akilan/
scp ../../vm.c home-1:/home/akilan/
scp ../../test.S home-1:/home/akilan/
scp ../../test_macros.h home-1:/home/akilan/
scp ../../malloc.c home-1:/home/akilan/
# scp ../../test.c home-1:/home/akilan/
scp richards.c home-1:/home/akilan/
# GCC compile
# ssh home-1 'cd /home/akilan/ && export PATH=/opt/riscv/bin:$PATH && riscv64-unknown-elf-gcc -DENTROPY=0xf21e02b -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -mabi=lp64 -T link.ld vm.c string.c entry.S test.S -o testC'
# Clang compile (architecture Regular RISCV)
ssh home-1 'clang --target=riscv64-unknown-elf -DENTROPY=0xf21e02b -DDEFINE_MALLOC -DDEFINE_FREE --gcc-toolchain=/opt/riscv -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -fno-builtin-malloc -mabi=lp64 -T link.ld vm.c string.c malloc.c entry.S test.S richards.c -o testC'
# Clang using the cheri clang compiler
# ssh home-1 'cd cheri/output/sdk/bin/ && ./clang --target=riscv64-unknown-freebsd -DENTROPY=0xf21e02b --sysroot=cheribsd-riscv64-for-purecap-rootfs.cfg -mcmodel=medany -nostdlib -nostartfiles -ffreestanding -fno-builtin -march=rv64imafdcxcheri -mabi=lp64d -T link.ld vm.c string.c entry.S test.S -o testC'
scp home-1:/home/akilan/testC ../../../
# scp home-1:/home/akilan/cheri/output/sdk/bin/testC .
# riscv64-unknown-elf-gcc \
# -march=rv64imac \
# -mabi=lp64 \
# -nostartfiles \
# -fno-builtin \
# -T link.ld \
# entry.S vm.c string.c \
# clang \
# --target=riscv64-unknown-elf \
# -march=rv64imac \
# -mabi=lp64 \
# -nostdlib \
# -nostartfiles \
# -fuse-ld=lld \
# -T link.ld \
# entry.S vm.c string.c \
# -I. \
# -o output.elf%

View File

@@ -0,0 +1,455 @@
// clang-format off
/* C version of the systems programming language benchmark
** Author: M. J. Jordan Cambridge Computer Laboratory.
**
** Modified by: M. Richards, Nov 1996
** to be ANSI C and runnable on 64 bit machines + other minor changes
** Modified by: M. Richards, 20 Oct 1998
** made minor corrections to improve ANSI compliance (suggested
** by David Levine)
** Modified by: Jeremy Singer, 25 May 2022
** adapted to use uintptr_t for compatibility with architectures
** that do not have word-sized pointers (e.g. CHERI)
** also adapted to use Boehm-Demers-Weiser GC instead of system
** malloc, when compiled with -DGC
**
** Compile with, say
**
** gcc -o bench bench.c
**
** or
**
** gcc -o bench100 -Dbench100 bench.c (for a version that obeys
** the main loop 100x more often)
*/
// #include <stdio.h>
#include <stdint.h>
#include <stddef.h>
// #include <stdlib.h>
// #include "harness.h"
// #include "stddefines.h"
// #ifdef GC
// #include "gc.h"
// #define MALLOC GC_MALLOC
// #else
// #define MALLOC malloc
// #endif // GC
// #define malloc tiny_malloc
// #define free tiny_free
void* malloc(size_t);
void free(void*);
#ifdef bench100
#define Count 10000*100
#define Qpktcountval 2326410
#define Holdcountval 930563
#else
#define Count 10000
#define Qpktcountval 23246
#define Holdcountval 9297
#endif
#define TRUE 1
#define FALSE 0
#define MAXINT 32767
#define BUFSIZE 3
#define I_IDLE 1
#define I_WORK 2
#define I_HANDLERA 3
#define I_HANDLERB 4
#define I_DEVA 5
#define I_DEVB 6
#define PKTBIT 1
#define WAITBIT 2
#define HOLDBIT 4
#define NOTPKTBIT !1
#define NOTWAITBIT !2
#define NOTHOLDBIT 0XFFFB
#define S_RUN 0
#define S_RUNPKT 1
#define S_WAIT 2
#define S_WAITPKT 3
#define S_HOLD 4
#define S_HOLDPKT 5
#define S_HOLDWAIT 6
#define S_HOLDWAITPKT 7
#define K_DEV 1000
#define K_WORK 1001
struct packet
{
struct packet *p_link;
int p_id;
int p_kind;
int p_a1;
char p_a2[BUFSIZE+1];
};
struct task
{
struct task *t_link;
int t_id;
int t_pri;
struct packet *t_wkq;
int t_state;
struct task *(*t_fn)(struct packet *);
uintptr_t t_v1;
uintptr_t t_v2;
};
char alphabet[28] = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ";
struct task *tasktab[11] = {(struct task *)10,0,0,0,0,0,0,0,0,0,0};
struct task *tasklist = 0;
struct task *tcb;
long taskid;
uintptr_t v1;
uintptr_t v2;
int qpktcount = 0;
int holdcount = 0;
int tracing = 0;
int layout = 0;
void append(struct packet *pkt, struct packet *ptr);
void createtask(int id,
int pri,
struct packet *wkq,
int state,
struct task *(*fn)(struct packet *),
uintptr_t v1,
uintptr_t v2)
{
struct task *t = (struct task *)malloc(sizeof(struct task));
tasktab[id] = t;
t->t_link = tasklist;
t->t_id = id;
t->t_pri = pri;
t->t_wkq = wkq;
t->t_state = state;
t->t_fn = fn;
t->t_v1 = v1;
t->t_v2 = v2;
tasklist = t;
}
struct packet *pkt(struct packet *link, int id, int kind)
{
int i;
struct packet *p = (struct packet *)malloc(sizeof(struct packet));
for (i=0; i<=BUFSIZE; i++)
p->p_a2[i] = 0;
p->p_link = link;
p->p_id = id;
p->p_kind = kind;
p->p_a1 = 0;
return (p);
}
void trace(char a)
{
if ( --layout <= 0 )
{
// printf("\n");
layout = 50;
}
// printf("%c", a);
}
void schedule()
{
while ( tcb != 0 )
{
struct packet *pkt;
struct task *newtcb;
pkt=0;
switch ( tcb->t_state )
{
case S_WAITPKT:
pkt = tcb->t_wkq;
tcb->t_wkq = pkt->p_link;
tcb->t_state = tcb->t_wkq == 0 ? S_RUN : S_RUNPKT;
case S_RUN:
case S_RUNPKT:
taskid = tcb->t_id;
v1 = tcb->t_v1;
v2 = tcb->t_v2;
if (tracing) {
trace(taskid+'0');
}
newtcb = (*(tcb->t_fn))(pkt);
tcb->t_v1 = v1;
tcb->t_v2 = v2;
tcb = newtcb;
break;
case S_WAIT:
case S_HOLD:
case S_HOLDPKT:
case S_HOLDWAIT:
case S_HOLDWAITPKT:
tcb = tcb->t_link;
break;
default:
return;
}
}
}
struct task *wait_task(void)
{
tcb->t_state |= WAITBIT;
return (tcb);
}
struct task *holdself(void)
{
++holdcount;
tcb->t_state |= HOLDBIT;
return (tcb->t_link) ;
}
struct task *findtcb(int id)
{
struct task *t = 0;
if (1<=id && id<=(long)tasktab[0])
t = tasktab[id];
// if (t==0) printf("\nBad task id %d\n", id);
return(t);
}
struct task *release(int id)
{
struct task *t;
t = findtcb(id);
if ( t==0 ) return (0);
t->t_state &= NOTHOLDBIT;
if ( t->t_pri > tcb->t_pri ) return (t);
return (tcb) ;
}
struct task *qpkt(struct packet *pkt)
{
struct task *t;
t = findtcb(pkt->p_id);
if (t==0) return (t);
qpktcount++;
pkt->p_link = 0;
pkt->p_id = taskid;
if (t->t_wkq==0)
{
t->t_wkq = pkt;
t->t_state |= PKTBIT;
if (t->t_pri > tcb->t_pri) return (t);
}
else
{
append(pkt, (struct packet *)&(t->t_wkq));
}
return (tcb);
}
struct task *idlefn(struct packet *pkt)
{
if ( --v2==0 ) return ( holdself() );
if ( (v1&1) == 0 )
{
v1 = ( v1>>1) & MAXINT;
return ( release(I_DEVA) );
}
else
{
v1 = ( (v1>>1) & MAXINT) ^ 0XD008;
return ( release(I_DEVB) );
}
}
struct task *workfn(struct packet *pkt)
{
if ( pkt==0 ) return ( wait_task() );
else
{
int i;
v1 = I_HANDLERA + I_HANDLERB - v1;
pkt->p_id = v1;
pkt->p_a1 = 0;
for (i=0; i<=BUFSIZE; i++)
{
v2++;
if ( v2 > 26 ) v2 = 1;
(pkt->p_a2)[i] = alphabet[v2];
}
return ( qpkt(pkt) );
}
}
struct task *handlerfn(struct packet *pkt)
{
if ( pkt!=0) {
append(pkt, (struct packet *)(pkt->p_kind==K_WORK ? &v1 : &v2));
}
if ( v1!=0 ) {
int count;
struct packet *workpkt = (struct packet *)v1;
count = workpkt->p_a1;
if ( count > BUFSIZE ) {
v1 = (uintptr_t)(((struct packet *)v1)->p_link);
return ( qpkt(workpkt) );
}
if ( v2!=0 ) {
struct packet *devpkt;
devpkt = (struct packet *)v2;
v2 = (uintptr_t)(((struct packet *)v2)->p_link);
devpkt->p_a1 = workpkt->p_a2[count];
workpkt->p_a1 = count+1;
return( qpkt(devpkt) );
}
}
return wait_task();
}
struct task *devfn(struct packet *pkt)
{
if ( pkt==0 )
{
if ( v1==0 ) return ( wait_task() );
pkt = (struct packet *)v1;
v1 = 0;
return ( qpkt(pkt) );
}
else
{
v1 = (uintptr_t)pkt;
if (tracing) trace(pkt->p_a1);
return ( holdself() );
}
}
void append(struct packet *pkt, struct packet *ptr)
{
pkt->p_link = 0;
while ( ptr->p_link ) ptr = ptr->p_link;
ptr->p_link = pkt;
}
int bench() {
struct packet *wkq = 0;
// printf("Bench mark starting\n");
createtask(I_IDLE, 0, wkq, S_RUN, idlefn, 1, Count);
wkq = pkt(0, 0, K_WORK);
wkq = pkt(wkq, 0, K_WORK);
createtask(I_WORK, 1000, wkq, S_WAITPKT, workfn, I_HANDLERA, 0);
wkq = pkt(0, I_DEVA, K_DEV);
wkq = pkt(wkq, I_DEVA, K_DEV);
wkq = pkt(wkq, I_DEVA, K_DEV);
createtask(I_HANDLERA, 2000, wkq, S_WAITPKT, handlerfn, 0, 0);
wkq = pkt(0, I_DEVB, K_DEV);
wkq = pkt(wkq, I_DEVB, K_DEV);
wkq = pkt(wkq, I_DEVB, K_DEV);
createtask(I_HANDLERB, 3000, wkq, S_WAITPKT, handlerfn, 0, 0);
wkq = 0;
createtask(I_DEVA, 4000, wkq, S_WAIT, devfn, 0, 0);
createtask(I_DEVB, 5000, wkq, S_WAIT, devfn, 0, 0);
tcb = tasklist;
qpktcount = holdcount = 0;
// printf("Starting\n");
tracing = FALSE;
layout = 0;
schedule();
// printf("\nfinished\n");
// if (!(qpktcount == Qpktcountval && holdcount == Holdcountval)) {
// printf("qpkt count = %d holdcount = %d\n", qpktcount, holdcount);
// printf("These results are incorrect");
// exit(1);
// }
// printf("\nend of run\n");
return qpktcount;
}
int inner_loop(int inner) {
int r = 0;
while (inner > 0) {
r += bench();
inner--;
}
return r;
}
int main(void)
{
//INITREGULARALLOC();
int iterations = 4;
int warmup = 0;
int inner_iterations = 4;
// parse_argv(argc, argv, &iterations, &warmup, &inner_iterations);
// while(1);
int result = 0;
while (iterations > 0) {
// unsigned long start = microseconds();
result += inner_loop(inner_iterations);
// unsigned long elapsed = microseconds() - start;
// printf("Richards: iterations=1 runtime: %lu%s\n", elapsed, "us");
// print(elapsed);
iterations--;
}
}

View File

@@ -15,5 +15,5 @@ SECTIONS
_end = .;
__malloc_start = .;
. = . + 512;
. = . + 0x10000;
}

View File

@@ -4,41 +4,41 @@
void* malloc(size_t size);
int main(void)
{
char* a = malloc(50);
char* b = malloc(160);
// asm volatile("fence rw, rw"); // make sure store completes
// volatile uint64_t* marker = (uint64_t*)0x80001000;
// *marker = 0xCAFEBABECAFED00D; // UNIQUE SIGNATURE
int main(void) {
// char *a = malloc(30);
// char *b = malloc(16);
// if (!a || !b) return;
// // if (!a || !b) return -1;
a[0] = 'A';
// // a[1] = 'C';
// // b[0] = 'B';
// a[0] = 'A';
// a[1] = 'C';
// b[0] = 'B';
// // This will fault (out-of-bounds)
// // a[20] = 'X';
if (a[0] != 'A') {
while (1);
}
// // char* a = malloc(100);
// // char* b = malloc(200);
// if (a[1] != 'C') {
// while (1);
// }
// a[0] = 'A'; // triggers page fault if unmapped
// b[19] = 'Z';
// if (b[0] != 'B') {
// while (1);
// }
// // free(b);
// // b = NULL;
// // if (b[0] == 'B') {
// // while (1);
// // }
// char *c = malloc(16);
// // if (c[0] != 'B') {
// // while (1);
// // }
// for (int i = 0; i < 1000; i++) {
// a[i * 64] = i; // each write new cache line
// }
// while(1);
return 0;
}

Binary file not shown.

View File

@@ -545,6 +545,7 @@ module mkL2Tlb(L2Tlb::L2Tlb);
end
else begin
dataSavedPageWalks.incr(saved);
$display("L2TlbdataSavedPageWalks = %0d", dataPageWalks);
end
end
// `endif
@@ -742,6 +743,7 @@ module mkL2Tlb(L2Tlb::L2Tlb);
end
else begin
dataPageWalks.incr(1);
$display("L2TlbdataPageWalks = %0d", dataPageWalks);
end
end
// `endif

View File

@@ -1,12 +1,5 @@
Let me know if this message works well on behalf of all of us.
Hi Jan,
This is a very small gesture from Jose, Mathews, Yukang and Akilan. We have transferred 200 pounds equally contributed by all of us. As you are moving in and settling into your new place, we hope this can help you and Samantha cover certain expenses like buying furniture or for your very efficient interrail travel pass in the near future.
We will definetely miss the german embassy in Slatefort. Happy new year in advance from all of us!
Regards,
Jose, Mathews, Yukang and Akilan
(Your UK representation of transportation
reform)
- [ ] Benchmarks to port over:
- [ ] Barnes (3)
- [ ] Matrix multiplication (2)
- [ ] Richards (1)