gem5/splash2/codes/apps/radiosity/smallobj.C
Sanchayan Maity 0f4b39775c Fix splash2 benchmark
During the last commit of splash2 benchmark it seems before committing
when we ran "make clean", it effectively undid what the patch at below
link did
http://www.capsl.udel.edu/splash/Download.html

Fix this since without this it is not possible to build the arcane
splash2 benchmark.
2017-04-26 21:33:02 +05:30

635 lines
18 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. */
/* */
/*************************************************************************/
/************************************************************************
*
* Class methods for small simple objects.
*
*
*************************************************************************/
#include <stdio.h>
EXTERN_ENV;
include(radiosity.h)
struct {
char pad1[PAGE_SIZE]; /* padding to avoid false-sharing
and allow page-placement */
long n_local_free_elemvertex ;
ElemVertex *local_free_elemvertex ;
long n_local_free_edge ;
Edge *local_free_edge ;
long lock_alloc_counter ;
char pad2[PAGE_SIZE]; /* padding to avoid false-sharing
and allow page-placement */
} sobj_struct[MAX_PROCESSORS];
/***************************************************************************
****************************************************************************
*
* Methods for Vertex object
*
****************************************************************************
****************************************************************************/
/***************************************************************************
*
* vector_length()
*
* Comute length of a vector represented by Vertex
* length = | v |
*
****************************************************************************/
float vector_length(Vertex *v)
{
double t0, t1, t2 ;
t0 = v->x * v->x ;
t1 = v->y * v->y ;
t2 = v->z * v->z ;
return( sqrt( t0 + t1 + t2 ) ) ;
}
/***************************************************************************
*
* distance()
*
* Comute distance of two points.
* dist = | P1 - P2 |
*
****************************************************************************/
float distance(Vertex *p1, Vertex *p2)
{
Vertex v12 ;
v12.x = p2->x - p1->x ;
v12.y = p2->y - p1->y ;
v12.z = p2->z - p1->z ;
return( vector_length( &v12 ) ) ;
}
/***************************************************************************
*
* normalize_vector()
*
* Normalize vector represented by Vertex
* v1 <- normalized( v2 )
*
****************************************************************************/
float normalize_vector(Vertex *v1, Vertex *v2)
{
float t0 ;
float length ;
length = vector_length( v2 ) ;
t0 = (float)1.0 / length ;
v1->x = v2->x * t0 ;
v1->y = v2->y * t0 ;
v1->z = v2->z * t0 ;
return( length ) ;
}
/**************************************************************************
*
* inner_product()
*
* (v1.v2) <- inner_product( v1, v2 )
*
***************************************************************************/
float inner_product(Vertex *v1, Vertex *v2)
{
float ip ;
ip = v1->x * v2->x ;
ip += v1->y * v2->y ;
ip += v1->z * v2->z ;
return( ip ) ;
}
/**************************************************************************
*
* cross_product()
*
* Vc = V1 X V2
*
***************************************************************************/
void cross_product(Vertex *vc, Vertex *v1, Vertex *v2)
{
vc->x = v1->y * v2->z - v1->z * v2->y ;
vc->y = v1->z * v2->x - v1->x * v2->z ;
vc->z = v1->x * v2->y - v1->y * v2->x ;
}
/**************************************************************************
*
* plane_normal()
*
* Vc = (P2-P1) X (P3-P1) / |(P2-P1) X (P3-P1)|
*
***************************************************************************/
float plane_normal(Vertex *vc, Vertex *p1, Vertex *p2, Vertex *p3)
{
Vertex v1, v2 ;
/* Compute vectors */
v1.x = p2->x - p1->x ;
v1.y = p2->y - p1->y ;
v1.z = p2->z - p1->z ;
v2.x = p3->x - p1->x ;
v2.y = p3->y - p1->y ;
v2.z = p3->z - p1->z ;
/* Compute cross product and normalize */
cross_product( vc, &v1, &v2 ) ;
return( normalize_vector( vc, vc ) ) ;
}
/**************************************************************************
*
* center_point()
*
* P = (P1 + P2 + P3) / 3
*
***************************************************************************/
void center_point(Vertex *p1, Vertex *p2, Vertex *p3, Vertex *pc)
{
/* Compute mid point of the element */
pc->x = (p1->x + p2->x + p3->x) * (float)(1.0/3.0) ;
pc->y = (p1->y + p2->y + p3->y) * (float)(1.0/3.0) ;
pc->z = (p1->z + p2->z + p3->z) * (float)(1.0/3.0) ;
}
/**************************************************************************
*
* four_center_points()
*
* P = (P1 + P2 + P3) / 3
*
***************************************************************************/
void four_center_points(Vertex *p1, Vertex *p2, Vertex *p3, Vertex *pc, Vertex *pc1, Vertex *pc2, Vertex *pc3)
{
/* Compute mid point of the element */
pc->x = (p1->x + p2->x + p3->x) * (float)(1.0/3.0) ;
pc->y = (p1->y + p2->y + p3->y) * (float)(1.0/3.0) ;
pc->z = (p1->z + p2->z + p3->z) * (float)(1.0/3.0) ;
pc1->x = (p1->x * 4 + p2->x + p3->x) * (float)(1.0/6.0) ;
pc1->y = (p1->y * 4 + p2->y + p3->y) * (float)(1.0/6.0) ;
pc1->z = (p1->z * 4 + p2->z + p3->z) * (float)(1.0/6.0) ;
pc2->x = (p1->x + p2->x * 4 + p3->x) * (float)(1.0/6.0) ;
pc2->y = (p1->y + p2->y * 4 + p3->y) * (float)(1.0/6.0) ;
pc2->z = (p1->z + p2->z * 4 + p3->z) * (float)(1.0/6.0) ;
pc3->x = (p1->x + p2->x + p3->x * 4) * (float)(1.0/6.0) ;
pc3->y = (p1->y + p2->y + p3->y * 4) * (float)(1.0/6.0) ;
pc3->z = (p1->z + p2->z + p3->z * 4) * (float)(1.0/6.0) ;
}
/***************************************************************************
*
* print_point()
*
* Print point information.
*
****************************************************************************/
void print_point(Vertex *point)
{
printf( "\tP(%.2f, %.2f, %.2f)\n", point->x, point->y, point->z ) ;
}
/***************************************************************************
****************************************************************************
*
* Methods for Rgb object
*
****************************************************************************
****************************************************************************
****************************************************************************
*
* print_rgb()
*
* Print RGB information.
*
****************************************************************************/
void print_rgb(Rgb *rgb)
{
printf( "\tRGB(%.2f, %.2f, %.2f)\n", rgb->r, rgb->g, rgb->b ) ;
}
/***************************************************************************
****************************************************************************
*
* Methods for ElementVertex
*
****************************************************************************
****************************************************************************/
/***************************************************************************
*
* create_elemvertex
*
* Given Vertex, create and return a new ElemVertex object.
*
****************************************************************************/
ElemVertex *create_elemvertex(Vertex *p, long process_id)
{
ElemVertex *ev_new ;
ev_new = get_elemvertex(process_id) ;
ev_new->p = *p ;
return( ev_new ) ;
}
/***************************************************************************
*
* get_elemvertex
*
* Returns an ElementVertex object
*
****************************************************************************/
ElemVertex *get_elemvertex(long process_id)
{
ElemVertex *ev ;
if( sobj_struct[process_id].n_local_free_elemvertex == 0 )
{
LOCK(global->free_elemvertex_lock);
if ( MAX_ELEMVERTICES - global->free_elemvertex
< N_ELEMVERTEX_ALLOCATE )
{
fprintf( stderr, "Fatal:Ran out of ElemVertex buffer\n" ) ;
UNLOCK(global->free_elemvertex_lock);
exit(1) ;
}
sobj_struct[process_id].n_local_free_elemvertex = N_ELEMVERTEX_ALLOCATE ;
sobj_struct[process_id].local_free_elemvertex
= &global->elemvertex_buf[ global->free_elemvertex ] ;
global->free_elemvertex += N_ELEMVERTEX_ALLOCATE ;
UNLOCK(global->free_elemvertex_lock);
}
ev = sobj_struct[process_id].local_free_elemvertex++ ;
sobj_struct[process_id].n_local_free_elemvertex-- ;
/* Initialize contents */
ev->col.r = 0.0 ;
ev->col.g = 0.0 ;
ev->col.b = 0.0 ;
ev->weight = 0.0 ;
return( ev ) ;
}
/***************************************************************************
*
* init_elemvertex()
*
* Initialize ElemVertex buffer.
* This routine must be called in single process state.
*
****************************************************************************/
void init_elemvertex(long process_id)
{
long ev_cnt ;
/* Initialize global free list */
LOCKINIT(global->free_elemvertex_lock);
global->free_elemvertex = 0 ;
/* Allocate locks */
for( ev_cnt = 0 ; ev_cnt < MAX_ELEMVERTICES ; ev_cnt++ )
global->elemvertex_buf[ ev_cnt ].ev_lock
= get_sharedlock( SHARED_LOCK_SEGANY, process_id ) ;
/* Initialize local free list */
sobj_struct[process_id].n_local_free_elemvertex = 0 ;
sobj_struct[process_id].local_free_elemvertex = 0 ;
}
/***************************************************************************
****************************************************************************
*
* Methods for Edge
*
****************************************************************************
****************************************************************************/
/***************************************************************************
*
* foreach_leaf_edge()
*
* For each leaf edges of the binary edge tree, apply the specified
* function. Edges are traversed from A to B (i.e., from Pa of the root
* to the Pb of the root) if 'reverse' is 0. Otherwise, it is traversed
* from B to A.
*
****************************************************************************/
void foreach_leaf_edge(Edge *edge, long reverse, void (*func)(), long arg1, long arg2, long process_id)
{
Edge *first, *second ;
if( edge == 0 )
return ;
if( (edge->ea == 0) && (edge->eb == 0) )
func( edge, reverse, arg1, arg2, process_id ) ;
else
{
if( reverse )
{
first = edge->eb ;
second = edge->ea ;
}
else
{
first = edge->ea ;
second = edge->eb ;
}
if( first )
foreach_leaf_edge( first, reverse, func, arg1, arg2, process_id ) ;
if( second )
foreach_leaf_edge( second, reverse, func, arg1, arg2, process_id ) ;
}
}
/***************************************************************************
*
* create_edge()
*
* Given two ElemVertices V1 and V2, create a new edge (V1,V2)
*
****************************************************************************/
Edge *create_edge(ElemVertex *v1, ElemVertex *v2, long process_id)
{
Edge *enew ;
enew = get_edge(process_id) ;
enew->pa = v1 ;
enew->pb = v2 ;
return( enew ) ;
}
/***************************************************************************
*
* subdivide_edge()
*
* Create child edges. If they already exist, do nothing.
*
****************************************************************************/
void subdivide_edge(Edge *e, float a_ratio, long process_id)
{
Edge *enew, *e_am ;
ElemVertex *ev_middle ;
float b_ratio ;
/* Lock the element before checking the value */
LOCK(e->edge_lock->lock);
/* Check if the element already has children */
if( ! _LEAF_EDGE(e) )
{
UNLOCK(e->edge_lock->lock);
return ;
}
/* Create the subdivision point */
b_ratio = (float)1.0 - a_ratio ;
ev_middle = get_elemvertex(process_id) ;
ev_middle->p.x = a_ratio * e->pa->p.x + b_ratio * e->pb->p.x ;
ev_middle->p.y = a_ratio * e->pa->p.y + b_ratio * e->pb->p.y ;
ev_middle->p.z = a_ratio * e->pa->p.z + b_ratio * e->pb->p.z ;
/* (1) Create edge(A-middle) */
enew = get_edge(process_id) ;
e_am = enew ;
enew->pa = e->pa ;
enew->pb = ev_middle ;
/* (2) Create edge(middle-B) */
enew = get_edge(process_id) ;
enew->pa = ev_middle ;
enew->pb = e->pb ;
e->eb = enew ;
/* Finally, set e->ea */
e->ea = e_am ;
/* Unlock the element */
UNLOCK(e->edge_lock->lock);
}
/***************************************************************************
*
* get_edge
*
* Returns an Edge object
*
****************************************************************************/
Edge *get_edge(long process_id)
{
Edge *edge ;
if( sobj_struct[process_id].n_local_free_edge == 0 )
{
LOCK(global->free_edge_lock);
if ( MAX_EDGES - global->free_edge < N_EDGE_ALLOCATE )
{
fprintf( stderr, "Fatal:Ran out of Edge buffer\n" ) ;
UNLOCK(global->free_edge_lock);
exit(1) ;
}
sobj_struct[process_id].n_local_free_edge = N_EDGE_ALLOCATE ;
sobj_struct[process_id].local_free_edge
= &global->edge_buf[ global->free_edge ] ;
global->free_edge += N_EDGE_ALLOCATE ;
UNLOCK(global->free_edge_lock);
}
edge = sobj_struct[process_id].local_free_edge++ ;
sobj_struct[process_id].n_local_free_edge-- ;
/* Initialize contents */
edge->pa = 0 ;
edge->pb = 0 ;
edge->ea = 0 ;
edge->eb = 0 ;
return( edge ) ;
}
/***************************************************************************
*
* init_edge()
*
* Initialize Edge buffer.
* This routine must be called in single process state.
*
****************************************************************************/
void init_edge(long process_id)
{
long edge_cnt ;
/* Initialize global free list */
LOCKINIT(global->free_edge_lock);
global->free_edge = 0 ;
/* Allocate locks */
for( edge_cnt = 0 ; edge_cnt < MAX_EDGES ; edge_cnt++ )
global->edge_buf[ edge_cnt ].edge_lock
= get_sharedlock( SHARED_LOCK_SEG0, process_id ) ;
/* Initialize local free list */
sobj_struct[process_id].n_local_free_edge = 0 ;
sobj_struct[process_id].local_free_edge = 0 ;
}
/***************************************************************************
****************************************************************************
*
* Methods for Shared_Lock
*
* Some machines provide a limited number of lock variables due to hardware
* constraints etc. This package controls the sharing of this limited number
* of locks among objects.
*
****************************************************************************
****************************************************************************/
/***************************************************************************
*
* init_sharedlock()
*
* Initialize shared lock.
*
****************************************************************************/
void init_sharedlock(long process_id)
{
long i ;
for( i = 0 ; i < MAX_SHARED_LOCK ; i++ )
{
LOCKINIT(global->sh_lock[i].lock);
}
sobj_struct[process_id].lock_alloc_counter = 0 ;
}
/***************************************************************************
*
* get_sharedlock()
*
* Return a shared lock variable. If SHARED_LOCK_SEG[01] is specified,
* the lock is selected from the specified segment. If SHARED_LOCK_SEGANY
* is specified, the lock is picked up from arbitrary segment.
*
****************************************************************************/
Shared_Lock *get_sharedlock(long segment, long process_id)
{
Shared_Lock *pshl ;
long effective_lock_ctr ;
/* Compute effective lock allocation counter value */
switch( segment )
{
case SHARED_LOCK_SEG0:
effective_lock_ctr = sobj_struct[process_id].lock_alloc_counter % SHARED_LOCK_SEG_SIZE ;
break ;
case SHARED_LOCK_SEG1:
effective_lock_ctr = sobj_struct[process_id].lock_alloc_counter % SHARED_LOCK_SEG_SIZE
+ SHARED_LOCK_SEG_SIZE ;
break ;
default:
effective_lock_ctr = sobj_struct[process_id].lock_alloc_counter ;
}
/* Get pointer to the lock */
pshl = &global->sh_lock[ effective_lock_ctr ] ;
/* Update the lock counter */
sobj_struct[process_id].lock_alloc_counter++ ;
if( sobj_struct[process_id].lock_alloc_counter >= MAX_SHARED_LOCK )
sobj_struct[process_id].lock_alloc_counter = 0 ;
return( pshl ) ;
}