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

Subversion Repositories or1k

[/] [or1k/] [tags/] [rel-0-3-0-rc1/] [or1ksim/] [cuc/] [cuc.c] - Blame information for rev 1748

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
 
3 1748 jeremybenn
   Copyright (C) 2002 Marko Mlinar, markom@opencores.org
4
   Copyright (C) 2008 Embecosm Limited
5
 
6
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7
 
8
   This file is part of OpenRISC 1000 Architectural Simulator.
9
 
10
   This program is free software; you can redistribute it and/or modify it
11
   under the terms of the GNU General Public License as published by the Free
12
   Software Foundation; either version 3 of the License, or (at your option)
13
   any later version.
14
 
15
   This program is distributed in the hope that it will be useful, but WITHOUT
16
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18
   more details.
19
 
20
   You should have received a copy of the GNU General Public License along
21
   with this program.  If not, see <http://www.gnu.org/licenses/>. */
22
 
23
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25
 
26 1244 hpanther
/* Main file, including code optimization and command prompt */
27
 
28 1308 phoenix
 
29 1748 jeremybenn
/* Autoconf and/or portability configuration */
30 1350 nogj
#include "config.h"
31 1748 jeremybenn
#include "port.h"
32 1350 nogj
 
33 1748 jeremybenn
/* System includes */
34
#include <stdlib.h>
35
#include <unistd.h>
36
#include <assert.h>
37 1350 nogj
 
38 1748 jeremybenn
/* Package includes */
39
#include "cuc.h"
40 1244 hpanther
#include "sim-config.h"
41 1748 jeremybenn
#include "profiler.h"
42 1244 hpanther
#include "insn.h"
43
#include "opcode/or32.h"
44
#include "parse.h"
45 1748 jeremybenn
#include "verilog.h"
46 1308 phoenix
#include "debug.h"
47 1244 hpanther
 
48
FILE *flog;
49
int cuc_debug = 0;
50
 
51
/* Last used registers by software convention */
52
/* Note that r11 is caller saved register, and we can destroy it.
53
   Due to CUC architecture we must always return something, even garbage (so that
54
   caller knows, we are finished, when we send acknowledge).
55
   In case r11 was not used (trivial register assignment) we will remove it later,
56
   but if we assigned a value to it, it must not be removed, so caller_saved[11] = 0 */
57
const int caller_saved[MAX_REGS] = {
58
  0, 0, 0, 1, 1, 1, 1, 1,
59
  1, 1, 0, 0, 0, 1, 0, 1,
60
  0, 1, 0, 1, 0, 1, 0, 1,
61
  0, 1, 0, 1, 0, 1, 0, 1,
62 1748 jeremybenn
  1, 1
63
};
64 1244 hpanther
 
65
/* Does all known instruction optimizations */
66 1748 jeremybenn
void
67
cuc_optimize (cuc_func * func)
68 1244 hpanther
{
69
  int modified = 0;
70
  int first = 1;
71
  log ("Optimizing.\n");
72 1748 jeremybenn
  do
73
    {
74
      modified = 0;
75
      clean_deps (func);
76
      if (cuc_debug >= 6)
77
        print_cuc_bb (func, "AFTER_CLEAN_DEPS");
78
      if (optimize_cmovs (func))
79
        {
80
          if (cuc_debug >= 6)
81
            print_cuc_bb (func, "AFTER_OPT_CMOVS");
82
          modified = 1;
83
        }
84
      if (cuc_debug)
85
        cuc_check (func);
86
      if (optimize_tree (func))
87
        {
88
          if (cuc_debug >= 6)
89
            print_cuc_bb (func, "AFTER_OPT_TREE1");
90
          modified = 1;
91
        }
92
      if (remove_nops (func))
93
        {
94
          if (cuc_debug >= 6)
95
            print_cuc_bb (func, "NO_NOPS");
96
          modified = 1;
97
        }
98
      if (cuc_debug)
99
        cuc_check (func);
100
      if (remove_dead (func))
101
        {
102
          if (cuc_debug >= 5)
103
            print_cuc_bb (func, "AFTER_DEAD");
104
          modified = 1;
105
        }
106
      if (cuc_debug)
107
        cuc_check (func);
108
      if (cse (func))
109
        {
110
          log ("Common subexpression elimination.\n");
111
          if (cuc_debug >= 3)
112
            print_cuc_bb (func, "AFTER_CSE");
113
          modified = 1;
114
        }
115
      if (first)
116
        {
117
          insert_conditional_facts (func);
118
          if (cuc_debug >= 3)
119
            print_cuc_bb (func, "AFTER_COND_FACT");
120
          if (cuc_debug)
121
            cuc_check (func);
122
          first = 0;
123
        }
124
      if (optimize_bb (func))
125
        {
126
          if (cuc_debug >= 5)
127
            print_cuc_bb (func, "AFTER_OPT_BB");
128
          modified = 1;
129
        }
130
      if (cuc_debug)
131
        cuc_check (func);
132
      if (remove_nops (func))
133
        {
134
          if (cuc_debug >= 6)
135
            print_cuc_bb (func, "NO_NOPS");
136
          modified = 1;
137
        }
138
      if (remove_dead_bb (func))
139
        {
140
          if (cuc_debug >= 5)
141
            print_cuc_bb (func, "AFTER_DEAD_BB");
142
          modified = 1;
143
        }
144
      if (remove_trivial_regs (func))
145
        {
146
          if (cuc_debug >= 2)
147
            print_cuc_bb (func, "AFTER_TRIVIAL");
148
          modified = 1;
149
        }
150
      if (remove_nops (func))
151
        {
152
          if (cuc_debug >= 6)
153
            print_cuc_bb (func, "NO_NOPS");
154
          modified = 1;
155
        }
156
      add_memory_dep (func, func->memory_order);
157
      if (cuc_debug >= 7)
158
        print_cuc_bb (func, "AFTER_MEMORY_DEP");
159
      add_data_dep (func);
160
      if (cuc_debug >= 8)
161
        print_cuc_bb (func, "AFTER_DATA_DEP");
162
      if (schedule_memory (func, func->memory_order))
163
        {
164
          if (cuc_debug >= 7)
165
            print_cuc_bb (func, "AFTER_SCHEDULE_MEM");
166
          modified = 1;
167
        }
168 1244 hpanther
    }
169 1748 jeremybenn
  while (modified);
170 1244 hpanther
  set_io (func);
171
#if 0
172
  detect_max_values (func);
173 1748 jeremybenn
  if (cuc_debug >= 5)
174
    print_cuc_bb (func, "AFTER_MAX_VALUES");
175 1244 hpanther
#endif
176
}
177
 
178
/* Pre/unrolls basic block and optimizes it */
179 1748 jeremybenn
cuc_timings *
180
preunroll_bb (char *bb_filename, cuc_func * f, cuc_timings * timings, int b,
181
              int i, int j)
182 1244 hpanther
{
183
  cuc_func *func;
184
  cucdebug (2, "BB%i unroll %i times preroll %i times\n", b, j, i);
185
  log ("BB%i unroll %i times preroll %i times\n", b, j, i);
186
  func = preunroll_loop (f, b, i, j, bb_filename);
187 1748 jeremybenn
  if (cuc_debug >= 2)
188
    print_cuc_bb (func, "AFTER_PREUNROLL");
189 1244 hpanther
  cuc_optimize (func);
190
  analyse_timings (func, timings);
191
 
192
  cucdebug (2, "new_time = %i, old_time = %i, size = %f\n",
193 1748 jeremybenn
            timings->new_time, func->orig_time, timings->size);
194 1244 hpanther
  log ("new time = %icyc, old_time = %icyc, size = %.0f gates\n",
195 1748 jeremybenn
       timings->new_time, func->orig_time, timings->size);
196 1244 hpanther
  //output_verilog (func, argv[1]);
197
  free_func (func);
198
  timings->b = b;
199
  timings->unroll = j;
200
  timings->preroll = i;
201
  timings->nshared = 0;
202
  return timings;
203
}
204
 
205
/* Simple comparison function */
206 1748 jeremybenn
int
207
tim_comp (cuc_timings * a, cuc_timings * b)
208 1244 hpanther
{
209 1748 jeremybenn
  if (a->new_time < b->new_time)
210
    return -1;
211
  else if (a->new_time > b->new_time)
212
    return 1;
213
  else
214
    return 0;
215 1244 hpanther
}
216
 
217
/* Analyses function; done when cuc command is entered in (sim) prompt */
218 1748 jeremybenn
cuc_func *
219
analyse_function (char *module_name, long orig_time,
220
                  unsigned long start_addr, unsigned long end_addr,
221
                  int memory_order, int num_runs)
222 1244 hpanther
{
223
  cuc_timings timings;
224
  cuc_func *func = (cuc_func *) malloc (sizeof (cuc_func));
225
  cuc_func *saved;
226
  int b, i, j;
227
  char tmp1[256];
228
  char tmp2[256];
229
 
230
  func->orig_time = orig_time;
231
  func->start_addr = start_addr;
232
  func->end_addr = end_addr;
233
  func->memory_order = memory_order;
234
  func->nfdeps = 0;
235
  func->fdeps = NULL;
236
  func->num_runs = num_runs;
237
 
238
  sprintf (tmp1, "%s.bin", module_name);
239
  cucdebug (2, "Loading %s.bin\n", module_name);
240 1748 jeremybenn
  if (cuc_load (tmp1))
241
    {
242
      free (func);
243
      return NULL;
244
    }
245 1244 hpanther
 
246
  log ("Detecting basic blocks\n");
247
  detect_bb (func);
248 1748 jeremybenn
  if (cuc_debug >= 2)
249
    print_cuc_insns ("WITH_BB_LIMITS", 0);
250 1244 hpanther
 
251
  //sprintf (tmp1, "%s.bin.mp", module_name);
252
  sprintf (tmp2, "%s.bin.bb", module_name);
253
  generate_bb_seq (func, config.sim.mprof_fn, tmp2);
254 1748 jeremybenn
  log ("Assuming %i clk cycle load (%i cyc burst)\n", runtime.cuc.mdelay[0],
255
       runtime.cuc.mdelay[2]);
256
  log ("Assuming %i clk cycle store (%i cyc burst)\n", runtime.cuc.mdelay[1],
257
       runtime.cuc.mdelay[3]);
258
 
259 1244 hpanther
  build_bb (func);
260 1748 jeremybenn
  if (cuc_debug >= 5)
261
    print_cuc_bb (func, "AFTER_BUILD_BB");
262 1244 hpanther
  reg_dep (func);
263
 
264
  log ("Detecting dependencies\n");
265 1748 jeremybenn
  if (cuc_debug >= 2)
266
    print_cuc_bb (func, "AFTER_REG_DEP");
267 1244 hpanther
  cuc_optimize (func);
268 1748 jeremybenn
 
269 1244 hpanther
#if 0
270
  csm (func);
271
#endif
272
  assert (saved = dup_func (func));
273
 
274
  timings.preroll = timings.unroll = 1;
275
  timings.nshared = 0;
276
 
277
  add_latches (func);
278 1748 jeremybenn
  if (cuc_debug >= 1)
279
    print_cuc_bb (func, "AFTER_LATCHES");
280 1244 hpanther
  analyse_timings (func, &timings);
281
 
282
  free_func (func);
283
  log ("Base option: pre%i,un%i,sha%i: %icyc %.1f\n",
284 1748 jeremybenn
       timings.preroll, timings.unroll, timings.nshared, timings.new_time,
285
       timings.size);
286 1244 hpanther
  saved->timings = timings;
287 1748 jeremybenn
 
288 1244 hpanther
#if 1
289
  /* detect and unroll simple loops */
290 1748 jeremybenn
  for (b = 0; b < saved->num_bb; b++)
291
    {
292
      cuc_timings t[MAX_UNROLL * MAX_PREROLL];
293
      cuc_timings *ut;
294
      cuc_timings *cut = &t[0];
295
      int nt = 1;
296
      double csize;
297
      saved->bb[b].selected_tim = -1;
298 1244 hpanther
 
299 1748 jeremybenn
      /* Is it a loop? */
300
      if (saved->bb[b].next[0] != b && saved->bb[b].next[1] != b)
301
        continue;
302
      log ("Found loop at BB%x.  Trying to unroll.\n", b);
303
      t[0] = timings;
304
      t[0].b = b;
305
      t[0].preroll = 1;
306
      t[0].unroll = 1;
307
      t[0].nshared = 0;
308 1244 hpanther
 
309 1748 jeremybenn
      sprintf (tmp1, "%s.bin.bb", module_name);
310
      i = 1;
311
      do
312
        {
313
          cuc_timings *pt;
314
          cuc_timings *cpt = cut;
315
          j = 1;
316 1244 hpanther
 
317 1748 jeremybenn
          do
318
            {
319
              pt = cpt;
320
              cpt = preunroll_bb (tmp1, saved, &t[nt++], b, ++j, i);
321
            }
322
          while (j <= MAX_PREROLL && pt->new_time > cpt->new_time);
323
          i++;
324
          ut = cut;
325
          cut = preunroll_bb (tmp1, saved, &t[nt++], b, 1, i);
326
        }
327
      while (i <= MAX_UNROLL && ut->new_time > cut->new_time);
328
 
329
      /* Sort the timings */
330 1244 hpanther
#if 0
331 1748 jeremybenn
      if (cuc_debug >= 3)
332
        for (i = 0; i < nt; i++)
333
          PRINTF ("%i:%i,%i: %icyc\n",
334
                  t[i].b, t[i].preroll, t[i].unroll, t[i].new_time);
335 1244 hpanther
#endif
336
 
337 1748 jeremybenn
      qsort (t, nt, sizeof (cuc_timings),
338
             (int (*)(const void *, const void *)) tim_comp);
339 1244 hpanther
 
340 1748 jeremybenn
      /* Delete timings, that have worst time and bigger size than other */
341
      j = 1;
342
      csize = t[0].size;
343
      for (i = 1; i < nt; i++)
344
        if (t[i].size < csize)
345
          t[j++] = t[i];
346
      nt = j;
347 1244 hpanther
 
348 1748 jeremybenn
      cucdebug (1, "Available options\n");
349
      for (i = 0; i < nt; i++)
350
        cucdebug (1, "%i:%i,%i: %icyc %.1f\n",
351
                  t[i].b, t[i].preroll, t[i].unroll, t[i].new_time,
352
                  t[i].size);
353
      /* Add results from CSM */
354
      j = nt;
355
      for (i = 0; i < saved->bb[b].ntim; i++)
356
        {
357
          int i1;
358
          for (i1 = 0; i1 < nt; i1++)
359
            {
360
              t[j] = t[i1];
361
              t[j].size += saved->bb[b].tim[i].size - timings.size;
362
              t[j].new_time +=
363
                saved->bb[b].tim[i].new_time - timings.new_time;
364
              t[j].nshared = saved->bb[b].tim[i].nshared;
365
              t[j].shared = saved->bb[b].tim[i].shared;
366
              if (++j >= MAX_UNROLL * MAX_PREROLL)
367
                goto full;
368
            }
369
        }
370 1244 hpanther
 
371 1748 jeremybenn
    full:
372
      nt = j;
373 1244 hpanther
 
374 1748 jeremybenn
      cucdebug (1, "Available options:\n");
375
      for (i = 0; i < nt; i++)
376
        cucdebug (1, "%i:%i,%i: %icyc %.1f\n",
377
                  t[i].b, t[i].preroll, t[i].unroll, t[i].new_time,
378
                  t[i].size);
379 1244 hpanther
 
380 1748 jeremybenn
      /* Sort again with new timings added */
381
      qsort (t, nt, sizeof (cuc_timings),
382
             (int (*)(const void *, const void *)) tim_comp);
383 1244 hpanther
 
384 1748 jeremybenn
      /* Delete timings, that have worst time and bigger size than other */
385
      j = 1;
386
      csize = t[0].size;
387
      for (i = 1; i < nt; i++)
388
        if (t[i].size < csize)
389
          t[j++] = t[i];
390
      nt = j;
391 1244 hpanther
 
392 1748 jeremybenn
      cucdebug (1, "Available options:\n");
393
      for (i = 0; i < nt; i++)
394
        cucdebug (1, "%i:%i,%i: %icyc %.1f\n",
395
                  t[i].b, t[i].preroll, t[i].unroll, t[i].new_time,
396
                  t[i].size);
397 1244 hpanther
 
398 1748 jeremybenn
      if (saved->bb[b].ntim)
399
        free (saved->bb[b].tim);
400
      saved->bb[b].ntim = nt;
401
      assert (saved->bb[b].tim =
402
              (cuc_timings *) malloc (sizeof (cuc_timings) * nt));
403
 
404
      /* Copy options in reverse order -- smallest first */
405
      for (i = 0; i < nt; i++)
406
        saved->bb[b].tim[i] = t[nt - 1 - i];
407
 
408
      log ("Available options:\n");
409
      for (i = 0; i < saved->bb[b].ntim; i++)
410
        {
411
          log ("%i:pre%i,un%i,sha%i: %icyc %.1f\n",
412
               saved->bb[b].tim[i].b, saved->bb[b].tim[i].preroll,
413
               saved->bb[b].tim[i].unroll, saved->bb[b].tim[i].nshared,
414
               saved->bb[b].tim[i].new_time, saved->bb[b].tim[i].size);
415
        }
416 1244 hpanther
    }
417
#endif
418
  return saved;
419
}
420
 
421
/* Utility option formatting functions */
422 1748 jeremybenn
static const char *option_char =
423
  "?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
424 1244 hpanther
 
425 1748 jeremybenn
/*static */ char *
426
gen_option (char *s, int bb_no, int f_opt)
427 1244 hpanther
{
428 1748 jeremybenn
  if (bb_no >= 0)
429
    sprintf (s, "%i", bb_no);
430 1244 hpanther
  assert (f_opt <= strlen (option_char));
431
  sprintf (s, "%s%c", s, option_char[f_opt]);
432
  return s;
433
}
434
 
435 1748 jeremybenn
/*static */ void
436
print_option (int bb_no, int f_opt)
437 1244 hpanther
{
438
  char tmp1[10];
439
  char tmp2[10];
440
  sprintf (tmp2, "%s", gen_option (tmp1, bb_no, f_opt));
441
  PRINTF ("%3s", tmp2);
442
}
443
 
444 1748 jeremybenn
static char *
445
format_func_options (char *s, cuc_func * f)
446 1244 hpanther
{
447
  int b, first = 1;
448
  *s = '\0';
449
  for (b = 0; b < f->num_bb; b++)
450 1748 jeremybenn
    if (f->bb[b].selected_tim >= 0)
451
      {
452
        char tmp[10];
453
        sprintf (s, "%s%s%s", s, first ? "" : ",",
454
                 gen_option (tmp, b, f->bb[b].selected_tim));
455
        first = 0;
456
      }
457 1244 hpanther
  return s;
458
}
459
 
460 1748 jeremybenn
static void
461
options_cmd (int func_no, cuc_func * f)
462 1244 hpanther
{
463
  int b, i;
464
  char tmp[30];
465
  char *name = prof_func[func_no].name;
466 1748 jeremybenn
  PRINTF
467
    ("-----------------------------------------------------------------------------\n");
468 1244 hpanther
  PRINTF ("|%-28s|pre/unrolled|shared|  time  |  gates |old_time|\n",
469 1748 jeremybenn
          strstrip (tmp, name, 28));
470
  PRINTF ("|                    BASE    |%4i / %4i | %4i |%8i|%8.f|%8i|\n", 1,
471
          1, 0, f->timings.new_time, f->timings.size, f->orig_time);
472
  for (b = 0; b < f->num_bb; b++)
473
    {
474
      /* Print out results */
475
      for (i = 1; i < f->bb[b].ntim; i++)
476
        {                       /* First one is base option */
477
          int time = f->bb[b].tim[i].new_time - f->timings.new_time;
478
          double size = f->bb[b].tim[i].size - f->timings.size;
479
          PRINTF ("|                   ");
480
          print_option (b, i);
481
          PRINTF ("      |%4i / %4i | %4i |%+8i|%+8.f|        |\n",
482
                  f->bb[b].tim[i].preroll, f->bb[b].tim[i].unroll,
483
                  f->bb[b].tim[i].nshared, time, size);
484
        }
485 1244 hpanther
    }
486
}
487
 
488
/* Generates a function, based on specified parameters */
489 1748 jeremybenn
cuc_func *
490
generate_function (cuc_func * rf, char *name, char *cut_filename)
491 1244 hpanther
{
492 1308 phoenix
  int b;
493 1244 hpanther
  char tmp[256];
494
  cuc_timings tt;
495
  cuc_func *f;
496
  assert (f = dup_func (rf));
497
 
498 1748 jeremybenn
  if (cuc_debug >= 2)
499
    print_cuc_bb (f, "BEFORE_GENERATE");
500 1244 hpanther
  log ("Generating function %s.\n", name);
501
  PRINTF ("Generating function %s.\n", name);
502
 
503
  format_func_options (tmp, rf);
504 1748 jeremybenn
  if (strlen (tmp))
505
    PRINTF ("Applying options: %s\n", tmp);
506
  else
507
    PRINTF ("Using basic options.\n");
508 1244 hpanther
 
509
  /* Generate function as specified by options */
510 1748 jeremybenn
  for (b = 0; b < f->num_bb; b++)
511
    {
512
      cuc_timings *st;
513
      if (rf->bb[b].selected_tim < 0)
514
        continue;
515
      st = &rf->bb[b].tim[rf->bb[b].selected_tim];
516
      sprintf (tmp, "%s.bin.bb", name);
517
      preunroll_bb (&tmp[0], f, &tt, b, st->preroll, st->unroll);
518
      if (cuc_debug >= 1)
519
        print_cuc_bb (f, "AFTER_PREUNROLL");
520
    }
521
  for (b = 0; b < f->num_bb; b++)
522
    {
523
      cuc_timings *st;
524
      if (rf->bb[b].selected_tim < 0)
525
        continue;
526
      st = &rf->bb[b].tim[rf->bb[b].selected_tim];
527
      if (!st->nshared)
528
        continue;
529
      assert (0);
530
      //csm_gen (f, rf, st->nshared, st->shared);
531
    }
532 1244 hpanther
  add_latches (f);
533 1748 jeremybenn
  if (cuc_debug >= 1)
534
    print_cuc_bb (f, "AFTER_LATCHES");
535 1244 hpanther
  analyse_timings (f, &tt);
536 1748 jeremybenn
 
537 1244 hpanther
  sprintf (tmp, "%s%s", cut_filename, name);
538
  output_verilog (f, tmp, name);
539
  return f;
540
}
541
 
542
/* Calculates required time, based on selected options */
543 1748 jeremybenn
int
544
calc_cycles (cuc_func * f)
545 1244 hpanther
{
546 1308 phoenix
  int b, ntime = f->timings.new_time;
547 1244 hpanther
  for (b = 0; b < f->num_bb; b++)
548 1748 jeremybenn
    if (f->bb[b].selected_tim >= 0)
549
      {
550
        assert (f->bb[b].selected_tim < f->bb[b].ntim);
551
        ntime +=
552
          f->bb[b].tim[f->bb[b].selected_tim].new_time - f->timings.new_time;
553
      }
554 1244 hpanther
  return ntime;
555
}
556
 
557
/* Calculates required size, based on selected options */
558 1748 jeremybenn
double
559
calc_size (cuc_func * f)
560 1244 hpanther
{
561 1308 phoenix
  int b;
562 1244 hpanther
  double size = f->timings.size;
563
  for (b = 0; b < f->num_bb; b++)
564 1748 jeremybenn
    if (f->bb[b].selected_tim >= 0)
565
      {
566
        assert (f->bb[b].selected_tim < f->bb[b].ntim);
567
        size += f->bb[b].tim[f->bb[b].selected_tim].size - f->timings.size;
568
      }
569 1244 hpanther
  return size;
570
}
571
 
572
/* Dumps specified function to file (hex) */
573 1748 jeremybenn
unsigned long
574
extract_function (char *out_fn, unsigned long start_addr)
575 1244 hpanther
{
576
  FILE *fo;
577
  unsigned long a = start_addr;
578
  int x = 0;
579
  assert (fo = fopen (out_fn, "wt+"));
580
 
581 1748 jeremybenn
  do
582
    {
583
      unsigned long d = eval_direct32 (a, 0, 0);
584
      int index = insn_decode (d);
585
      assert (index >= 0);
586
      if (x)
587
        x++;
588
      if (strcmp (insn_name (index), "l.jr") == 0)
589
        x = 1;
590
      a += 4;
591
      fprintf (fo, "%08lx\n", d);
592
    }
593
  while (x < 2);
594 1244 hpanther
 
595
  fclose (fo);
596
  return a - 4;
597
}
598
 
599
static cuc_func *func[MAX_FUNCS];
600
static int func_v[MAX_FUNCS];
601
 
602
/* Detects function dependencies and removes  */
603 1748 jeremybenn
static void
604
set_func_deps ()
605 1244 hpanther
{
606
  int f, b, i, j;
607
restart:
608 1748 jeremybenn
  for (f = 0; f < prof_nfuncs - 1; f++)
609
    if (func[f])
610
      {
611
        int fused[MAX_FUNCS] = { 0 };
612
        int c = 0;
613
        for (b = 0; b < func[f]->num_bb; b++)
614
          for (i = 0; i < func[f]->bb[b].ninsn; i++)
615
            {
616
              cuc_insn *ii = &func[f]->bb[b].insn[i];
617
              if (ii->index == II_CALL)
618
                {
619
                  assert (ii->opt[0] == OPT_CONST);
620
                  for (j = 0; j < prof_nfuncs - 1; j++)
621
                    if (func[j] && func[j]->start_addr == ii->op[0])
622
                      break;
623
                  if (j >= prof_nfuncs - 1)
624
                    {
625
                      log ("%s is calling unknown function, address %08lx\n",
626
                           prof_func[f].name, ii->op[0]);
627
                      debug (1,
628
                             "%s is calling unknown function, address %08lx\n",
629
                             prof_func[f].name, ii->op[0]);
630
                      free_func (func[f]);
631
                      func[f] = NULL;
632
                      goto restart;
633
                    }
634
                  else if (f == j)
635
                    {
636
                      log ("%s is recursive, ignoring\n", prof_func[f].name);
637
                      debug (1, "%s is recursive, ignoring\n",
638
                             prof_func[f].name);
639
                      free_func (func[f]);
640
                      func[f] = NULL;
641
                      goto restart;
642
                    }
643
                  else
644
                    fused[j]++;
645
                }
646
            }
647
        for (i = 0; i < MAX_FUNCS; i++)
648
          if (fused[i])
649
            c++;
650
        if (func[f]->nfdeps)
651
          free (func[f]->fdeps);
652
        func[f]->nfdeps = c;
653
        func[f]->fdeps = (cuc_func **) malloc (sizeof (cuc_func *) * c);
654
        for (i = 0, j = 0; i < MAX_FUNCS; i++)
655
          if (fused[i])
656
            func[f]->fdeps[j++] = func[i];
657 1244 hpanther
      }
658
 
659
  /* Detect loops */
660
  {
661
    int change;
662 1748 jeremybenn
    for (f = 0; f < MAX_FUNCS; f++)
663
      if (func[f])
664
        func[f]->tmp = 0;
665
    do
666
      {
667
        change = 0;
668
        for (f = 0; f < MAX_FUNCS; f++)
669
          if (func[f] && !func[f]->tmp)
670
            {
671
              int o = 1;
672
              for (i = 0; i < func[f]->nfdeps; i++)
673
                if (!func[f]->fdeps[i]->tmp)
674
                  {
675
                    o = 0;
676
                    break;
677
                  }
678
              if (o)
679
                {
680
                  func[f]->tmp = 1;
681
                  change = 1;
682
                }
683
            }
684 1244 hpanther
      }
685 1748 jeremybenn
    while (change);
686
 
687 1244 hpanther
    change = 0;
688 1748 jeremybenn
    for (f = 0; f < MAX_FUNCS; f++)
689
      if (func[f] && !func[f]->tmp)
690
        {
691
          free_func (func[f]);
692
          func[f] = NULL;
693
          change = 1;
694
        }
695
    if (change)
696
      goto restart;
697 1244 hpanther
  }
698
}
699
 
700 1748 jeremybenn
void
701
main_cuc (char *filename)
702 1244 hpanther
{
703
  int i, j;
704
  char tmp1[256];
705
  char filename_cut[256];
706 1748 jeremybenn
#if 0                           /* Select prefix, based on binary program name */
707
  for (i = 0; i < sizeof (filename_cut); i++)
708
    {
709
      if (isalpha (filename[i]))
710
        filename_cut[i] = filename[i];
711
      else
712
        {
713
          filename_cut[i] = '\0';
714
          break;
715
        }
716 1244 hpanther
    }
717
#else
718
  strcpy (filename_cut, "cu");
719
#endif
720
 
721
  PRINTF ("Entering OpenRISC Custom Unit Compiler command prompt\n");
722 1748 jeremybenn
  PRINTF ("Using profile file \"%s\" and memory profile file \"%s\".\n",
723
          config.sim.prof_fn, config.sim.mprof_fn);
724 1244 hpanther
  sprintf (tmp1, "%s.log", filename_cut);
725
  PRINTF ("Analyzing. (log file \"%s\").\n", tmp1);
726
  assert (flog = fopen (tmp1, "wt+"));
727
 
728
  /* Loads in the specified timings table */
729 1748 jeremybenn
  PRINTF ("Using timings from \"%s\" at %s\n", config.cuc.timings_fn,
730
          generate_time_pretty (tmp1, config.sim.clkcycle_ps));
731 1244 hpanther
  load_timing_table (config.cuc.timings_fn);
732
  runtime.cuc.cycle_duration = 1000. * config.sim.clkcycle_ps;
733
  PRINTF ("Multicycle logic %s, bursts %s, %s memory order.\n",
734 1748 jeremybenn
          config.cuc.no_multicycle ? "OFF" : "ON",
735
          config.cuc.enable_bursts ? "ON" : "OFF",
736
          config.cuc.memory_order ==
737
          MO_NONE ? "no" : config.cuc.memory_order ==
738
          MO_WEAK ? "weak" : config.cuc.memory_order ==
739
          MO_STRONG ? "strong" : "exact");
740 1244 hpanther
 
741
  prof_set (1, 0);
742
  assert (prof_acquire (config.sim.prof_fn) == 0);
743 1748 jeremybenn
 
744 1244 hpanther
  if (config.cuc.calling_convention)
745
    PRINTF ("Assuming OpenRISC standard calling convention.\n");
746
 
747 1748 jeremybenn
  /* Try all functions except "total" */
748
  for (i = 0; i < prof_nfuncs - 1; i++)
749
    {
750
      long orig_time;
751
      unsigned long start_addr, end_addr;
752
      orig_time = prof_func[i].cum_cycles;
753
      start_addr = prof_func[i].addr;
754
 
755
      /* Extract the function from the binary */
756
      sprintf (tmp1, "%s.bin", prof_func[i].name);
757
      end_addr = extract_function (tmp1, start_addr);
758
 
759
      log ("Testing function %s (%08lx - %08lx)\n", prof_func[i].name,
760
           start_addr, end_addr);
761
      PRINTF ("Testing function %s (%08lx - %08lx)\n", prof_func[i].name,
762
              start_addr, end_addr);
763
      func[i] =
764
        analyse_function (prof_func[i].name, orig_time, start_addr, end_addr,
765
                          config.cuc.memory_order, prof_func[i].calls);
766
      func_v[i] = 0;
767
    }
768 1244 hpanther
  set_func_deps ();
769
 
770 1748 jeremybenn
  while (1)
771
    {
772
      char *s;
773
    wait_command:
774
      PRINTF ("(cuc) ");
775
      fflush (stdout);
776
    wait_command_empty:
777
      s = fgets (tmp1, sizeof tmp1, stdin);
778
      usleep (100);
779
      if (!s)
780
        goto wait_command_empty;
781
      for (s = tmp1; *s != '\0' && *s != '\n' && *s != '\r'; s++);
782
      *s = '\0';
783
 
784 1244 hpanther
      /* quit command */
785 1748 jeremybenn
      if (strcmp (tmp1, "q") == 0 || strcmp (tmp1, "quit") == 0)
786
        {
787
          /* Delete temporary files */
788
          for (i = 0; i < prof_nfuncs - 1; i++)
789
            {
790
              sprintf (tmp1, "%s.bin", prof_func[i].name);
791
              log ("Deleting temporary file %s %s\n", tmp1,
792
                   remove (tmp1) ? "FAILED" : "OK");
793
              sprintf (tmp1, "%s.bin.bb", prof_func[i].name);
794
              log ("Deleting temporary file %s %s\n", tmp1,
795
                   remove (tmp1) ? "FAILED" : "OK");
796
            }
797
          break;
798 1244 hpanther
 
799 1748 jeremybenn
          /* profile command */
800
        }
801
      else if (strcmp (tmp1, "p") == 0 || strcmp (tmp1, "profile") == 0)
802
        {
803
          int ntime = 0;
804
          int size = 0;
805
          PRINTF
806
            ("-----------------------------------------------------------------------------\n");
807
          PRINTF
808
            ("|function name       |calls|avg cycles  |old%%| max. f.  | impr. f.| options |\n");
809
          PRINTF
810
            ("|--------------------+-----+------------+----+----------|---------+---------|\n");
811
          for (j = 0; j < prof_nfuncs; j++)
812
            {
813
              int bestcyc = 0, besti = 0;
814
              char tmp[100];
815
              for (i = 0; i < prof_nfuncs; i++)
816
                if (prof_func[i].cum_cycles > bestcyc)
817
                  {
818
                    bestcyc = prof_func[i].cum_cycles;
819
                    besti = i;
820
                  }
821
              i = besti;
822
              PRINTF ("|%-20s|%5li|%12.1f|%3.0f%%| ",
823
                      strstrip (tmp, prof_func[i].name, 20),
824
                      prof_func[i].calls,
825
                      ((double) prof_func[i].cum_cycles / prof_func[i].calls),
826
                      (100. * prof_func[i].cum_cycles / prof_cycles));
827
              if (func[i])
828
                {
829
                  double f = 1.0;
830
                  if (func_v[i])
831
                    {
832
                      int nt = calc_cycles (func[i]);
833
                      int s = calc_size (func[i]);
834
                      f = 1. * func[i]->orig_time / nt;
835
                      ntime += nt;
836
                      size += s;
837
                    }
838
                  else
839
                    ntime += prof_func[i].cum_cycles;
840
                  PRINTF ("%8.1f |%8.1f | %-8s|\n",
841
                          1.f * prof_func[i].cum_cycles /
842
                          func[i]->timings.new_time, f,
843
                          format_func_options (tmp, func[i]));
844
                }
845
              else
846
                {
847
                  PRINTF ("     N/A |     N/A |     N/A |\n");
848
                  ntime += prof_func[i].cum_cycles;
849
                }
850
              prof_func[i].cum_cycles = -prof_func[i].cum_cycles;
851
            }
852
          for (i = 0; i < prof_nfuncs; i++)
853
            prof_func[i].cum_cycles = -prof_func[i].cum_cycles;
854
          PRINTF
855
            ("-----------------------------------------------------------------------------\n");
856
          PRINTF
857
            ("Total %i cycles (was %i), total added gates = %i. Speed factor %.1f\n",
858
             ntime, prof_cycles, size, 1. * prof_cycles / ntime);
859 1244 hpanther
 
860 1748 jeremybenn
          /* debug command */
861
        }
862
      else if (strncmp (tmp1, "d", 1) == 0 || strncmp (tmp1, "debug", 5) == 0)
863
        {
864
          sscanf (tmp1, "%*s %i", &cuc_debug);
865
          if (cuc_debug < 0)
866
            cuc_debug = 0;
867
          if (cuc_debug > 9)
868
            cuc_debug = 9;
869 1244 hpanther
 
870 1748 jeremybenn
          /* generate command */
871
        }
872
      else if (strcmp (tmp1, "g") == 0 || strcmp (tmp1, "generate") == 0)
873
        {
874
          /* check for function dependencies */
875
          for (i = 0; i < prof_nfuncs; i++)
876
            if (func[i])
877
              func[i]->tmp = func_v[i];
878
          for (i = 0; i < prof_nfuncs; i++)
879
            if (func[i])
880
              for (j = 0; j < func[i]->nfdeps; j++)
881
                if (!func[i]->fdeps[j] || !func[i]->fdeps[j]->tmp)
882
                  {
883
                    PRINTF
884
                      ("Function %s must be selected for translation (required by %s)\n",
885
                       prof_func[j].name, prof_func[i].name);
886
                    goto wait_command;
887
                  }
888
          for (i = 0; i < prof_nfuncs; i++)
889
            if (func[i] && func_v[i])
890
              generate_function (func[i], prof_func[i].name, filename_cut);
891
          generate_main (prof_nfuncs, func, filename_cut);
892 1244 hpanther
 
893 1748 jeremybenn
          /* list command */
894
        }
895
      else if (strcmp (tmp1, "l") == 0 || strcmp (tmp1, "list") == 0)
896
        {
897
          /* check for function dependencies */
898
          for (i = 0; i < prof_nfuncs; i++)
899
            if (func_v[i])
900
              {
901
                PRINTF ("%s\n", prof_func[i].name);
902
              }
903 1244 hpanther
 
904 1748 jeremybenn
          /* selectall command */
905
        }
906
      else if (strcmp (tmp1, "sa") == 0 || strcmp (tmp1, "selectall") == 0)
907
        {
908
          int f;
909
          for (f = 0; f < prof_nfuncs; f++)
910
            if (func[f])
911
              {
912
                func_v[f] = 1;
913
                PRINTF ("Function %s selected for translation.\n",
914
                        prof_func[f].name);
915
              }
916 1244 hpanther
 
917 1748 jeremybenn
          /* select command */
918
        }
919
      else if (strncmp (tmp1, "s", 1) == 0
920
               || strncmp (tmp1, "select", 6) == 0)
921
        {
922
          char tmp[50], ch;
923
          int p, o, b, f;
924
          p = sscanf (tmp1, "%*s %s %i%c", tmp, &b, &ch);
925
          if (p < 1)
926
            PRINTF ("Invalid parameters.\n");
927
          else
928
            {
929
              /* Check if we have valid option */
930
              for (f = 0; f < prof_nfuncs; f++)
931
                if (strcmp (prof_func[f].name, tmp) == 0 && func[f])
932
                  break;
933
              if (f < prof_nfuncs)
934
                {
935
                  if (p == 1)
936
                    {
937
                      if (func[f])
938
                        {
939
                          func_v[f] = 1;
940
                          PRINTF ("Function %s selected for translation.\n",
941
                                  prof_func[f].name);
942
                        }
943
                      else
944
                        PRINTF ("Function %s not suitable for translation.\n",
945
                                prof_func[f].name);
946
                    }
947
                  else
948
                    {
949
                      if (!func_v[f])
950
                        PRINTF
951
                          ("Function %s not yet selected for translation.\n",
952
                           prof_func[f].name);
953
                      if (p < 3)
954
                        goto invalid_option;
955
                      for (o = 0;
956
                           option_char[o] != '\0' && option_char[o] != ch;
957
                           o++);
958
                      if (!option_char[o])
959
                        goto invalid_option;
960
                      if (b < 0 || b >= func[f]->num_bb)
961
                        goto invalid_option;
962
                      if (o < 0 || o >= func[f]->bb[b].ntim)
963
                        goto invalid_option;
964
 
965
                      /* select an option */
966
                      func[f]->bb[b].selected_tim = o;
967
                      if (func[f]->bb[b].tim[o].nshared)
968
                        {
969
                          PRINTF ("Option has shared instructions: ");
970
                          print_shared (func[f], func[f]->bb[b].tim[o].shared,
971
                                        func[f]->bb[b].tim[o].nshared);
972
                          PRINTF ("\n");
973
                        }
974
                      goto wait_command;
975
                    invalid_option:
976
                      PRINTF ("Invalid option.\n");
977
                    }
978
                }
979
              else
980
                PRINTF ("Invalid function.\n");
981
            }
982
 
983
          /* unselect command */
984
        }
985
      else if (strncmp (tmp1, "u", 1) == 0
986
               || strncmp (tmp1, "unselect", 8) == 0)
987
        {
988
          char tmp[50], ch;
989
          int p, o, b, f;
990
          p = sscanf (tmp1, "%*s %s %i%c", tmp, &b, &ch);
991
          if (p < 1)
992
            PRINTF ("Invalid parameters.\n");
993
          else
994
            {
995
              /* Check if we have valid option */
996
              for (f = 0; f < prof_nfuncs; f++)
997
                if (strcmp (prof_func[f].name, tmp) == 0 && func[f])
998
                  break;
999
              if (f < prof_nfuncs)
1000
                {
1001
                  if (p == 1)
1002
                    {
1003
                      if (func[f])
1004
                        {
1005
                          func_v[f] = 0;
1006
                          PRINTF ("Function %s unselected for translation.\n",
1007
                                  prof_func[f].name);
1008
                        }
1009
                      else
1010
                        PRINTF ("Function %s not suitable for translation.\n",
1011
                                prof_func[f].name);
1012
                    }
1013
                  else
1014
                    {
1015
                      if (p < 3)
1016
                        goto invalid_option;
1017
                      for (o = 0;
1018
                           option_char[o] != '\0' && option_char[o] != ch;
1019
                           o++);
1020
                      if (!option_char[o])
1021
                        goto invalid_option;
1022
                      if (b < 0 || b >= func[f]->num_bb)
1023
                        goto invalid_option;
1024
                      if (o < 0 || o >= func[f]->bb[b].ntim)
1025
                        goto invalid_option;
1026
 
1027
                      /* select an option */
1028
                      func[f]->bb[b].selected_tim = -1;
1029
                    }
1030
                }
1031
              else
1032
                PRINTF ("Invalid function.\n");
1033
            }
1034
 
1035
          /* options command */
1036
        }
1037
      else if (strcmp (tmp1, "o") == 0 || strcmp (tmp1, "options") == 0)
1038
        {
1039
          int any = 0;
1040
          PRINTF ("Available options:\n");
1041
          for (i = 0; i < prof_nfuncs; i++)
1042
            if (func[i])
1043
              {
1044
                options_cmd (i, func[i]);
1045
                any = 1;
1046
              }
1047
          if (any)
1048
            PRINTF
1049
              ("-----------------------------------------------------------------------------\n");
1050
          else
1051
            PRINTF ("Sorry. No available options.\n");
1052
 
1053
          /* Ignore empty string */
1054
        }
1055
      else if (strcmp (tmp1, "") == 0)
1056
        {
1057
 
1058
          /* help command */
1059
        }
1060
      else
1061
        {
1062
          if (strcmp (tmp1, "h") != 0 && strcmp (tmp1, "help") != 0)
1063
            PRINTF ("Unknown command.\n");
1064
          PRINTF ("OpenRISC Custom Unit Compiler command prompt\n");
1065
          PRINTF ("Available commands:\n");
1066
          PRINTF ("  h | help                   displays this help\n");
1067
          PRINTF ("  q | quit                   returns to or1ksim prompt\n");
1068
          PRINTF
1069
            ("  p | profile                displays function profiling\n");
1070
          PRINTF ("  d | debug #                sets debug level (0-9)\n");
1071
          PRINTF
1072
            ("  o | options                displays available options\n");
1073
          PRINTF
1074
            ("  s | select func [option]   selects an option/function\n");
1075
          PRINTF
1076
            ("  u | unselect func [option] unselects an option/function\n");
1077
          PRINTF ("  g | generate               generates verilog file\n");
1078
          PRINTF
1079
            ("  l | list                   displays selected functions\n");
1080
        }
1081 1244 hpanther
    }
1082
 
1083
  /* Dispose memory */
1084 1748 jeremybenn
  for (i = 0; i < prof_nfuncs - 1; i++)
1085
    if (func[i])
1086
      free_func (func[i]);
1087 1244 hpanther
 
1088
  fclose (flog);
1089
}
1090
 
1091 1358 nogj
/*----------------------------------------------------[ CUC Configuration ]---*/
1092 1748 jeremybenn
 
1093
/*---------------------------------------------------------------------------*/
1094
/*!Set the memory order
1095
 
1096
   Value must be one of none, weak, strong or exact. Invalid values are
1097
   ignored with a warning.
1098
 
1099
   @param[in] val  The value to use
1100
   @param[in] dat  The config data structure (not used here)                 */
1101
/*---------------------------------------------------------------------------*/
1102
static void
1103
cuc_memory_order (union param_val val, void *dat)
1104 1358 nogj
{
1105 1748 jeremybenn
  if (strcasecmp (val.str_val, "none") == 0)
1106
    {
1107
      config.cuc.memory_order = MO_NONE;
1108
    }
1109
  else if (strcasecmp (val.str_val, "weak") == 0)
1110
    {
1111
      config.cuc.memory_order = MO_WEAK;
1112
    }
1113
  else if (strcasecmp (val.str_val, "strong") == 0)
1114
    {
1115
      config.cuc.memory_order = MO_STRONG;
1116
    }
1117
  else if (strcasecmp (val.str_val, "exact") == 0)
1118
    {
1119
      config.cuc.memory_order = MO_EXACT;
1120
    }
1121
  else
1122
    {
1123
      fprintf (stderr, "Warning: CUC memory order invalid. Ignored");
1124
    }
1125
}                               /* cuc_memory_order() */
1126
 
1127
 
1128
static void
1129
cuc_calling_conv (union param_val val, void *dat)
1130
{
1131 1358 nogj
  config.cuc.calling_convention = val.int_val;
1132
}
1133
 
1134 1748 jeremybenn
static void
1135
cuc_enable_bursts (union param_val val, void *dat)
1136 1358 nogj
{
1137
  config.cuc.enable_bursts = val.int_val;
1138
}
1139
 
1140 1748 jeremybenn
static void
1141
cuc_no_multicycle (union param_val val, void *dat)
1142 1358 nogj
{
1143
  config.cuc.no_multicycle = val.int_val;
1144
}
1145
 
1146
 
1147 1748 jeremybenn
/*---------------------------------------------------------------------------*/
1148
/*!Set the timings file
1149
 
1150
   Free any existing string.
1151
 
1152
   @param[in] val  The value to use
1153
   @param[in] dat  The config data structure (not used here)                 */
1154
/*---------------------------------------------------------------------------*/
1155
static void
1156
cuc_timings_fn (union param_val val, void *dat)
1157 1358 nogj
{
1158 1748 jeremybenn
  if (NULL != config.cuc.timings_fn)
1159
    {
1160
      free (config.cuc.timings_fn);
1161
    }
1162 1358 nogj
 
1163 1748 jeremybenn
  config.cuc.timings_fn = strdup (val.str_val);
1164
 
1165
}                               /* cuc_timings_fn() */
1166
 
1167
 
1168
void
1169
reg_cuc_sec ()
1170 1358 nogj
{
1171 1748 jeremybenn
  struct config_section *sec = reg_config_sec ("cuc", NULL, NULL);
1172 1358 nogj
 
1173 1748 jeremybenn
  reg_config_param (sec, "memory_order", paramt_word, cuc_memory_order);
1174
  reg_config_param (sec, "calling_convention", paramt_int, cuc_calling_conv);
1175
  reg_config_param (sec, "enable_bursts", paramt_int, cuc_enable_bursts);
1176
  reg_config_param (sec, "no_multicycle", paramt_int, cuc_no_multicycle);
1177
  reg_config_param (sec, "timings_file", paramt_str, cuc_timings_fn);
1178
  reg_config_param (sec, "timings_fn", paramt_str, cuc_timings_fn);
1179 1358 nogj
}

powered by: WebSVN 2.1.0

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