Logo Search packages:      
Sourcecode: fauhdlc version File versions

GatherImplicits.cpp

/* $Id: GatherImplicits.cpp 4323 2009-01-27 13:48:12Z potyra $ 
 *
 * Gather implicitly needed variables (e.g. drivers).
 *
 * 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 "frontend/visitor/GatherImplicits.hpp"
#include "frontend/ast/SigAssignStat.hpp"
#include "frontend/ast/VarAssignStat.hpp"
#include "frontend/ast/SimpleName.hpp"
#include "frontend/ast/SignalDeclaration.hpp"
#include "frontend/ast/Process.hpp"
#include "frontend/ast/ProcCallStat.hpp"
#include "frontend/ast/FunctionCall.hpp"
#include "frontend/ast/AssociationElement.hpp"
#include "frontend/ast/ProcedureDeclaration.hpp"
#include "frontend/ast/ValDeclaration.hpp"
#include "frontend/ast/LibUnit.hpp"
#include "frontend/reporting/CompileError.hpp"
#include "frontend/reporting/ErrorRegistry.hpp"

// subprogram: out, inout / signal -> driver to process
// signal gets assigned -> driver to process
//
// TODO it might be a more elegant idea to store ConstArrays 
//      as constants (and Aggregates as well).

namespace ast {

00035 GatherImplicits::GatherImplicits() : mode(VMODE_SOURCE), driverCounter(0),
                              uhfCounter(0)
{
}

void
00041 GatherImplicits::visit(SigAssignStat &node)
{
      this->mode = VMODE_TARGET_SIGNAL;
      node.target->accept(*this);
      this->mode = VMODE_SOURCE;
      assert(node.waveForm);
      this->listTraverse(*node.waveForm);
}

void
00051 GatherImplicits::visit(VarAssignStat &node)
{
      this->mode = VMODE_TARGET_VAR;
      node.target->accept(*this);
      this->mode = VMODE_SOURCE;
      node.source->accept(*this);
}

void
00060 GatherImplicits::visit(SimpleName &node)
{

      switch(this->mode) {
      case VMODE_TARGET_SIGNAL: {
            SignalDeclaration *sig 
                  = dynamic_cast<SignalDeclaration*>(
                                    node.getDeclaration());
            if (sig == NULL) {
                  CompileError *err = new CompileError(node, 
                        "Target of signal assignment not a signal.");
                  ErrorRegistry::addError(err);
                  return;
            }
            node.driver = this->registerDriver(*sig, node);
            break;
          }
      case VMODE_TARGET_VAR: {
            // only check, if it is in fact a VarDeclaration.
            const VarDeclaration *var = 
                  dynamic_cast<const VarDeclaration*>(
                                    node.getDeclaration());
            if (var == NULL) {
                  CompileError *err = new CompileError(node,
                        "Target of a variable assignment not a "
                        "variable.");
                  ErrorRegistry::addError(err);
            }
            break;
          }
      case VMODE_SOURCE:
            // nothing to check
            break;
      }
}

void
00097 GatherImplicits::visit(Process &node)
{
      assert(this->drivers.empty());
      assert(this->formals.empty());
      assert(node.declarations != NULL);

      if (node.seqStats != NULL) {
            this->listTraverse(*node.seqStats);
      }

      assert(node.drivers.empty());

      for (std::map<const SignalDeclaration*, Driver*>::const_iterator i = 
            this->drivers.begin(); i != this->drivers.end(); i++) {
            
            node.drivers.push_back(i->second);
      }

      for (formalMapT::const_iterator i = this->formals.begin(); 
            i != this->formals.end(); i++) {

            node.declarations->push_back(i->second.first);
      }

      this->drivers.clear();
      this->formals.clear();
}

void
00126 GatherImplicits::visit(FunctionCall &node)
{
      // type resolution must have happened before
      assert(node.definition != NULL);

      switch(this->mode) {
      case VMODE_TARGET_SIGNAL:
      case VMODE_TARGET_VAR: {
            CompileError *err = 
                  new CompileError(node, 
                              "Invalid lvalue in assignment");
            ErrorRegistry::addError(err);
            return;
          }
      default:
            // nothing to do
            break;
      }

      if (node.arguments == NULL) {
            return;
      }

      if (node.definition->arguments == NULL) {
            return;
      }

      std::list<ValDeclaration *>::const_iterator i = 
                        node.definition->arguments->begin();

      for (std::list<AssociationElement*>::const_iterator j = 
            node.arguments->begin(); j != node.arguments->end();
            i++, j++) {

            assert(i != node.definition->arguments->end());

            switch ((*i)->storageClass) {
            case ValDeclaration::OBJ_CLASS_CONSTANT:
                  // need hidden formals for composite types only.
                  assert((*i)->subtypeIndic != NULL);
                  switch ((*i)->subtypeIndic->baseType) {
                  case BASE_TYPE_ARRAY:
                  case BASE_TYPE_RECORD:
                        (*j)->hiddenFormal = 
                              this->registerFormal(*i, 
                                          (*j)->actual->type);
                        break;

                  default:
                        break;
                  }
                  break;

            default:
                  break;
            }
      }
}

void
00186 GatherImplicits::visit(ProcCallStat &node)
{
      assert(node.definition != NULL);

      if (node.definition->arguments == NULL) {
            return;
      }

      // TODO register implicit formals as necessary.
      if (node.arguments == NULL) {
            return;
      }

      assert(node.definition->arguments != NULL);
      std::list<ValDeclaration*>::const_iterator f = 
            node.definition->arguments->begin();

      // pickup drivers from actuals
      for (std::list<AssociationElement*>::iterator i = 
            node.arguments->begin();
            i != node.arguments->end(); i++, f++) {

            switch ((*f)->mode) {
            case ValDeclaration::MODE_OUT:
            case ValDeclaration::MODE_INOUT:
                  switch ((*f)->storageClass) {
                  case ValDeclaration::OBJ_CLASS_SIGNAL:
                        this->mode = VMODE_TARGET_SIGNAL;
                        break;

                  case ValDeclaration::OBJ_CLASS_VARIABLE:
                        this->mode = VMODE_TARGET_VAR;
                        break;

                  default:
                        break;
                  }
            default:
                  break;
            }

            switch ((*f)->storageClass) {
            case ValDeclaration::OBJ_CLASS_CONSTANT:
                  assert((*f)->subtypeIndic != NULL);
                  switch ((*f)->subtypeIndic->baseType) {
                  case BASE_TYPE_RECORD:
                  case BASE_TYPE_ARRAY:
                        (*i)->hiddenFormal = 
                              this->registerFormal(*f, 
                                          (*i)->actual->type);
                        break;

                  default:
                        break;
                  }
                  break;

            default:
                  break;
            }

            (*i)->actual->accept(*this);
            this->mode = VMODE_SOURCE;
      }
}

void
00253 GatherImplicits::visit(FunctionDeclaration &node)
{
      this->processCallable(node);
}

void
00259 GatherImplicits::visit(ProcedureDeclaration &node)
{
      this->processCallable(node);
}

void
00265 GatherImplicits::processCallable(Callable &node)
{
      assert(this->drivers.empty());
      assert(this->formals.empty());

      if (node.definition != NULL) {
            node.definition->accept(*this);
      }

      // FIXME that's still ugly and will fail for procedures that 
      //       are defined in a process and directly modify signals.

      if (node.arguments != NULL) {
            for (std::list<ValDeclaration*>::const_iterator i = 
                  node.arguments->begin();
                  i != node.arguments->end(); i++) {

                  switch ((*i)->mode) {
                  case ValDeclaration::MODE_IN:
                        break;

                  case ValDeclaration::MODE_OUT:
                  case ValDeclaration::MODE_INOUT:
                        switch ((*i)->storageClass) {
                        case ValDeclaration::OBJ_CLASS_SIGNAL:
                              this->registerDriver(**i,
                                          SYMBOL_PARAMETER);
                              break;

                        default:
                              break;
                        }
                        break;
                  }
            }
      }


      for (std::map<const SignalDeclaration*, Driver*>::const_iterator i = 
            this->drivers.begin(); i != this->drivers.end(); i++) {
            node.drivers.push_back(i->second);
      }

      // FIXME do s.th. with formals!

      this->formals.clear();
      this->drivers.clear();
}

void
00315 GatherImplicits::process(LibUnit &node)
{
      if (node.declarations != NULL) {
            this->listTraverse(*node.declarations);
      }
}

Driver *
00323 GatherImplicits::registerDriver(const SignalDeclaration &decl, SimpleName &n)
{

      std::map<const SignalDeclaration*, Driver*>::const_iterator i = 
            this->drivers.find(&decl);
      
      if (i != this->drivers.end()) {
            // driver registered already
            return i->second;
      }

      // driver not yet present.
      Driver *d = new Driver(decl, this->driverCounter, &n);
      this->driverCounter++;
      this->drivers[&decl] = d;
      return d;
}

void
00342 GatherImplicits::registerDriver(ValDeclaration &decl, enum symType t)
{
      // must not throw an exception, otherwise logic error
      SignalDeclaration &d = dynamic_cast<SignalDeclaration&>(decl);

      std::map<const SignalDeclaration*, Driver*>::const_iterator i = 
            this->drivers.find(&d);
      
      if (i != this->drivers.end()) {
            // driver registered already
            return;
      }

      Symbol *sym = new Symbol(d.name, t, NULL, d);
      std::list<Symbol *> cands = std::list<Symbol*>();
      cands.push_back(sym);
      SimpleName *sn = new SimpleName(new std::string(*d.name), cands, 
                              d.location);
      this->registerDriver(d, *sn);
}

SimpleName *
00364 GatherImplicits::registerFormal(
      const ValDeclaration *formal,
      TypeDeclaration *actualType
)
{
      formalMapT::const_iterator i = this->formals.find(formal);
      if (i != this->formals.end()) {
            return i->second.second;
      }

      std::string *name = new std::string("__");
      *name += *formal->name;
      *name += "__hidden_formal__";

      SubtypeIndication *si;
      bool isUnconstraint = formal->isUnconstraint();
      if (isUnconstraint) {
            si = dynamic_cast<SubtypeIndication*>(actualType);
            assert(si != NULL);
            *name += util::MiscUtil::toString(this->uhfCounter);
            this->uhfCounter++;
      } else {
            si = formal->subtypeIndic;
      }

      // generate a ValDeclaration
      VarDeclaration *hidden = 
            new VarDeclaration(
                              formal->mode, 
                              name, 
                              NULL, 
                              si,
                              Location("__hidden_formal__"));
      Symbol *sym = new Symbol(name, SYMBOL_VARIABLE, NULL, *hidden);
      std::list<Symbol *> cands = std::list<Symbol*>();
      cands.push_back(sym);
      
      SimpleName *ref = new SimpleName(new std::string(*name), 
                              cands,
                              Location("__builtin__"));

      if (isUnconstraint) {
            // need seperate entries for each actual of a 
            // unconstraint formal, since the storage size
            // can differs.
            this->formals[hidden] =
                  std::pair<ValDeclaration*, SimpleName*>(hidden, ref);
      } else {
            // but only one entry for a constraint formal, since
            // the storage size is fixed.
            this->formals[formal] = 
                  std::pair<ValDeclaration*, SimpleName*>(hidden, ref);
      }
      return ref;
}


}; /* namespace ast */

Generated by  Doxygen 1.6.0   Back to index