#ifdef VHDL

#ifndef morpheo_behavioural_Vhdl_h
#define morpheo_behavioural_Vhdl_h

/*
 * $Id: Vhdl.h 113 2009-04-14 18:39:12Z rosiere $
 *
 * [ Description ]
 * 
 */

#include <stdint.h>
#include <iostream>
#include <list>
#include <map>
#include "Common/include/Environment.h"
#include "Behavioural/include/Direction.h"
#include "Common/include/ToString.h"
#include "Common/include/Debug.h"
#include "Common/include/ErrorMorpheo.h"

namespace morpheo              {
  namespace behavioural          {

#define VHDL_EXTENSION ".vhdl"

    typedef enum 
      {
        VHDL_SEVERITY_NOTE   ,
        VHDL_SEVERITY_WARNING,
        VHDL_SEVERITY_ERROR  ,
        VHDL_SEVERITY_FAILURE
      } vhdl_severity_t;
    
    std::string  std_logic        (uint32_t size);
    std::string  std_logic_conv   (uint32_t size, std::string   value);
    std::string  std_logic_conv   (uint32_t size, uint32_t value);
    std::string  std_logic_cst    (uint32_t size, uint32_t value);
    std::string  std_logic_range  (uint32_t size, uint32_t max , uint32_t min );
    std::string  std_logic_range  (               uint32_t max , uint32_t min );
    std::string  std_logic_range  (uint32_t size                              );
    std::string _std_logic_range  (uint32_t size, uint32_t max , uint32_t min );
    std::string _std_logic_range  (               uint32_t max , uint32_t min );
    std::string _std_logic_range  (uint32_t size                              );
    std::string  std_logic_others (uint32_t size, bool cst);

    class Vhdl
    {
      typedef struct
      {
        std::list<std::string> _list_signal;
        std::list<std::string> _list_type  ;
        std::list<std::string> _list_alias ;
        std::list<std::string> _list_body  ;
        std::list<std::string> _list_debug ;
      } vhdl_architecture_t;

      // -----[ fields ]----------------------------------------------------
    private   : const std::string                         _name;
    private   : const std::string                         _id;

    private   : std::list<std::string>                    _list_library;
      // Entity
//  private   : std::string                               _port_clock;
    private   : std::list<std::string>                    _list_port;
      // Architecture
    public    : const std::string                         _name_architecture_default;
    private   :       std::string                         _name_architecture;
    private   : std::map<std::string,vhdl_architecture_t> _architecture;

      // -----[ methods ]---------------------------------------------------
    public    :                  Vhdl                        (std::string name,
                                                              std::string id="");
    public    :                  ~Vhdl                       ();

    public    : void             generate_file               (void);
    public    : void             generate_file               (bool generate_package,
							      bool generate_model  );

    private   : void             generate_file_package       (void);
    private   : void             generate_file_model         (void);
      
    private   : std::string      get_package                 (uint32_t    depth                 ,
                                                              std::string filename              ,
                                                              std::string package_name          ,
                                                              std::string entity_name           );
    private   : std::string      get_model                   (uint32_t    depth                 ,
                                                              std::string filename              ,
                                                              std::string entity_name           );
    private   : std::string      get_header                  (uint32_t    depth                 ,
                                                              std::string filename              );
    private   : std::string      get_entity                  (uint32_t    depth                 ,
                                                              std::string name                  );
    private   : void             test_architecture           (void);
    private   : std::string      test_architecture           (std::string name                  );
    public    : std::string      set_architecture            (std::string name                  );
    private   : std::string      get_architecture            (uint32_t    depth                 , 
                                                              std::string entity_name           );
    private   : std::string      get_configuration           (uint32_t    depth                 ,
                                                              std::string entity_name           ,
                                                              std::string configuration_name    );
    private   : std::string      get_component               (uint32_t    depth                 ,
                                                              std::string name                  );
      
    private   : std::string      get_port                    (uint32_t    depth                 );
    public    : void             set_port                    (std::string name                  ,
							      direction_t direction             ,
							      std::string type                  );
    public    : void             set_port                    (std::string name                  ,
							      direction_t direction             ,
							      uint32_t    size                  );
//  public    : void             set_port_clock              (std::string name                  );
    private   : std::string      get_signal                  (uint32_t    depth                 );
    public    : void             set_signal                  (std::string name                  ,
							      std::string type                  );
    public    : void             set_signal                  (std::string name                  ,
							      uint32_t    size                  );
    public    : void             set_signal                  (std::string name                  ,
							      std::string type                  ,
							      std::string init                  );
    public    : void             set_signal                  (std::string name                  ,
							      uint32_t    size                  ,
							      std::string init                  );
    public    : void             set_signal                  (std::string name                  ,
							      uint32_t    size                  ,
							      uint32_t    init                  );
    public    : void             set_constant                (std::string name                  ,
							      std::string type                  ,
							      std::string init                  );
    public    : void             set_constant                (std::string name                  ,
							      uint32_t    size                  ,
							      std::string init                  );
    public    : void             set_constant                (std::string name                  ,
							      uint32_t    size                  ,
							      uint32_t    init                  );

    private   : std::string      get_type                    (uint32_t    depth                 );
    public    : void             set_type                    (std::string name                  ,
							      std::string type                  );
    private   : std::string      get_alias                   (uint32_t    depth                 );
    public    : void             set_alias                   (std::string name1                 ,
							      std::string type1                 ,
							      std::string name2                 ,
							      std::string range2                );
    public    : void             set_alias                   (std::string name1                 ,
							      uint32_t    size1                 ,
							      std::string name2                 ,
							      std::string range2                );
      
    public    : std::string      get_list                    (std::list<std::string> liste      ,
                                                              uint32_t     depth                ,
                                                              std::string  separator            ,
                                                              bool         last_separator       );
    public    : void             set_list                    (std::list<std::string> & liste    ,
							      std::string  text                 );

    private   : std::string      get_body                    (uint32_t     depth                );
    public    : void             set_body                    (std::string  text                 );
    public    : void             set_body                    (uint32_t     depth                ,
                                                              std::string  text                 );
                                                                                    
    public    : void             set_body                    (uint32_t     depth                ,
                                                              Vhdl *       vhdl                 );
    public    : void             set_body_component          (std::string  name_instance        ,
                                                              std::string  name_component       ,
                                                              std::string  name_architecture    ,
                                                              std::string  name_package         ,
                                                              std::list<std::string>   list_port_map);
    public    : void             set_body_component_port_map (std::list<std::string> & list_port_map,
                                                              std::string  name_port            ,
                                                              uint32_t     size_port            ,
                                                              std::string  name_signal          ,
                                                              uint32_t     size_signal          );

    public    : void             set_comment                 (std::string  text                 );
    public    : void             set_comment                 (uint32_t     depth                ,
                                                              std::string  text                 );

    public    : void             set_debug                   (std::string  condition            ,
                                                              std::string  text                 ,
                                                              vhdl_severity_t severity = VHDL_SEVERITY_NOTE);
    private   : std::string      get_debug                   (uint32_t     depth                );

    private   : std::string      get_library                 (uint32_t     depth                );
    private   : std::string      get_library_default         (uint32_t     depth                );
    private   : void             set_library_default         (void                              );
    public    : void             set_library                 (std::string  library_name         ,
                                                              std::string  package_name         ,
                                                              std::string  declarative_unit="all");
    public    : void             set_library_work            (std::string  package_name         );

    private   : std::string      direction_toString          (direction_t  direction            );
    };

    std::string vhdl_get_id (std::string model_name);

  }; // end namespace behavioural          

  template<> inline std::string toString<morpheo::behavioural::vhdl_severity_t>(const morpheo::behavioural::vhdl_severity_t& x)
  {
    switch (x)
      {
      case morpheo::behavioural::VHDL_SEVERITY_NOTE    : return "note"   ; break;
      case morpheo::behavioural::VHDL_SEVERITY_WARNING : return "warning"; break;
      case morpheo::behavioural::VHDL_SEVERITY_ERROR   : return "error"  ; break;
      case morpheo::behavioural::VHDL_SEVERITY_FAILURE : return "failure"; break;
      default : return ""; break;
      }
  };

}; // end namespace morpheo              

#endif
#endif
