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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc1/] [or1ksim/] [cuc/] [cuc.c] - Diff between revs 883 and 897

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 883 Rev 897
Line 26... Line 26...
#include "sim-config.h"
#include "sim-config.h"
#include "cuc.h"
#include "cuc.h"
#include "insn.h"
#include "insn.h"
#include "profiler.h"
#include "profiler.h"
#include "opcode/or32.h"
#include "opcode/or32.h"
 
#include "parse.h"
 
 
FILE *flog;
FILE *flog;
int cuc_debug = 0;
int cuc_debug = 0;
 
 
/* Last used registers by software convention */
/* Last used registers by software convention */
Line 38... Line 39...
  1, 1, 0, 1, 0, 1, 0, 1,
  1, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1,
  0, 1, 0, 1, 0, 1, 0, 1,
  1, 1};
  1, 1};
 
 
/* Prints out instructions */
 
void print_insns (cuc_insn *insn, int ninsn, int verbose)
 
{
 
  int i, j;
 
  for (i = 0; i < ninsn; i++) {
 
    dep_list *l = insn[i].dep;
 
    printf ("%4x%c %-4s ", i, insn[i].index >= 0 ? ':' : '?', cuc_insn_name (&insn[i]));
 
    if (verbose) {
 
      printf ("%-20s insn = %08x, index = %i, type = %04x ",
 
                      insn[i].disasm, insn[i].insn, insn[i].index, insn[i].type);
 
    } else printf ("type = %04x ", insn[i].type);
 
    for (j = 0; j < MAX_OPERANDS; j++) {
 
      if (insn[i].opt[j] & OPT_DEST) printf ("*");
 
      switch (insn[i].opt[j] & ~OPT_DEST) {
 
        case OPT_NONE: break;
 
        case OPT_CONST: printf ("0x%08x, ", insn[i].op[j]); break;
 
        case OPT_JUMP: printf ("J%x ", insn[i].op[j]); break;
 
        case OPT_REGISTER: printf ("r%i, ", insn[i].op[j]); break;
 
        case OPT_REF: printf ("[%x.%x], ", REF_BB(insn[i].op[j]), REF_I(insn[i].op[j])); break;
 
        case OPT_BB: printf ("BB%x, ", insn[i].op[j]); break;
 
        case OPT_LRBB: printf ("LRBB, "); break;
 
        default:
 
          fprintf (stderr, "Invalid operand type %s(%x.%x) = %x\n",
 
                         cuc_insn_name (&insn[i]), i, j, insn[i].opt[j]);
 
          assert (0);
 
      }
 
    }
 
    if (l) {
 
      printf ("\n\tdep:");
 
      while (l) {
 
        printf (" [%x.%x],", REF_BB (l->ref), REF_I (l->ref));
 
        l = l->next;
 
      }
 
    }
 
    printf ("\n");
 
  }
 
}
 
 
 
void add_dep (dep_list **list, int dep)
 
{
 
  dep_list *ndep;
 
  dep_list **tmp = list;
 
 
 
  while (*tmp) {
 
    if ((*tmp)->ref == dep) return; /* already there */
 
    tmp = &((*tmp)->next);
 
  }
 
  ndep = (dep_list *)malloc (sizeof (dep_list));
 
  ndep->ref = dep;
 
  ndep->next = NULL;
 
  *tmp = ndep;
 
}
 
 
 
void dispose_list (dep_list **list)
 
{
 
  while (*list) {
 
    dep_list *tmp = *list;
 
    *list = tmp->next;
 
    free (tmp);
 
  }
 
}
 
 
 
void add_data_dep (cuc_func *f)
 
{
 
  int b, i, j;
 
  dep_list *tmp;
 
  for (b = 0; b < f->num_bb; b++) {
 
    cuc_insn *insn = f->bb[b].insn;
 
    for (i = 0; i < f->bb[b].ninsn; i++)
 
      for (j = 0; j < MAX_OPERANDS; j++) {
 
        fflush (stdout);
 
        if (insn[i].opt[j] & OPT_REF) {
 
          /* Copy list from predecessor */
 
          dep_list *l = f->INSN(insn[i].op[j]).dep;
 
          while (l) {
 
            add_dep (&insn[i].dep, l->ref);
 
            l = l->next;
 
          }
 
          /* add predecessor */
 
          add_dep (&insn[i].dep, insn[i].op[j]);
 
        }
 
      }
 
  }
 
}
 
 
 
/* returns nonzero, if instruction was simplified */
 
int apply_edge_condition (cuc_insn *ii)
 
{
 
  unsigned int c = ii->op[2];
 
 
 
  if (ii->index == II_AND) {
 
    if (ii->opt[2] & OPT_CONST && c == 0) {
 
      change_insn_type (ii, II_ADD);
 
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
 
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
 
      return 1;
 
    }
 
  } else if (ii->index == II_OR) {
 
    if (ii->opt[2] & OPT_CONST && c == 0xffffffff) {
 
      change_insn_type (ii, II_ADD);
 
      ii->op[1] = c; ii->opt[1] = OPT_CONST;
 
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
 
      return 1;
 
    }
 
  } else if (ii->index == II_SUB) {
 
    if (ii->opt[1] == ii->opt[2] && ii->op[1] == ii->op[2]) {
 
      change_insn_type (ii, II_ADD);
 
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
 
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
 
      return 1;
 
    }
 
  } else if (ii->index == II_MUL) {
 
    if (ii->opt[2] & OPT_CONST && c == 0) {
 
      change_insn_type (ii, II_ADD);
 
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
 
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
 
      return 1;
 
    } else
 
    if (ii->opt[2] & OPT_CONST && c == 1) {
 
      change_insn_type (ii, II_ADD);
 
      ii->op[1] = c; ii->opt[1] = OPT_CONST;
 
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
 
      return 1;
 
    } else
 
    if (ii->opt[2] & OPT_CONST && c == 0xffffffff) {
 
      change_insn_type (ii, II_SUB);
 
      ii->op[2] = ii->op[1]; ii->opt[2] = ii->opt[1];
 
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
 
      return 1;
 
    }
 
  } else if (ii->index == II_SRL) {
 
    if (ii->opt[2] & OPT_CONST && c == 0) {
 
      change_insn_type (ii, II_ADD);
 
      ii->op[1] = c; ii->opt[1] = OPT_CONST;
 
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
 
      return 1;
 
    } else if (ii->opt[2] & OPT_CONST && c >= 32) {
 
      change_insn_type (ii, II_ADD);
 
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
 
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
 
      return 1;
 
    }
 
  } else if (ii->index == II_SLL) {
 
    if (ii->opt[2] & OPT_CONST && c == 0) {
 
      change_insn_type (ii, II_ADD);
 
      ii->op[1] = c; ii->opt[1] = OPT_CONST;
 
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
 
      return 1;
 
    } else if (ii->opt[2] & OPT_CONST && c >= 32) {
 
      change_insn_type (ii, II_ADD);
 
      ii->op[1] = 0; ii->opt[1] = OPT_CONST;
 
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
 
      return 1;
 
    }
 
  } else if (ii->index == II_SRA) {
 
    if (ii->opt[2] & OPT_CONST && c == 0) {
 
      change_insn_type (ii, II_ADD);
 
      ii->op[1] = c; ii->opt[1] = OPT_CONST;
 
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
 
      return 1;
 
    }
 
  } else if (ii->index == II_CMOV) {
 
    if (ii->opt[1] == ii->opt[2] && ii->op[1] == ii->op[2]) {
 
      change_insn_type (ii, II_ADD);
 
      ii->op[2] = 0; ii->opt[2] = OPT_CONST;
 
      ii->opt[3] = OPT_NONE;
 
      return 1;
 
    }
 
  }
 
  return 0;
 
}
 
 
 
/* Optimizes dataflow tree */
 
void optimize_tree (cuc_func *f)
 
{
 
  int b, i, j;
 
  int modified;
 
 
 
  do {
 
    modified = 0;
 
    for (b = 0; b < f->num_bb; b++) if (!(f->bb[b].type & BB_DEAD)) {
 
      for (i = 0; i < f->bb[b].ninsn; i++) {
 
        cuc_insn *ii = &f->bb[b].insn[i];
 
        /* We tend to have the third parameter const if instruction is cumutative */
 
        if ((ii->opt[1] & OPT_CONST) && !(ii->opt[2] & OPT_CONST)
 
            && known[ii->index].comutative) {
 
          unsigned long t = ii->opt[1];
 
          ii->opt[1] = ii->opt[2];
 
          ii->opt[2] = t;
 
          t = ii->op[1];
 
          ii->op[1] = ii->op[2];
 
          ii->op[2] = t;
 
          modified = 1; cucdebug (2, "%08x:<>\n", REF(b, i));
 
        }
 
 
 
        /* Try to do the promotion */
 
        /* We have two consecutive expressions, containing constants,
 
         * if previous is a simple expression we can handle it simply: */
 
        for (j = 0; j < MAX_OPERANDS; j++)
 
          if (ii->opt[j] & OPT_REF) {
 
            cuc_insn *t = &f->INSN(ii->op[j]);
 
            if (f->INSN(ii->op[j]).index == II_ADD
 
             && f->INSN(ii->op[j]).opt[2] & OPT_CONST
 
             && f->INSN(ii->op[j]).op[2] == 0
 
             && !(ii->type & IT_MEMORY && t->type & IT_MEMADD)
 
             && !(ii->type & IT_BRANCH) && !(t->type & IT_COND)) {
 
            /* do not promote through add-mem, and branches */
 
              modified = 1; cucdebug (2, "%8x:promote%i %8x %8x\n", REF (b, i), j, ii->op[j], t->op[1]);
 
              ii->op[j] = t->op[1]; ii->opt[j] = t->opt[1];
 
            }
 
          }
 
 
 
        /* In case of x = cmov x, y; or x = cmov y, x; we have
 
           asynchroneous loop -> remove it */
 
        if (ii->index == II_CMOV) {
 
          int f = 0;
 
          if ((ii->opt[1] & OPT_REF) && ii->op[1] == REF (b, i)) f = 1;
 
          if ((ii->opt[2] & OPT_REF) && ii->op[2] == REF (b, i)) f = 2;
 
          if (ii->opt[1] == ii->opt[2] && ii->op[1] == ii->op[2]) f = 2;
 
          if (f) {
 
            change_insn_type (ii, II_ADD);
 
            cucdebug (2, "%8x:cmov     %i\n", REF(b, i), f);
 
            ii->opt[f] = OPT_CONST;
 
            ii->op[f] = 0;
 
            ii->opt[3] = OPT_NONE;
 
            modified = 1;
 
            continue;
 
          }
 
        }
 
 
 
        /* Do nothing to volatile instructions */
 
        if (ii->type & IT_VOLATILE) continue;
 
 
 
        /* Check whether we can simplify the instruction */
 
        if (apply_edge_condition (ii)) {
 
          modified = 1;
 
          continue;
 
        }
 
        /* We cannot do anything more if at least one is not constant */
 
        if (!(ii->opt[2] & OPT_CONST)) continue;
 
 
 
        if (ii->opt[1] & OPT_CONST) { /* We have constant expression */
 
          unsigned long value;
 
          int ok = 1;
 
          /* Was constant expression already? */
 
          if (ii->index == II_ADD && !ii->op[2]) continue;
 
 
 
          if (ii->index == II_ADD) value = ii->op[1] + ii->op[2];
 
          else if (ii->index == II_SUB) value = ii->op[1] - ii->op[2];
 
          else if (ii->index == II_SLL) value = ii->op[1] << ii->op[2];
 
          else if (ii->index == II_SRL) value = ii->op[1] >> ii->op[2];
 
          else if (ii->index == II_MUL) value = ii->op[1] * ii->op[2];
 
          else if (ii->index == II_OR) value = ii->op[1] | ii->op[2];
 
          else if (ii->index == II_XOR) value = ii->op[1] ^ ii->op[2];
 
          else if (ii->index == II_AND) value = ii->op[1] & ii->op[2];
 
          else ok = 0;
 
          if (ok) {
 
            change_insn_type (ii, II_ADD);
 
            ii->op[0] = -1; ii->opt[0] = OPT_REGISTER | OPT_DEST;
 
            ii->op[1] = value; ii->opt[1] = OPT_CONST;
 
            ii->op[2] = 0; ii->opt[2] = OPT_CONST;
 
            modified = 1; cucdebug (2, "%8x:const\n", REF (b, i));
 
          }
 
        } else if (ii->opt[1] & OPT_REF) {
 
          cuc_insn *prev = &f->INSN(ii->op[1]);
 
          /* Is this just a link? */
 
          if (ii->index == II_ADD
 
           && !(ii->type & IT_MEMADD) && ii->op[2] == 0) {
 
            int b1, i1, j1;
 
            cucdebug (2, "%8x:link      %8x: ", REF(b, i), ii->op[1]);
 
            for (b1 = 0; b1 < f->num_bb; b1++) if (!(f->bb[b1].type & BB_DEAD))
 
              for (i1 = 0; i1 < f->bb[b1].ninsn; i1++)
 
                for (j1 = 0; j1 < MAX_OPERANDS; j1++)
 
                  if ((f->bb[b1].insn[i1].opt[j1] & OPT_REF)
 
                   && f->bb[b1].insn[i1].op[j1] == REF(b, i)) {
 
                    cucdebug (2, "%x ", REF (b1, i1));
 
                    f->bb[b1].insn[i1].op[j1] = ii->op[1];
 
                  }
 
            cucdebug (2, "\n");
 
            change_insn_type (ii, II_NOP);
 
          } else if (prev->opt[2] & OPT_CONST) {
 
            /* Handle some common cases */
 
            /* add - add joining */
 
            if (ii->index == II_ADD && prev->index == II_ADD) {
 
              ii->op[1] = prev->op[1]; ii->opt[1] = prev->opt[1];
 
              ii->op[2] += prev->op[2];
 
              modified = 1; cucdebug (2, "%8x: add-add\n", REF(b, i));
 
            } else /* add - sub joining */
 
            if (ii->index == II_ADD && prev->index == II_SUB) {
 
              change_insn_type (&insn[i], II_SUB);
 
              ii->op[1] = prev->op[1]; ii->opt[1] = prev->opt[1];
 
              ii->op[2] += prev->op[2];
 
              modified = 1; cucdebug (2, "%8x: add-sub\n", REF(b, i));
 
            } else /* sub - add joining */
 
            if (ii->index == II_SUB && prev->index == II_ADD) {
 
              ii->op[1] = prev->op[1]; ii->opt[1] = prev->opt[1];
 
              ii->op[2] += prev->op[2];
 
              modified = 1; cucdebug (2, "%8x: sub-add\n", REF(b, i));
 
            }
 
          }
 
        }
 
      }
 
    }
 
  } while (modified);
 
}
 
 
 
/* Remove nop instructions */
 
void remove_nops (cuc_func *f)
 
{
 
  int b;
 
  for (b = 0; b < f->num_bb; b++) {
 
    int c, d = 0, i, j;
 
    cuc_insn *insn = f->bb[b].insn;
 
    for (i = 0; i < f->bb[b].ninsn; i++)
 
      if (insn[i].index != II_NOP) {
 
        reloc [i] = d;
 
        insn[d++] = insn[i];
 
      } else {
 
        reloc[i] = d; /* For jumps only */
 
      }
 
    f->bb[b].ninsn = d;
 
 
 
    /* Relocate references from all basic blocks */
 
    for (c = 0; c < f->num_bb; c++)
 
      for (i = 0; i < f->bb[c].ninsn; i++) {
 
        dep_list *d = f->bb[c].insn[i].dep;
 
        for (j = 0; j < MAX_OPERANDS; j++)
 
          if ((f->bb[c].insn[i].opt[j] & OPT_REF)
 
            && REF_BB(f->bb[c].insn[i].op[j]) == b)
 
            f->bb[c].insn[i].op[j] = REF (b, reloc[REF_I (f->bb[c].insn[i].op[j])]);
 
 
 
        while (d) {
 
          if (REF_BB(d->ref) == b) d->ref = REF (b, reloc[REF_I (d->ref)]);
 
          d = d->next;
 
        }
 
      }
 
  }
 
}
 
 
 
/* Remove unused assignments */
 
void remove_dead (cuc_func *f)
 
{
 
  int b, i, j;
 
  for (b = 0; b < f->num_bb; b++)
 
    for (i = 0; i < f->bb[b].ninsn; i++)
 
      if (!(f->bb[b].insn[i].type & (IT_VOLATILE | IT_OUTPUT)))
 
        f->bb[b].insn[i].type |= IT_UNUSED;
 
 
 
  for (b = 0; b < f->num_bb; b++) {
 
    for (i = 0; i < f->bb[b].ninsn; i++)
 
      for (j = 0; j < MAX_OPERANDS; j++)
 
        if (f->bb[b].insn[i].opt[j] & OPT_REF) {
 
          f->INSN(f->bb[b].insn[i].op[j]).type &= ~IT_UNUSED;
 
        }
 
  }
 
 
 
  for (b = 0; b < f->num_bb; b++)
 
    for (i = 0; i < f->bb[b].ninsn; i++)
 
      if (f->bb[b].insn[i].type & IT_UNUSED) {
 
        change_insn_type (&f->bb[b].insn[i], II_NOP);
 
      }
 
 
 
  remove_nops (f);
 
}
 
 
 
/* Removes trivial register assignments */
 
void remove_trivial_regs (cuc_func *f)
 
{
 
  int b, i;
 
  for (i = 0; i < MAX_REGS; i++) f->saved_regs[i] = call_saved[i];
 
 
 
  for (b = 0; b < f->num_bb; b++) {
 
    cuc_insn *insn = f->bb[b].insn;
 
    for (i = 0; i < f->bb[b].ninsn; i++) {
 
      if (insn[i].index == II_ADD
 
        && insn[i].opt[0] & OPT_REGISTER
 
        && insn[i].opt[1] & OPT_REGISTER && insn[i].op[0] == insn[i].op[1]
 
        && insn[i].opt[2] & OPT_CONST && insn[i].op[2] == 0) {
 
          if (insn[i].type & IT_OUTPUT) f->saved_regs[insn[i].op[0]] = 1;
 
          change_insn_type (&insn[i], II_NOP);
 
        }
 
    }
 
  }
 
  if (cuc_debug >= 2) {
 
    printf ("saved regs ");
 
    for (i = 0; i < MAX_REGS; i++) printf ("%i:%i ", i, f->saved_regs[i]);
 
    printf ("\n");
 
  }
 
  remove_nops (f);
 
}
 
 
 
/* Determine inputs and outputs */
 
void set_io (cuc_func *f)
 
{
 
  int b, i, j;
 
  /* Determine register usage */
 
  for (i = 0; i < MAX_REGS; i++) {
 
    f->lur[i] = -1;
 
    f->used_regs[i] = 0;
 
  }
 
  for (b = 0; b < f->num_bb; b++) {
 
    for (i = 0; i < f->bb[b].ninsn; i++)
 
      for (j = 0; j < MAX_OPERANDS; j++)
 
        if (f->bb[b].insn[i].opt[j] & OPT_REGISTER && f->bb[b].insn[i].op[j] >= 0)
 
          if (f->bb[b].insn[i].opt[j] & OPT_DEST) f->lur[f->bb[b].insn[i].op[j]] = REF (b, i);
 
          else f->used_regs[f->bb[b].insn[i].op[j]] = 1;
 
  }
 
}
 
 
 
/* relocate all accesses inside of BB b to back/fwd */
 
static void relocate_bb (cuc_bb *bb, int b, int back, int fwd)
 
{
 
  int i, j;
 
  for (i = 0; i < bb->ninsn; i++)
 
    for (j = 0; j < MAX_OPERANDS; j++)
 
      if (bb->insn[i].opt[j] & OPT_REF
 
       && REF_BB (bb->insn[i].op[j]) == b) {
 
        int t = REF_I (bb->insn[i].op[j]);
 
        if (t < i) bb->insn[i].op[j] = REF (back, t);
 
        else bb->insn[i].op[j] = REF (fwd, t);
 
      }
 
}
 
 
 
/* split the BB, based on the group numbers in .tmp */
 
void expand_bb (cuc_func *f, int b)
 
{
 
  int n = f->num_bb;
 
  int mg = 0;
 
  int b1, i, j;
 
 
 
  for (i = 0; i < f->bb[b].ninsn; i++)
 
    if (f->bb[b].insn[i].tmp > mg) mg = f->bb[b].insn[i].tmp;
 
 
 
  /* Create copies */
 
  for (b1 = 1; b1 <= mg; b1++) {
 
    assert (f->num_bb < MAX_BB);
 
    cpy_bb (&f->bb[f->num_bb], &f->bb[b]);
 
    f->num_bb++;
 
  }
 
 
 
  /* Relocate */
 
  for (b1 = 0; b1 < f->num_bb; b1++)
 
    for (i = 0; i < f->bb[b1].ninsn; i++) {
 
      dep_list *d = f->bb[b1].insn[i].dep;
 
      for (j = 0; j < MAX_OPERANDS; j++)
 
        if (f->bb[b1].insn[i].opt[j] & OPT_REF) {
 
          int t = f->bb[b1].insn[i].op[j];
 
          if (REF_BB(t) == b && f->INSN(t).tmp != 0)
 
            f->bb[b1].insn[i].op[j] = REF (n + f->INSN(t).tmp - 1, REF_I(t));
 
        }
 
      while (d) {
 
        if (REF_BB (d->ref) == b && f->INSN(d->ref).tmp != 0)
 
          d->ref = REF (n + f->INSN(d->ref).tmp - 1, REF_I(d->ref));
 
        d = d->next;
 
      }
 
    }
 
 
 
  /* Delete unused instructions */
 
  for (j = 0; j <= mg; j++) {
 
    if (j == 0) b1 = b;
 
    else b1 = n + j - 1;
 
    for (i = 0; i < f->bb[b1].ninsn; i++) {
 
      if (f->bb[b1].insn[i].tmp != j)
 
        change_insn_type (&f->bb[b1].insn[i], II_NOP);
 
      f->bb[b1].insn[i].tmp = 0;
 
    }
 
    if (j < mg) {
 
      f->bb[b1].next[0] = n + j;
 
      f->bb[b1].next[1] = -1;
 
      f->bb[n + j].prev[0] = b1;
 
      f->bb[n + j].prev[1] = -1;
 
    } else {
 
      i = f->bb[b1].next[0];
 
      f->bb[n + j].prev[0] = j == 1 ? b : b1 - 1;
 
      f->bb[n + j].prev[1] = -1;
 
      if (i >= 0) {
 
        if (f->bb[i].prev[0] == b) f->bb[i].prev[0] = b1;
 
        if (f->bb[i].prev[1] == b) f->bb[i].prev[1] = b1;
 
      }
 
      i = f->bb[b1].next[1];
 
      if (i >= 0) {
 
        if (f->bb[i].prev[0] == b) f->bb[i].prev[0] = b1;
 
        if (f->bb[i].prev[1] == b) f->bb[i].prev[1] = b1;
 
      }
 
    }
 
  }
 
}
 
 
 
/* Latch outputs in loops */
 
void add_latches (cuc_func *f)
 
{
 
  int b, i, j;
 
 
 
  //print_cuc_bb (f, "ADD_LATCHES a");
 
  /* Cuts the tree and marks registers */
 
  mark_cut (f);
 
 
 
  /* Split BBs with more than one group */
 
  for (b = 0; b < f->num_bb; b++) expand_bb (f, b);
 
  remove_nops (f);
 
  //print_cuc_bb (f, "ADD_LATCHES 0");
 
 
 
  /* Convert accesses in BB_INLOOP type block to latched */
 
  for (b = 0; b < f->num_bb; b++) {
 
    int j;
 
    for (i = 0; i < f->bb[b].ninsn; i++)
 
      for (j = 0; j < MAX_OPERANDS; j++) if (f->bb[b].insn[i].opt[j] == OPT_REF) {
 
        int t = f->bb[b].insn[i].op[j];
 
        /* If we are pointing to a INLOOP block from outside, or forward
 
           (= previous loop iteration) we must register that data */
 
        if ((f->bb[REF_BB(t)].type & BB_INLOOP || no_multicycle)
 
         && !(f->INSN(t).type & (IT_BRANCH | IT_COND))
 
         && (REF_BB(t) != b || REF_I(t) >= i)) {
 
          f->INSN(t).type |= IT_LATCHED;
 
        }
 
      }
 
  }
 
  //print_cuc_bb (f, "ADD_LATCHES 1");
 
 
 
  /* Add latches at the end of blocks as needed */
 
  for (b = 0; b < f->num_bb; b++) {
 
    int nreg = 0;
 
    cuc_insn *insn;
 
    for (i = 0; i < f->bb[b].ninsn; i++)
 
      if (f->bb[b].insn[i].type & IT_LATCHED) nreg++;
 
    if (nreg) {
 
      insn = (cuc_insn *) malloc (sizeof (cuc_insn) * (f->bb[b].ninsn + nreg));
 
      j = 0;
 
      for (i = 0; i < f->bb[b].ninsn; i++) {
 
        insn[i] = f->bb[b].insn[i];
 
        if (insn[i].type & IT_LATCHED) {
 
          cuc_insn *ii = &insn[f->bb[b].ninsn + j++];
 
          change_insn_type (ii, II_REG);
 
          ii->op[0] = -1; ii->opt[0] = OPT_DEST | OPT_REGISTER;
 
          ii->op[1] = REF (b, i); ii->opt[1] = OPT_REF;
 
          ii->opt[2] = ii->opt[3] = OPT_NONE;
 
          ii->dep = NULL;
 
          ii->type = IT_VOLATILE;
 
          sprintf (ii->disasm, "reg %i_%i", b, i);
 
        }
 
      }
 
      f->bb[b].ninsn += nreg;
 
      free (f->bb[b].insn);
 
      f->bb[b].insn = insn;
 
    }
 
  }
 
  //print_cuc_bb (f, "ADD_LATCHES 2");
 
 
 
  /* Repair references */
 
  for (b = 0; b < f->num_bb; b++)
 
    for (i = 0; i < f->bb[b].ninsn; i++)
 
      for (j = 0; j < MAX_OPERANDS; j++)
 
        /* If destination instruction is latched, use register instead */
 
        if (f->bb[b].insn[i].opt[j] == OPT_REF
 
         && f->INSN(f->bb[b].insn[i].op[j]).type & IT_LATCHED) {
 
          int b1, i1;
 
          b1 = REF_BB (f->bb[b].insn[i].op[j]);
 
          //cucdebug (2, "%i.%i.%i %x\n", b, i, j, f->bb[b].insn[i].op[j]);
 
          if (b1 != b || REF_I(f->bb[b].insn[i].op[j]) >= i) {
 
            for (i1 = f->bb[b1].ninsn - 1; i1 >= 0; i1--) {
 
              assert (f->bb[b1].insn[i1].index == II_REG);
 
              if (f->bb[b1].insn[i1].op[1] == f->bb[b].insn[i].op[j]) {
 
                f->bb[b].insn[i].op[j] = REF (b1, i1);
 
                break;
 
              }
 
            }
 
          }
 
        }
 
}
 
 
 
cuc_timings *preunroll_bb (char *bb_filename, cuc_func *f, cuc_timings *timings, int b, int i, int j)
cuc_timings *preunroll_bb (char *bb_filename, cuc_func *f, cuc_timings *timings, int b, int i, int j)
{
{
  cuc_func *func;
  cuc_func *func;
  cucdebug (2, "BB%i unroll %i times preroll %i times\n", b, j, i);
  cucdebug (2, "BB%i unroll %i times preroll %i times\n", b, j, i);
  func = preunroll_loop (f, b, i, j, bb_filename);
  func = preunroll_loop (f, b, i, j, bb_filename);
Line 638... Line 69...
  remove_trivial_regs (func);
  remove_trivial_regs (func);
  if (cuc_debug >= 2) print_cuc_bb (func, "AFTER_TRIVIAL");
  if (cuc_debug >= 2) print_cuc_bb (func, "AFTER_TRIVIAL");
  add_latches (func);
  add_latches (func);
  if (cuc_debug >= 1) print_cuc_bb (func, "AFTER_LATCHES");
  if (cuc_debug >= 1) print_cuc_bb (func, "AFTER_LATCHES");
  set_io (func);
  set_io (func);
  add_memory_dep (func, memory_order);
  add_memory_dep (func, func->memory_order);
  if (cuc_debug >= 7) print_cuc_bb (func, "AFTER_MEMORY_DEP");
  if (cuc_debug >= 7) print_cuc_bb (func, "AFTER_MEMORY_DEP");
  add_data_dep (func);
  add_data_dep (func);
  if (cuc_debug >= 8) print_cuc_bb (func, "AFTER_DATA_DEP");
  if (cuc_debug >= 8) print_cuc_bb (func, "AFTER_DATA_DEP");
  schedule_memory (func, memory_order);
  schedule_memory (func, func->memory_order);
  if (cuc_debug >= 7) print_cuc_bb (func, "AFTER_SCHEDULE_MEM");
  if (cuc_debug >= 7) print_cuc_bb (func, "AFTER_SCHEDULE_MEM");
 
 
  analyse_timings (func, timings);
  analyse_timings (func, timings);
  cucdebug (2, "new_time = %i, old_time = %i, size = %f\n",
  cucdebug (2, "new_time = %i, old_time = %i, size = %f\n",
           timings->new_time, func->orig_time, timings->size);
           timings->new_time, func->orig_time, timings->size);
Line 667... Line 98...
  else if (a->new_time > b->new_time) return 1;
  else if (a->new_time > b->new_time) return 1;
  else return 0;
  else return 0;
}
}
 
 
cuc_func *analyse_function (char *module_name, long orig_time,
cuc_func *analyse_function (char *module_name, long orig_time,
                unsigned long start_addr, unsigned long end_addr)
                unsigned long start_addr, unsigned long end_addr,
 
                int memory_order)
{
{
  cuc_timings timings;
  cuc_timings timings;
  cuc_func *func = (cuc_func *) malloc (sizeof (cuc_func));
  cuc_func *func = (cuc_func *) malloc (sizeof (cuc_func));
  cuc_func *saved;
  cuc_func *saved;
  int b, i, j;
  int b, i, j;
Line 679... Line 111...
  char tmp2[256];
  char tmp2[256];
 
 
  func->orig_time = orig_time;
  func->orig_time = orig_time;
  func->start_addr = start_addr;
  func->start_addr = start_addr;
  func->end_addr = end_addr;
  func->end_addr = end_addr;
 
  func->memory_order = memory_order;
 
 
  sprintf (tmp1, "%s.bin", module_name);
  sprintf (tmp1, "%s.bin", module_name);
  cucdebug (2, "Loading %s.bin\n", module_name);
  cucdebug (2, "Loading %s.bin\n", module_name);
  cuc_load (tmp1);
  if (cuc_load (tmp1)) {
 
    free (func);
 
    return NULL;
 
  }
 
 
  log ("Detecting basic blocks\n");
  log ("Detecting basic blocks\n");
  detect_bb (func);
  detect_bb (func);
  if (cuc_debug >= 2) print_cuc_insns ("WITH_BB_LIMITS", 0);
  if (cuc_debug >= 2) print_cuc_insns ("WITH_BB_LIMITS", 0);
 
 
  //sprintf (tmp1, "%s.bin.mp", module_name);
  //sprintf (tmp1, "%s.bin.mp", module_name);
  sprintf (tmp2, "%s.bin.bb", module_name);
  sprintf (tmp2, "%s.bin.bb", module_name);
  generate_bb_seq (func, config.sim.mprof_fn, tmp2);
  generate_bb_seq (func, config.sim.mprof_fn, tmp2);
 
  log ("Assuming %i clk cycle load (%i cyc burst)\n", runtime.cuc.mdelay[0], runtime.cuc.mdelay[2]);
 
  log ("Assuming %i clk cycle store (%i cyc burst)\n", runtime.cuc.mdelay[1], runtime.cuc.mdelay[3]);
 
 
  build_bb (func);
  build_bb (func);
  if (cuc_debug >= 5) print_cuc_bb (func, "AFTER_BUILD_BB");
  if (cuc_debug >= 5) print_cuc_bb (func, "AFTER_BUILD_BB");
  reg_dep (func);
  reg_dep (func);
 
 
Line 719... Line 157...
  remove_dead (func);
  remove_dead (func);
  if (cuc_debug >= 5) print_cuc_bb (func, "AFTER_DEAD");
  if (cuc_debug >= 5) print_cuc_bb (func, "AFTER_DEAD");
  remove_trivial_regs (func);
  remove_trivial_regs (func);
  if (cuc_debug >= 2) print_cuc_bb (func, "AFTER_TRIVIAL");
  if (cuc_debug >= 2) print_cuc_bb (func, "AFTER_TRIVIAL");
 
 
 
#if 0
  csm (func);
  csm (func);
 
#endif
  assert (saved = dup_func (func));
  assert (saved = dup_func (func));
 
 
  timings.preroll = timings.unroll = 1;
  timings.preroll = timings.unroll = 1;
  timings.nshared = 0;
  timings.nshared = 0;
  add_latches (func);
  add_latches (func);
  set_io (func);
  set_io (func);
 
 
  if (cuc_debug >= 1) print_cuc_bb (func, "AFTER_LATCHES");
  if (cuc_debug >= 1) print_cuc_bb (func, "AFTER_LATCHES");
  analyse_timings (func, &timings);
  analyse_timings (func, &timings);
  add_memory_dep (func, memory_order);
  add_memory_dep (func, func->memory_order);
  if (cuc_debug >= 7) print_cuc_bb (func, "AFTER_MEMORY_DEP");
  if (cuc_debug >= 7) print_cuc_bb (func, "AFTER_MEMORY_DEP");
  add_data_dep (func);
  add_data_dep (func);
  if (cuc_debug >= 8) print_cuc_bb (func, "AFTER_DATA_DEP");
  if (cuc_debug >= 8) print_cuc_bb (func, "AFTER_DATA_DEP");
  schedule_memory (func, memory_order);
  schedule_memory (func, memory_order);
  if (cuc_debug >= 7) print_cuc_bb (func, "AFTER_SCHEDULE_MEM");
  if (cuc_debug >= 7) print_cuc_bb (func, "AFTER_SCHEDULE_MEM");
Line 750... Line 190...
    cuc_timings t[MAX_UNROLL * MAX_PREROLL];
    cuc_timings t[MAX_UNROLL * MAX_PREROLL];
    cuc_timings *ut;
    cuc_timings *ut;
    cuc_timings *cut = &t[0];
    cuc_timings *cut = &t[0];
    int nt = 1;
    int nt = 1;
    double csize;
    double csize;
 
    saved->bb[b].selected_tim = -1;
 
 
    /* Is it a loop? */
    /* Is it a loop? */
    if (saved->bb[b].next[0] != b && saved->bb[b].next[1] != b) continue;
    if (saved->bb[b].next[0] != b && saved->bb[b].next[1] != b) continue;
    t[0] = timings;
    t[0] = timings;
    t[0].b = b;
    t[0].b = b;
Line 847... Line 288...
  }
  }
#endif
#endif
  return saved;
  return saved;
}
}
 
 
void options_cmd (cuc_func *f, char *name)
/* Utility option formatting functions */
 
static const char *option_char = "?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
 
 
/*static */char *gen_option (char *s, int bb_no, int f_opt)
 
{
 
  if (bb_no >= 0) sprintf (s, "%i", bb_no);
 
  assert (f_opt <= strlen (option_char));
 
  sprintf (s, "%s%c", s, option_char[f_opt]);
 
  return s;
 
}
 
 
 
/*static */void print_option (int bb_no, int f_opt)
 
{
 
  char tmp1[10];
 
  char tmp2[10];
 
  sprintf (tmp2, "%s", gen_option (tmp1, bb_no, f_opt));
 
  printf ("%3s", tmp2);
 
}
 
 
 
static char *format_func_options (char *s, cuc_func *f)
 
{
 
  int b, first = 1;
 
  *s = '\0';
 
  for (b = 0; b < f->num_bb; b++)
 
    if (f->bb[b].selected_tim >= 0) {
 
      char tmp[10];
 
      sprintf (s, "%s%s%s", s, first ? "" : ",", gen_option (tmp, b, f->bb[b].selected_tim));
 
      first = 0;
 
    }
 
  return s;
 
}
 
 
 
static void options_cmd (int func_no, cuc_func *f)
{
{
  int b, i;
  int b, i;
  printf ("%-12s    :pre%i,un%i,sha%i:  time = %i cyc;  size = %.f gates (old time = %i)\n", name,
  char tmp[20];
        f->timings.preroll, f->timings.unroll, f->timings.nshared,
  char *name = prof_func[func_no].name;
        f->timings.new_time, f->timings.size, f->orig_time);
  printf ("--------------------------------------------------------\n");
 
  printf ("|%-16s|pre/unrolled|shared|  time  |  gates | old_time = %i \n",
 
            strstrip (tmp, name, 16), f->orig_time);
 
  printf ("|        BASE    |%4i / %4i | %4i |%8i|%8.f|\n", 1, 1, 0,
 
          f->timings.new_time, f->timings.size);
  for (b = 0; b < f->num_bb; b++) {
  for (b = 0; b < f->num_bb; b++) {
    /* Print out results */
    /* Print out results */
    for (i = 0; i < f->bb[b].ntim; i++) {
    for (i = 1; i < f->bb[b].ntim; i++) { /* First one is base option */
      printf ("%-12sBB%-2i:pre%i,un%i,sha%i:  time = %i cyc;  size = %.f gates\n", name,
      int time = f->bb[b].tim[i].new_time - f->timings.new_time;
        f->bb[b].tim[i].b, f->bb[b].tim[i].preroll, f->bb[b].tim[i].unroll,
      double size = f->bb[b].tim[i].size - f->timings.size;
        f->bb[b].tim[i].nshared, f->bb[b].tim[i].new_time, f->bb[b].tim[i].size);
      printf ("|       ");
 
      print_option (b, i);
 
      printf ("      |%4i / %4i | %4i |%+8i|%+8.f|\n",
 
        f->bb[b].tim[i].preroll, f->bb[b].tim[i].unroll, f->bb[b].tim[i].nshared,
 
        time, size);
 
    }
 
  }
 
}
 
 
 
/* Generates a function, based on specified parameters */
 
cuc_func *generate_function (cuc_func *rf, char *name)
 
{
 
  int b, i, j;
 
  char tmp[256];
 
  cuc_timings tt;
 
  cuc_func *f;
 
  assert (f = dup_func (rf));
 
 
 
  log ("Generating function %s.\n", name);
 
  printf ("Generating function %s.\n", name);
 
 
 
  print_cuc_bb (f, "BEFORE_GENERATE");
 
  add_latches (f);
 
  set_io (f);
 
  if (cuc_debug >= 1) print_cuc_bb (f, "AFTER_LATCHES");
 
 
 
  format_func_options (tmp, rf);
 
  if (strlen (tmp)) printf ("Applying options: %s\n", tmp);
 
  else printf ("Basic options.\n");
 
 
 
  /* Generate function as specified by options */
 
  for (b = 0; b < f->num_bb; b++) {
 
    cuc_timings *st;
 
    if (rf->bb[b].selected_tim < 0) continue;
 
    st = &rf->bb[b].tim[rf->bb[b].selected_tim];
 
    sprintf (tmp, "%s.bin.bb", name);
 
    preunroll_bb (&tmp[0], f, &tt, b, st->preroll, st->unroll);
 
    if (cuc_debug >= 1) print_cuc_bb (f, "AFTER_PREUNROLL");
 
  }
 
  for (b = 0; b < f->num_bb; b++) {
 
    cuc_timings *st;
 
    if (rf->bb[b].selected_tim < 0) continue;
 
    st = &rf->bb[b].tim[rf->bb[b].selected_tim];
 
    if (!st->nshared) continue;
 
    assert (0);
 
    //csm_gen (f, rf, st->nshared, st->shared);
 
  }
 
  analyse_timings (f, &tt);
 
  add_memory_dep (f, f->memory_order);
 
  if (cuc_debug >= 7) print_cuc_bb (f, "AFTER_MEMORY_DEP");
 
  add_data_dep (f);
 
  if (cuc_debug >= 8) print_cuc_bb (f, "AFTER_DATA_DEP");
 
  schedule_memory (f, f->memory_order);
 
  if (cuc_debug >= 7) print_cuc_bb (f, "AFTER_SCHEDULE_MEM");
 
  output_verilog (f, name);
 
  return f;
 
}
 
 
 
/* Calculates required time, based on selected options */
 
int calc_cycles (cuc_func *f)
 
{
 
  int b, i, ntime = f->timings.new_time;
 
  for (b = 0; b < f->num_bb; b++)
 
    if (f->bb[b].selected_tim >= 0) {
 
      assert (f->bb[b].selected_tim < f->bb[b].ntim);
 
      ntime += f->bb[b].tim[f->bb[b].selected_tim].new_time - f->timings.new_time;
 
    }
 
  return ntime;
    }
    }
 
 
 
/* Calculates required size, based on selected options */
 
double calc_size (cuc_func *f)
 
{
 
  int b, i;
 
  double size = f->timings.size;
 
  for (b = 0; b < f->num_bb; b++)
 
    if (f->bb[b].selected_tim >= 0) {
 
      assert (f->bb[b].selected_tim < f->bb[b].ntim);
 
      size += f->bb[b].tim[f->bb[b].selected_tim].size - f->timings.size;
  }
  }
 
  return size;
}
}
 
 
/* Dumps specified function to file (hex) */
/* Dumps specified function to file (hex) */
unsigned long extract_function (char *out_fn, unsigned long start_addr)
unsigned long extract_function (char *out_fn, unsigned long start_addr)
{
{
Line 886... Line 441...
  fclose (fo);
  fclose (fo);
  return a - 4;
  return a - 4;
}
}
 
 
static cuc_func *func[MAX_FUNCS];
static cuc_func *func[MAX_FUNCS];
 
static int func_v[MAX_FUNCS];
 
 
void main_cuc (char *filename)
void main_cuc (char *filename)
{
{
  int i, j;
  int i, j;
  char tmp1[256];
  char tmp1[256];
Line 899... Line 455...
  sprintf (tmp1, "%s.log", filename);
  sprintf (tmp1, "%s.log", filename);
  printf ("Analyzing. (log file \"%s\").\n", tmp1);
  printf ("Analyzing. (log file \"%s\").\n", tmp1);
  assert (flog = fopen (tmp1, "wt+"));
  assert (flog = fopen (tmp1, "wt+"));
 
 
  /* Loads in the specified timings table */
  /* Loads in the specified timings table */
  load_timing_table ("virtex.tim");
  printf ("Using timings from \"%s\" at %s\n",config.cuc.timings_fn,
 
                 generate_time_pretty (tmp1, config.sim.clkcycle_ps));
 
  load_timing_table (config.cuc.timings_fn);
 
  runtime.cuc.cycle_duration = 1000. * config.sim.clkcycle_ps;
 
  printf ("Multicycle logic %s, bursts %s, %s memory order.\n",
 
    config.cuc.no_multicycle ? "OFF" : "ON", config.cuc.enable_bursts ? "ON" : "OFF",
 
    config.cuc.memory_order == MO_NONE ? "no" : config.cuc.memory_order == MO_WEAK ? "weak" :
 
    config.cuc.memory_order == MO_STRONG ? "strong" : "exact");
 
 
  prof_set (1, 0);
  prof_set (1, 0);
  assert (prof_acquire (config.sim.prof_fn) == 0);
  assert (prof_acquire (config.sim.prof_fn) == 0);
 
 
  cycle_duration = 40.;
  if (config.cuc.calling_convention)
 
    printf ("Assuming OpenRISC standard calling convention.\n");
 
 
  /* Try all functions except "total" */
  /* Try all functions except "total" */
  for (i = 0; i < prof_nfuncs - 1; i++) {
  for (i = 0; i < prof_nfuncs - 1; i++) {
    long orig_time;
    long orig_time;
    unsigned long start_addr, end_addr;
    unsigned long start_addr, end_addr;
Line 918... Line 482...
    /* Extract the function from the binary */
    /* Extract the function from the binary */
    sprintf (tmp1, "%s.bin", prof_func[i].name);
    sprintf (tmp1, "%s.bin", prof_func[i].name);
    end_addr = extract_function (tmp1, start_addr);
    end_addr = extract_function (tmp1, start_addr);
 
 
    log ("Testing function %s (%08x - %08x)\n", prof_func[i].name, start_addr, end_addr);
    log ("Testing function %s (%08x - %08x)\n", prof_func[i].name, start_addr, end_addr);
    func[i] = analyse_function (prof_func[i].name, orig_time, start_addr, end_addr);
    printf ("Testing function %s (%08x - %08x)\n", prof_func[i].name, start_addr, end_addr);
 
    func[i] = analyse_function (prof_func[i].name, orig_time, start_addr,
 
                   end_addr, config.cuc.memory_order);
 
    func_v[i] = 0;
  }
  }
 
 
  while (1) {
  while (1) {
    char *s;
    char *s;
    printf ("(cuc) ");
    printf ("(cuc) ");
Line 932... Line 499...
    *s = '\0';
    *s = '\0';
 
 
    if (strcmp (tmp1, "q") == 0 || strcmp (tmp1, "quit") == 0) {
    if (strcmp (tmp1, "q") == 0 || strcmp (tmp1, "quit") == 0) {
      break;
      break;
    } else if (strcmp (tmp1, "p") == 0 || strcmp (tmp1, "profile") == 0) {
    } else if (strcmp (tmp1, "p") == 0 || strcmp (tmp1, "profile") == 0) {
      printf ("----------------------------------------------------------------------------\n");
      int ntime = 0;
      printf ("|function name            |addr    |# calls |avg cycles  | old% | impr. f. |\n");
      int size = 0;
      printf ("|-------------------------+--------+--------+------------+------+----------|\n");
      printf ("-----------------------------------------------------------------------------\n");
 
      printf ("|function name       |calls|avg cycles  |old%| max. f.  | impr. f.| options |\n");
 
      printf ("|--------------------+-----+------------+----+----------|---------+---------|\n");
      for (j = 0; j < prof_nfuncs; j++) {
      for (j = 0; j < prof_nfuncs; j++) {
        int bestcyc = 0, besti = 0;
        int bestcyc = 0, besti = 0;
 
        char tmp[100];
        for (i = 0; i < prof_nfuncs; i++)
        for (i = 0; i < prof_nfuncs; i++)
          if (prof_func[i].cum_cycles > bestcyc) {
          if (prof_func[i].cum_cycles > bestcyc) {
            bestcyc = prof_func[i].cum_cycles;
            bestcyc = prof_func[i].cum_cycles;
            besti = i;
            besti = i;
          }
          }
        i = besti;
        i = besti;
        printf ("| %-24s|%08X|%8i|%12.1f| %3.0f%% |",
        printf ("|%-20s|%5i|%12.1f|%3.0f%%| ",
                prof_func[i].name, prof_func[i].addr, prof_func[i].calls,
                strstrip (tmp, prof_func[i].name, 20),  prof_func[i].calls,
                ((double)prof_func[i].cum_cycles / prof_func[i].calls),
                ((double)prof_func[i].cum_cycles / prof_func[i].calls),
                (100. * prof_func[i].cum_cycles / prof_cycles));
                (100. * prof_func[i].cum_cycles / prof_cycles));
        if (func[i]) {
        if (func[i]) {
          printf ("%9.2f |\n", 1.f *  prof_func[i].cum_cycles / func[i]->timings.new_time);
          double f = 1.0;
        } else printf ("    N/A   |\n");
          if (func_v[i]) {
        prof_func[i].cum_cycles = -1;
            int nt = calc_cycles (func[i]);
 
            int s = calc_size (func[i]);
 
            f = func[i]->orig_time / nt;
 
            ntime += nt * func[i]->num_runs;
 
            size += s;
 
          } else ntime += prof_func[i].cum_cycles;
 
          printf ("%8.1f |%8.1f | %-8s|\n", 1.f * prof_func[i].cum_cycles / func[i]->timings.new_time, f, format_func_options (tmp, func[i]));
 
        } else {
 
          printf ("     N/A |     N/A |         |\n");
 
          ntime += prof_func[i].cum_cycles;
 
        }
 
        prof_func[i].cum_cycles = -prof_func[i].cum_cycles;
      }
      }
      printf ("----------------------------------------------------------------------------\n");
      for (i = 0; i < prof_nfuncs; i++)
      printf ("Total %i functions, %i cycles.\n", prof_nfuncs, prof_cycles);
        prof_func[i].cum_cycles = -prof_func[i].cum_cycles;
 
      printf ("-----------------------------------------------------------------------------\n");
 
      printf ("Total %i cycles (was %i), total added gates = %i.\n", ntime, prof_cycles, size);
    } else if (strncmp (tmp1, "d", 1) == 0 || strncmp (tmp1, "debug", 5) == 0) {
    } else if (strncmp (tmp1, "d", 1) == 0 || strncmp (tmp1, "debug", 5) == 0) {
 
      /* debug command */
      sscanf (tmp1, "%*s %i", &cuc_debug);
      sscanf (tmp1, "%*s %i", &cuc_debug);
      if (cuc_debug < 0) cuc_debug = 0;
      if (cuc_debug < 0) cuc_debug = 0;
      if (cuc_debug > 9) cuc_debug = 9;
      if (cuc_debug > 9) cuc_debug = 9;
    } else if (strcmp (tmp1, "g") == 0 || strcmp (tmp1, "generate") == 0) {
    } else if (strcmp (tmp1, "g") == 0 || strcmp (tmp1, "generate") == 0) {
      for (i = 0; i < prof_nfuncs; i++);
      /* generate command */
 
      for (i = 0; i < prof_nfuncs; i++)
 
        if (func[i] && func_v[i]) generate_function (func[i], prof_func[i].name);
 
    } else if (strncmp (tmp1, "s", 1) == 0 || strncmp (tmp1, "select", 6) == 0) {
 
      /* select command */
 
      char tmp[50], ch;
 
      int p, o, b, f;
 
      p = sscanf (tmp1, "%*s %s %i%c", tmp, &b, &ch);
 
      if (p < 1) printf ("Invalid parameters.\n");
 
      else {
 
        /* Check if we have valid option */
 
        for (f = 0; f < prof_nfuncs; f++)
 
          if (strcmp (prof_func[f].name, tmp) == 0 && func[f]) break;
 
        if (f < prof_nfuncs) {
 
          if (p == 1) {
 
            if (func[f]) {
 
              func_v[f] = 1;
 
              printf ("Function %s selected for translation.\n", prof_func[f].name);
 
            } else printf ("Function %s not suitable for translation.\n", prof_func[f].name);
 
          } else {
 
            if (!func_v[f])
 
              printf ("Function %s not yet selected for translation.\n", prof_func[f].name);
 
            if (p < 3) goto invalid_option;
 
            for (o = 0; option_char[o] != '\0' && option_char[o] != ch; o++);
 
            if (!option_char[o]) goto invalid_option;
 
            if (b < 0 || b >= func[f]->num_bb) goto invalid_option;
 
            if (o < 0 || o >= func[f]->bb[b].ntim) goto invalid_option;
 
 
 
            /* select an option */
 
            func[f]->bb[b].selected_tim = o;
 
            if (func[f]->bb[b].tim[o].nshared) {
 
              printf ("Option has shared instructions: ");
 
              print_shared (func[f], func[f]->bb[b].tim[o].shared, func[f]->bb[b].tim[o].nshared);
 
              printf ("\n");
 
            }
 
            continue;
 
invalid_option:
 
            printf ("Invalid option.\n");
 
          }
 
        } else printf ("Invalid function.\n");
 
      }
 
    } else if (strncmp (tmp1, "u", 1) == 0 || strncmp (tmp1, "unselect", 8) == 0) {
 
      /* unselect command */
 
      char tmp[50], ch;
 
      int p, o, b, f;
 
      p = sscanf (tmp1, "%*s %s %i%c", tmp, &b, &ch);
 
      if (p < 1) printf ("Invalid parameters.\n");
 
      else {
 
        /* Check if we have valid option */
 
        for (f = 0; f < prof_nfuncs; f++)
 
          if (strcmp (prof_func[f].name, tmp) == 0 && func[f]) break;
 
        if (f < prof_nfuncs) {
 
          if (p == 1) {
 
            if (func[f]) {
 
              func_v[f] = 0;
 
              printf ("Function %s unselected for translation.\n", prof_func[f].name);
 
            } else printf ("Function %s not suitable for translation.\n", prof_func[f].name);
 
          } else {
 
            if (p < 3) goto invalid_option;
 
            for (o = 0; option_char[o] != '\0' && option_char[o] != ch; o++);
 
            if (!option_char[o]) goto invalid_option;
 
            if (b < 0 || b >= func[f]->num_bb) goto invalid_option;
 
            if (o < 0 || o >= func[f]->bb[b].ntim) goto invalid_option;
 
 
 
            /* select an option */
 
            func[f]->bb[b].selected_tim = -1;
 
          }
 
        } else printf ("Invalid function.\n");
 
      }
    } else if (strcmp (tmp1, "o") == 0 || strcmp (tmp1, "options") == 0) {
    } else if (strcmp (tmp1, "o") == 0 || strcmp (tmp1, "options") == 0) {
 
      int any = 0;
 
      /* options command */
      printf ("Available options:\n");
      printf ("Available options:\n");
      for (i = 0; i < prof_nfuncs; i++)
      for (i = 0; i < prof_nfuncs; i++)
        if (func[i]) options_cmd (func[i], prof_func[i].name);
        if (func[i]) {
 
          options_cmd (i, func[i]);
 
          any = 1;
 
        }
 
      if (any) printf ("--------------------------------------------------------\n");
 
      else printf ("Sorry. No available options.\n");
    } else {
    } else {
 
      /* help command */
      if (strcmp (tmp1, "h") != 0 && strcmp (tmp1, "help") != 0)
      if (strcmp (tmp1, "h") != 0 && strcmp (tmp1, "help") != 0)
        printf ("Unknown command.\n");
        printf ("Unknown command.\n");
      printf ("OpenRISC Custom Unit Compiler command prompt\n");
      printf ("OpenRISC Custom Unit Compiler command prompt\n");
 
      printf ("Available commands:\n");
      printf ("h|help       displays this help\n");
      printf ("h|help       displays this help\n");
      printf ("q|quit       returns to or1ksim prompt\n");
      printf ("q|quit       returns to or1ksim prompt\n");
      printf ("p|profile    displays function profiling\n");
      printf ("p|profile    displays function profiling\n");
      printf ("d|debug #    sets debug level (0-9)\n");
      printf ("d|debug #    sets debug level (0-9)\n");
      printf ("o|options    displays available options\n");
      printf ("o|options    displays available options\n");
 
      printf ("  s | select func [option]   selects an option/function\n");
 
      printf ("  u | unselect func [option] unselects an option/function\n");
      printf ("g|generate   generates verilog file\n");
      printf ("g|generate   generates verilog file\n");
    }
    }
  }
  }
 
 
  /* Dispose memory */
  /* Dispose memory */

powered by: WebSVN 2.1.0

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