/*
 Do not modify, auto-generated by classes.py

 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:   module_inst.h
 * Author:
 *
 * Created on December 14, 2019, 10:03 PM
 */

#ifndef UHDM_MODULE_INST_H
#define UHDM_MODULE_INST_H

#include <uhdm/sv_vpi_user.h>
#include <uhdm/uhdm_vpi_user.h>

#include <uhdm/containers.h>
#include <uhdm/instance.h>

#include "expr_dist.h"


namespace UHDM {
class clocking_block;
class instance_array;
class module_array;

class module_inst final : public instance {
  UHDM_IMPLEMENT_RTTI(module_inst, instance)
public:
  // Implicit constructor used to initialize all members,
  // comment: module_inst();
  virtual ~module_inst() final = default;

  int32_t VpiIndex() const { return vpiIndex_; }
  bool VpiIndex(int32_t data) {
    vpiIndex_ = data;
    return true;
  }

  uint32_t VpiType() const final { return vpiModule; }

  bool VpiTopModule() const { return vpiTopModule_; }
  bool VpiTopModule(bool data) {
    vpiTopModule_ = data;
    return true;
  }

  int32_t VpiDefDecayTime() const { return vpiDefDecayTime_; }
  bool VpiDefDecayTime(int32_t data) {
    vpiDefDecayTime_ = data;
    return true;
  }

  clocking_block* Global_clocking()  { return global_clocking_; }
  const clocking_block* Global_clocking() const { return global_clocking_; }
  template <typename T>
  T* Global_clocking() {
    return (global_clocking_ == nullptr) ? nullptr : any_cast<T*>(global_clocking_);
  }
  template <typename T>
  const T* Global_clocking() const {
    return (global_clocking_ == nullptr) ? nullptr : any_cast<const T*>(global_clocking_);
  }
  bool Global_clocking(clocking_block* data) {
    global_clocking_ = data;
    return true;
  }

  clocking_block* Default_clocking()  { return default_clocking_; }
  const clocking_block* Default_clocking() const { return default_clocking_; }
  template <typename T>
  T* Default_clocking() {
    return (default_clocking_ == nullptr) ? nullptr : any_cast<T*>(default_clocking_);
  }
  template <typename T>
  const T* Default_clocking() const {
    return (default_clocking_ == nullptr) ? nullptr : any_cast<const T*>(default_clocking_);
  }
  bool Default_clocking(clocking_block* data) {
    default_clocking_ = data;
    return true;
  }

  any* Expr_dist()  { return expr_dist_; }
  const any* Expr_dist() const { return expr_dist_; }
  template <typename T>
  T* Expr_dist() {
    return (expr_dist_ == nullptr) ? nullptr : any_cast<T*>(expr_dist_);
  }
  template <typename T>
  const T* Expr_dist() const {
    return (expr_dist_ == nullptr) ? nullptr : any_cast<const T*>(expr_dist_);
  }
  bool Expr_dist(any* data) {
    if (!expr_distGroupCompliant(data)) return false;
    expr_dist_ = data;
    return true;
  }

  module_array* Module_array()  { return module_array_; }
  const module_array* Module_array() const { return module_array_; }
  template <typename T>
  T* Module_array() {
    return (module_array_ == nullptr) ? nullptr : any_cast<T*>(module_array_);
  }
  template <typename T>
  const T* Module_array() const {
    return (module_array_ == nullptr) ? nullptr : any_cast<const T*>(module_array_);
  }
  bool Module_array(module_array* data) {
    module_array_ = data;
    return true;
  }

  instance_array* Instance_array()  { return instance_array_; }
  const instance_array* Instance_array() const { return instance_array_; }
  template <typename T>
  T* Instance_array() {
    return (instance_array_ == nullptr) ? nullptr : any_cast<T*>(instance_array_);
  }
  template <typename T>
  const T* Instance_array() const {
    return (instance_array_ == nullptr) ? nullptr : any_cast<const T*>(instance_array_);
  }
  bool Instance_array(instance_array* data) {
    instance_array_ = data;
    return true;
  }

  VectorOfport* Ports() const { return ports_; }
  bool Ports(VectorOfport* data) {
    ports_ = data;
    return true;
  }

  VectorOfinterface_inst* Interfaces() const { return interfaces_; }
  bool Interfaces(VectorOfinterface_inst* data) {
    interfaces_ = data;
    return true;
  }

  VectorOfinterface_array* Interface_arrays() const { return interface_arrays_; }
  bool Interface_arrays(VectorOfinterface_array* data) {
    interface_arrays_ = data;
    return true;
  }

  VectorOfprocess_stmt* Process() const { return process_; }
  bool Process(VectorOfprocess_stmt* data) {
    process_ = data;
    return true;
  }

  VectorOfmodule_inst* Modules() const { return modules_; }
  bool Modules(VectorOfmodule_inst* data) {
    modules_ = data;
    return true;
  }

  VectorOfmodule_array* Module_arrays() const { return module_arrays_; }
  bool Module_arrays(VectorOfmodule_array* data) {
    module_arrays_ = data;
    return true;
  }

  VectorOfgen_scope_array* Gen_scope_arrays() const { return gen_scope_arrays_; }
  bool Gen_scope_arrays(VectorOfgen_scope_array* data) {
    gen_scope_arrays_ = data;
    return true;
  }

  VectorOfcont_assign* Cont_assigns() const { return cont_assigns_; }
  bool Cont_assigns(VectorOfcont_assign* data) {
    cont_assigns_ = data;
    return true;
  }

  VectorOfprimitive* Primitives() const { return primitives_; }
  bool Primitives(VectorOfprimitive* data) {
    primitives_ = data;
    return true;
  }

  VectorOfprimitive_array* Primitive_arrays() const { return primitive_arrays_; }
  bool Primitive_arrays(VectorOfprimitive_array* data) {
    primitive_arrays_ = data;
    return true;
  }

  VectorOfmod_path* Mod_paths() const { return mod_paths_; }
  bool Mod_paths(VectorOfmod_path* data) {
    mod_paths_ = data;
    return true;
  }

  VectorOftchk* Tchks() const { return tchks_; }
  bool Tchks(VectorOftchk* data) {
    tchks_ = data;
    return true;
  }

  VectorOfdef_param* Def_params() const { return def_params_; }
  bool Def_params(VectorOfdef_param* data) {
    def_params_ = data;
    return true;
  }

  VectorOfio_decl* Io_decls() const { return io_decls_; }
  bool Io_decls(VectorOfio_decl* data) {
    io_decls_ = data;
    return true;
  }

  VectorOfalias_stmt* Alias_stmts() const { return alias_stmts_; }
  bool Alias_stmts(VectorOfalias_stmt* data) {
    alias_stmts_ = data;
    return true;
  }

  VectorOfclocking_block* Clocking_blocks() const { return clocking_blocks_; }
  bool Clocking_blocks(VectorOfclocking_block* data) {
    clocking_blocks_ = data;
    return true;
  }

  VectorOftf_call* Elab_tasks() const { return elab_tasks_; }
  bool Elab_tasks(VectorOftf_call* data) {
    elab_tasks_ = data;
    return true;
  }

  VectorOfref_module* Ref_modules() const { return ref_modules_; }
  bool Ref_modules(VectorOfref_module* data) {
    ref_modules_ = data;
    return true;
  }

  VectorOfgen_stmt* Gen_stmts() const { return gen_stmts_; }
  bool Gen_stmts(VectorOfgen_stmt* data) {
    gen_stmts_ = data;
    return true;
  }

  bool VpiEndLabel(std::string_view data);
  std::string_view VpiEndLabel() const;

  virtual module_inst* DeepClone(BaseClass* parent, CloneContext* context) const override;

  virtual const BaseClass* GetByVpiName(std::string_view name) const override;

  virtual std::tuple<const BaseClass*, UHDM_OBJECT_TYPE, const std::vector<const BaseClass*>*> GetByVpiType(int32_t type) const override;

  virtual vpi_property_value_t GetVpiPropertyValue(int32_t property) const override;

  virtual int32_t Compare(const BaseClass* other, CompareContext* context) const override;

  virtual  UHDM_OBJECT_TYPE UhdmType() const final { return UHDM_OBJECT_TYPE::uhdmmodule_inst; }

protected:
  void DeepCopy(module_inst* clone, BaseClass* parent, CloneContext* context) const;

private:
  int32_t vpiIndex_ = 0;

  bool vpiTopModule_ = false;

  int32_t vpiDefDecayTime_ = 0;

  clocking_block* global_clocking_ = nullptr;

  clocking_block* default_clocking_ = nullptr;

  any* expr_dist_ = nullptr;

  module_array* module_array_ = nullptr;

  instance_array* instance_array_ = nullptr;

  VectorOfport* ports_ = nullptr;

  VectorOfinterface_inst* interfaces_ = nullptr;

  VectorOfinterface_array* interface_arrays_ = nullptr;

  VectorOfprocess_stmt* process_ = nullptr;

  VectorOfmodule_inst* modules_ = nullptr;

  VectorOfmodule_array* module_arrays_ = nullptr;

  VectorOfgen_scope_array* gen_scope_arrays_ = nullptr;

  VectorOfcont_assign* cont_assigns_ = nullptr;

  VectorOfprimitive* primitives_ = nullptr;

  VectorOfprimitive_array* primitive_arrays_ = nullptr;

  VectorOfmod_path* mod_paths_ = nullptr;

  VectorOftchk* tchks_ = nullptr;

  VectorOfdef_param* def_params_ = nullptr;

  VectorOfio_decl* io_decls_ = nullptr;

  VectorOfalias_stmt* alias_stmts_ = nullptr;

  VectorOfclocking_block* clocking_blocks_ = nullptr;

  VectorOftf_call* elab_tasks_ = nullptr;

  VectorOfref_module* ref_modules_ = nullptr;

  VectorOfgen_stmt* gen_stmts_ = nullptr;

  SymbolId vpiEndLabel_;
};


typedef FactoryT<module_inst> module_instFactory;


typedef FactoryT<std::vector<module_inst *>> VectorOfmodule_instFactory;

}  // namespace UHDM

#endif
