1 //**************************************************************************
2 // Towers of Hanoi benchmark
3 //--------------------------------------------------------------------------
5 // Towers of Hanoi is a classic puzzle problem. The game consists of
6 // three pegs and a set of discs. Each disc is a different size, and
7 // initially all of the discs are on the left most peg with the smallest
8 // disc on top and the largest disc on the bottom. The goal is to move all
9 // of the discs onto the right most peg. The catch is that you are only
10 // allowed to move one disc at a time and you can never place a larger
11 // disc on top of a smaller disc.
13 // This implementation starts with NUM_DISC discs and uses a recursive
14 // algorithm to sovel the puzzle. The smips-gcc toolchain does not support
15 // system calls so printf's can only be used on a host system, not on the
16 // smips processor simulator itself. You should not change anything except
17 // the HOST_DEBUG and PREALLOCATE macros for your timing run.
22 //--------------------------------------------------------------------------
25 // Set HOST_DEBUG to 1 if you are going to compile this for a host
26 // machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG
27 // to 0 if you are compiling with the smips-gcc toolchain.
33 // Set PREALLOCATE to 1 if you want to preallocate the benchmark
34 // function before starting stats. If you have instruction/data
35 // caches and you don't want to count the overhead of misses, then
36 // you will need to use preallocation.
42 // Set SET_STATS to 1 if you want to carve out the piece that actually
43 // does the computation.
49 // This is the number of discs in the puzzle.
53 //--------------------------------------------------------------------------
56 void setStats( int enable
)
58 #if ( !HOST_DEBUG && SET_STATS )
59 asm( "mtpcr %0, cr10" : : "r" (enable
) );
63 //--------------------------------------------------------------------------
64 // List data structure and functions
78 struct List g_nodeFreeList
;
79 struct Node g_nodePool
[NUM_DISCS
];
81 int list_getSize( struct List
* list
)
86 void list_init( struct List
* list
)
92 void list_push( struct List
* list
, int val
)
96 // Pop the next free node off the free list
97 newNode
= g_nodeFreeList
.head
;
98 g_nodeFreeList
.head
= g_nodeFreeList
.head
->next
;
100 // Push the new node onto the given list
101 newNode
->next
= list
->head
;
102 list
->head
= newNode
;
105 list
->head
->val
= val
;
112 int list_pop( struct List
* list
)
114 struct Node
* freedNode
;
117 // Get the value from the->head of given list
118 val
= list
->head
->val
;
120 // Pop the head node off the given list
121 freedNode
= list
->head
;
122 list
->head
= list
->head
->next
;
124 // Push the freed node onto the free list
125 freedNode
->next
= g_nodeFreeList
.head
;
126 g_nodeFreeList
.head
= freedNode
;
134 void list_clear( struct List
* list
)
136 while ( list_getSize(list
) > 0 )
140 //--------------------------------------------------------------------------
141 // Tower data structure and functions
152 void towers_init( struct Towers
* this, int n
)
159 list_init( &(this->pegA
) );
160 list_init( &(this->pegB
) );
161 list_init( &(this->pegC
) );
163 for ( i
= 0; i
< n
; i
++ )
164 list_push( &(this->pegA
), n
-i
);
168 void towers_clear( struct Towers
* this )
171 list_clear( &(this->pegA
) );
172 list_clear( &(this->pegB
) );
173 list_clear( &(this->pegC
) );
175 towers_init( this, this->numDiscs
);
180 void towers_print( struct Towers
* this )
186 for ( i
= 0; i
< ((this->numDiscs
)-list_getSize(&(this->pegA
))); i
++ )
188 for ( ptr
= this->pegA
.head
; ptr
!= 0; ptr
= ptr
->next
)
189 printf( "%d ", ptr
->val
);
192 for ( i
= 0; i
< ((this->numDiscs
)-list_getSize(&(this->pegB
))); i
++ )
194 for ( ptr
= this->pegB
.head
; ptr
!= 0; ptr
= ptr
->next
)
195 printf( "%d ", ptr
->val
);
198 for ( i
= 0; i
< ((this->numDiscs
)-list_getSize(&(this->pegC
))); i
++ )
200 for ( ptr
= this->pegC
.head
; ptr
!= 0; ptr
= ptr
->next
)
201 printf( "%d ", ptr
->val
);
207 void towers_solve_h( struct Towers
* this, int n
,
208 struct List
* startPeg
,
209 struct List
* tempPeg
,
210 struct List
* destPeg
)
218 val
= list_pop(startPeg
);
219 list_push(destPeg
,val
);
223 towers_solve_h( this, n
-1, startPeg
, destPeg
, tempPeg
);
224 towers_solve_h( this, 1, startPeg
, tempPeg
, destPeg
);
225 towers_solve_h( this, n
-1, tempPeg
, startPeg
, destPeg
);
230 void towers_solve( struct Towers
* this )
232 towers_solve_h( this, this->numDiscs
, &(this->pegA
), &(this->pegB
), &(this->pegC
) );
235 int towers_verify( struct Towers
* this )
240 if ( list_getSize(&this->pegA
) != 0 ) {
242 printf( "ERROR: Peg A is not empty!\n" );
247 if ( list_getSize(&this->pegB
) != 0 ) {
249 printf( "ERROR: Peg B is not empty!\n" );
254 if ( list_getSize(&this->pegC
) != this->numDiscs
) {
256 printf( " ERROR: Expected %d discs but found only %d discs!\n", \
257 this->numDiscs
, list_getSize(&this->pegC
) );
262 for ( ptr
= this->pegC
.head
; ptr
!= 0; ptr
= ptr
->next
) {
264 if ( ptr
->val
!= numDiscs
) {
266 printf( " ERROR: Expecting disc %d on peg C but found disc %d instead!\n", \
267 numDiscs
, ptr
->val
);
273 if ( this->numMoves
!= ((1 << this->numDiscs
) - 1) ) {
275 printf( " ERROR: Expecting %d num moves but found %d instead!\n", \
276 ((1 << this->numDiscs
) - 1), this->numMoves
);
284 //--------------------------------------------------------------------------
287 int main( int argc
, char* argv
[] )
289 struct Towers towers
;
292 // Initialize free list
294 list_init( &g_nodeFreeList
);
295 g_nodeFreeList
.head
= &(g_nodePool
[0]);
296 g_nodeFreeList
.size
= NUM_DISCS
;
297 g_nodePool
[NUM_DISCS
-1].next
= 0;
298 g_nodePool
[NUM_DISCS
-1].val
= 99;
299 for ( i
= 0; i
< (NUM_DISCS
-1); i
++ ) {
300 g_nodePool
[i
].next
= &(g_nodePool
[i
+1]);
301 g_nodePool
[i
].val
= i
;
304 towers_init( &towers
, NUM_DISCS
);
306 // If needed we preallocate everything in the caches
309 towers_solve( &towers
);
314 towers_clear( &towers
);
316 towers_solve( &towers
);
319 // Print out the results
322 towers_print( &towers
);
327 finishTest( towers_verify( &towers
) );