Logo Search packages:      
Sourcecode: fauhdlc version File versions

NormalizeAssocLists.cpp

/* $Id: NormalizeAssocLists.cpp 4323 2009-01-27 13:48:12Z potyra $
 *
 * Normalize association lists.
 *
 * 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/NormalizeAssocLists.hpp"
#include "frontend/ast/CompInstStat.hpp"
#include "frontend/ast/AttributeName.hpp"
#include "frontend/ast/SelectedName.hpp"
#include "frontend/ast/SimpleName.hpp"
#include "frontend/ast/TemporaryName.hpp"
#include "frontend/ast/AssociationElement.hpp"
#include "frontend/ast/LibraryList.hpp"
#include "frontend/ast/Library.hpp"
#include "frontend/ast/Architecture.hpp"
#include "frontend/reporting/ErrorRegistry.hpp"
#include <algorithm>
#include <vector>


namespace ast {

void
00029 NormalizeAssocLists::visit(CompInstStat &node)
{
      assert(node.entity != NULL);
      assert(node.entity->ports != NULL);
      assert(node.entity->region != NULL);
      this->ports = *node.entity->ports;
      this->positional = true;
      this->pos = 0;
      this->region = node.entity->region;

      if (node.portMap != NULL) {
            this->listTraverse(*node.portMap);
            this->addMissingPortAssocs(node);

            /* sort port map by position */
            std::vector<AssociationElement*> v;
            v.insert(v.begin(), 
                  node.portMap->begin(), node.portMap->end());

            std::sort(v.begin(), v.end(), 
                  NormalizeAssocLists::sortPosPred);

            node.portMap->clear();
            node.portMap->insert(node.portMap->begin(), 
                  v.begin(), v.end());
      }

      this->ports.clear();
      this->region = NULL;
}

void
00061 NormalizeAssocLists::visit(AssociationElement &node)
{
      if (node.formal == NULL) {
            if (! this->positional) {
                  CompileError *ce = 
                        new CompileError(node, 
                              "Positional association "
                              "used after named association.");
                  ErrorRegistry::addError(ce);
                  return;
            }
            
            if (this->ports.empty()) {
                  CompileError *ce = 
                        new CompileError(node,
                              "Cannot associate positional "
                              "association (too many arguments?).");
                  ErrorRegistry::addError(ce);
                  return;
            }

            // register SimpleName as formal
            assert(this->region != NULL);
            const SignalDeclaration *formal = this->ports.front();
            SimpleName *sn = 
                  NormalizeAssocLists::makeNameOfSignal(
                                          formal, 
                                          this->region,
                                          node.location);

            node.formal = sn;
            this->ports.pop_front();
            node.pos = this->pos;
            this->pos++;

            return;
      }

      // named association
      this->positional = false;
      this->pickedUpSig = NULL;
      node.formal->accept(*this);
      assert(this->pickedUpSig != NULL);

      node.pos = this->findAndRemovePort(this->pickedUpSig, node.location);
      this->pickedUpSig = NULL;
}

void
00110 NormalizeAssocLists::visit(SimpleName &node)
{
      const SymbolDeclaration *decl = node.getDeclaration();
      const SignalDeclaration *sig = 
            dynamic_cast<const SignalDeclaration*>(decl);
      
      assert(sig != NULL);
      this->pickedUpSig = sig;
}

void
00121 NormalizeAssocLists::visit(TemporaryName &node)
{
      CompileError *ce = 
            new CompileError(node,
                        "Cannot use temporary names in "
                        "associations.");
      ErrorRegistry::addError(ce);
}

void
00131 NormalizeAssocLists::visit(SelectedName &node)
{
      // FIXME individual association currently unsupported.
      assert(false);
}

void
00138 NormalizeAssocLists::visit(AttributeName &node)
{
      CompileError *ce = 
            new CompileError(node, 
                        "Cannot use attributes in port "
                        "associations.");
      ErrorRegistry::addError(ce);                          
}

void 
00148 NormalizeAssocLists::visit(Architecture &node) 
{
      /* traverse to concurrentStats */
      this->arch = &node;
      if (node.concurrentStats != NULL) {
            this->listTraverse(*node.concurrentStats);
      }
      this->arch = NULL;
}

void
00159 NormalizeAssocLists::visit(Library& node)
{
      this->listTraverse(node.units);
}

void
00165 NormalizeAssocLists::visit(LibraryList& node)
{
      this->listTraverse(node.libraries);
}

int
00171 NormalizeAssocLists::findAndRemovePort(
      const SignalDeclaration *sig, 
      Location errLoc
)
{
      int p = this->pos;
      for (std::list<SignalDeclaration*>::iterator i = this->ports.begin();
            i != this->ports.end(); i++, p++) {
            
            if ((*i) == sig) {
                  this->ports.erase(i);
                  return p;
            }
      }

      std::string msg = "Error in association: <";
      msg += *(sig->name);
      msg += "> already associated.";

      CompileError *ce = new CompileError(errLoc, msg);
      ErrorRegistry::addError(ce);
      return -1;        
}

void
00196 NormalizeAssocLists::addMissingPortAssocs(CompInstStat &node)
{
      while (! this->ports.empty()) {
            SignalDeclaration *sig = this->ports.front();

            switch (sig->mode) {
            case ValDeclaration::MODE_IN: {
                  std::string msg = 
                        std::string("Must associate port <");
                  msg += *sig->name;
                  msg += "> which has mode IN.";
                  CompileError *ce = new CompileError(node, msg);
                  ErrorRegistry::addError(ce);
                  break;
                }
            case ValDeclaration::MODE_INOUT:
                  // must have initializer
                  if (sig->init == NULL) {
                        std::string msg = 
                              std::string("Must associate");
                        msg += " port <";
                        msg += *sig->name;
                        msg += "> which has mode INOUT but no ";
                        msg += "initializer.";
                        CompileError *ce = 
                              new CompileError(node, msg);
                        ErrorRegistry::addError(ce);
                  }
                  break;

            case ValDeclaration::MODE_OUT:
                  // ok
                  break;
            }
            
            // make excplicit association with an implicit signal
            std::string *n = new std::string(*(sig->name));
            (*n) += "__hidden__";
            (*n) += util::MiscUtil::toString(this->hiddenCounter);

            SignalDeclaration *hiddenSig = 
                  new SignalDeclaration(
                              n,
                              sig->mode,
                              false,
                              sig->init,
                              sig->subtypeIndic,
                              node.location);

            assert(this->arch != NULL);
            assert(this->arch->declarations != NULL);
            assert(this->arch->region != NULL);
            assert(this->region != NULL);

            this->arch->declarations->push_back(hiddenSig);
            Symbol *sym = new Symbol(n, SYMBOL_SIGNAL, NULL, *hiddenSig);
            this->arch->region->registerSymbol(sym);

            SimpleName *actual = 
                  NormalizeAssocLists::makeNameOfSignal(
                                          hiddenSig, 
                                          this->arch->region,
                                          node.location);
            SimpleName *formal = 
                  NormalizeAssocLists::makeNameOfSignal(
                                          sig,
                                          this->region,
                                          node.location);
            AssociationElement *elem = 
                  new AssociationElement(formal, actual, node.location);

            actual->baseType = sig->subtypeIndic->baseType;
            formal->baseType = sig->subtypeIndic->baseType;

            assert(node.portMap != NULL);
            node.portMap->push_back(elem);
            
            this->hiddenCounter++;
            this->ports.pop_front();
      }
}

bool 
00279 NormalizeAssocLists::sortPosPred(
      AssociationElement *l, 
      AssociationElement *r
) {
      return l->pos < r->pos;
}

SimpleName *
00287 NormalizeAssocLists::makeNameOfSignal(
      const SignalDeclaration *sig,
      const DeclarativeRegion *lookupRegion,
      Location loc
)
{
      std::list<Symbol *> formalCands = 
            lookupRegion->lookupLocal(*sig->name);
      assert(formalCands.size() == 1);

      SimpleName *sn = 
            new SimpleName(new std::string(*sig->name),
                        formalCands,
                        loc);
      return sn;
}
      

}; /* namespace ast */

Generated by  Doxygen 1.6.0   Back to index