/*
 Copyright 2019 Alain Dargelas

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

/*
 * File:   DesignElaboration.cpp
 * Author: alain
 *
 * Created on July 12, 2017, 8:55 PM
 */
#include "Utils/StringUtils.h"
#include "SourceCompile/VObjectTypes.h"
#include "Design/VObject.h"
#include "Library/Library.h"
#include "Design/FileContent.h"
#include "SourceCompile/SymbolTable.h"
#include "ErrorReporting/Error.h"
#include "ErrorReporting/Location.h"
#include "ErrorReporting/Error.h"
#include "ErrorReporting/ErrorDefinition.h"
#include "ErrorReporting/ErrorContainer.h"
#include "Config/ConfigSet.h"
#include "CommandLine/CommandLineParser.hpp"
#include "SourceCompile/CompilationUnit.h"
#include "SourceCompile/PreprocessFile.h"
#include "SourceCompile/CompileSourceFile.h"
#include "SourceCompile/ParseFile.h"
#include "SourceCompile/Compiler.h"
#include "DesignCompile/CompileDesign.h"
#include "Testbench/Property.h"
#include "Design/Function.h"
#include "Testbench/ClassDefinition.h"
#include "DesignCompile/DesignElaboration.h"
#include <queue>

using namespace SURELOG;

DesignElaboration::DesignElaboration(CompileDesign* compileDesign)
    : ElaborationStep(compileDesign) {
  m_moduleDefFactory = NULL;
  m_moduleInstFactory = NULL;
  m_exprBuilder.seterrorReporting(
      m_compileDesign->getCompiler()->getErrorContainer(),
      m_compileDesign->getCompiler()->getSymbolTable());
}

DesignElaboration::~DesignElaboration() {}

bool DesignElaboration::elaborate() {
  createBuiltinPrimitives_();
  setupConfigurations_();
  identifyTopModules_();
  elaborateAllModules_(true);
  elaborateAllModules_(false);
  reduceUnnamedBlocks_();
  checkElaboration_();
  reportElaboration_();
  return true;
}

bool DesignElaboration::setupConfigurations_() {
  ConfigSet* configSet =
      m_compileDesign->getCompiler()->getDesign()->getConfigSet();
  SymbolTable* st =
      m_compileDesign->getCompiler()->getCommandLineParser()->getSymbolTable();
  std::vector<Config>& allConfigs = configSet->getAllConfigs();
  std::vector<SymbolId> selectedConfigIds =
      m_compileDesign->getCompiler()->getCommandLineParser()->getUseConfigs();
  std::set<std::string> selectedConfigs;
  for (auto confId : selectedConfigIds) {
    std::string name = st->getSymbol(confId);
    if (name.find(".") == std::string::npos) {
      name = "work@" + name;
    } else {
      name = StringUtils::replaceAll(name, ".", "@");
    }
    selectedConfigs.insert(name);
    bool found = false;
    for (auto& config : allConfigs) {
      if (config.getName() == name) {
        found = true;
        break;
      }
    }
    if (!found) {
      Location loc(st->registerSymbol(name));
      Error err(ErrorDefinition::CMD_UNDEFINED_CONFIG, loc);
      m_compileDesign->getCompiler()->getErrorContainer()->addError(err);
    }
  }

  std::queue<std::string> configq;
  for (auto& config : allConfigs) {
    if (selectedConfigs.find(config.getName()) != selectedConfigs.end()) {
      config.setIsUsed();
      config.setTopLevel(true);
      configq.push(config.getName());
    }
  }
  std::set<Config*> configS;
  while (configq.size()) {
    std::string configName = configq.front();
    configq.pop();
    Config* conf = configSet->getConfig(configName);
    if (conf) {
      if (configS.find(conf) != configS.end()) {
        continue;
      }
      configS.insert(conf);

      conf->setIsUsed();
      for (auto& usec : conf->getInstanceUseClauses()) {
        if (usec.second.getType() == UseClause::UseConfig) {
          std::string confName = usec.second.getName();
          configq.push(confName);
          Config* conf = configSet->getConfig(confName);
          if (!conf) {
            FileContent* fC = usec.second.getFileContent();
            Location loc(
                st->registerSymbol(fC->getFileName(usec.second.getNodeId())),
                fC->Line(usec.second.getNodeId()), 0,
                st->registerSymbol(confName));
            Error err(ErrorDefinition::ELAB_UNDEFINED_CONFIG, loc);
            m_compileDesign->getCompiler()->getErrorContainer()->addError(err);
          }
        }
      }
    }
  }

  std::vector<std::string> unused;
  for (auto& config : allConfigs) {
    std::string name = config.getName();
    FileContent* fC = config.getFileContent();
    SymbolId fid = st->registerSymbol(fC->getFileName(config.getNodeId()));
    unsigned int line = fC->Line(config.getNodeId());
    Location loc(fid, line, 0, st->getId(config.getName()));
    if (!config.isUsed()) {
      Error err(ErrorDefinition::ELAB_CONFIGURATION_IGNORED, loc);
      m_compileDesign->getCompiler()->getErrorContainer()->addError(err);
      unused.push_back(name);
    } else {
      Error err(ErrorDefinition::ELAB_CONFIGURATION_USED, loc);
      m_compileDesign->getCompiler()->getErrorContainer()->addError(err);
    }
  }

  // Remove unused configs from set
  for (auto name : unused) {
    std::vector<Config>::iterator itr;
    for (itr = allConfigs.begin(); itr != allConfigs.end(); itr++) {
      if ((*itr).getName() == name) {
        allConfigs.erase(itr);
        break;
      }
    }
  }

  // Create top level module list and recurse configs
  for (auto& config : allConfigs) {
    if (config.isTopLevel()) {
      std::string lib = config.getDesignLib();
      std::string top = config.getDesignTop();
      std::string name = lib + "@" + top;
      m_toplevelConfigModules.insert(name);
      m_instConfig.insert(std::make_pair(name, config));
      m_cellConfig.insert(std::make_pair(name, config));

      for (auto& instClause : config.getInstanceUseClauses()) {
        m_instUseClause.insert(
            std::make_pair(lib + "@" + instClause.first, instClause.second));
        if (instClause.second.getType() == UseClause::UseConfig) {
          Config* config = configSet->getConfig(instClause.second.getName());
          if (config) {
            std::set<Config*> configStack;
            recurseBuildInstanceClause_(lib + "@" + instClause.first, config,
                                        configStack);
          }
        }
      }
      for (auto& cellClause : config.getCellUseClauses()) {
        m_cellUseClause.insert(
            std::make_pair(cellClause.first, cellClause.second));
      }
    }
  }
  return true;
}

void DesignElaboration::recurseBuildInstanceClause_(
    std::string parentPath, Config* config, std::set<Config*>& configStack) {
  if (configStack.find(config) != configStack.end()) {
    return;
  }
  configStack.insert(config);

  ConfigSet* configSet =
      m_compileDesign->getCompiler()->getDesign()->getConfigSet();
  for (auto& useClause : config->getInstanceUseClauses()) {
    std::string inst = useClause.first;
    std::string fullPath = parentPath + "." + inst;
    m_instUseClause.insert(std::make_pair(fullPath, useClause.second));
    if (useClause.second.getType() == UseClause::UseConfig) {
      Config* config = configSet->getConfig(useClause.second.getName());
      if (config) {
        recurseBuildInstanceClause_(parentPath + "." + useClause.first, config,
                                    configStack);
      }
    }
  }
  for (auto& useClause : config->getCellUseClauses()) {
    std::string inst = useClause.first;
    std::string fullPath = inst;
    m_cellUseClause.insert(std::make_pair(fullPath, useClause.second));
  }
}

bool DesignElaboration::identifyTopModules_() {
  m_topLevelModules.clear();
  bool modulePresent = false;
  bool toplevelModuleFound = false;
  SymbolTable* st = m_compileDesign->getCompiler()->getSymbolTable();
  auto all_files =
      m_compileDesign->getCompiler()->getDesign()->getAllFileContents();
  typedef std::multimap<std::string, std::pair<DesignElement*, FileContent*>>
      ModuleMultiMap;
  ModuleMultiMap all_modules;
  for (auto file : all_files) {
    if (m_compileDesign->getCompiler()->isLibraryFile(file.first)) continue;
    for (DesignElement& element : file.second->getDesignElements()) {
      std::string elemName = st->getSymbol(element.m_name);
      if (element.m_type == DesignElement::Module) {
        if (element.m_parent) {
          // This is a nested element
          continue;
        }
        std::string topname = file.second->getLibrary()->getName();
        topname += "@" + elemName;

        if (!file.second->getParent()) {
          // Files that have parent are splited files (When a module is too
          // large it is splited)
          all_modules.insert(
              std::make_pair(topname, std::make_pair(&element, file.second)));
        }

        modulePresent = true;
        bool used = false;
        for (auto file1 : all_files) {
          if (file1.second->getReferencedObjects().find(elemName) !=
              file1.second->getReferencedObjects().end()) {
            used = true;
            break;
          }
        }

        if (!used) {
          bool isTop = true;

          if (m_toplevelConfigModules.size()) {
            isTop = false;
            if (m_toplevelConfigModules.find(topname) !=
                m_toplevelConfigModules.end()) {
              isTop = true;
            }
          }

          if (isTop) {
            SymbolId topid = st->registerSymbol(topname);
            auto itr = m_uniqueTopLevelModules.find(topname);
            Location loc(
                st->registerSymbol(file.second->getFileName(element.m_node)),
                element.m_line, 0, topid);
            if (itr == m_uniqueTopLevelModules.end()) {
              m_uniqueTopLevelModules.insert(topname);
              m_topLevelModules.push_back(std::make_pair(topname, file.second));
              toplevelModuleFound = true;
              Error err(ErrorDefinition::ELAB_TOP_LEVEL_MODULE, loc);
              m_compileDesign->getCompiler()->getErrorContainer()->addError(
                  err);
            }
          }
        }
      }
    }
  }

  // Check for multiple definition
  std::string prevModuleName = "";
  DesignElement* prevModuleDefinition = NULL;
  FileContent* prevFileContent = NULL;
  for (ModuleMultiMap::iterator itr = all_modules.begin();
       itr != all_modules.end(); itr++) {
    std::string moduleName = (*itr).first;
    DesignElement* moduleDefinition = (*itr).second.first;
    FileContent* fileContent = (*itr).second.second;
    bool done = false;
    if (moduleName == prevModuleName) {
      FileContent* fC1 = (*itr).second.second;
      NodeId nodeId1 = moduleDefinition->m_node;
      std::string fileName1 = fC1->getFileName(nodeId1);
      unsigned int line1 = fC1->Line(nodeId1);
      Location loc1(st->registerSymbol(fileName1), line1, 0,
                    st->registerSymbol(moduleName));

      std::vector<Location> locations;

      while (1) {
        FileContent* fC2 = prevFileContent;
        NodeId nodeId2 = prevModuleDefinition->m_node;
        std::string fileName2 = fC2->getFileName(nodeId2);
        unsigned int line2 = fC2->Line(nodeId2);
        Location loc2(st->registerSymbol(fileName2), line2, 0,
                      st->registerSymbol(moduleName));

        if ((fileName1 != fileName2) || (line1 != line2)) {
          locations.push_back(loc2);
        }

        itr++;
        if (itr == all_modules.end()) {
          done = true;
          break;
        } else {
          std::string nextModuleName = (*itr).first;
          DesignElement* nextModuleDefinition = (*itr).second.first;
          FileContent* nextFileContent = (*itr).second.second;
          prevModuleName = nextModuleName;
          prevModuleDefinition = nextModuleDefinition;
          prevFileContent = nextFileContent;
          if (prevModuleName != moduleName) {
            moduleName = prevModuleName;
            moduleDefinition = prevModuleDefinition;
            fileContent = prevFileContent;
            break;
          }
        }
      }

      if (locations.size()) {
        Error err1(ErrorDefinition::ELAB_MULTIPLY_DEFINED_MODULE, loc1,
                   &locations);
        m_compileDesign->getCompiler()->getErrorContainer()->addError(err1);
      }
    }
    prevModuleName = moduleName;
    prevModuleDefinition = moduleDefinition;
    prevFileContent = fileContent;
    if (done) break;
  }

  if (m_topLevelModules.size() > 1) {
    Location loc(0);
    Error err(ErrorDefinition::ELAB_MULTIPLE_TOP_LEVEL_MODULES, loc);
    m_compileDesign->getCompiler()->getErrorContainer()->addError(err);
  }
  if (modulePresent && (!toplevelModuleFound)) {
    Location loc(0);
    Error err(ErrorDefinition::ELAB_NO_TOP_LEVEL_MODULE, loc);
    m_compileDesign->getCompiler()->getErrorContainer()->addError(err);
  }

  return true;
}

bool DesignElaboration::createBuiltinPrimitives_() {
  m_moduleDefFactory = new ModuleDefinitionFactory();
  Design* design = m_compileDesign->getCompiler()->getDesign();

  // Register built-in primitives
  for (auto type :
       {"cmos",     "rcmos",    "bufif0", "bufif1",  "notif0",
        "notif1",   "nmos",     "pmos",   "rnmos",   "rpmos",
        "and",      "or",       "nand",   "nor",     "xor",
        "xnor",     "buf",      "not",    "tranif0", "tranif1",
        "rtranif0", "rtranif1", "tran",   "rtran",   "UnsupportedPrimitive"}) {
    std::string name = std::string("work@") + type;
    design->addModuleDefinition(name,
                                m_moduleDefFactory->newModuleDefinition(
                                    NULL, 0, std::string("work@") + type));
  }

  return true;
}

bool DesignElaboration::elaborateAllModules_(bool onlyTopLevel) {
  bool status = true;
  for (auto topmodule : m_topLevelModules) {
    if (!elaborateModule_(topmodule.first, topmodule.second, onlyTopLevel)) {
      status = false;
    }
  }
  return status;
}

Config* DesignElaboration::getInstConfig(std::string name) {
  Config* config = NULL;
  auto itr = m_instConfig.find(name);
  if (itr != m_instConfig.end()) {
    config = &(*itr).second;
  }
  return config;
}

Config* DesignElaboration::getCellConfig(std::string name) {
  Config* config = NULL;
  auto itr = m_cellConfig.find(name);
  if (itr != m_cellConfig.end()) {
    config = &(*itr).second;
  }
  return config;
}

bool DesignElaboration::elaborateModule_(std::string moduleName,
                                         FileContent* fC, bool onlyTopLevel) {
  FileContent::NameIdMap& nameIds = fC->getObjectLookup();
  std::vector<VObjectType> types = {VObjectType::slUdp_instantiation,
                                    VObjectType::slModule_instantiation,
                                    VObjectType::slInterface_instantiation,
                                    VObjectType::slProgram_instantiation};
  std::string libName = fC->getLibrary()->getName();
  Config* config = getInstConfig(moduleName);
  if (config == NULL) config = getCellConfig(moduleName);
  Design* design = m_compileDesign->getCompiler()->getDesign();
  if (!m_moduleInstFactory) m_moduleInstFactory = new ModuleInstanceFactory();
  for (auto nameId : nameIds) {
    if ((fC->Type(nameId.second) == VObjectType::slModule_declaration) &&
        (moduleName == (libName + "@" + nameId.first))) {
      DesignComponent* def = design->getComponentDefinition(moduleName);
      if (onlyTopLevel) {
        ModuleInstance* instance = m_moduleInstFactory->newModuleInstance(
            def, fC, nameId.second, NULL, moduleName, moduleName);
        design->addTopLevelModuleInstance(instance);
      } else {
        ModuleInstance* instance = design->findInstance(moduleName);
        for (unsigned int i = 0; i < def->getFileContents().size(); i++)
          elaborateInstance_(def->getFileContents()[i], def->getNodeIds()[i], 0,
                             m_moduleInstFactory, instance, config);
      }
      break;
    }
  }
  return true;
}

void DesignElaboration::recurseInstanceLoop_(
    std::vector<int>& from, std::vector<int>& to, std::vector<int>& indexes,
    unsigned int pos, DesignComponent* def, FileContent* fC,
    NodeId subInstanceId, NodeId paramOverride, ModuleInstanceFactory* factory,
    ModuleInstance* parent, Config* config, std::string instanceName,
    std::string modName, std::vector<ModuleInstance*>& allSubInstances) {
  if (pos == indexes.size()) {
    // This is where the real logic goes.
    // indexes[i] contain the value of the i-th index.
    for (unsigned int i = 0; i < indexes.size(); i++) {
      instanceName += std::to_string(indexes[i]);
    }
    ModuleInstance* child = factory->newModuleInstance(
        def, fC, subInstanceId, parent, instanceName, modName);
    VObjectType type = fC->Type(subInstanceId);
    if (def && (type != VObjectType::slGate_instantiation))
      for (unsigned int i = 0; i < def->getFileContents().size(); i++)
        elaborateInstance_(def->getFileContents()[i], def->getNodeIds()[i],
                           paramOverride, factory, child, config);
    allSubInstances.push_back(child);

  } else {
    for (indexes[pos] = from[pos]; indexes[pos] <= to[pos]; indexes[pos]++) {
      // Recurse for the next level
      recurseInstanceLoop_(from, to, indexes, pos + 1, def, fC, subInstanceId,
                           paramOverride, factory, parent, config, instanceName,
                           modName, allSubInstances);
    }
  }
}

void DesignElaboration::elaborateInstance_(FileContent* fC, NodeId nodeId,
                                           NodeId parentParamOverride,
                                           ModuleInstanceFactory* factory,
                                           ModuleInstance* parent,
                                           Config* config) {
  if (!parent) return;
  std::vector<ModuleInstance*> allSubInstances;
  std::string genBlkBaseName = "genblk";
  unsigned int genBlkIndex = 1;
  bool reuseInstance = false;
  std::string mname;
  std::vector<VObjectType> types;
  std::vector<std::string> params;

  // Scan for parameters, including DefParams
  collectParams_(params, fC, nodeId, parent, parentParamOverride);

  // Apply DefParams
  Design* design = m_compileDesign->getCompiler()->getDesign();
  for (auto name : params) {
    DefParam* defparam =
        design->getDefParam(parent->getFullPathName() + "." + name);
    if (defparam) {
      Value* value = defparam->getValue();
      if (value) {
        parent->setValue(name, value, m_exprBuilder);
        defparam->setUsed();
      }
    }
  }

  // Scan for regular instances and generate blocks
  types = {
      VObjectType::slUdp_instantiation,
      VObjectType::slModule_instantiation,
      VObjectType::slInterface_instantiation,
      VObjectType::slProgram_instantiation,
      VObjectType::slGate_instantiation,
      VObjectType::slConditional_generate_construct,  // Generate construct are
                                                      // a kind of instantiation
      VObjectType::slGenerate_module_conditional_statement,
      VObjectType::slLoop_generate_construct,
      VObjectType::slGenerate_module_loop_statement,
      VObjectType::slPar_block,
      VObjectType::slSeq_block};

  std::vector<VObjectType> stopPoints = {
      VObjectType::slConditional_generate_construct,
      VObjectType::slGenerate_module_conditional_statement,
      VObjectType::slLoop_generate_construct,
      VObjectType::slGenerate_module_loop_statement,
      VObjectType::slPar_block,
      VObjectType::slSeq_block,
      VObjectType::slModule_declaration};

  std::vector<NodeId> subInstances =
      fC->sl_collect_all(nodeId, types, stopPoints);

  for (auto subInstanceId : subInstances) {
    NodeId childId = 0;
    std::string instName;
    std::string modName;
    DesignComponent* def = NULL;
    NodeId paramOverride = 0;
    Config* subConfig = config;
    VObjectType type = fC->Type(subInstanceId);

    if (type == slSeq_block || type == slPar_block) {
      NodeId identifierId = fC->Child(subInstanceId);
      if (fC->Name(identifierId))
        instName = fC->SymName(identifierId);
      else
        instName = "UNNAMED";
    } else if (type == slConditional_generate_construct) {
      NodeId constructId = fC->Child(subInstanceId);
      NodeId condId = fC->Child(constructId);
      NodeId blockId = fC->Sibling(condId);
      NodeId nameId = fC->Child(blockId);
      if (fC->Name(nameId))
        instName = fC->SymName(nameId);
      else
        instName = "UNNAMED";
    } else {
      NodeId instId = fC->sl_collect(subInstanceId, slName_of_instance);
      NodeId identifierId = 0;
      if (instId != InvalidNodeId) {
        identifierId = fC->Child(instId);
        instName = fC->SymName(identifierId);
      }
    }

    // Special module binding for built-in primitives
    if (type == VObjectType::slGate_instantiation) {
      VObjectType gatetype = fC->Type(fC->Child(subInstanceId));
      switch (gatetype) {
        case VObjectType::slNInpGate_And:
          modName = "work@and";
          break;
        case VObjectType::slNInpGate_Or:
          modName = "work@or";
          break;
        case VObjectType::slNInpGate_Nand:
          modName = "work@nand";
          break;
        case VObjectType::slNInpGate_Nor:
          modName = "work@nor";
          break;
        case VObjectType::slNInpGate_Xor:
          modName = "work@xor";
          break;
        case VObjectType::slNInpGate_Xnor:
          modName = "work@xnor";
          break;
        case VObjectType::slNOutGate_Buf:
          modName = "work@buf";
          break;
        case VObjectType::slNOutGate_Not:
          modName = "work@not";
          break;
          // TODO: Cater for the transistor level
        default:
          modName = "work@UnsupportedPrimitive";
          break;
      }

      def = design->getComponentDefinition(modName);
      childId = 0;  // = def->getNodeId ();
      ModuleInstance* child = factory->newModuleInstance(
          def, fC, subInstanceId, parent, instName, modName);
      allSubInstances.push_back(child);

    }
    // Special module binding for generate statements
    else if (type == VObjectType::slConditional_generate_construct ||
             type == VObjectType::slGenerate_module_conditional_statement ||
             type == VObjectType::slLoop_generate_construct ||
             type == VObjectType::slGenerate_module_loop_statement) {
      modName = genBlkBaseName + std::to_string(genBlkIndex);

      std::vector<VObjectType> btypes = {
          VObjectType::slGenerate_module_block, VObjectType::slGenerate_block,
          VObjectType::slGenerate_module_named_block};

      std::vector<NodeId> blockIds =
          fC->sl_collect_all(subInstanceId, btypes, true);
      bool namedBlock = false;
      if (blockIds.size()) {
        NodeId blockId = blockIds[0];
        NodeId blockNameId = fC->Child(blockId);
        if (fC->Type(blockNameId) == VObjectType::slStringConst) {
          namedBlock = true;
          modName = fC->SymName(blockNameId);
        }
      }
      if (!namedBlock) genBlkIndex++;
      instName = modName;
      std::string fullName;
      std::string libName = fC->getLibrary()->getName();
      if (instName == parent->getInstanceName()) {
        fullName += parent->getFullPathName();
        reuseInstance = true;
      } else {
        fullName += parent->getModuleName() + "." + instName;
      }
      def = design->getComponentDefinition(fullName);
      if (def == NULL) {
        def = m_moduleDefFactory->newModuleDefinition(fC, subInstanceId,
                                                      fullName);
        design->addModuleDefinition(fullName, (ModuleDefinition*)def);
      }

      NodeId conditionId = fC->Child(subInstanceId);

      if (fC->Type(conditionId) == VObjectType::slGenvar_initialization ||
          fC->Type(conditionId) ==
              VObjectType::slGenvar_decl_assignment) {  // For loop stmt

        // Var init
        NodeId varId = fC->Child(conditionId);
        NodeId constExpr = fC->Sibling(varId);
        Value* initValue = m_exprBuilder.evalExpr(fC, constExpr, parent);
        std::string name = fC->SymName(varId);
        parent->setValue(name, initValue, m_exprBuilder);

        // End-loop test
        NodeId endLoopTest = fC->Sibling(conditionId);

        // Iteration
        NodeId iteration = fC->Sibling(endLoopTest);
        NodeId var = fC->Child(iteration);
        NodeId assignOp = fC->Sibling(var);
        NodeId expr = fC->Sibling(assignOp);
        if (expr == 0) {  // Unary operator like i++
          expr = var;
        }
        // Generate block
        NodeId genBlock = fC->Sibling(iteration);

        bool cont = true;
        Value* testCond = m_exprBuilder.evalExpr(fC, endLoopTest, parent);
        cont = testCond->getValueUL();
        m_exprBuilder.deleteValue(testCond);

        while (cont) {
          Value* currentIndexValue = parent->getValue(name);
          long currVal = currentIndexValue->getValueUL();
          std::string indexedModName =
              modName + "[" + std::to_string(currVal) + "]";
          instName = indexedModName;
          ModuleInstance* child = factory->newModuleInstance(
              def, fC, genBlock, parent, instName, indexedModName);
          child->setValue(name, currentIndexValue, m_exprBuilder);
          elaborateInstance_(def->getFileContents()[0], genBlock, 0, factory,
                             child, config);
          allSubInstances.push_back(child);

          Value* newVal = m_exprBuilder.evalExpr(fC, expr, parent);
          parent->setValue(name, newVal, m_exprBuilder);
          Value* testCond = m_exprBuilder.evalExpr(fC, endLoopTest, parent);
          cont = testCond->getValueUL();
          m_exprBuilder.deleteValue(testCond);
        }
        if (allSubInstances.size()) {
          ModuleInstance** children =
              new ModuleInstance*[allSubInstances.size()];
          for (unsigned int index = 0; index < allSubInstances.size();
               index++) {
            children[index] = allSubInstances[index];
          }
          parent->addSubInstances(children, allSubInstances.size());
        }
        continue;

      } else {  // If-Else or Case stmt
        if (fC->Type(conditionId) != VObjectType::slConstant_expression) {
          conditionId = fC->Child(conditionId);
        }
        Value* condValue = m_exprBuilder.evalExpr(fC, conditionId, parent);
        long condVal = condValue->getValueUL();
        m_exprBuilder.deleteValue(condValue);
        NodeId tmp = fC->Sibling(conditionId);
        if (fC->Type(tmp) == VObjectType::slCase_generate_item) {  // Case stmt
          NodeId caseItem = tmp;
          bool nomatch = true;
          while (nomatch) {
            NodeId exprItem = fC->Child(caseItem);
            if (fC->Type(exprItem) ==
                VObjectType::slGenerate_block)  // Default block
              nomatch = false;
            while (nomatch) {
              // Find if one of the case expr matches the case expr
              if (fC->Type(exprItem) == VObjectType::slConstant_expression) {
                Value* caseValue = m_exprBuilder.evalExpr(fC, exprItem, parent);
                long caseVal = caseValue->getValueUL();
                m_exprBuilder.deleteValue(caseValue);
                if (condVal == caseVal) {
                  nomatch = false;
                  break;
                }
              } else
                break;
              exprItem = fC->Sibling(exprItem);
            }

            if (nomatch) {
              // Next case stmt
              caseItem = fC->Sibling(caseItem);
              if (!caseItem) break;
              if (fC->Type(caseItem) != VObjectType::slCase_generate_item)
                break;
            } else {
              // We found a match
              while (fC->Type(exprItem) == VObjectType::slConstant_expression)
                exprItem = fC->Sibling(exprItem);
              childId = exprItem;
            }
          }
        } else {          // If-Else stmt
          if (condVal) {  // If branch
            if (tmp)
              childId = tmp;
            else  // There is no If stmt
              continue;
          } else {  // Else branch
            if (tmp) tmp = fC->Sibling(tmp);
            if (tmp)
              childId = tmp;
            else  // There is no Else stmt
              continue;
          }
        }
      }

      libName = fC->getLibrary()->getName();
      fullName = parent->getModuleName() + "." + instName;
      def = design->getComponentDefinition(fullName);
      if (def == NULL) {
        def = m_moduleDefFactory->newModuleDefinition(fC, subInstanceId,
                                                      fullName);
        design->addModuleDefinition(fullName, (ModuleDefinition*)def);
      }

      ModuleInstance* child = factory->newModuleInstance(
          def, fC, subInstanceId, parent, instName, modName);
      elaborateInstance_(def->getFileContents()[0], childId, paramOverride,
                         factory, child, config);
      allSubInstances.push_back(child);

    }
    // Named blocks
    else if (type == slSeq_block || type == slPar_block) {
      std::string libName = fC->getLibrary()->getName();
      std::string fullName = parent->getModuleName() + "." + instName;

      def = design->getComponentDefinition(fullName);
      if (def == NULL) {
        def = m_moduleDefFactory->newModuleDefinition(fC, subInstanceId,
                                                      fullName);
        design->addModuleDefinition(fullName, (ModuleDefinition*)def);
      }

      ModuleInstance* child = factory->newModuleInstance(
          def, fC, subInstanceId, parent, instName, modName);
      elaborateInstance_(def->getFileContents()[0], subInstanceId,
                         paramOverride, factory, child, config);
      allSubInstances.push_back(child);

    }
    // Regular module binding
    else {
      NodeId moduleName =
          fC->sl_collect(subInstanceId, VObjectType::slStringConst);
      std::string libName = fC->getLibrary()->getName();
      mname = fC->SymName(moduleName);

      std::vector<std::string> libs;
      if (config) {
        for (auto lib : config->getDefaultLibs()) {
          libs.push_back(lib);
        }
        libs.push_back(libName);
      } else {
        libs.push_back(libName);
      }

      for (auto lib : libs) {
        modName = lib + "@" + mname;
        def = design->getComponentDefinition(modName);
        if (def) {
          break;
        } else {
          modName = parent->getDefinition()->getName() + "::" + mname;
          def = design->getComponentDefinition(modName);
          if (def) {
            break;
          }
        }
      }

      auto itr = m_cellUseClause.find(mname);
      if (itr != m_cellUseClause.end()) {
        UseClause& use = (*itr).second;
        switch (use.getType()) {
          case UseClause::UseModule: {
            std::string name = use.getName();
            def = design->getComponentDefinition(name);
            if (def) use.setUsed();
            break;
          }
          case UseClause::UseLib: {
            for (auto lib : use.getLibs()) {
              modName = lib + "@" + mname;
              def = design->getComponentDefinition(modName);
              if (def) {
                use.setUsed();
                break;
              }
            }
            break;
          }
          default:
            break;
        }
      }

      if (def) childId = def->getNodeIds()[0];

      NodeId tmpId = fC->Sibling(moduleName);
      if (fC->Type(tmpId) == VObjectType::slParameter_value_assignment) {
        paramOverride = tmpId;
      }

      bool loopDetected = false;
      ModuleInstance* tmp = parent;
      while (tmp) {
        if (tmp->getDefinition() == def) {
          loopDetected = true;
          break;
        }
        tmp = tmp->getParent();
      }
      if (loopDetected) {
        SymbolTable* st = m_compileDesign->getCompiler()
                              ->getErrorContainer()
                              ->getSymbolTable();
        Location loc(st->registerSymbol(fC->getFileName(subInstanceId)),
                     fC->Line(subInstanceId), 0, st->registerSymbol(modName));
        Location loc2(st->registerSymbol(
                          tmp->getFileContent()->getFileName(tmp->getNodeId())),
                      tmp->getFileContent()->Line(tmp->getNodeId()), 0);
        Error err(ErrorDefinition::ELAB_INSTANTIATION_LOOP, loc, loc2);
        m_compileDesign->getCompiler()->getErrorContainer()->addError(err);
      } else {
        std::vector<int> from;
        std::vector<int> to;
        std::vector<int> index;

        std::vector<VObjectType> insttypes = {
            VObjectType::slHierarchical_instance,
            VObjectType::slN_input_gate_instance,
            VObjectType::slN_output_gate_instance, VObjectType::slUdp_instance};

        std::vector<NodeId> hierInstIds =
            fC->sl_collect_all(subInstanceId, insttypes, true);

        NodeId hierInstId = InvalidNodeId;
        if (hierInstIds.size()) hierInstId = hierInstIds[0];

        if (hierInstId == InvalidNodeId) continue;

        while (hierInstId) {
          NodeId instId = fC->sl_collect(hierInstId, slName_of_instance);
          NodeId identifierId = 0;
          if (instId != InvalidNodeId) {
            identifierId = fC->Child(instId);
            instName = fC->SymName(identifierId);
          }

          auto itr =
              m_instUseClause.find(parent->getFullPathName() + "." + instName);
          if (itr != m_instUseClause.end()) {
            UseClause& use = (*itr).second;
            switch (use.getType()) {
              case UseClause::UseModule: {
                std::string name = use.getName();
                def = design->getComponentDefinition(name);
                if (def) use.setUsed();
                break;
              }
              case UseClause::UseLib: {
                for (auto lib : use.getLibs()) {
                  modName = lib + "@" + mname;
                  def = design->getComponentDefinition(modName);
                  if (def) {
                    use.setUsed();
                    break;
                  }
                }
                break;
              }
              case UseClause::UseConfig: {
                std::string useConfig = use.getName();
                Config* config = design->getConfigSet()->getConfig(useConfig);
                if (config) {
                  subConfig = config;
                  std::string lib = config->getDesignLib();
                  std::string top = config->getDesignTop();
                  modName = lib + "@" + top;
                  def = design->getComponentDefinition(modName);
                  if (def) use.setUsed();
                }
              }
              default:
                break;
            }
          }

          if (def)
            childId = def->getNodeIds()[0];
          else {
            SymbolTable* st = m_compileDesign->getCompiler()
                                  ->getErrorContainer()
                                  ->getSymbolTable();
            Location loc(st->registerSymbol(fC->getFileName(subInstanceId)),
                         fC->Line(subInstanceId), 0,
                         st->registerSymbol(modName));
            Error err(ErrorDefinition::ELAB_NO_MODULE_DEFINITION, loc);
            m_compileDesign->getCompiler()->getErrorContainer()->addError(
                err, false, false);
          }

          NodeId unpackedDimId = 0;

          if (identifierId) unpackedDimId = fC->Sibling(identifierId);

          if (unpackedDimId) {
            // Vector instances
            while (unpackedDimId) {
              if (fC->Type(unpackedDimId) == slUnpacked_dimension) {
                NodeId constantRangeId = fC->Child(unpackedDimId);
                NodeId leftNode = fC->Child(constantRangeId);
                NodeId rightNode = fC->Sibling(leftNode);
                Value* leftVal = m_exprBuilder.evalExpr(fC, leftNode, parent);
                Value* rightVal = m_exprBuilder.evalExpr(fC, rightNode, parent);
                unsigned long left = leftVal->getValueUL();
                unsigned long right = rightVal->getValueUL();
                m_exprBuilder.deleteValue(leftVal);
                m_exprBuilder.deleteValue(rightVal);
                if (left < right) {
                  from.push_back(left);
                  to.push_back(right);
                  index.push_back(left);
                } else {
                  from.push_back(right);
                  to.push_back(left);
                  index.push_back(right);
                }
              }
              unpackedDimId = fC->Sibling(unpackedDimId);
            }
            recurseInstanceLoop_(from, to, index, 0, def, fC, subInstanceId,
                                 paramOverride, factory, parent, subConfig,
                                 instName, modName, allSubInstances);
          } else {
            // Simple instance
            ModuleInstance* child = NULL;
            if (reuseInstance) {
              child = parent;
              child->setNodeId(subInstanceId);
            } else {
              child = factory->newModuleInstance(def, fC, subInstanceId, parent,
                                                 instName, modName);
            }
            if (def && (type != VObjectType::slGate_instantiation))
              elaborateInstance_(def->getFileContents()[0], childId,
                                 paramOverride, factory, child, subConfig);

            if (!reuseInstance) allSubInstances.push_back(child);
          }

          hierInstId = fC->Sibling(hierInstId);
        }

        // std::cout << "INST: " << modName << " " << instName << " " << def <<
        // std::endl;
      }
    }
  }
  // Record sub-scopes and sub-instances
  if (allSubInstances.size()) {
    ModuleInstance** children = new ModuleInstance*[allSubInstances.size()];
    for (unsigned int index = 0; index < allSubInstances.size(); index++) {
      children[index] = allSubInstances[index];
    }
    parent->addSubInstances(children, allSubInstances.size());
  }
}

void DesignElaboration::reportElaboration_() {
  unsigned int nbTopLevelModules = 0;
  unsigned int maxDepth = 0;
  unsigned int numberOfInstances = 0;
  unsigned int numberOfLeafInstances = 0;
  unsigned int nbUndefinedModules = 0;
  unsigned int nbUndefinedInstances = 0;

  m_compileDesign->getCompiler()->getDesign()->reportInstanceTreeStats(
      nbTopLevelModules, maxDepth, numberOfInstances, numberOfLeafInstances,
      nbUndefinedModules, nbUndefinedInstances);

  SymbolTable* symtable = m_compileDesign->getCompiler()->getSymbolTable();

  Location loc1(symtable->registerSymbol(std::to_string(nbTopLevelModules)));
  Error err1(ErrorDefinition::ELAB_NB_TOP_LEVEL_MODULES, loc1);
  m_compileDesign->getCompiler()->getErrorContainer()->addError(err1);

  Location loc2(symtable->registerSymbol(std::to_string(maxDepth)));
  Error err2(ErrorDefinition::ELAB_MAX_INSTANCE_DEPTH, loc2);
  m_compileDesign->getCompiler()->getErrorContainer()->addError(err2);

  Location loc3(symtable->registerSymbol(std::to_string(numberOfInstances)));
  Error err3(ErrorDefinition::ELAB_NB_INSTANCES, loc3);
  m_compileDesign->getCompiler()->getErrorContainer()->addError(err3);

  Location loc4(
      symtable->registerSymbol(std::to_string(numberOfLeafInstances)));
  Error err4(ErrorDefinition::ELAB_NB_LEAF_INSTANCES, loc4);
  m_compileDesign->getCompiler()->getErrorContainer()->addError(err4);

  if (nbUndefinedModules) {
    Location loc5(symtable->registerSymbol(std::to_string(nbUndefinedModules)));
    Error err5(ErrorDefinition::ELAB_NB_UNDEF_MODULES, loc5);
    m_compileDesign->getCompiler()->getErrorContainer()->addError(err5);
  }

  if (nbUndefinedInstances) {
    Location loc6(
        symtable->registerSymbol(std::to_string(nbUndefinedInstances)));
    Error err6(ErrorDefinition::ELAB_NB_UNDEF_INSTANCES, loc6);
    m_compileDesign->getCompiler()->getErrorContainer()->addError(err6);
  }
  CommandLineParser* cl =
      m_compileDesign->getCompiler()->getCommandLineParser();
  if (cl->getDebugInstanceTree() && (!cl->muteStdout())) {
    std::cout << "Instance tree:" << std::endl;
    std::cout
        << m_compileDesign->getCompiler()->getDesign()->reportInstanceTree();
    std::cout << std::endl;
  }
}

void DesignElaboration::collectParams_(std::vector<std::string>& params,
                                       FileContent* fC, NodeId nodeId,
                                       ModuleInstance* instance,
                                       NodeId parentParamOverride) {
  if (!nodeId) return;
  if (!instance) return;
  Design* design = m_compileDesign->getCompiler()->getDesign();
  SymbolTable* st = m_compileDesign->getCompiler()->getSymbolTable();
  ErrorContainer* errors = m_compileDesign->getCompiler()->getErrorContainer();
  DesignComponent* module = instance->getDefinition();

  // Parameters imported by package imports
  std::vector<FileCNodeId> pack_imports;
  for (auto import : fC->getObjects(VObjectType::slPackage_import_item)) {
    pack_imports.push_back(import);
  }
  for (auto import : module->getObjects(VObjectType::slPackage_import_item)) {
    pack_imports.push_back(import);
  }

  for (auto pack_import : pack_imports) {
    NodeId pack_id = pack_import.fC->Child(pack_import.nodeId);
    std::string pack_name = pack_import.fC->SymName(pack_id);
    Package* def = design->getPackage(pack_name);
    if (def) {
      auto& paramSet = def->getObjects(VObjectType::slParam_assignment);
      for (unsigned int i = 0; i < paramSet.size(); i++) {
        FileContent* packageFile = paramSet[i].fC;
        NodeId param = paramSet[i].nodeId;

        NodeId ident = packageFile->Child(param);
        std::string name = packageFile->SymName(ident);
        Value* value = m_exprBuilder.clone(def->getValues()[i]);
        instance->setValue(name, value, m_exprBuilder);
        params.push_back(name);
      }
    } else {
      Location loc(st->registerSymbol(pack_import.fC->getFileName(pack_id)),
                   pack_import.fC->Line(pack_id), 0,
                   st->registerSymbol(pack_name));
      Error err(ErrorDefinition::ELAB_UNDEFINED_PACKAGE, loc);
      errors->addError(err);
    }
  }

  for (FileCNodeId param :
       module->getObjects(VObjectType::slParam_assignment)) {
    NodeId ident = param.fC->Child(param.nodeId);
    std::string name = param.fC->SymName(ident);
    Value* value =
        m_exprBuilder.evalExpr(param.fC, param.fC->Sibling(ident), instance);
    instance->setValue(name, value, m_exprBuilder);
    params.push_back(name);
  }

  std::vector<VObjectType> types;
  // Param overrides
  if (parentParamOverride) {
    FileContent* parentFile =
        instance->getParent()->getDefinition()->getFileContents()[0];
    types = {VObjectType::slOrdered_parameter_assignment,
             VObjectType::slNamed_parameter_assignment};
    std::vector<NodeId> overrideParams =
        parentFile->sl_collect_all(parentParamOverride, types);

    unsigned int index = 0;
    for (auto paramAssign : overrideParams) {
      NodeId child = parentFile->Child(paramAssign);
      if (parentFile->Type(child) == VObjectType::slStringConst) {
        // Named param
        std::string name = parentFile->SymName(child);
        NodeId expr = parentFile->Sibling(child);
        Value* value =
            m_exprBuilder.evalExpr(parentFile, expr, instance->getParent());
        instance->setValue(name, value, m_exprBuilder);
      } else {
        // Index param
        NodeId expr = child;
        Value* value =
            m_exprBuilder.evalExpr(parentFile, expr, instance->getParent());
        std::string name = "OUT_OF_RANGE_PARAM_INDEX";
        if (index < params.size()) {
          name = params[index];
        } else {
          Location loc(st->registerSymbol(parentFile->getFileName(paramAssign)),
                       parentFile->Line(paramAssign), 0,
                       st->registerSymbol(std::to_string(index)));
          Error err(ErrorDefinition::ELAB_OUT_OF_RANGE_PARAM_INDEX, loc);
          errors->addError(err);
        }
        instance->setValue(name, value, m_exprBuilder);
        index++;
      }
    }
  }

  // Defparams
  types = {VObjectType::slDefparam_assignment};
  std::vector<VObjectType> stopPoints = {
      VObjectType::slConditional_generate_construct,
      VObjectType::slGenerate_module_conditional_statement,
      VObjectType::slLoop_generate_construct,
      VObjectType::slGenerate_module_loop_statement,
      VObjectType::slPar_block,
      VObjectType::slSeq_block,
      VObjectType::slModule_declaration};

  std::vector<NodeId> defParams = fC->sl_collect_all(nodeId, types, stopPoints);
  for (auto defParam : defParams) {
    NodeId hIdent = fC->Child(defParam);
    NodeId var = fC->Child(hIdent);
    NodeId value = fC->Sibling(hIdent);
    std::string fullPath = fC->SymName(var);
    std::string path;
    for (unsigned int i = 0; i < fullPath.size(); i++) {
      if (fullPath[i] == '.') break;
      path += fullPath[i];
    }
    std::string pathRoot;
    pathRoot = fC->getLibrary()->getName() + "@";
    pathRoot += path;
    path = fullPath;

    // path refers to a sub instance
    std::string prefix;
    if (design->findInstance(pathRoot)) {
      std::string p = design->findInstance(pathRoot)->getFullPathName();
      if (strstr(p.c_str(), ".")) {
        prefix = instance->getFullPathName() + ".";
      } else {
        prefix = fC->getLibrary()->getName() + "@";
      }
    } else {
      prefix = instance->getFullPathName() + ".";
    }
    path = prefix + path;
    Value* val = m_exprBuilder.evalExpr(fC, value, instance);
    design->addDefParam(path, fC, hIdent, val);
  }
}

void DesignElaboration::checkElaboration_() {
  Design* design = m_compileDesign->getCompiler()->getDesign();
  design->checkDefParamUsage();
  checkConfigurations_();
}

void DesignElaboration::checkConfigurations_() {
  SymbolTable* st = m_compileDesign->getCompiler()->getSymbolTable();
  for (auto& pathUseC : m_cellUseClause) {
    UseClause& useC = pathUseC.second;
    if (!useC.isUsed()) {
      FileContent* fC = useC.getFileContent();
      Location loc(st->registerSymbol(fC->getFileName(useC.getNodeId())),
                   fC->Line(useC.getNodeId()), 0,
                   st->registerSymbol(pathUseC.first));
      Error err(ErrorDefinition::ELAB_USE_CLAUSE_IGNORED, loc);
      m_compileDesign->getCompiler()->getErrorContainer()->addError(err);
    }
  }
  for (auto& pathUseC : m_instUseClause) {
    UseClause& useC = pathUseC.second;
    if (!useC.isUsed()) {
      FileContent* fC = useC.getFileContent();
      Location loc(st->registerSymbol(fC->getFileName(useC.getNodeId())),
                   fC->Line(useC.getNodeId()), 0,
                   st->registerSymbol(pathUseC.first));
      Error err(ErrorDefinition::ELAB_USE_CLAUSE_IGNORED, loc);
      m_compileDesign->getCompiler()->getErrorContainer()->addError(err);
    }
  }
}

void DesignElaboration::reduceUnnamedBlocks_() {
  Design* design = m_compileDesign->getCompiler()->getDesign();
  std::queue<ModuleInstance*> queue;
  for (auto instance : design->getTopLevelModuleInstances()) {
    queue.push(instance);
  }

  while (queue.size()) {
    ModuleInstance* current = queue.front();
    queue.pop();
    for (unsigned int i = 0; i < current->getNbChildren(); i++) {
      queue.push(current->getChildren(i));
    }
    FileContent* fC = current->getFileContent();
    NodeId id = current->getNodeId();
    VObjectType type = fC->Type(id);

    ModuleInstance* parent = current->getParent();
    if (parent) {
      FileContent* fCP = parent->getFileContent();
      NodeId idP = parent->getNodeId();
      VObjectType typeP = fCP->Type(idP);

      if ((type == VObjectType::slConditional_generate_construct ||
           type == VObjectType::slGenerate_module_conditional_statement ||
           type == VObjectType::slLoop_generate_construct ||
           type == VObjectType::slGenerate_module_loop_statement) &&
          (typeP == VObjectType::slConditional_generate_construct ||
           typeP == VObjectType::slGenerate_module_conditional_statement ||
           typeP == VObjectType::slLoop_generate_construct ||
           typeP == VObjectType::slGenerate_module_loop_statement)) {
        std::string fullModName = current->getModuleName();
        fullModName = StringUtils::leaf(fullModName);
        std::string fullModNameP = parent->getModuleName();
        fullModNameP = StringUtils::leaf(fullModNameP);
        if (strstr(fullModName.c_str(), "genblk")) {
          if (fullModName == fullModNameP)
            parent->getParent()->overrideParentChild(parent->getParent(),
                                                     parent, current);
        } else {
          if (strstr(fullModNameP.c_str(), "genblk"))
            parent->getParent()->overrideParentChild(parent->getParent(),
                                                     parent, current);
        }
      }
    }
  }
}
