Logo Search packages:      
Sourcecode: fauhdlc version File versions

libfauhdli.c

/* $Id: libfauhdli.c 4321 2009-01-27 13:02:52Z potyra $
 * Interpreter library.
 *
 * Copyright (C) 2008-2009 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#include "libfauhdli.h"
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include "lookup_symbols.h"
#include "kernel.h"
#include "glue-log.h"
#include "signals.h"
#include "trace.h"

#define ARRAY_SIZE(t)   (sizeof t / sizeof(t[0]))

/* definition of scanner */
extern FILE *yyin;
/* definition of parser */
extern int yyparse(struct fauhdli *instance, const char *filename);


static void
fauhdli_destroy_operand(struct operand *op)
{
      if (op == NULL) {
            return;
      }

      switch (op->kind) {
      case OPERAND_TARGET:
            free(op->bytype.target.name);
            break;

      case OPERAND_REFERENCE:
            free(op->bytype.data.name);
            break;

      case OPERAND_IMMEDIATE:
      case OPERAND_INDIRECT:
      case OPERAND_REGISTER:
            /* nothing to do */
            break;
      }

      free(op);
}

static void
fauhdli_destroy_annotations(struct slist *annotations)
{
      struct slist_entry *i;

      if (annotations == NULL) {
            return;
      }

      for (i = annotations->first; i != NULL; i = i->next) {
            struct annotation_spec *a = (struct annotation_spec*)i->data;

            if (a->string_value != NULL) {
                  free(a->string_value);
            }
            free(a->name);
            free(a);
      }

      slist_destroy(annotations);
}

static void
fauhdli_destroy_type_element(struct type_element *elem)
{
      if (elem == NULL) {
            return;
      }
      
      free(elem->name);
      fauhdli_destroy_operand(elem->initial);
      fauhdli_destroy_annotations(elem->annotations);
      free(elem);
}


/** destroy one declaration element.
 *  @param elem declaration element to destroy.
 */
static void
fauhdli_destroy_declaration(struct declaration_element *elem)
{
      struct slist_entry *i;

      if (elem == NULL) {
            return;
      }

      switch (elem->kind) {
      case DECLARATION_TYPE:
            assert(elem->bytype.type_decl.elements != NULL);

            for (i = elem->bytype.type_decl.elements->first; i != NULL;
                  i = i->next) {
                  
                  fauhdli_destroy_type_element(
                        (struct type_element*)i->data);
            }
            slist_destroy(elem->bytype.type_decl.elements);
            break;

      case DECLARATION_DATA:
            free(elem->bytype.data_def.name);
            fauhdli_destroy_type_element(elem->bytype.data_def.type);
            fauhdli_destroy_annotations(
                              elem->bytype.data_def.annotations);
            break;
      }

      free(elem);
}

/** destroy a transfer or stack segment.
 *  @param seg transfer or stack segment to destroy.
 */
static void
fauhdli_destroy_data_seg(struct slist *seg)
{
      struct slist_entry *i;

      if (seg == NULL) {
            return;
      }
      
      for (i = seg->first; i != NULL; i = i->next) {
            fauhdli_destroy_declaration(
                  (struct declaration_element*)i->data);
      }

      slist_destroy(seg);
}

static void
fauhdli_destroy_opcode(struct opcode *opcode)
{
      if (opcode == NULL) {
            return;
      }

      fauhdli_destroy_operand(opcode->op1);
      fauhdli_destroy_operand(opcode->op2);
      fauhdli_destroy_operand(opcode->op3);
      fauhdli_destroy_type_element(opcode->indexed_type);
      fauhdli_destroy_annotations(opcode->annotations);

      switch (opcode->kind) {
      case OPCODE_LABEL:
            free(opcode->label);
            break;

      default:
            break;
      }

      free(opcode);
}

/** destroy a text segment.
 *  @param seg text segment to destroy.
 */
static void
fauhdli_destroy_text_seg(struct slist *seg)
{
      struct slist_entry *i;

      if (seg == NULL) {
            return;
      }

      for (i = seg->first; i != NULL; i = i->next) {
            fauhdli_destroy_opcode((struct opcode *)i->data);
      }
      slist_destroy(seg);
}

/** destroy the code_container hierarchy again recursively.
 *  @param instance fauhdli instance.
 */
static void
fauhdli_destroy_container(struct code_container *container)
{
      struct slist_entry *i;
      assert(container != NULL);
      free(container->name);

      fauhdli_destroy_data_seg(container->transfer_segment);
      fauhdli_destroy_data_seg(container->stack_segment);
      fauhdli_destroy_text_seg(container->text_segment);

      if (container->sub_containers != NULL) {
            for (i = container->sub_containers->first; i != NULL; 
                  i = i->next) {

                  fauhdli_destroy_container(
                        (struct code_container *)i->data);
            }
            slist_destroy(container->sub_containers);
      }

      free(container);
}

static void
fauhdli_destroy_signals(struct slset *sigs)
{
      struct slset_entry *i;
      for (i = sigs->first; i != NULL; i = i->next) {
            signal_destroy((struct signal *)i->data);
      }
      slset_destroy(sigs);
}

static bool
fauhdli_parse(struct fauhdli *instance, const char *file_name)
{
      int ret;
      assert(file_name != NULL);

      yyin = fopen(file_name, "r");
      if (yyin == NULL) {
            faum_log(FAUM_LOG_ERROR, "fauhdli", __func__, 
                  "Failed to open file \"%s\": %s\n",
                  file_name, strerror(errno));
            return false;
      }

      ret = yyparse(instance, file_name);
      if (ret != 0) {
            faum_log(FAUM_LOG_ERROR, "fauhdli", __func__,
                  "Failed to parse file \"%s\"\n", file_name);
            ret = fclose(yyin);
            assert(ret >= 0);
            return false;
      }

      ret = fclose(yyin);
      assert(ret >= 0);
      return true;
}

static void
fauhdli_initialize_registers(struct fauhdli *instance)
{
      unsigned int i;

      /* special return registers */
      /* FIXME: actually these should *not* be initialized */
      instance->registers[0].value.univ_int = 0;
      instance->registers[0].initialized = true;
      instance->registers[0].kind = TYPE_INT;

      instance->registers[1].value.univ_real = 0.0;
      instance->registers[1].initialized = true;
      instance->registers[1].kind = TYPE_FLOAT;

      instance->registers[2].value.pointer = NULL;
      instance->registers[2].initialized = true;
      instance->registers[2].kind = TYPE_POINTER;

      /* simulation time */
      instance->registers[3].value.univ_int = 0;
      instance->registers[3].initialized = true;
      instance->registers[3].kind = TYPE_INT;

      for (i = 4; i < ARRAY_SIZE(instance->registers); i++) {
            instance->registers[i].value.univ_int = 0;
            instance->registers[i].initialized = false;
      }
}

struct opcode *
fauhdli_alloc_opcode(enum opcode_kind kind)
{
      struct opcode *ret = malloc(sizeof(struct opcode));
      assert(ret != NULL);

      ret->kind = kind;
      ret->label = NULL;
      ret->op1 = NULL;
      ret->op2 = NULL;
      ret->op3 = NULL;
      ret->indexed_type = NULL;
      ret->annotations = NULL;

      return ret;
}

struct fauhdli *
fauhdli_create(const char *parse_file, const char *trace_file, bool debug)
{
      struct fauhdli *ret;
      bool r;

      ret = malloc(sizeof(struct fauhdli));
      assert(ret != NULL);
      ret->container = NULL;
      ret->cleanup_ptrs = slset_create(NULL);
      ret->scheduler = vhdl_sched_create();
      ret->signals = slset_create(NULL);
      ret->pending_stack_frames = slset_create(NULL);
      ret->processes = slset_create(NULL);
      ret->sim_time = 0;
      ret->debug = debug;
      ret->drivers = slset_create(NULL);
      ret->foreign_drivers = slset_create(NULL);

      if (trace_file != NULL) {
            ret->tracer = trace_create(trace_file);
      } else {
            ret->tracer = NULL;
      }

      fauhdli_initialize_registers(ret);
      ret->glue_vhdl = NULL;

      r = fauhdli_parse(ret, parse_file);
      if (! r) {
            assert(0);
            return ret;
      }

      return ret;
}

void
fauhdli_destroy(struct fauhdli *instance)
{
      assert(instance != NULL);
      assert(instance->cleanup_ptrs != NULL);

      if (instance->container != NULL) {
            fauhdli_destroy_container(instance->container);
      }

      fauhdli_kernel_destroy(instance);
      slset_destroy(instance->pending_stack_frames);
      slset_destroy(instance->drivers);
      slset_destroy(instance->foreign_drivers);
      slset_destroy_data(instance->cleanup_ptrs);
      fauhdli_destroy_signals(instance->signals);
      vhdl_sched_destroy(instance->scheduler);
      slset_destroy(instance->processes);
      if (instance->tracer != NULL) {
            trace_destroy(instance->tracer);
      }
      glue_vhdl_destroy(instance->glue_vhdl);

      free(instance);
}

void
fauhdli_init(
      struct fauhdli *instance, 
      const char *top_entity
)
{
      if (top_entity == NULL) {
            faum_log(FAUM_LOG_WARNING, "fauhdli", __func__,
                  "Top entity not specified!\n");
      }

      fauhdli_resolve_symbols(instance);
      instance->glue_vhdl = glue_vhdl_create();
      fauhdli_kernel_init(instance, top_entity);
}

const struct annotation_spec *
fauhdli_find_annotation(const char *name, const struct slist *annotations)
{
      struct slist_entry *i;

      if (annotations == NULL) {
            return NULL;
      }

      for (i = annotations->first; i != NULL; i = i->next) {
            const struct annotation_spec *spec = 
                  (const struct annotation_spec *)i->data;
            if (strcmp(spec->name, name) == 0) {
                  return spec;
            }
      }

      return NULL;
}


Generated by  Doxygen 1.6.0   Back to index