/*
 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 "CompileDesign.h"
#include "../Testbench/Property.h"
#include "../Design/Function.h"
#include "../Testbench/ClassDefinition.h"
#include "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);
        }
      }
    }
  }
}
