Exemple #1
0
void motors_init(void) {

	int i;
	uint8_t pin_mask;
	uint32_t motor_per;

	// Set Pins to output/PWM in GPIO
	SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);
	GPIOPinConfigure(GPIO_PF2_M1PWM6);
	GPIOPinConfigure(GPIO_PF3_M1PWM7);
	GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3);

	// Configure the pin for standby control
	GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6);

	SysCtlPWMClockSet(SYSCTL_PWMDIV_64);
	// Configure the PWM for each pin:
	// Turn on the generators and set the PW to 0
	// The output is still OFF. Turn on with set_motor_pwm_state
	for (i = 0; i < NUM_MOTORS; i++) {
		PWMGenConfigure(motors[i].pwm_base_module, motors[i].pwm_generator, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
		motor_per = calc_cycles(MOTOR_PERIOD);
		PWMGenPeriodSet(motors[i].pwm_base_module, motors[i].pwm_generator, motor_per);
		PWMPulseWidthSet(motors[i].pwm_base_module, motors[i].pwm_pin, 0);
		PWMGenEnable(motors[i].pwm_base_module, motors[i].pwm_generator);
		pin_mask = 1 << (0x0000000F & motors[i].pwm_pin);
		PWMOutputState(motors[i].pwm_base_module, pin_mask, 0);
	}

}
Exemple #2
0
void set_pulse_width(motor_index_t index, uint32_t *uSec) {
	uint32_t cycles = calc_cycles(*uSec);

	uint8_t pin_mask;
	// set uSec as closest value as possible with Timer settings
	*uSec = calc_usec(cycles);
	pin_mask = 1 << (0x0000000F & motors[index].pwm_pin);

	if(cycles <= 0){
		PWMOutputState(motors[index].pwm_base_module, pin_mask, 0);
	}
	else{
		PWMOutputState(motors[index].pwm_base_module, pin_mask, 1);
		PWMPulseWidthSet(motors[index].pwm_base_module, motors[index].pwm_pin, cycles);
	}

}
char *parse_note_string(char *ptr, struct defaults *def, struct note *note){
  char len_string[3];
  char pitch_string[3];
  char octave_string[2];
  char dot[2];

  // eat whitespace / commas and advance the pointer
  char* dummy = malloc(strlen(ptr)+1);
  if (dummy == NULL){ error("malloc failed");}
  dummy[0] = '\0';
  sscanf(ptr,"%[ ,]",dummy);
  ptr += strlen(dummy);
  free(dummy);

  DEBUG&&printf("Begin Parsing Note String...\n");
  ptr = get_len(ptr, len_string, def->len);
  DEBUG&&printf("get_len Successful...\n");
  ptr = get_pitch(ptr, pitch_string);
  DEBUG&&printf("get_pitch Successful...\n");
  ptr = get_octave(ptr, octave_string, def->oct);
  DEBUG&&printf("get_octave Successful...\n");
  ptr = get_dot(ptr, dot);
  DEBUG&&printf("get_dot Successful...\n");

  strcpy(note->pitch, pitch_string);
  sscanf(len_string, "%d", &(note->length));
  sscanf(octave_string, "%d", &(note->octave));

  note->divisor = calc_divisor(pitch_string, octave_string);
  DEBUG&&printf("divisor successful\n");

  note->cycles = calc_cycles(def, len_string, dot);
  DEBUG&&printf("cycles successful\n");

  return ptr;
}
Exemple #4
0
/*
 * Version - 6.0
 *
 * Perform exhaustive search across different bank organizatons,
 * router configurations, grid organizations, and wire models and
 * find an optimal NUCA organization
 * For different bank count values
 * 1. Optimal bank organization is calculated
 * 2. For each bank organization, find different NUCA organizations
 *    using various router configurations, grid organizations,
 *    and wire models.
 * 3. NUCA model with the least cost is picked for
 *    this particular bank count
 * Finally include contention statistics and find the optimal
 *    NUCA configuration
 */
  void
Nuca::sim_nuca()
{
  /* temp variables */
  int it, ro, wr;
  int num_cyc;
  unsigned int i, j;
  unsigned int r, c;
  int l2_c;
  int bank_count = 0;
  uca_org_t ures;
  nuca_org_t *opt_n;
  mem_array tag, data;
  list<nuca_org_t *> nuca_list;
  Router *router_s[ROUTER_TYPES];
  router_s[0] = new Router(64.0, 8, 4, &(g_tp.peri_global));
  router_s[0]->print_router();
  router_s[1] = new Router(128.0, 8, 4, &(g_tp.peri_global));
  router_s[1]->print_router();
  router_s[2] = new Router(256.0, 8, 4, &(g_tp.peri_global));
  router_s[2]->print_router();

  int core_in; // to store no. of cores

  /* to search diff grid organizations */
  double curr_hop, totno_hops, totno_hhops, totno_vhops, tot_lat,
         curr_acclat;
  double avg_lat, avg_hop, avg_hhop, avg_vhop, avg_dyn_power,
         avg_leakage_power;

  double opt_acclat = INF;
  //double opt_avg_lat = INF;
  //double opt_tot_lat = INF;
  int opt_rows = 0;
  int opt_columns = 0;
  //double opt_totno_hops = 0;
  double opt_avg_hop = 0;
  double opt_dyn_power = 0, opt_leakage_power = 0;
  min_values_t minval;

  int bank_start = 0;

  int flit_width = 0;

  /* vertical and horizontal hop latency values */
  int ver_hop_lat, hor_hop_lat; /* in cycles */


  /* no. of different bank sizes to consider */
  int iterations;


  g_ip->nuca_cache_sz = g_ip->cache_sz;
  nuca_list.push_back(new nuca_org_t());

  if (g_ip->cache_level == 0) l2_c = 1;
  else l2_c = 0;

  if (g_ip->cores <= 4) core_in = 2;
  else if (g_ip->cores <= 8) core_in = 3;
  else if (g_ip->cores <= 16) core_in = 4;
  else {cout << "Number of cores should be <= 16!\n"; exit(0);}


  // set the lower bound to an appropriate value. this depends on cache associativity
  if (g_ip->assoc > 2) {
    i = 2;
    while (i != g_ip->assoc) {
      MIN_BANKSIZE *= 2;
      i *= 2;
    }
  }

  iterations = (int)logtwo((int)g_ip->cache_sz/MIN_BANKSIZE);

  if (g_ip->force_wiretype)
  {
    if (g_ip->wt == Low_swing) {
      wt_min = Low_swing;
      wt_max = Low_swing;
    }
    else {
      wt_min = Global;
      wt_max = Low_swing-1;
    }
  }
  else {
    wt_min = Global;
    wt_max = Low_swing;
  }
  if (g_ip->nuca_bank_count != 0) { // simulate just one bank
    if (g_ip->nuca_bank_count != 2 && g_ip->nuca_bank_count != 4 &&
        g_ip->nuca_bank_count != 8 && g_ip->nuca_bank_count != 16 &&
        g_ip->nuca_bank_count != 32 && g_ip->nuca_bank_count != 64) {
      fprintf(stderr,"Incorrect bank count value! Please fix the value in cache.cfg\n");
    }
    bank_start = (int)logtwo((double)g_ip->nuca_bank_count);
    iterations = bank_start+1;
    g_ip->cache_sz = g_ip->cache_sz/g_ip->nuca_bank_count;
  }
  cout << "Simulating various NUCA configurations\n";
  for (it=bank_start; it<iterations; it++) { /* different bank count values */
    ures.tag_array2 = &tag;
    ures.data_array2 = &data;
    /*
     * find the optimal bank organization
     */
    solve(&ures);
//    output_UCA(&ures);
    bank_count = g_ip->nuca_cache_sz/g_ip->cache_sz;
    cout << "====" <<  g_ip->cache_sz << "\n";

    for (wr=wt_min; wr<=wt_max; wr++) {

      for (ro=0; ro<ROUTER_TYPES; ro++)
      {
        flit_width = (int) router_s[ro]->flit_size; //initialize router
        nuca_list.back()->nuca_pda.cycle_time = router_s[ro]->cycle_time;

        /* calculate router and wire parameters */

        double vlength = ures.cache_ht; /* length of the wire (u)*/
        double hlength = ures.cache_len; // u

        /* find delay, area, and power for wires */
        wire_vertical[wr] = new Wire((enum Wire_type) wr, vlength);
        wire_horizontal[wr] = new Wire((enum Wire_type) wr, hlength);


        hor_hop_lat = calc_cycles(wire_horizontal[wr]->delay,
            1/(nuca_list.back()->nuca_pda.cycle_time*.001));
        ver_hop_lat = calc_cycles(wire_vertical[wr]->delay,
            1/(nuca_list.back()->nuca_pda.cycle_time*.001));

        /*
         * assume a grid like topology and explore for optimal network
         * configuration using different row and column count values.
         */
        for (c=1; c<=(unsigned int)bank_count; c++) {
          while (bank_count%c != 0) c++;
          r = bank_count/c;

          /*
           * to find the avg access latency of a NUCA cache, uncontended
           * access time to each bank from the
           * cache controller is calculated.
           * avg latency =
           * sum of the access latencies to individual banks)/bank
           * count value.
           */
          totno_hops = totno_hhops = totno_vhops = tot_lat = 0;
         // k = 1;
          for (i=0; i<r; i++) {
            for (j=0; j<c; j++) {
              /*
               * vertical hops including the
               * first hop from the cache controller
               */
              curr_hop = i + 1;
              curr_hop += j; /* horizontal hops */
              totno_hhops += j;
              totno_vhops += (i+1);
              curr_acclat = (i * ver_hop_lat + CONTR_2_BANK_LAT +
                  j * hor_hop_lat);

              tot_lat += curr_acclat;
              totno_hops += curr_hop;
            }
          }
          avg_lat = tot_lat/bank_count;
          avg_hop = totno_hops/bank_count;
          avg_hhop = totno_hhops/bank_count;
          avg_vhop = totno_vhops/bank_count;

          /* net access latency */
          curr_acclat = 2*avg_lat + 2*(router_s[ro]->delay*avg_hop) +
            calc_cycles(ures.access_time,
                1/(nuca_list.back()->nuca_pda.cycle_time*.001));

          /* avg access lat of nuca */
          avg_dyn_power =
            avg_hop *
            (router_s[ro]->power.readOp.dynamic) + avg_hhop *
            (wire_horizontal[wr]->power.readOp.dynamic) *
            (g_ip->block_sz*8 + 64) + avg_vhop *
            (wire_vertical[wr]->power.readOp.dynamic) *
            (g_ip->block_sz*8 + 64) + ures.power.readOp.dynamic;

          avg_leakage_power =
            bank_count * router_s[ro]->power.readOp.leakage +
            avg_hhop * (wire_horizontal[wr]->power.readOp.leakage*
                wire_horizontal[wr]->delay) * flit_width +
            avg_vhop * (wire_vertical[wr]->power.readOp.leakage *
                wire_horizontal[wr]->delay);

          if (curr_acclat < opt_acclat) {
            opt_acclat = curr_acclat;
            //opt_tot_lat = tot_lat;
            //opt_avg_lat = avg_lat;
            //opt_totno_hops = totno_hops;
            opt_avg_hop = avg_hop;
            opt_rows = r;
            opt_columns = c;
            opt_dyn_power = avg_dyn_power;
            opt_leakage_power = avg_leakage_power;
          }
          totno_hops = 0;
          tot_lat = 0;
          totno_hhops = 0;
          totno_vhops = 0;
        }
        nuca_list.back()->wire_pda.power.readOp.dynamic =
          opt_avg_hop * flit_width *
          (wire_horizontal[wr]->power.readOp.dynamic +
           wire_vertical[wr]->power.readOp.dynamic);
        nuca_list.back()->avg_hops = opt_avg_hop;
        /* network delay/power */
        nuca_list.back()->h_wire = wire_horizontal[wr];
        nuca_list.back()->v_wire = wire_vertical[wr];
        nuca_list.back()->router = router_s[ro];
        /* bank delay/power */

        nuca_list.back()->bank_pda.delay = ures.access_time;
        nuca_list.back()->bank_pda.power = ures.power;
        nuca_list.back()->bank_pda.area.h = ures.cache_ht;
        nuca_list.back()->bank_pda.area.w = ures.cache_len;
        nuca_list.back()->bank_pda.cycle_time = ures.cycle_time;

        num_cyc = calc_cycles(nuca_list.back()->bank_pda.delay /*s*/,
            1/(nuca_list.back()->nuca_pda.cycle_time*.001/*GHz*/));
        if(num_cyc%2 != 0) num_cyc++;
        if (num_cyc > 16) num_cyc = 16; // we have data only up to 16 cycles

        if (it < 7) {
          nuca_list.back()->nuca_pda.delay = opt_acclat +
            cont_stats[l2_c][core_in][ro][it][num_cyc/2-1];
          nuca_list.back()->contention =
            cont_stats[l2_c][core_in][ro][it][num_cyc/2-1];
        }
        else {
          nuca_list.back()->nuca_pda.delay = opt_acclat +
            cont_stats[l2_c][core_in][ro][6][num_cyc/2-1];
          nuca_list.back()->contention =
            cont_stats[l2_c][core_in][ro][6][num_cyc/2-1];
        }
        nuca_list.back()->nuca_pda.power.readOp.dynamic = opt_dyn_power;
        nuca_list.back()->nuca_pda.power.readOp.leakage = opt_leakage_power;

        /* array organization */
        nuca_list.back()->bank_count = bank_count;
        nuca_list.back()->rows = opt_rows;
        nuca_list.back()->columns = opt_columns;
        calculate_nuca_area (nuca_list.back());

        minval.update_min_values(nuca_list.back());
        nuca_list.push_back(new nuca_org_t());
        opt_acclat = BIGNUM;

      }
    }
    g_ip->cache_sz /= 2;
  }

  delete(nuca_list.back());
  nuca_list.pop_back();
  opt_n = find_optimal_nuca(&nuca_list, &minval);
  print_nuca(opt_n);
  g_ip->cache_sz = g_ip->nuca_cache_sz/opt_n->bank_count;

  list<nuca_org_t *>::iterator niter;
  for (niter = nuca_list.begin(); niter != nuca_list.end(); ++niter)
  {
    delete *niter;
  }
  nuca_list.clear();

  for(int i=0; i < ROUTER_TYPES; i++)
  {
    delete router_s[i];
  }
  g_ip->display_ip();
  //  g_ip->force_cache_config = true;
  //  g_ip->ndwl = 8;
  //  g_ip->ndbl = 16;
  //  g_ip->nspd = 4;
  //  g_ip->ndcm = 1;
  //  g_ip->ndsam1 = 8;
  //  g_ip->ndsam2 = 32;

}
Exemple #5
0
void
main_cuc (char *filename)
{
  int i, j;
  char tmp1[256];
  char filename_cut[256];
#if 0				/* Select prefix, based on binary program name */
  for (i = 0; i < sizeof (filename_cut); i++)
    {
      if (isalpha (filename[i]))
	filename_cut[i] = filename[i];
      else
	{
	  filename_cut[i] = '\0';
	  break;
	}
    }
#else
  strcpy (filename_cut, "cu");
#endif

  PRINTF ("Entering OpenRISC Custom Unit Compiler command prompt\n");
  PRINTF ("Using profile file \"%s\" and memory profile file \"%s\".\n",
	  config.sim.prof_fn, config.sim.mprof_fn);
  sprintf (tmp1, "%s.log", filename_cut);
  PRINTF ("Analyzing. (log file \"%s\").\n", tmp1);
  assert (flog = fopen (tmp1, "wt+"));

  /* Loads in the specified timings table */
  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);
  assert (prof_acquire (config.sim.prof_fn) == 0);

  if (config.cuc.calling_convention)
    PRINTF ("Assuming OpenRISC standard calling convention.\n");

  /* Try all functions except "total" */
  for (i = 0; i < prof_nfuncs - 1; i++)
    {
      long orig_time;
      unsigned long start_addr, end_addr;
      orig_time = prof_func[i].cum_cycles;
      start_addr = prof_func[i].addr;

      /* Extract the function from the binary */
      sprintf (tmp1, "%s.bin", prof_func[i].name);
      end_addr = extract_function (tmp1, start_addr);

      log ("Testing function %s (%08lx - %08lx)\n", prof_func[i].name,
	   start_addr, end_addr);
      PRINTF ("Testing function %s (%08lx - %08lx)\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, prof_func[i].calls);
      func_v[i] = 0;
    }
  set_func_deps ();

  while (1)
    {
      char *s;
    wait_command:
      PRINTF ("(cuc) ");
      fflush (stdout);
    wait_command_empty:
      s = fgets (tmp1, sizeof tmp1, stdin);
      usleep (100);
      if (!s)
	goto wait_command_empty;
      for (s = tmp1; *s != '\0' && *s != '\n' && *s != '\r'; s++);
      *s = '\0';

      /* quit command */
      if (strcmp (tmp1, "q") == 0 || strcmp (tmp1, "quit") == 0)
	{
	  /* Delete temporary files */
	  for (i = 0; i < prof_nfuncs - 1; i++)
	    {
	      sprintf (tmp1, "%s.bin", prof_func[i].name);
	      log ("Deleting temporary file %s %s\n", tmp1,
		   remove (tmp1) ? "FAILED" : "OK");
	      sprintf (tmp1, "%s.bin.bb", prof_func[i].name);
	      log ("Deleting temporary file %s %s\n", tmp1,
		   remove (tmp1) ? "FAILED" : "OK");
	    }
	  break;

	  /* profile command */
	}
      else if (strcmp (tmp1, "p") == 0 || strcmp (tmp1, "profile") == 0)
	{
	  int ntime = 0;
	  int size = 0;
	  PRINTF
	    ("-----------------------------------------------------------------------------\n");
	  PRINTF
	    ("|function name       |calls|avg cycles  |old%%| max. f.  | impr. f.| options |\n");
	  PRINTF
	    ("|--------------------+-----+------------+----+----------|---------+---------|\n");
	  for (j = 0; j < prof_nfuncs; j++)
	    {
	      int bestcyc = 0, besti = 0;
	      char tmp[100];
	      for (i = 0; i < prof_nfuncs; i++)
		if (prof_func[i].cum_cycles > bestcyc)
		  {
		    bestcyc = prof_func[i].cum_cycles;
		    besti = i;
		  }
	      i = besti;
	      PRINTF ("|%-20s|%5li|%12.1f|%3.0f%%| ",
		      strstrip (tmp, prof_func[i].name, 20),
		      prof_func[i].calls,
		      ((double) prof_func[i].cum_cycles / prof_func[i].calls),
		      (100. * prof_func[i].cum_cycles / prof_cycles));
	      if (func[i])
		{
		  double f = 1.0;
		  if (func_v[i])
		    {
		      int nt = calc_cycles (func[i]);
		      int s = calc_size (func[i]);
		      f = 1. * func[i]->orig_time / nt;
		      ntime += nt;
		      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/A |\n");
		  ntime += prof_func[i].cum_cycles;
		}
	      prof_func[i].cum_cycles = -prof_func[i].cum_cycles;
	    }
	  for (i = 0; i < prof_nfuncs; i++)
	    prof_func[i].cum_cycles = -prof_func[i].cum_cycles;
	  PRINTF
	    ("-----------------------------------------------------------------------------\n");
	  PRINTF
	    ("Total %i cycles (was %i), total added gates = %i. Speed factor %.1f\n",
	     ntime, prof_cycles, size, 1. * prof_cycles / ntime);

	  /* debug command */
	}
      else if (strncmp (tmp1, "d", 1) == 0 || strncmp (tmp1, "debug", 5) == 0)
	{
	  sscanf (tmp1, "%*s %i", &cuc_debug);
	  if (cuc_debug < 0)
	    cuc_debug = 0;
	  if (cuc_debug > 9)
	    cuc_debug = 9;

	  /* generate command */
	}
      else if (strcmp (tmp1, "g") == 0 || strcmp (tmp1, "generate") == 0)
	{
	  /* check for function dependencies */
	  for (i = 0; i < prof_nfuncs; i++)
	    if (func[i])
	      func[i]->tmp = func_v[i];
	  for (i = 0; i < prof_nfuncs; i++)
	    if (func[i])
	      for (j = 0; j < func[i]->nfdeps; j++)
		if (!func[i]->fdeps[j] || !func[i]->fdeps[j]->tmp)
		  {
		    PRINTF
		      ("Function %s must be selected for translation (required by %s)\n",
		       prof_func[j].name, prof_func[i].name);
		    goto wait_command;
		  }
	  for (i = 0; i < prof_nfuncs; i++)
	    if (func[i] && func_v[i])
	      generate_function (func[i], prof_func[i].name, filename_cut);
	  generate_main (prof_nfuncs, func, filename_cut);

	  /* list command */
	}
      else if (strcmp (tmp1, "l") == 0 || strcmp (tmp1, "list") == 0)
	{
	  /* check for function dependencies */
	  for (i = 0; i < prof_nfuncs; i++)
	    if (func_v[i])
	      {
		PRINTF ("%s\n", prof_func[i].name);
	      }

	  /* selectall command */
	}
      else if (strcmp (tmp1, "sa") == 0 || strcmp (tmp1, "selectall") == 0)
	{
	  int f;
	  for (f = 0; f < prof_nfuncs; f++)
	    if (func[f])
	      {
		func_v[f] = 1;
		PRINTF ("Function %s selected for translation.\n",
			prof_func[f].name);
	      }

	  /* select command */
	}
      else if (strncmp (tmp1, "s", 1) == 0
	       || strncmp (tmp1, "select", 6) == 0)
	{
	  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");
			}
		      goto wait_command;
		    invalid_option:
		      PRINTF ("Invalid option.\n");
		    }
		}
	      else
		PRINTF ("Invalid function.\n");
	    }

	  /* unselect command */
	}
      else if (strncmp (tmp1, "u", 1) == 0
	       || strncmp (tmp1, "unselect", 8) == 0)
	{
	  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");
	    }

	  /* options command */
	}
      else if (strcmp (tmp1, "o") == 0 || strcmp (tmp1, "options") == 0)
	{
	  int any = 0;
	  PRINTF ("Available options:\n");
	  for (i = 0; i < prof_nfuncs; i++)
	    if (func[i])
	      {
		options_cmd (i, func[i]);
		any = 1;
	      }
	  if (any)
	    PRINTF
	      ("-----------------------------------------------------------------------------\n");
	  else
	    PRINTF ("Sorry. No available options.\n");

	  /* Ignore empty string */
	}
      else if (strcmp (tmp1, "") == 0)
	{

	  /* help command */
	}
      else
	{
	  if (strcmp (tmp1, "h") != 0 && strcmp (tmp1, "help") != 0)
	    PRINTF ("Unknown command.\n");
	  PRINTF ("OpenRISC Custom Unit Compiler command prompt\n");
	  PRINTF ("Available commands:\n");
	  PRINTF ("  h | help                   displays this help\n");
	  PRINTF ("  q | quit                   returns to or1ksim prompt\n");
	  PRINTF
	    ("  p | profile                displays function profiling\n");
	  PRINTF ("  d | debug #                sets debug level (0-9)\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
	    ("  l | list                   displays selected functions\n");
	}
    }

  /* Dispose memory */
  for (i = 0; i < prof_nfuncs - 1; i++)
    if (func[i])
      free_func (func[i]);

  fclose (flog);
}