summaryrefslogblamecommitdiffstats
path: root/tools/cpu/nios2/output.c
blob: bd4a30b0fe3e05f43e5026e0abfdbfa946097f6e (plain) (tree)




























































































                                                                     
                                              
















                                                                    
                  







































                                                                                               


                                                             

                                                  
                                                         






                          
                                                     













                                                                     
                                                                           












                                                                   
 
/*
 *  Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.com/license/LICENSE.
 *
 *  $Id$
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "ptf.h"
#include "devices.h"
#include "output.h"

typedef struct
{
  FILE *file;
  device_desc *dev;
  char *def_name;
  char *orig_value;
  clock_desc *clocks;
  device_desc *devices;
}
out_desc;

int is_not_connected(struct ptf_item *pi)
{
  if(pi->item[0] == NULL) return 0;
  if(pi->item[0]->name == NULL) return 0;

  if(strcmp(pi->item[0]->name, "SLAVE") == 0)
  {
    struct ptf *t;
    struct ptf_item ti;
    t = ptf_find(pi->item[0]->sub, &ti, item, "N2G_Selected", "1");

    if(t == NULL) return 1;
  };

  return 0;
}

void fwrite_devhead_def(struct ptf_item *pi, void *arg)
{
  out_desc *dinfo = arg;

  if(pi != NULL) if(is_not_connected(pi)) return;

  fprintf(dinfo->file, "#define %s_%s %s\n",
    dinfo->dev->cfgname, dinfo->def_name, dinfo->orig_value);
}

void fwrite_devhead_line(struct ptf_item *pi, void *arg)
{
  out_desc *dinfo = arg;

  if(is_not_connected(pi)) return;

  if(strncmp(dinfo->orig_value, "N2G_", 4)==0)
  {
    if(strncmp(dinfo->orig_value, "N2G_CLOCKREF_", 13)==0)
    {
      clock_desc *c;
      for(c = dinfo->clocks; c; c=c->next)
      {
        if(strcmp(c->name, pi->item[pi->level]->value) == 0)
        {
          fprintf(dinfo->file, "#define %s_%s %s\n",
            dinfo->dev->cfgname, dinfo->orig_value + 13, c->cfgname);
          break;
        };
      };
    }
    else if(strncmp(dinfo->orig_value, "N2G_DEVICEREF_", 14)==0)
    {
      device_desc *d;
      for(d = dinfo->devices; d; d=d->next)
      {
        if(strcmp(d->ptf->value, pi->item[pi->level]->value) == 0)
        {
          fprintf(dinfo->file, "#define %s_%s %s\n",
            dinfo->dev->cfgname, dinfo->orig_value + 14, d->cfgname);
          break;
        };
      };
    }
  }
  else
  {
    fprintf(dinfo->file, "#define %s_%s %s\n",
      dinfo->dev->cfgname, dinfo->orig_value,
      pi->item[pi->level]->value);
  };
}

void fwrite_device_header(struct ptf_item *pi, void *arg)
{
  struct ptf *f;
  struct ptf_item fi;
  out_desc *dinfo = arg;

  /* This is called for every matching CLASS section in the
     configuration. The following loop iterates through all
     items in the CLASS section regardless of their nesting level */

  f = ptf_find(pi->item[pi->level]->sub, &fi, item, 0, 0);

  while(f != NULL)
  {
    dinfo->orig_value = f->value;
    if(f->name && strncmp(f->name, "N2G_DEFINE_", 11)==0)
    {
      dinfo->def_name = f->name + 11;
      if(fi.level >= 2)
      {
        fi.level--; /* match only the enclosing section */
        ptf_match(dinfo->dev->ptf->sub, &fi, fwrite_devhead_def, dinfo);
        fi.level++;
      }
      else
      {
        fwrite_devhead_def( 0, dinfo );
      };
    }
    else
    {
      f->value = 0; /* Match ANY value */
      ptf_match(dinfo->dev->ptf->sub, &fi, fwrite_devhead_line, dinfo);
      f->value = dinfo->orig_value;
    };
    f = ptf_next(&fi, item, 0, 0);
  };
}

void fwrite_value(struct ptf_item *pi, void *arg)
{
  FILE *file = arg;
  fputs(pi->item[pi->level]->value, file);
}

void fwrite_header_file( FILE *file, struct ptf *cfg, device_desc *devices, clock_desc *clocks)
{
  struct ptf *p;
  struct ptf_item pi;

  struct ptf aclass = { section, "CLASS", 0, 0, 0 };
  struct ptf_item matchaclass = { 1, &aclass };

  struct ptf bspsect = { section, "BSPHEADER", 0, 0, 0 };
  struct ptf leadtext = { item, "LEADTEXT", 0, 0, 0 };
  struct ptf_item matchleadtext = { 2, &bspsect, &leadtext };

  struct ptf epilog = { item, "EPILOG", 0, 0, 0 };
  struct ptf_item matchepilog = { 2, &bspsect, &epilog };

  out_desc dinfo;

  dinfo.file    = file;
  dinfo.clocks  = clocks;
  dinfo.devices = devices;

  ptf_match(cfg, &matchleadtext, fwrite_value, file);

  if(clocks)
  {
    clock_desc *cs;
    for(cs = clocks; cs; cs = cs->next)
    {
      fprintf(file, "#define %s_FREQ %luu\n", cs->cfgname, cs->freq);
    };
  };

  if(devices)
  {
    for(dinfo.dev = devices; dinfo.dev; dinfo.dev=dinfo.dev->next)
    {
      /* fprintf(file, "\n#define SOPC_HAS_%s 1\n", dinfo.dev->cfgname); */

      p = ptf_find(dinfo.dev->ptf, &pi, item, "class", 0);
      if(p)
      {
        aclass.value = p->value;
        ptf_match(cfg, &matchaclass, fwrite_device_header, &dinfo);
      };
    };
  };

  ptf_match(cfg, &matchepilog, fwrite_value, file);
}