<commit_before>//-----------------------------------------------------------------------------
// Title:      tb_ahb_mem.cpp
//
// ScssId:
//
// Origin:     HW-SW SystemC Co-Simulation SoC Validation Platform
//
// Purpose:    Provide a test bench memory class with AHB slave interface.
//
// Method:     Memory is modeled with a map.
//             Considered field of the tlm_generic_payload are:
//                - command
//                - address
//                - data_ptr
//                - data_length
//                - response
//             All other fields are ignored.
//             Delays are not modeled.
//             Address checking is performed in that way, that transactions
//             are only executed if the slave select condition defined in
//             grlib user manual holds.
//             Transactions generating a correct slave select but exceeding
//             the memory region due to theri length are reported as warning
//             and executed anyhow.
//
// Modified on $Date$
//          at $Revision$
//          by $Author$
//
// Principal:  European Space Agency
// Author:     VLSI working group @ IDA @ TUBS
// Maintainer: <NAME>
// Reviewed:
//-----------------------------------------------------------------------------

#include "tb_ahb_mem.h"
#include <fstream>
#include <iostream>
#include <iomanip>
#include "verbose.h"

/// Constructor
Ctb_ahb_mem::Ctb_ahb_mem(sc_core::sc_module_name nm,   // Module name
                           uint16_t haddr_,   // AMBA AHB address (12 bit)
                           uint16_t hmask_,   // AMBA AHB address mask (12 bit)
                           char infile[],    // Memory initialization file
                           uint32_t addr) :  // Address for memory initalization
   sc_module(nm),
   pnpahb(
      0x04, // vendor_id: ESA
      0,    // device: TODO: get real device ID
      0,    //
      0,    // IRQ
      GrlibBAR(CGrlibDevice::AHBMEM, hmask_, 0, 0, haddr),    // GrlibBAR 0
      0,    // GrlibBAR 1
      0,    // GrlibBAR 2
      0     // GrlibBAR 3
   ),
   ahb(
      "ahb",            // sc_module_name
      amba::amba_AHB,   // bus type
      amba::amba_LT,    // abstraction level
      false             // is arbiter
   ),
   ahbBaseAddress(static_cast<uint32_t>(hmask_ & haddr_) << 20),
   ahbSize( ~(static_cast<uint32_t>(hmask_) << 20) + 1),
   hmask(static_cast<uint32_t>(hmask_ << 20)),
   haddr(static_cast<uint32_t>(haddr_ << 20)) {

      // Display AHB slave information
      v::info << name() << "AHB slave @0x" << hex << std::setw(8)
              << std::setfill('0') << get_base_addr() << " size: 0x" << hex
              << std::setw(8) << std::setfill('0') << get_size() << " byte"
              << endl;

      ahb.register_b_transport(this, &Ctb_ahb_mem::b_transport);
      if(infile!=NULL) {
         readmem(infile, addr);
      }
}  // End constructor


/// Destructor
Ctb_ahb_mem::~Ctb_ahb_mem() {

   // Delete memory contents
   mem.clear();
}  // End destructor

/// TLM blocking transport function
void Ctb_ahb_mem::b_transport(unsigned int id,
                              tlm::tlm_generic_payload &gp,
                              sc_core::sc_time &delay) {

   // Check address for before doing anything else
   if( !((haddr ^ (gp.get_address() & 0xfff00000)) & hmask) ) {
      // warn if access exceeds slave memory region
      if( (gp.get_address() + gp.get_data_length()) > (ahbBaseAddress + ahbSize) ) {
         v::warn << name() << "Transaction exceeds slave memory region" << endl;
      }

      switch(gp.get_command()) {
         // Read command
         case tlm::TLM_READ_COMMAND:
            for(uint32_t i=0; i<gp.get_data_length(); i++) {

               *(gp.get_data_ptr() + i) = mem[gp.get_address() + i];

            }
            gp.set_response_status(tlm::TLM_OK_RESPONSE);
            break;

         // Write command
         case tlm::TLM_WRITE_COMMAND:
            for(uint32_t i=0; i<gp.get_data_length(); i++) {

               mem[gp.get_address() + i] = *(gp.get_data_ptr() + i);

            }
            gp.set_response_status(tlm::TLM_OK_RESPONSE);
            break;

         // Neither read or write command
         default:
            v::warn << name() << "Received unknown command." << endl;
            gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);
            break;
      }
   }  // if( !((haddr ^ (gp.get_address() & 0xfff00000)) & hmask) )
}  // void Ctb_ahb_mem::b_transport()

/// Method to initialize memory contents from a text file<commit_msg>Implemented use of byte enable.<commit_after>//-----------------------------------------------------------------------------
// Title:      tb_ahb_mem.cpp
//
// ScssId:
//
// Origin:     HW-SW SystemC Co-Simulation SoC Validation Platform
//
// Purpose:    Provide a test bench memory class with AHB slave interface.
//
// Method:     Memory is modeled with a map.
//             DMI and streaming width fields are ignored.
//             Delays are not modeled.
//             Address checking is performed in that way, that transactions
//             are only executed if the slave select condition defined in
//             grlib user manual holds.
//             Transactions generating a correct slave select but exceeding
//             the memory region due to their length are reported as warning
//             and executed anyhow.
//
// Modified on $Date$
//          at $Revision$
//          by $Author$
//
// Principal:  European Space Agency
// Author:     VLSI working group @ IDA @ TUBS
// Maintainer: <NAME>
// Reviewed:
//-----------------------------------------------------------------------------

#include "tb_ahb_mem.h"
#include <fstream>
#include <iostream>
#include <iomanip>
#include "verbose.h"

/// Constructor
Ctb_ahb_mem::Ctb_ahb_mem(sc_core::sc_module_name nm,   // Module name
                         uint16_t haddr_,   // AMBA AHB address (12 bit)
                         uint16_t hmask_,   // AMBA AHB address mask (12 bit)
                         char infile[],     // Memory initialization file
                         uint32_t addr) :   // Address for memory initalization
   sc_module(nm),
   pnpahb(
      0x04, // vendor_id: ESA
      0,    // device: TODO: get real device ID
      0,    //
      0,    // IRQ
      GrlibBAR(CGrlibDevice::AHBMEM, hmask_, 0, 0, haddr),    // GrlibBAR 0
      0,    // GrlibBAR 1
      0,    // GrlibBAR 2
      0     // GrlibBAR 3
   ),
   ahb(
      "ahb",            // sc_module_name
      amba::amba_AHB,   // bus type
      amba::amba_LT,    // abstraction level
      false             // is arbiter
   ),
   ahbBaseAddress(static_cast<uint32_t>(hmask_ & haddr_) << 20),
   ahbSize( ~(static_cast<uint32_t>(hmask_) << 20) + 1),
   hmask(static_cast<uint32_t>(hmask_ << 20)),
   haddr(static_cast<uint32_t>(haddr_ << 20)) {

      // Display AHB slave information
      v::info << name() << "AHB slave @0x" << hex << std::setw(8)
              << std::setfill('0') << get_base_addr() << " size: 0x" << hex
              << std::setw(8) << std::setfill('0') << get_size() << " byte"
              << endl;

      ahb.register_b_transport(this, &Ctb_ahb_mem::b_transport);
      if(infile!=NULL) {
         readmem(infile, addr);
      }
}  // End constructor


/// Destructor
Ctb_ahb_mem::~Ctb_ahb_mem() {

   // Delete memory contents
   mem.clear();
}  // End destructor

/// TLM blocking transport function
void Ctb_ahb_mem::b_transport(unsigned int id,
                              tlm::tlm_generic_payload &gp,
                              sc_core::sc_time &delay) {

   // Check address for before doing anything else
   if( !((haddr ^ (gp.get_address() & 0xfff00000)) & hmask) ) {
      // warn if access exceeds slave memory region
      if( (gp.get_address() + gp.get_data_length()) > (ahbBaseAddress + ahbSize) ) {
         v::warn << name() << "Transaction exceeds slave memory region" << endl;
      }

      // if a byte enable array is present its length must not be zero
      unsigned char *byteEnablePtr   = gp.get_byte_enable_ptr();
      unsigned int  byteEnableLength = gp.get_byte_enable_length();
      assert( (byteEnableLength != 0) || (byteEnablePtr==NULL) );

      switch(gp.get_command()) {
         // Read command
         case tlm::TLM_READ_COMMAND:
            if(byteEnablePtr != NULL) {
               // Use byte enable
               for(uint32_t i=0; i<gp.get_data_length(); i++) {
                  if(byteEnablePtr[i % byteEnableLength] == TLM_BYTE_ENABLED) {
                     *(gp.get_data_ptr() + i) = mem[gp.get_address() + i];
                  }
               }
            } else {
               // no byte enable
               for(uint32_t i=0; i<gp.get_data_length(); i++) {
                  *(gp.get_data_ptr() + i) = mem[gp.get_address() + i];
               }
            }
            gp.set_response_status(tlm::TLM_OK_RESPONSE);
            break;

         // Write command
         case tlm::TLM_WRITE_COMMAND:
            if(byteEnablePtr != NULL) {
               // Use byte enable
               for(uint32_t i=0; i<gp.get_data_length(); i++) {
                  if(byteEnablePtr[i % byteEnableLength] == TLM_BYTE_ENABLED) {
                     mem[gp.get_address() + i] = *(gp.get_data_ptr() + i);
                  }
               }
            } else {
               // no byte enable
               for(uint32_t i=0; i<gp.get_data_length(); i++) {
                  mem[gp.get_address() + i] = *(gp.get_data_ptr() + i);
               }
            }
            gp.set_response_status(tlm::TLM_OK_RESPONSE);
            break;

         // Neither read or write command
         default:
            v::warn << name() << "Received unknown command." << endl;
            gp.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);
            break;
      }
   }  // if( !((haddr ^ (gp.get_address() & 0xfff00000)) & hmask) )
}  // void Ctb_ahb_mem::b_transport()

/// Method to initialize memory contents from a text file
{'fraction_non_alphanumeric': 0.1531961427577294, 'fraction_numerical': 0.01381847102097624, 'mean_word_length': 1.6452800420720484, 'pattern_counts': {'":': 0, '<': 117, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '7528644', 'n_tokens_mistral': 3201, 'n_tokens_neox': 3033, 'n_words': 755}