OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_51/] [or1ksim/] [cuc/] [cuc.c] - Blame information for rev 1244

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1244 hpanther
/* cuc.c -- OpenRISC Custom Unit Compiler
2
 *    Copyright (C) 2002 Marko Mlinar, markom@opencores.org
3
 *
4
 *    This file is part of OpenRISC 1000 Architectural Simulator.
5
 *
6
 *    This program is free software; you can redistribute it and/or modify
7
 *    it under the terms of the GNU General Public License as published by
8
 *    the Free Software Foundation; either version 2 of the License, or
9
 *    (at your option) any later version.
10
 *
11
 *    This program is distributed in the hope that it will be useful,
12
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *    GNU General Public License for more details.
15
 *
16
 *    You should have received a copy of the GNU General Public License
17
 *    along with this program; if not, write to the Free Software
18
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
 
20
/* Main file, including code optimization and command prompt */
21
 
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <stdarg.h>
25
#include <assert.h>
26
#include <ctype.h>
27
#include "sim-config.h"
28
#include "cuc.h"
29
#include "insn.h"
30
#include "profiler.h"
31
#include "opcode/or32.h"
32
#include "parse.h"
33
 
34
FILE *flog;
35
int cuc_debug = 0;
36
 
37
/* Last used registers by software convention */
38
/* Note that r11 is caller saved register, and we can destroy it.
39
   Due to CUC architecture we must always return something, even garbage (so that
40
   caller knows, we are finished, when we send acknowledge).
41
   In case r11 was not used (trivial register assignment) we will remove it later,
42
   but if we assigned a value to it, it must not be removed, so caller_saved[11] = 0 */
43
const int caller_saved[MAX_REGS] = {
44
  0, 0, 0, 1, 1, 1, 1, 1,
45
  1, 1, 0, 0, 0, 1, 0, 1,
46
  0, 1, 0, 1, 0, 1, 0, 1,
47
  0, 1, 0, 1, 0, 1, 0, 1,
48
  1, 1};
49
 
50
/* returns log2(x) */
51
/* Call this log2_int, because there is a library function named log2 */
52
int log2_int (unsigned long x)
53
{
54
  int c = 0;
55
  assert (x >= 0);
56
  if (!x) return 0; /* not by the book, but practical */
57
  while (x != 1) x >>= 1, c++;
58
  return c;
59
}
60
 
61
/* Does all known instruction optimizations */
62
void cuc_optimize (cuc_func *func)
63
{
64
  int modified = 0;
65
  int first = 1;
66
  log ("Optimizing.\n");
67
  do {
68
    modified = 0;
69
    clean_deps (func);
70
    if (cuc_debug >= 6) print_cuc_bb (func, "AFTER_CLEAN_DEPS");
71
    if (optimize_cmovs (func)) {
72
      if (cuc_debug >= 6) print_cuc_bb (func, "AFTER_OPT_CMOVS");
73
      modified = 1;
74
    }
75
    if (cuc_debug) cuc_check (func);
76
    if (optimize_tree (func)) {
77
      if (cuc_debug >= 6) print_cuc_bb (func, "AFTER_OPT_TREE1");
78
      modified = 1;
79
    }
80
    if (remove_nops (func)) {
81
      if (cuc_debug >= 6) print_cuc_bb (func, "NO_NOPS");
82
      modified = 1;
83
    }
84
    if (cuc_debug) cuc_check (func);
85
    if (remove_dead (func)) {
86
      if (cuc_debug >= 5) print_cuc_bb (func, "AFTER_DEAD");
87
      modified = 1;
88
    }
89
    if (cuc_debug) cuc_check (func);
90
    if (cse (func)) {
91
      log ("Common subexpression elimination.\n");
92
      if (cuc_debug >= 3) print_cuc_bb (func, "AFTER_CSE");
93
      modified = 1;
94
    }
95
    if (first) {
96
      insert_conditional_facts (func);
97
      if (cuc_debug >= 3) print_cuc_bb (func, "AFTER_COND_FACT");
98
      if (cuc_debug) cuc_check (func);
99
      first = 0;
100
    }
101
    if (optimize_bb (func)) {
102
      if (cuc_debug >= 5) print_cuc_bb (func, "AFTER_OPT_BB");
103
      modified = 1;
104
    }
105
    if (cuc_debug) cuc_check (func);
106
    if (remove_nops (func)) {
107
      if (cuc_debug >= 6) print_cuc_bb (func, "NO_NOPS");
108
      modified = 1;
109
    }
110
    if (remove_dead_bb (func)) {
111
      if (cuc_debug >= 5) print_cuc_bb (func, "AFTER_DEAD_BB");
112
      modified = 1;
113
    }
114
    if (remove_trivial_regs (func)) {
115
      if (cuc_debug >= 2) print_cuc_bb (func, "AFTER_TRIVIAL");
116
      modified = 1;
117
    }
118
    if (remove_nops (func)) {
119
      if (cuc_debug >= 6) print_cuc_bb (func, "NO_NOPS");
120
      modified = 1;
121
    }
122
    add_memory_dep (func, func->memory_order);
123
    if (cuc_debug >= 7) print_cuc_bb (func, "AFTER_MEMORY_DEP");
124
    add_data_dep (func);
125
    if (cuc_debug >= 8) print_cuc_bb (func, "AFTER_DATA_DEP");
126
    if (schedule_memory (func, func->memory_order)) {
127
      if (cuc_debug >= 7) print_cuc_bb (func, "AFTER_SCHEDULE_MEM");
128
      modified = 1;
129
    }
130
  } while (modified);
131
  set_io (func);
132
#if 0
133
  detect_max_values (func);
134
  if (cuc_debug >= 5) print_cuc_bb (func, "AFTER_MAX_VALUES");
135
#endif
136
}
137
 
138
/* Pre/unrolls basic block and optimizes it */
139
cuc_timings *preunroll_bb (char *bb_filename, cuc_func *f, cuc_timings *timings, int b, int i, int j)
140
{
141
  cuc_func *func;
142
  cucdebug (2, "BB%i unroll %i times preroll %i times\n", b, j, i);
143
  log ("BB%i unroll %i times preroll %i times\n", b, j, i);
144
  func = preunroll_loop (f, b, i, j, bb_filename);
145
  if (cuc_debug >= 2) print_cuc_bb (func, "AFTER_PREUNROLL");
146
  cuc_optimize (func);
147
  analyse_timings (func, timings);
148
 
149
  cucdebug (2, "new_time = %i, old_time = %i, size = %f\n",
150
           timings->new_time, func->orig_time, timings->size);
151
  log ("new time = %icyc, old_time = %icyc, size = %.0f gates\n",
152
         timings->new_time, func->orig_time, timings->size);
153
  //output_verilog (func, argv[1]);
154
  free_func (func);
155
  timings->b = b;
156
  timings->unroll = j;
157
  timings->preroll = i;
158
  timings->nshared = 0;
159
  return timings;
160
}
161
 
162
/* Simple comparison function */
163
int tim_comp (cuc_timings *a, cuc_timings *b)
164
{
165
  if (a->new_time < b->new_time) return -1;
166
  else if (a->new_time > b->new_time) return 1;
167
  else return 0;
168
}
169
 
170
/* Analyses function; done when cuc command is entered in (sim) prompt */
171
cuc_func *analyse_function (char *module_name, long orig_time,
172
                unsigned long start_addr, unsigned long end_addr,
173
                int memory_order, int num_runs)
174
{
175
  cuc_timings timings;
176
  cuc_func *func = (cuc_func *) malloc (sizeof (cuc_func));
177
  cuc_func *saved;
178
  int b, i, j;
179
  char tmp1[256];
180
  char tmp2[256];
181
 
182
  func->orig_time = orig_time;
183
  func->start_addr = start_addr;
184
  func->end_addr = end_addr;
185
  func->memory_order = memory_order;
186
  func->nfdeps = 0;
187
  func->fdeps = NULL;
188
  func->num_runs = num_runs;
189
 
190
  sprintf (tmp1, "%s.bin", module_name);
191
  cucdebug (2, "Loading %s.bin\n", module_name);
192
  if (cuc_load (tmp1)) {
193
    free (func);
194
    return NULL;
195
  }
196
 
197
  log ("Detecting basic blocks\n");
198
  detect_bb (func);
199
  if (cuc_debug >= 2) print_cuc_insns ("WITH_BB_LIMITS", 0);
200
 
201
  //sprintf (tmp1, "%s.bin.mp", module_name);
202
  sprintf (tmp2, "%s.bin.bb", module_name);
203
  generate_bb_seq (func, config.sim.mprof_fn, tmp2);
204
  log ("Assuming %i clk cycle load (%i cyc burst)\n", runtime.cuc.mdelay[0], runtime.cuc.mdelay[2]);
205
  log ("Assuming %i clk cycle store (%i cyc burst)\n", runtime.cuc.mdelay[1], runtime.cuc.mdelay[3]);
206
 
207
  build_bb (func);
208
  if (cuc_debug >= 5) print_cuc_bb (func, "AFTER_BUILD_BB");
209
  reg_dep (func);
210
 
211
  log ("Detecting dependencies\n");
212
  if (cuc_debug >= 2) print_cuc_bb (func, "AFTER_REG_DEP");
213
  cuc_optimize (func);
214
 
215
#if 0
216
  csm (func);
217
#endif
218
  assert (saved = dup_func (func));
219
 
220
  timings.preroll = timings.unroll = 1;
221
  timings.nshared = 0;
222
 
223
  add_latches (func);
224
  if (cuc_debug >= 1) print_cuc_bb (func, "AFTER_LATCHES");
225
  analyse_timings (func, &timings);
226
 
227
  free_func (func);
228
  log ("Base option: pre%i,un%i,sha%i: %icyc %.1f\n",
229
        timings.preroll, timings.unroll, timings.nshared, timings.new_time, timings.size);
230
  saved->timings = timings;
231
 
232
#if 1
233
  /* detect and unroll simple loops */
234
  for (b = 0; b < saved->num_bb; b++) {
235
    cuc_timings t[MAX_UNROLL * MAX_PREROLL];
236
    cuc_timings *ut;
237
    cuc_timings *cut = &t[0];
238
    int nt = 1;
239
    double csize;
240
    saved->bb[b].selected_tim = -1;
241
 
242
    /* Is it a loop? */
243
    if (saved->bb[b].next[0] != b && saved->bb[b].next[1] != b) continue;
244
    log ("Found loop at BB%x.  Trying to unroll.\n", b);
245
    t[0] = timings;
246
    t[0].b = b;
247
    t[0].preroll = 1;
248
    t[0].unroll = 1;
249
    t[0].nshared = 0;
250
 
251
    sprintf (tmp1, "%s.bin.bb", module_name);
252
    i = 1;
253
    do {
254
      cuc_timings *pt;
255
      cuc_timings *cpt = cut;
256
      j = 1;
257
 
258
      do {
259
        pt = cpt;
260
        cpt = preunroll_bb (tmp1, saved, &t[nt++], b, ++j, i);
261
      } while (j <= MAX_PREROLL && pt->new_time > cpt->new_time);
262
      i++;
263
      ut = cut;
264
      cut = preunroll_bb (tmp1, saved, &t[nt++], b, 1, i);
265
    } while (i <= MAX_UNROLL && ut->new_time > cut->new_time);
266
 
267
    /* Sort the timings */
268
#if 0
269
    if (cuc_debug >= 3)
270
    for (i = 0; i < nt; i++) PRINTF ("%i:%i,%i: %icyc\n",
271
                    t[i].b, t[i].preroll, t[i].unroll, t[i].new_time);
272
#endif
273
 
274
    qsort (t, nt, sizeof (cuc_timings), (int (*)(const void *, const void *))tim_comp);
275
 
276
    /* Delete timings, that have worst time and bigger size than other */
277
    j = 1;
278
    csize = t[0].size;
279
    for (i = 1; i < nt; i++)
280
      if (t[i].size < csize) t[j++] = t[i];
281
    nt = j;
282
 
283
    cucdebug (1, "Available options\n");
284
    for (i = 0; i < nt; i++) cucdebug (1, "%i:%i,%i: %icyc %.1f\n",
285
        t[i].b, t[i].preroll, t[i].unroll, t[i].new_time, t[i].size);
286
    /* Add results from CSM */
287
    j = nt;
288
    for (i = 0; i < saved->bb[b].ntim; i++) {
289
      int i1;
290
      for (i1 = 0; i1 < nt; i1++) {
291
        t[j] = t[i1];
292
        t[j].size += saved->bb[b].tim[i].size - timings.size;
293
        t[j].new_time += saved->bb[b].tim[i].new_time - timings.new_time;
294
        t[j].nshared = saved->bb[b].tim[i].nshared;
295
        t[j].shared = saved->bb[b].tim[i].shared;
296
        if (++j >= MAX_UNROLL * MAX_PREROLL) goto full;
297
      }
298
    }
299
 
300
full:
301
    nt = j;
302
 
303
    cucdebug (1, "Available options:\n");
304
    for (i = 0; i < nt; i++) cucdebug (1, "%i:%i,%i: %icyc %.1f\n",
305
        t[i].b, t[i].preroll, t[i].unroll, t[i].new_time, t[i].size);
306
 
307
    /* Sort again with new timings added */
308
    qsort (t, nt, sizeof (cuc_timings), (int (*)(const void *, const void *))tim_comp);
309
 
310
    /* Delete timings, that have worst time and bigger size than other */
311
    j = 1;
312
    csize = t[0].size;
313
    for (i = 1; i < nt; i++)
314
      if (t[i].size < csize) t[j++] = t[i];
315
    nt = j;
316
 
317
    cucdebug (1, "Available options:\n");
318
    for (i = 0; i < nt; i++) cucdebug (1, "%i:%i,%i: %icyc %.1f\n",
319
                               t[i].b, t[i].preroll, t[i].unroll, t[i].new_time, t[i].size);
320
 
321
    if (saved->bb[b].ntim) free (saved->bb[b].tim);
322
    saved->bb[b].ntim = nt;
323
    assert (saved->bb[b].tim = (cuc_timings *) malloc (sizeof (cuc_timings) * nt));
324
 
325
    /* Copy options in reverse order -- smallest first */
326
    for (i = 0; i < nt; i++) saved->bb[b].tim[i] = t[nt - 1 - i];
327
 
328
    log ("Available options:\n");
329
    for (i = 0; i < saved->bb[b].ntim; i++) {
330
      log ("%i:pre%i,un%i,sha%i: %icyc %.1f\n",
331
        saved->bb[b].tim[i].b, saved->bb[b].tim[i].preroll, saved->bb[b].tim[i].unroll,
332
        saved->bb[b].tim[i].nshared, saved->bb[b].tim[i].new_time, saved->bb[b].tim[i].size);
333
    }
334
  }
335
#endif
336
  return saved;
337
}
338
 
339
/* Utility option formatting functions */
340
static const char *option_char = "?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
341
 
342
/*static */char *gen_option (char *s, int bb_no, int f_opt)
343
{
344
  if (bb_no >= 0) sprintf (s, "%i", bb_no);
345
  assert (f_opt <= strlen (option_char));
346
  sprintf (s, "%s%c", s, option_char[f_opt]);
347
  return s;
348
}
349
 
350
/*static */void print_option (int bb_no, int f_opt)
351
{
352
  char tmp1[10];
353
  char tmp2[10];
354
  sprintf (tmp2, "%s", gen_option (tmp1, bb_no, f_opt));
355
  PRINTF ("%3s", tmp2);
356
}
357
 
358
static char *format_func_options (char *s, cuc_func *f)
359
{
360
  int b, first = 1;
361
  *s = '\0';
362
  for (b = 0; b < f->num_bb; b++)
363
    if (f->bb[b].selected_tim >= 0) {
364
      char tmp[10];
365
      sprintf (s, "%s%s%s", s, first ? "" : ",", gen_option (tmp, b, f->bb[b].selected_tim));
366
      first = 0;
367
    }
368
  return s;
369
}
370
 
371
static void options_cmd (int func_no, cuc_func *f)
372
{
373
  int b, i;
374
  char tmp[30];
375
  char *name = prof_func[func_no].name;
376
  PRINTF ("-----------------------------------------------------------------------------\n");
377
  PRINTF ("|%-28s|pre/unrolled|shared|  time  |  gates |old_time|\n",
378
            strstrip (tmp, name, 28));
379
  PRINTF ("|                    BASE    |%4i / %4i | %4i |%8i|%8.f|%8i|\n", 1, 1, 0,
380
          f->timings.new_time, f->timings.size, f->orig_time);
381
  for (b = 0; b < f->num_bb; b++) {
382
    /* Print out results */
383
    for (i = 1; i < f->bb[b].ntim; i++) { /* First one is base option */
384
      int time = f->bb[b].tim[i].new_time - f->timings.new_time;
385
      double size = f->bb[b].tim[i].size - f->timings.size;
386
      PRINTF ("|                   ");
387
      print_option (b, i);
388
      PRINTF ("      |%4i / %4i | %4i |%+8i|%+8.f|        |\n",
389
        f->bb[b].tim[i].preroll, f->bb[b].tim[i].unroll, f->bb[b].tim[i].nshared,
390
        time, size);
391
    }
392
  }
393
}
394
 
395
/* Generates a function, based on specified parameters */
396
cuc_func *generate_function (cuc_func *rf, char *name, char *cut_filename)
397
{
398
  int b, i, j;
399
  char tmp[256];
400
  cuc_timings tt;
401
  cuc_func *f;
402
  assert (f = dup_func (rf));
403
 
404
  if (cuc_debug >= 2) print_cuc_bb (f, "BEFORE_GENERATE");
405
  log ("Generating function %s.\n", name);
406
  PRINTF ("Generating function %s.\n", name);
407
 
408
  format_func_options (tmp, rf);
409
  if (strlen (tmp)) PRINTF ("Applying options: %s\n", tmp);
410
  else PRINTF ("Using basic options.\n");
411
 
412
  /* Generate function as specified by options */
413
  for (b = 0; b < f->num_bb; b++) {
414
    cuc_timings *st;
415
    if (rf->bb[b].selected_tim < 0) continue;
416
    st = &rf->bb[b].tim[rf->bb[b].selected_tim];
417
    sprintf (tmp, "%s.bin.bb", name);
418
    preunroll_bb (&tmp[0], f, &tt, b, st->preroll, st->unroll);
419
    if (cuc_debug >= 1) print_cuc_bb (f, "AFTER_PREUNROLL");
420
  }
421
  for (b = 0; b < f->num_bb; b++) {
422
    cuc_timings *st;
423
    if (rf->bb[b].selected_tim < 0) continue;
424
    st = &rf->bb[b].tim[rf->bb[b].selected_tim];
425
    if (!st->nshared) continue;
426
    assert (0);
427
    //csm_gen (f, rf, st->nshared, st->shared);
428
  }
429
  add_latches (f);
430
  if (cuc_debug >= 1) print_cuc_bb (f, "AFTER_LATCHES");
431
  analyse_timings (f, &tt);
432
 
433
  sprintf (tmp, "%s%s", cut_filename, name);
434
  output_verilog (f, tmp, name);
435
  return f;
436
}
437
 
438
/* Calculates required time, based on selected options */
439
int calc_cycles (cuc_func *f)
440
{
441
  int b, i, ntime = f->timings.new_time;
442
  for (b = 0; b < f->num_bb; b++)
443
    if (f->bb[b].selected_tim >= 0) {
444
      assert (f->bb[b].selected_tim < f->bb[b].ntim);
445
      ntime += f->bb[b].tim[f->bb[b].selected_tim].new_time - f->timings.new_time;
446
    }
447
  return ntime;
448
}
449
 
450
/* Calculates required size, based on selected options */
451
double calc_size (cuc_func *f)
452
{
453
  int b, i;
454
  double size = f->timings.size;
455
  for (b = 0; b < f->num_bb; b++)
456
    if (f->bb[b].selected_tim >= 0) {
457
      assert (f->bb[b].selected_tim < f->bb[b].ntim);
458
      size += f->bb[b].tim[f->bb[b].selected_tim].size - f->timings.size;
459
    }
460
  return size;
461
}
462
 
463
/* Dumps specified function to file (hex) */
464
unsigned long extract_function (char *out_fn, unsigned long start_addr)
465
{
466
  FILE *fo;
467
  unsigned long a = start_addr;
468
  int x = 0;
469
  assert (fo = fopen (out_fn, "wt+"));
470
 
471
  do {
472
    unsigned long d = evalsim_mem32 (a);
473
    int index = insn_decode (d);
474
    assert (index >= 0);
475
    if (x) x++;
476
    if (strcmp (insn_name (index), "l.jr") == 0) x = 1;
477
    a += 4;
478
    fprintf (fo, "%08x\n", d);
479
  } while (x < 2);
480
 
481
  fclose (fo);
482
  return a - 4;
483
}
484
 
485
static cuc_func *func[MAX_FUNCS];
486
static int func_v[MAX_FUNCS];
487
 
488
/* Detects function dependencies and removes  */
489
static void set_func_deps ()
490
{
491
  int f, b, i, j;
492
restart:
493
  for (f = 0; f < prof_nfuncs - 1; f++) if (func[f]) {
494
    int fused[MAX_FUNCS] = {0};
495
    int c;
496
    for (b = 0; b < func[f]->num_bb; b++)
497
      for (i = 0; i < func[f]->bb[b].ninsn; i++) {
498
        cuc_insn *ii = &func[f]->bb[b].insn[i];
499
        if (ii->index == II_CALL) {
500
          assert (ii->opt[0] == OPT_CONST);
501
          for (j = 0; j < prof_nfuncs - 1; j++)
502
            if (func[j] && func[j]->start_addr == ii->op[0]) break;
503
          if (j >= prof_nfuncs - 1) {
504
            log ("%s is calling unknown function, address %08x\n",
505
                            prof_func[f].name, ii->op[0]);
506
            debug (1, "%s is calling unknown function, address %08x\n",
507
                            prof_func[f].name, ii->op[0]);
508
            free_func (func[f]);
509
            func[f] = NULL;
510
            goto restart;
511
          } else if (f == j) {
512
            log ("%s is recursive, ignoring\n", prof_func[f].name);
513
            debug (1, "%s is recursive, ignoring\n", prof_func[f].name);
514
            free_func (func[f]);
515
            func[f] = NULL;
516
            goto restart;
517
          } else fused[j]++;
518
        }
519
      }
520
    for (i = 0; i < MAX_FUNCS; i++) if (fused[i]) c++;
521
    if (func[f]->nfdeps) free (func[f]->fdeps);
522
    func[f]->nfdeps = c;
523
    func[f]->fdeps = (cuc_func **) malloc (sizeof (cuc_func *) * c);
524
    for (i = 0, j = 0; i < MAX_FUNCS; i++)
525
      if (fused[i]) func[f]->fdeps[j++] = func[i];
526
  }
527
 
528
  /* Detect loops */
529
  {
530
    int change;
531
    for (f = 0; f < MAX_FUNCS; f++) if (func[f]) func[f]->tmp = 0;
532
    do {
533
      change = 0;
534
      for (f = 0; f < MAX_FUNCS; f++) if (func[f] && !func[f]->tmp) {
535
        int o = 1;
536
        for (i = 0; i < func[f]->nfdeps; i++)
537
          if (!func[f]->fdeps[i]->tmp) {o = 0; break;}
538
        if (o) {
539
          func[f]->tmp = 1;
540
          change = 1;
541
        }
542
      }
543
    } while (change);
544
 
545
    change = 0;
546
    for (f = 0; f < MAX_FUNCS; f++) if (func[f] && !func[f]->tmp) {
547
      free_func (func[f]);
548
      func[f] = NULL;
549
      change = 1;
550
    }
551
    if (change) goto restart;
552
  }
553
}
554
 
555
void main_cuc (char *filename)
556
{
557
  int i, j;
558
  char tmp1[256];
559
  char filename_cut[256];
560
#if 0 /* Select prefix, based on binary program name */
561
  for (i = 0; i < sizeof (filename_cut); i++) {
562
    if (isalpha(filename[i])) filename_cut[i] = filename[i];
563
    else {
564
      filename_cut[i] = '\0';
565
      break;
566
    }
567
  }
568
#else
569
  strcpy (filename_cut, "cu");
570
#endif
571
 
572
  PRINTF ("Entering OpenRISC Custom Unit Compiler command prompt\n");
573
  PRINTF ("Using profile file \"%s\" and memory profile file \"%s\".\n", config.sim.prof_fn, config.sim.mprof_fn);
574
  sprintf (tmp1, "%s.log", filename_cut);
575
  PRINTF ("Analyzing. (log file \"%s\").\n", tmp1);
576
  assert (flog = fopen (tmp1, "wt+"));
577
 
578
  /* Loads in the specified timings table */
579
  PRINTF ("Using timings from \"%s\" at %s\n",config.cuc.timings_fn,
580
                 generate_time_pretty (tmp1, config.sim.clkcycle_ps));
581
  load_timing_table (config.cuc.timings_fn);
582
  runtime.cuc.cycle_duration = 1000. * config.sim.clkcycle_ps;
583
  PRINTF ("Multicycle logic %s, bursts %s, %s memory order.\n",
584
    config.cuc.no_multicycle ? "OFF" : "ON", config.cuc.enable_bursts ? "ON" : "OFF",
585
    config.cuc.memory_order == MO_NONE ? "no" : config.cuc.memory_order == MO_WEAK ? "weak" :
586
    config.cuc.memory_order == MO_STRONG ? "strong" : "exact");
587
 
588
  prof_set (1, 0);
589
  assert (prof_acquire (config.sim.prof_fn) == 0);
590
 
591
  if (config.cuc.calling_convention)
592
    PRINTF ("Assuming OpenRISC standard calling convention.\n");
593
 
594
  /* Try all functions except "total" */
595
  for (i = 0; i < prof_nfuncs - 1; i++) {
596
    long orig_time;
597
    unsigned long start_addr, end_addr;
598
    orig_time = prof_func[i].cum_cycles;
599
    start_addr = prof_func[i].addr;
600
 
601
    /* Extract the function from the binary */
602
    sprintf (tmp1, "%s.bin", prof_func[i].name);
603
    end_addr = extract_function (tmp1, start_addr);
604
 
605
    log ("Testing function %s (%08x - %08x)\n", prof_func[i].name, start_addr, end_addr);
606
    PRINTF ("Testing function %s (%08x - %08x)\n", prof_func[i].name, start_addr, end_addr);
607
    func[i] = analyse_function (prof_func[i].name, orig_time, start_addr,
608
                   end_addr, config.cuc.memory_order, prof_func[i].calls);
609
    func_v[i] = 0;
610
  }
611
  set_func_deps ();
612
 
613
  while (1) {
614
    char *s;
615
wait_command:
616
    PRINTF ("(cuc) ");
617
    fflush (stdout);
618
wait_command_empty:
619
    s = fgets(tmp1, sizeof tmp1, stdin);
620
    usleep (100);
621
    if (!s) goto wait_command_empty;
622
    for (s = tmp1; *s != '\0' && *s != '\n' && *s != '\r'; s++);
623
    *s = '\0';
624
 
625
      /* quit command */
626
    if (strcmp (tmp1, "q") == 0 || strcmp (tmp1, "quit") == 0) {
627
      /* Delete temporary files */
628
      for (i = 0; i < prof_nfuncs - 1; i++) {
629
        sprintf (tmp1, "%s.bin", prof_func[i].name);
630
        log ("Deleting temporary file %s %s\n", tmp1, remove (tmp1) ? "FAILED" : "OK");
631
        sprintf (tmp1, "%s.bin.bb", prof_func[i].name);
632
        log ("Deleting temporary file %s %s\n", tmp1, remove (tmp1) ? "FAILED" : "OK");
633
      }
634
      break;
635
 
636
      /* profile command */
637
    } else if (strcmp (tmp1, "p") == 0 || strcmp (tmp1, "profile") == 0) {
638
      int ntime = 0;
639
      int size = 0;
640
      PRINTF ("-----------------------------------------------------------------------------\n");
641
      PRINTF ("|function name       |calls|avg cycles  |old%| max. f.  | impr. f.| options |\n");
642
      PRINTF ("|--------------------+-----+------------+----+----------|---------+---------|\n");
643
      for (j = 0; j < prof_nfuncs; j++) {
644
        int bestcyc = 0, besti = 0;
645
        char tmp[100];
646
        for (i = 0; i < prof_nfuncs; i++)
647
          if (prof_func[i].cum_cycles > bestcyc) {
648
            bestcyc = prof_func[i].cum_cycles;
649
            besti = i;
650
          }
651
        i = besti;
652
        PRINTF ("|%-20s|%5i|%12.1f|%3.0f%%| ",
653
                strstrip (tmp, prof_func[i].name, 20),  prof_func[i].calls,
654
                ((double)prof_func[i].cum_cycles / prof_func[i].calls),
655
                (100. * prof_func[i].cum_cycles / prof_cycles));
656
        if (func[i]) {
657
          double f = 1.0;
658
          if (func_v[i]) {
659
            int nt = calc_cycles (func[i]);
660
            int s = calc_size (func[i]);
661
            f = 1. * func[i]->orig_time / nt;
662
            ntime += nt;
663
            size += s;
664
          } else ntime += prof_func[i].cum_cycles;
665
          PRINTF ("%8.1f |%8.1f | %-8s|\n", 1.f * prof_func[i].cum_cycles
666
                          / func[i]->timings.new_time, f, format_func_options (tmp, func[i]));
667
        } else {
668
          PRINTF ("     N/A |     N/A |     N/A |\n");
669
          ntime += prof_func[i].cum_cycles;
670
        }
671
        prof_func[i].cum_cycles = -prof_func[i].cum_cycles;
672
      }
673
      for (i = 0; i < prof_nfuncs; i++)
674
        prof_func[i].cum_cycles = -prof_func[i].cum_cycles;
675
      PRINTF ("-----------------------------------------------------------------------------\n");
676
      PRINTF ("Total %i cycles (was %i), total added gates = %i. Speed factor %.1f\n",
677
                      ntime, prof_cycles, size, 1. * prof_cycles / ntime);
678
 
679
      /* debug command */
680
    } else if (strncmp (tmp1, "d", 1) == 0 || strncmp (tmp1, "debug", 5) == 0) {
681
      sscanf (tmp1, "%*s %i", &cuc_debug);
682
      if (cuc_debug < 0) cuc_debug = 0;
683
      if (cuc_debug > 9) cuc_debug = 9;
684
 
685
      /* generate command */
686
    } else if (strcmp (tmp1, "g") == 0 || strcmp (tmp1, "generate") == 0) {
687
      /* check for function dependencies */
688
      for (i = 0; i < prof_nfuncs; i++)
689
        if (func[i]) func[i]->tmp = func_v[i];
690
      for (i = 0; i < prof_nfuncs; i++) if (func[i])
691
        for (j = 0; j < func[i]->nfdeps; j++)
692
          if (!func[i]->fdeps[j] || !func[i]->fdeps[j]->tmp) {
693
            PRINTF ("Function %s must be selected for translation (required by %s)\n",
694
                    prof_func[j].name, prof_func[i].name);
695
            goto wait_command;
696
          }
697
      for (i = 0; i < prof_nfuncs; i++)
698
        if (func[i] && func_v[i]) generate_function (func[i], prof_func[i].name, filename_cut);
699
      generate_main (prof_nfuncs, func, filename_cut);
700
 
701
      /* list command */
702
    } else if (strcmp (tmp1, "l") == 0 || strcmp (tmp1, "list") == 0) {
703
      /* check for function dependencies */
704
      for (i = 0; i < prof_nfuncs; i++)
705
        if (func_v[i]) {
706
          PRINTF ("%s\n", prof_func[j].name);
707
        }
708
 
709
      /* selectall command */
710
    } else if (strcmp (tmp1, "sa") == 0 || strcmp (tmp1, "selectall") == 0) {
711
      char tmp[50], ch;
712
      int p, o, b, f;
713
      for (f = 0; f < prof_nfuncs; f++) if (func[f]) {
714
        func_v[f] = 1;
715
        PRINTF ("Function %s selected for translation.\n", prof_func[f].name);
716
      }
717
 
718
      /* select command */
719
    } else if (strncmp (tmp1, "s", 1) == 0 || strncmp (tmp1, "select", 6) == 0) {
720
      char tmp[50], ch;
721
      int p, o, b, f;
722
      p = sscanf (tmp1, "%*s %s %i%c", tmp, &b, &ch);
723
      if (p < 1) PRINTF ("Invalid parameters.\n");
724
      else {
725
        /* Check if we have valid option */
726
        for (f = 0; f < prof_nfuncs; f++)
727
          if (strcmp (prof_func[f].name, tmp) == 0 && func[f]) break;
728
        if (f < prof_nfuncs) {
729
          if (p == 1) {
730
            if (func[f]) {
731
              func_v[f] = 1;
732
              PRINTF ("Function %s selected for translation.\n", prof_func[f].name);
733
            } else PRINTF ("Function %s not suitable for translation.\n", prof_func[f].name);
734
          } else {
735
            if (!func_v[f])
736
              PRINTF ("Function %s not yet selected for translation.\n", prof_func[f].name);
737
            if (p < 3) goto invalid_option;
738
            for (o = 0; option_char[o] != '\0' && option_char[o] != ch; o++);
739
            if (!option_char[o]) goto invalid_option;
740
            if (b < 0 || b >= func[f]->num_bb) goto invalid_option;
741
            if (o < 0 || o >= func[f]->bb[b].ntim) goto invalid_option;
742
 
743
            /* select an option */
744
            func[f]->bb[b].selected_tim = o;
745
            if (func[f]->bb[b].tim[o].nshared) {
746
              PRINTF ("Option has shared instructions: ");
747
              print_shared (func[f], func[f]->bb[b].tim[o].shared, func[f]->bb[b].tim[o].nshared);
748
              PRINTF ("\n");
749
            }
750
            goto wait_command;
751
invalid_option:
752
            PRINTF ("Invalid option.\n");
753
          }
754
        } else PRINTF ("Invalid function.\n");
755
      }
756
 
757
      /* unselect command */
758
    } else if (strncmp (tmp1, "u", 1) == 0 || strncmp (tmp1, "unselect", 8) == 0) {
759
      char tmp[50], ch;
760
      int p, o, b, f;
761
      p = sscanf (tmp1, "%*s %s %i%c", tmp, &b, &ch);
762
      if (p < 1) PRINTF ("Invalid parameters.\n");
763
      else {
764
        /* Check if we have valid option */
765
        for (f = 0; f < prof_nfuncs; f++)
766
          if (strcmp (prof_func[f].name, tmp) == 0 && func[f]) break;
767
        if (f < prof_nfuncs) {
768
          if (p == 1) {
769
            if (func[f]) {
770
              func_v[f] = 0;
771
              PRINTF ("Function %s unselected for translation.\n", prof_func[f].name);
772
            } else PRINTF ("Function %s not suitable for translation.\n", prof_func[f].name);
773
          } else {
774
            if (p < 3) goto invalid_option;
775
            for (o = 0; option_char[o] != '\0' && option_char[o] != ch; o++);
776
            if (!option_char[o]) goto invalid_option;
777
            if (b < 0 || b >= func[f]->num_bb) goto invalid_option;
778
            if (o < 0 || o >= func[f]->bb[b].ntim) goto invalid_option;
779
 
780
            /* select an option */
781
            func[f]->bb[b].selected_tim = -1;
782
          }
783
        } else PRINTF ("Invalid function.\n");
784
      }
785
 
786
      /* options command */
787
    } else if (strcmp (tmp1, "o") == 0 || strcmp (tmp1, "options") == 0) {
788
      int any = 0;
789
      PRINTF ("Available options:\n");
790
      for (i = 0; i < prof_nfuncs; i++)
791
        if (func[i]) {
792
          options_cmd (i, func[i]);
793
          any = 1;
794
        }
795
      if (any) PRINTF ("-----------------------------------------------------------------------------\n");
796
      else PRINTF ("Sorry. No available options.\n");
797
 
798
      /* Ignore empty string */
799
    } else if (strcmp (tmp1, "") == 0) {
800
 
801
      /* help command */
802
    } else {
803
      if (strcmp (tmp1, "h") != 0 && strcmp (tmp1, "help") != 0)
804
        PRINTF ("Unknown command.\n");
805
      PRINTF ("OpenRISC Custom Unit Compiler command prompt\n");
806
      PRINTF ("Available commands:\n");
807
      PRINTF ("  h | help                   displays this help\n");
808
      PRINTF ("  q | quit                   returns to or1ksim prompt\n");
809
      PRINTF ("  p | profile                displays function profiling\n");
810
      PRINTF ("  d | debug #                sets debug level (0-9)\n");
811
      PRINTF ("  o | options                displays available options\n");
812
      PRINTF ("  s | select func [option]   selects an option/function\n");
813
      PRINTF ("  u | unselect func [option] unselects an option/function\n");
814
      PRINTF ("  g | generate               generates verilog file\n");
815
      PRINTF ("  l | list                   displays selected functions\n");
816
    }
817
  }
818
 
819
  /* Dispose memory */
820
  for (i = 0; i < prof_nfuncs -1; i++)
821
    if (func[i]) free_func (func[i]);
822
 
823
  fclose (flog);
824
}
825
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.