<commit_before>/**
 * @file      ac_memport.H
 * @author    <NAME>
 *
 *            The ArchC Team
 *            http://www.archc.org/
 *
 *            Computer Systems Laboratory (LSC)
 *            IC-UNICAMP
 *            http://www.lsc.ic.unicamp.br/
 *
 * @version   1.0
 * @date      Thu Sep 22 11:47:36 2005
 *
 * @brief     Defines a wrapper template class for memory access.
 *
 * @attention Copyright (C) 2002-2006 --- The ArchC Team
 *
 */

//////////////////////////////////////////////////////////////////////////////

#ifndef _AC_MEMPORT_H_
#define _AC_MEMPORT_H_

//////////////////////////////////////////////////////////////////////////////

// Standard includes
#include <stdint.h>
#include <list>
#include <fstream>

// SystemC includes

// ArchC includes
#include "ac_inout_if.H"
#include "ac_log.H"
#include "ac_arch_ref.H"
#include "ac_utils.H"

//////////////////////////////////////////////////////////////////////////////

// 'using' statements
using std::string;
using std::list;
using std::istringstream;
using std::ifstream;

//////////////////////////////////////////////////////////////////////////////

// Forward class declarations, needed to compile

//////////////////////////////////////////////////////////////////////////////

/// Template wrapper class for memory access.
template<typename ac_word, typename ac_Hword> class ac_memport :
  public ac_arch_ref<ac_word, ac_Hword> {

private:
  ac_inout_if* storage;

  ac_word aux_word;
  ac_Hword aux_Hword;
  uint8_t aux_byte;

protected:
  typedef list<change_log<ac_word> > log_list;
#ifdef AC_UPDATE_LOG
  log_list changes;                 //!< Update log.
  fstream update_file;              //!< Update log binary file.
#endif

#ifdef AC_DELAY
  log_list delays;                  //!< Delayed update queue.
#endif

public:

  ///Default constructor
  explicit ac_memport(ac_arch<ac_word, ac_Hword>& ref) : ac_arch_ref<ac_word, ac_Hword>(ref) {}

  ///Default constructor with initialization
  explicit ac_memport(ac_arch<ac_word, ac_Hword>& ref, ac_inout_if& stg) : ac_arch_ref<ac_word, ac_Hword>(ref), storage(&stg) {}

  virtual ~ac_memport() {}

  ///Reads a word
  inline ac_word read(uint32_t address) {
    storage->read(&aux_word, address, sizeof(ac_word) * 8);
    if (!this->ac_mt_endian) {
      aux_word = byte_swap(aux_word);
    }
    return aux_word;
  }

  ///Reads a byte
  inline uint8_t read_byte(uint32_t address) {
    storage->read(&aux_byte, address, 8);
    return aux_byte;
  }

  ///Reads half word
  inline ac_Hword read_half(uint32_t address) {

    if (!this->ac_mt_endian) {
      storage->read(&aux_Hword, address, sizeof(ac_Hword) * 8);
      aux_Hword = convert_endian(sizeof(ac_Hword), aux_Hword, 0);
      return aux_Hword;
    }
    else {
      storage->read(&aux_Hword, address, sizeof(ac_Hword) * 8);
      return aux_Hword;
    } 

  }
  
  //!Writing a word
  inline void write(uint32_t address, ac_word datum) {
    aux_word = datum;
    if (!this->ac_mt_endian) {
      aux_word = byte_swap(datum);
    }
    storage->write(&aux_word, address, sizeof(ac_word) * 8);
  }

  //!Writing a byte 
  inline void write_byte(uint32_t address, uint8_t datum) {
    storage->write(&datum, address, 8);
  }

  //!Writing a short int 
  inline void write_half(uint32_t address, ac_Hword datum) {
    if (!this->ac_mt_endian) {
      aux_Hword = convert_endian(sizeof(ac_Hword), datum, 0);
      storage->write(&aux_Hword, address, sizeof(ac_Hword) * 8);
    }
    else {
      storage->write(&datum, address, sizeof(ac_Hword) * 8);
    }
  }

#ifdef AC_DELAY
  //!Writing a word
  inline void write(uint32_t address, ac_word datum, uint32_t time) {
    if (!this->ac_mt_endian)
      delays.push_back(change_log<ac_word>(address, byte_swap(datum), time));
    else
      delays.push_back(change_log<ac_word>(address, datum, time));
  }

  //!Writing a byte 
  inline void write_byte(uint32_t address, uint8_t datum,
			 uint32_t time) {
    uint32_t oset_addr = address % sizeof(ac_word);
    uint32_t base_addr = address - oset_addr;

    storage->read(&aux_word, base_addr, sizeof(ac_word) * 8);

    if (!this->ac_mt_endian) {
      oset_addr = ((sizeof(ac_word) - 1) - oset_addr);
    }

    ((uint8_t*)(&aux_word))[oset_addr] = datum;
    
    delays.push_back(change_log<ac_word>(base_addr, aux_word, time));
    
  }

  //!Writing a short int 
  inline void write_half(uint32_t address, ac_Hword datum, uint32_t time) {
    uint32_t oset_addr = address % sizeof(ac_word);
    uint32_t base_addr = address - oset_addr;

    storage->read(&aux_word, base_addr, sizeof(ac_word) * 8);

    if (!this->ac_mt_endian) {
//       oset_addr = oset_addr ? 0 : 1;
      oset_addr = oset_addr == 0;
    }
    else {
//       oset_addr = oset_addr ? 1 : 0;
      oset_addr = oset_addr != 0;
    }
    aux_Hword = datum;
    if (!this->ac_mt_endian) {
      aux_Hword = convert_endian(sizeof(ac_Hword), datum, 0);
    }
    ((ac_Hword*)(&aux_word))[oset_addr] = aux_Hword;
    
    delays.push_back(change_log<ac_word>(base_addr, aux_word, time));
    
  }

#endif

  /** 
   * Locks the device.
   * 
   */
  inline void lock() {
    storage->lock();
  } 

  /** 
   * Unlocks the device.
   * 
   */
  inline void unlock() {
    storage->unlock();
  }

#ifdef AC_UPDATE_LOG
  //! Reset log lists.<commit_msg>ac_memport endian correction when AC_DELAY is used<commit_after>/**
 * @file      ac_memport.H
 * @author    <NAME>
 *
 *            The ArchC Team
 *            http://www.archc.org/
 *
 *            Computer Systems Laboratory (LSC)
 *            IC-UNICAMP
 *            http://www.lsc.ic.unicamp.br/
 *
 * @version   1.0
 * @date      Thu Sep 22 11:47:36 2005
 *
 * @brief     Defines a wrapper template class for memory access.
 *
 * @attention Copyright (C) 2002-2006 --- The ArchC Team
 *
 */

//////////////////////////////////////////////////////////////////////////////

#ifndef _AC_MEMPORT_H_
#define _AC_MEMPORT_H_

//////////////////////////////////////////////////////////////////////////////

// Standard includes
#include <stdint.h>
#include <list>
#include <fstream>

// SystemC includes

// ArchC includes
#include "ac_inout_if.H"
#include "ac_log.H"
#include "ac_arch_ref.H"
#include "ac_utils.H"

//////////////////////////////////////////////////////////////////////////////

// 'using' statements
using std::string;
using std::list;
using std::istringstream;
using std::ifstream;

//////////////////////////////////////////////////////////////////////////////

// Forward class declarations, needed to compile

//////////////////////////////////////////////////////////////////////////////

/// Template wrapper class for memory access.
template<typename ac_word, typename ac_Hword> class ac_memport :
  public ac_arch_ref<ac_word, ac_Hword> {

private:
  ac_inout_if* storage;

  ac_word aux_word;
  ac_Hword aux_Hword;
  uint8_t aux_byte;

protected:
  typedef list<change_log<ac_word> > log_list;
#ifdef AC_UPDATE_LOG
  log_list changes;                 //!< Update log.
  fstream update_file;              //!< Update log binary file.
#endif

#ifdef AC_DELAY
  log_list delays;                  //!< Delayed update queue.
#endif

public:

  ///Default constructor
  explicit ac_memport(ac_arch<ac_word, ac_Hword>& ref) : ac_arch_ref<ac_word, ac_Hword>(ref) {}

  ///Default constructor with initialization
  explicit ac_memport(ac_arch<ac_word, ac_Hword>& ref, ac_inout_if& stg) : ac_arch_ref<ac_word, ac_Hword>(ref), storage(&stg) {}

  virtual ~ac_memport() {}

  ///Reads a word
  inline ac_word read(uint32_t address) {
    storage->read(&aux_word, address, sizeof(ac_word) * 8);
    if (!this->ac_mt_endian) {
      aux_word = byte_swap(aux_word);
    }
    return aux_word;
  }

  ///Reads a byte
  inline uint8_t read_byte(uint32_t address) {
    storage->read(&aux_byte, address, 8);
    return aux_byte;
  }

  ///Reads half word
  inline ac_Hword read_half(uint32_t address) {

    if (!this->ac_mt_endian) {
      storage->read(&aux_Hword, address, sizeof(ac_Hword) * 8);
      aux_Hword = convert_endian(sizeof(ac_Hword), aux_Hword, 0);
      return aux_Hword;
    }
    else {
      storage->read(&aux_Hword, address, sizeof(ac_Hword) * 8);
      return aux_Hword;
    } 

  }
  
  //!Writing a word
  inline void write(uint32_t address, ac_word datum) {
    aux_word = datum;
    if (!this->ac_mt_endian) {
      aux_word = byte_swap(datum);
    }
    storage->write(&aux_word, address, sizeof(ac_word) * 8);
  }

  //!Writing a byte 
  inline void write_byte(uint32_t address, uint8_t datum) {
    storage->write(&datum, address, 8);
  }

  //!Writing a short int 
  inline void write_half(uint32_t address, ac_Hword datum) {
    if (!this->ac_mt_endian) {
      aux_Hword = convert_endian(sizeof(ac_Hword), datum, 0);
      storage->write(&aux_Hword, address, sizeof(ac_Hword) * 8);
    }
    else {
      storage->write(&datum, address, sizeof(ac_Hword) * 8);
    }
  }

#ifdef AC_DELAY
  //!Writing a word
  inline void write(uint32_t address, ac_word datum, uint32_t time) {
    if (!this->ac_mt_endian)
      delays.push_back(change_log<ac_word>(address, byte_swap(datum), time));
    else
      delays.push_back(change_log<ac_word>(address, datum, time));
  }

  //!Writing a byte 
  inline void write_byte(uint32_t address, uint8_t datum,
			 uint32_t time) {
    uint32_t oset_addr = address % sizeof(ac_word);
    uint32_t base_addr = address - oset_addr;

    storage->read(&aux_word, base_addr, sizeof(ac_word) * 8);

    ((uint8_t*)(&aux_word))[oset_addr] = datum;
    
    delays.push_back(change_log<ac_word>(base_addr, aux_word, time));
    
  }

  //!Writing a short int 
  inline void write_half(uint32_t address, ac_Hword datum, uint32_t time) {
    uint32_t oset_addr = address % sizeof(ac_word);
    uint32_t base_addr = address - oset_addr;

    storage->read(&aux_word, base_addr, sizeof(ac_word) * 8);

    aux_Hword = datum;
    if (!this->ac_mt_endian) {
      aux_Hword = convert_endian(sizeof(ac_Hword), datum, 0);
    }
    ((ac_Hword*)(&aux_word))[oset_addr] = aux_Hword;
    
    delays.push_back(change_log<ac_word>(base_addr, aux_word, time));
    
  }

#endif

  /** 
   * Locks the device.
   * 
   */
  inline void lock() {
    storage->lock();
  } 

  /** 
   * Unlocks the device.
   * 
   */
  inline void unlock() {
    storage->unlock();
  }

#ifdef AC_UPDATE_LOG
  //! Reset log lists.
{'fraction_non_alphanumeric': 0.1928406466512702, 'fraction_numerical': 0.014530408006158584, 'mean_word_length': 2.2764817150063053, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6794800', 'n_tokens_mistral': 3747, 'n_tokens_neox': 3556, 'n_words': 768}