Sanchayan Maity
2fcc51c2c1
While at it also add the libpthread static library amd m5op_x86 for matrix multiplication test code as well. Note that the splash2 benchmark code does not comply with gem5 coding guidelines. Academic guys never seem to follow 80 columns and no whitespace guideline :(.
368 lines
9.9 KiB
C
368 lines
9.9 KiB
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 <cmath>
|
|
#include <cstdio>
|
|
|
|
#include "box.h"
|
|
#include "defs.h"
|
|
#include "memory.h"
|
|
#include "particle.h"
|
|
|
|
/* How many boxes can fit on one line */
|
|
#define BOXES_PER_LINE 4
|
|
#define TERMS_PER_LINE 2
|
|
|
|
box *Grid = NULL;
|
|
|
|
void ZeroBox(long my_id, box *b);
|
|
|
|
void
|
|
CreateBoxes (long my_id, long num_boxes)
|
|
{
|
|
long i;
|
|
|
|
LOCK(G_Memory->mal_lock);
|
|
Local[my_id].B_Heap = (box *) G_MALLOC(num_boxes * sizeof(box));
|
|
|
|
/* POSSIBLE ENHANCEMENT: Here is where one might distribute the
|
|
B_Heap data across physically distributed memories as desired.
|
|
|
|
One way to do this is as follows:
|
|
|
|
char *starting_address;
|
|
char *ending_address;
|
|
|
|
starting_address = (char *) Local[my_id].B_Heap;
|
|
ending_address = (((char *) Local[my_id].B_Heap)
|
|
+ (num_boxes * sizeof(particle *)) - 1);
|
|
|
|
Place all addresses x such that (starting_address <= x < ending_address)
|
|
on node my_id
|
|
|
|
*/
|
|
|
|
UNLOCK(G_Memory->mal_lock);
|
|
Local[my_id].Max_B_Heap = num_boxes;
|
|
Local[my_id].Index_B_Heap = 0;
|
|
|
|
for (i = 0; i < num_boxes; i++) {
|
|
Local[my_id].B_Heap[i].exp_lock_index = i % (MAX_LOCKS - 1);
|
|
Local[my_id].B_Heap[i].particle_lock_index = i % (MAX_LOCKS - 1);
|
|
Local[my_id].B_Heap[i].id = i + ((double) my_id / ID_LIMIT);
|
|
ZeroBox(my_id, &Local[my_id].B_Heap[i]);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
FreeBoxes (long my_id)
|
|
{
|
|
long i;
|
|
box *b_array;
|
|
|
|
b_array = Local[my_id].B_Heap;
|
|
for (i = 0; i < Local[my_id].Index_B_Heap; i++)
|
|
ZeroBox(my_id, &b_array[i]);
|
|
Local[my_id].Index_B_Heap = 0;
|
|
}
|
|
|
|
|
|
void
|
|
ZeroBox (long my_id, box *b)
|
|
{
|
|
long i;
|
|
|
|
b->type = CHILDLESS;
|
|
b->num_particles = 0;
|
|
for (i = 0; i < MAX_PARTICLES_PER_BOX; i++)
|
|
b->particles[i] = NULL;
|
|
b->parent = NULL;
|
|
for (i = 0; i < NUM_OFFSPRING; i++) {
|
|
b->children[i] = NULL;
|
|
b->shadow[i] = NULL;
|
|
}
|
|
b->num_children = 0;
|
|
b->construct_synch = 0;
|
|
b->interaction_synch = 0;
|
|
b->cost = 0;
|
|
b->proc = my_id;
|
|
b->subtree_cost = 0;
|
|
b->next = NULL;
|
|
b->prev = NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
* InitBox (long my_id, real x_center, real y_center, real length, long level, box *parent)
|
|
*
|
|
* Args : the x_center and y_center of the center of the box;
|
|
* the length of the box;
|
|
* the level of the box;
|
|
* the address of b's parent.
|
|
*
|
|
* Returns : the address of the newly created box.
|
|
*
|
|
* Side Effects : Initializes num_particles to 0, all other pointers to NULL,
|
|
* and sets the box ID to a unique number. It also creates the space for
|
|
* the two expansion arrays.
|
|
*
|
|
*/
|
|
box *
|
|
InitBox (long my_id, real x_center, real y_center, real length, box *parent)
|
|
{
|
|
box *b;
|
|
|
|
if (Local[my_id].Index_B_Heap == Local[my_id].Max_B_Heap) {
|
|
LockedPrint("ERROR (P%d) : Ran out of boxes\n", my_id);
|
|
exit(-1);
|
|
}
|
|
b = &Local[my_id].B_Heap[Local[my_id].Index_B_Heap++];
|
|
b->x_center = x_center;
|
|
b->y_center = y_center;
|
|
b->length = length;
|
|
b->parent = parent;
|
|
if (parent == NULL)
|
|
b->level = 0;
|
|
else
|
|
b->level = parent->level + 1;
|
|
return b;
|
|
}
|
|
|
|
|
|
/*
|
|
* PrintBox (box *b)
|
|
*
|
|
* Args : the address of a box, b.
|
|
*
|
|
* Returns : nothing.
|
|
*
|
|
* Side Effects : Prints to stdout the information stored for b.
|
|
*
|
|
*/
|
|
void
|
|
PrintBox (box *b)
|
|
{
|
|
LOCK(G_Memory->io_lock);
|
|
fflush(stdout);
|
|
if (b != NULL) {
|
|
printf("Info for B%f :\n", b->id);
|
|
printf(" X center = %.40g\n", b->x_center);
|
|
printf(" Y center = %.40g\n", b->y_center);
|
|
printf(" Length = %.40g\n", b->length);
|
|
printf(" Level = %ld\n", b->level);
|
|
printf(" Type = %d\n", b->type);
|
|
printf(" Child Num = %ld\n", b->child_num);
|
|
if (b->parent == NULL)
|
|
printf(" Parent = NONE\n");
|
|
else
|
|
printf(" Parent = B%f\n", b->parent->id);
|
|
printf(" Children's IDs : ");
|
|
if (b->num_children != 0)
|
|
PrintBoxArrayIds(b->children, b->num_children);
|
|
else
|
|
printf("NONE\n");
|
|
printf(" Sibling's IDs : ");
|
|
if (b->num_siblings != 0)
|
|
PrintBoxArrayIds(b->siblings, b->num_siblings);
|
|
else
|
|
printf("NONE\n");
|
|
printf(" Colleagues' IDs : ");
|
|
PrintBoxArrayIds(b->colleagues, b->num_colleagues);
|
|
printf(" U List IDs : ");
|
|
PrintBoxArrayIds(b->u_list, b->num_u_list);
|
|
printf(" V List IDs : ");
|
|
PrintBoxArrayIds(b->v_list, b->num_v_list);
|
|
printf(" W List IDs : ");
|
|
PrintBoxArrayIds(b->w_list, b->num_w_list);
|
|
printf(" # of Particles = %ld\n", b->num_particles);
|
|
printf(" Particles' IDs : ");
|
|
PrintParticleArrayIds(b->particles, b->num_particles);
|
|
printf(" Assigned Process ID : %ld\n", b->proc);
|
|
printf(" Cost : %ld\n", b->cost);
|
|
printf("\n");
|
|
}
|
|
else
|
|
printf("Box has not been initialized yet.\n\n");
|
|
UNLOCK(G_Memory->io_lock);
|
|
}
|
|
|
|
|
|
/*
|
|
* PrintBoxArrayIds (box_node *b_array[], long array_length)
|
|
*
|
|
* Args : the address of the box array, b_array;
|
|
* the length of the array, array_length.
|
|
*
|
|
* Returns : nothing.
|
|
*
|
|
* Side Effects : Prints to stdout just the id numbers for every box in
|
|
* b_array.
|
|
*
|
|
*/
|
|
void
|
|
PrintBoxArrayIds (box *b_array[], long array_length)
|
|
{
|
|
long i;
|
|
long tab_count;
|
|
|
|
tab_count = 0;
|
|
for (i = 0; i < array_length; i++) {
|
|
if (tab_count == 0) {
|
|
printf("\n");
|
|
tab_count = BOXES_PER_LINE;
|
|
}
|
|
if (b_array[i] != NULL)
|
|
printf("\tB%f", b_array[i]->id);
|
|
tab_count -= 1;
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
|
|
/*
|
|
* PrintExpansionTerms (real expansion[])
|
|
*
|
|
* Args : the array of expansion terms, expansion.
|
|
*
|
|
* Returns : nothing.
|
|
*
|
|
* Side Effects : Prints to stdout the contents of expansion.
|
|
*
|
|
*/
|
|
void
|
|
PrintExpansionTerms (complex expansion[])
|
|
{
|
|
long i;
|
|
long tab_count = 0;
|
|
|
|
for (i = 0; i < Expansion_Terms; i++) {
|
|
if (tab_count == 0) {
|
|
printf("\n");
|
|
tab_count = TERMS_PER_LINE;
|
|
}
|
|
if (expansion[i].i >= (real) 0.0)
|
|
printf("\ta%ld = %.3e + %.3ei", i, expansion[i].r, expansion[i].i);
|
|
else
|
|
printf("\ta%ld = %.3e - %.3ei", i, expansion[i].r, -expansion[i].i);
|
|
tab_count -= 1;
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
|
|
void
|
|
ListIterate (long my_id, box *b, box **list, long length, list_function function)
|
|
{
|
|
long i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
if (list[i] == NULL) {
|
|
LockedPrint("ERROR (P%d) : NULL list entry\n", my_id);
|
|
exit(-1);
|
|
}
|
|
(*function)(my_id, list[i], b);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* AdjacentBoxes (box *b1, box *b2)
|
|
*
|
|
* Args : two potentially adjacent boxes, b1 and b2.
|
|
*
|
|
* Returns : TRUE, if boxes are adjacent, FALSE if not.
|
|
*
|
|
* Side Effects : none.
|
|
*
|
|
* Comments : Two boxes are adjacent if their centers are separated in either
|
|
* the x or y directions by (1/2 the length of b1) + (1/2 length of b2),
|
|
* and separated in the other direction by a distance less than or equal
|
|
* to (1/2 the length of b1) + (1/2 the length of b2).
|
|
*
|
|
* NOTE : By this definition, parents are NOT adjacent to their children.
|
|
*/
|
|
long
|
|
AdjacentBoxes (box *b1, box *b2)
|
|
{
|
|
real exact_separation;
|
|
real x_separation;
|
|
real y_separation;
|
|
long ret_val;
|
|
|
|
exact_separation = (b1->length / (real) 2.0) + (b2->length / (real) 2.0);
|
|
x_separation = (real) fabs((double)(b1->x_center - b2->x_center));
|
|
y_separation = (real) fabs((double)(b1->y_center - b2->y_center));
|
|
|
|
if ((x_separation == exact_separation) &&
|
|
(y_separation <= exact_separation))
|
|
ret_val = TRUE;
|
|
else
|
|
if ((y_separation == exact_separation) &&
|
|
(x_separation <= exact_separation))
|
|
ret_val = TRUE;
|
|
else
|
|
ret_val = FALSE;
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
|
|
/*
|
|
* WellSeparatedBoxes (box *b1, box *b2)
|
|
*
|
|
* Args : Two potentially well separated boxes, b1 and b2.
|
|
*
|
|
* Returns : TRUE, if the two boxes are well separated, and FALSE if not.
|
|
*
|
|
* Side Effects : none.
|
|
*
|
|
* Comments : Well separated means that the two boxes are separated by the
|
|
* length of the boxes. If one of the boxes is bigger than the other,
|
|
* the smaller box is given the length of the larger box. This means
|
|
* that the centers of the two boxes, regardless of their relative size,
|
|
* must be separated in the x or y direction (or both) by at least
|
|
* twice the length of the biggest box.
|
|
*
|
|
*/
|
|
long
|
|
WellSeparatedBoxes (box *b1, box *b2)
|
|
{
|
|
real min_ws_distance;
|
|
real x_separation;
|
|
real y_separation;
|
|
long ret_val;
|
|
|
|
if (b1->length > b2->length)
|
|
min_ws_distance = b1->length * (real) 2.0;
|
|
else
|
|
min_ws_distance = b2->length * (real) 2.0;
|
|
|
|
x_separation = (real) fabs((double)(b1->x_center - b2->x_center));
|
|
y_separation = (real) fabs((double)(b1->y_center - b2->y_center));
|
|
|
|
if ((x_separation >= min_ws_distance) || (y_separation >= min_ws_distance))
|
|
ret_val = TRUE;
|
|
else
|
|
ret_val = FALSE;
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
|
|
#undef BOXES_PER_LINE
|
|
#undef TERMS_PER_LINE
|
|
|