Reflect changes to ISA
[riscv-tests.git] / benchmarks / towers / towers_main.c
1 //**************************************************************************
2 // Towers of Hanoi benchmark
3 //--------------------------------------------------------------------------
4 //
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.
12 //
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.
18
19 //--------------------------------------------------------------------------
20 // Macros
21
22 // Set HOST_DEBUG to 1 if you are going to compile this for a host
23 // machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG
24 // to 0 if you are compiling with the smips-gcc toolchain.
25
26 #ifndef HOST_DEBUG
27 #define HOST_DEBUG 0
28 #endif
29
30 // Set PREALLOCATE to 1 if you want to preallocate the benchmark
31 // function before starting stats. If you have instruction/data
32 // caches and you don't want to count the overhead of misses, then
33 // you will need to use preallocation.
34
35 #ifndef PREALLOCATE
36 #define PREALLOCATE 0
37 #endif
38
39 // Set SET_STATS to 1 if you want to carve out the piece that actually
40 // does the computation.
41
42 #ifndef SET_STATS
43 #define SET_STATS 0
44 #endif
45
46 // This is the number of discs in the puzzle.
47
48 #define NUM_DISCS 7
49
50 //--------------------------------------------------------------------------
51 // Helper functions
52
53 void finishTest( int toHostValue )
54 {
55 #if HOST_DEBUG
56 if ( toHostValue == 1 )
57 printf( "*** PASSED ***\n" );
58 else
59 printf( "*** FAILED *** (tohost = %d)\n", toHostValue );
60 exit(0);
61 #else
62 asm( "mtpcr %0, tohost" : : "r" (toHostValue) );
63 while ( 1 ) { }
64 #endif
65 }
66
67 void setStats( int enable )
68 {
69 #if ( !HOST_DEBUG && SET_STATS )
70 asm( "mtpcr %0, cr10" : : "r" (enable) );
71 #endif
72 }
73
74 //--------------------------------------------------------------------------
75 // List data structure and functions
76
77 struct Node
78 {
79 int val;
80 struct Node* next;
81 };
82
83 struct List
84 {
85 int size;
86 struct Node* head;
87 };
88
89 struct List g_nodeFreeList;
90 struct Node g_nodePool[NUM_DISCS];
91
92 int list_getSize( struct List* list )
93 {
94 return list->size;
95 }
96
97 void list_init( struct List* list )
98 {
99 list->size = 0;
100 list->head = 0;
101 }
102
103 void list_push( struct List* list, int val )
104 {
105 struct Node* newNode;
106
107 // Pop the next free node off the free list
108 newNode = g_nodeFreeList.head;
109 g_nodeFreeList.head = g_nodeFreeList.head->next;
110
111 // Push the new node onto the given list
112 newNode->next = list->head;
113 list->head = newNode;
114
115 // Assign the value
116 list->head->val = val;
117
118 // Increment size
119 list->size++;
120
121 }
122
123 int list_pop( struct List* list )
124 {
125 struct Node* freedNode;
126 int val;
127
128 // Get the value from the->head of given list
129 val = list->head->val;
130
131 // Pop the head node off the given list
132 freedNode = list->head;
133 list->head = list->head->next;
134
135 // Push the freed node onto the free list
136 freedNode->next = g_nodeFreeList.head;
137 g_nodeFreeList.head = freedNode;
138
139 // Decrement size
140 list->size--;
141
142 return val;
143 }
144
145 void list_clear( struct List* list )
146 {
147 while ( list_getSize(list) > 0 )
148 list_pop(list);
149 }
150
151 //--------------------------------------------------------------------------
152 // Tower data structure and functions
153
154 struct Towers
155 {
156 int numDiscs;
157 int numMoves;
158 struct List pegA;
159 struct List pegB;
160 struct List pegC;
161 };
162
163 void towers_init( struct Towers* this, int n )
164 {
165 int i;
166
167 this->numDiscs = n;
168 this->numMoves = 0;
169
170 list_init( &(this->pegA) );
171 list_init( &(this->pegB) );
172 list_init( &(this->pegC) );
173
174 for ( i = 0; i < n; i++ )
175 list_push( &(this->pegA), n-i );
176
177 }
178
179 void towers_clear( struct Towers* this )
180 {
181
182 list_clear( &(this->pegA) );
183 list_clear( &(this->pegB) );
184 list_clear( &(this->pegC) );
185
186 towers_init( this, this->numDiscs );
187
188 }
189
190 #if HOST_DEBUG
191 void towers_print( struct Towers* this )
192 {
193 struct Node* ptr;
194 int i, numElements;
195
196 printf( " pegA: " );
197 for ( i = 0; i < ((this->numDiscs)-list_getSize(&(this->pegA))); i++ )
198 printf( ". " );
199 for ( ptr = this->pegA.head; ptr != 0; ptr = ptr->next )
200 printf( "%d ", ptr->val );
201
202 printf( " pegB: " );
203 for ( i = 0; i < ((this->numDiscs)-list_getSize(&(this->pegB))); i++ )
204 printf( ". " );
205 for ( ptr = this->pegB.head; ptr != 0; ptr = ptr->next )
206 printf( "%d ", ptr->val );
207
208 printf( " pegC: " );
209 for ( i = 0; i < ((this->numDiscs)-list_getSize(&(this->pegC))); i++ )
210 printf( ". " );
211 for ( ptr = this->pegC.head; ptr != 0; ptr = ptr->next )
212 printf( "%d ", ptr->val );
213
214 printf( "\n" );
215 }
216 #endif
217
218 void towers_solve_h( struct Towers* this, int n,
219 struct List* startPeg,
220 struct List* tempPeg,
221 struct List* destPeg )
222 {
223 int val;
224
225 if ( n == 1 ) {
226 #if HOST_DEBUG
227 towers_print(this);
228 #endif
229 val = list_pop(startPeg);
230 list_push(destPeg,val);
231 this->numMoves++;
232 }
233 else {
234 towers_solve_h( this, n-1, startPeg, destPeg, tempPeg );
235 towers_solve_h( this, 1, startPeg, tempPeg, destPeg );
236 towers_solve_h( this, n-1, tempPeg, startPeg, destPeg );
237 }
238
239 }
240
241 void towers_solve( struct Towers* this )
242 {
243 towers_solve_h( this, this->numDiscs, &(this->pegA), &(this->pegB), &(this->pegC) );
244 }
245
246 int towers_verify( struct Towers* this )
247 {
248 struct Node* ptr;
249 int numDiscs = 0;
250
251 if ( list_getSize(&this->pegA) != 0 ) {
252 #if HOST_DEBUG
253 printf( "ERROR: Peg A is not empty!\n" );
254 #endif
255 return 2;
256 }
257
258 if ( list_getSize(&this->pegB) != 0 ) {
259 #if HOST_DEBUG
260 printf( "ERROR: Peg B is not empty!\n" );
261 #endif
262 return 3;
263 }
264
265 if ( list_getSize(&this->pegC) != this->numDiscs ) {
266 #if HOST_DEBUG
267 printf( " ERROR: Expected %d discs but found only %d discs!\n", \
268 this->numDiscs, list_getSize(&this->pegC) );
269 #endif
270 return 4;
271 }
272
273 for ( ptr = this->pegC.head; ptr != 0; ptr = ptr->next ) {
274 numDiscs++;
275 if ( ptr->val != numDiscs ) {
276 #if HOST_DEBUG
277 printf( " ERROR: Expecting disc %d on peg C but found disc %d instead!\n", \
278 numDiscs, ptr->val );
279 #endif
280 return 5;
281 }
282 }
283
284 if ( this->numMoves != ((1 << this->numDiscs) - 1) ) {
285 #if HOST_DEBUG
286 printf( " ERROR: Expecting %d num moves but found %d instead!\n", \
287 ((1 << this->numDiscs) - 1), this->numMoves );
288 #endif
289 return 6;
290 }
291
292 return 1;
293 }
294
295 //--------------------------------------------------------------------------
296 // Main
297
298 int main( int argc, char* argv[] )
299 {
300 struct Towers towers;
301 int i;
302
303 // Initialize free list
304
305 list_init( &g_nodeFreeList );
306 g_nodeFreeList.head = &(g_nodePool[0]);
307 g_nodeFreeList.size = NUM_DISCS;
308 g_nodePool[NUM_DISCS-1].next = 0;
309 g_nodePool[NUM_DISCS-1].val = 99;
310 for ( i = 0; i < (NUM_DISCS-1); i++ ) {
311 g_nodePool[i].next = &(g_nodePool[i+1]);
312 g_nodePool[i].val = i;
313 }
314
315 towers_init( &towers, NUM_DISCS );
316
317 // If needed we preallocate everything in the caches
318
319 #if PREALLOCATE
320 towers_solve( &towers );
321 #endif
322
323 // Solve it
324
325 towers_clear( &towers );
326 setStats(1);
327 towers_solve( &towers );
328 setStats(0);
329
330 // Print out the results
331
332 #if HOST_DEBUG
333 towers_print( &towers );
334 #endif
335
336 // Check the results
337
338 finishTest( towers_verify( &towers ) );
339
340 }
341