<commit_before>#ifndef TESTERDRIVER_H
#define TESTERDRIVER_H

#include <iostream>
#include <string.h>
using namespace std;
#include "wrapperregdriver.h"
#include "TesterWrapper.h"

// uncomment the second line here to enable verbose reg read/writes
//#define __TESTERDRIVER_DEBUG(x) (cout << x)
#define __TESTERDRIVER_DEBUG(x) (0)

// register driver for the Tester platform, using the Chisel-generated C++ model to
// interface with the accelerator model
// note that TesterWrapper.h must be generated for each new accelerator, it is the
// model header not just for the wrapper, but the entire system (wrapper+accel)

class TesterRegDriver : public WrapperRegDriver {
public:
  TesterRegDriver() {m_freePtr = 0;}

  virtual void attach(const char * name) {
    m_inst = new TesterWrapper_t();
    // get # words in the memory
    m_memWords = m_inst->TesterWrapper__mem.length();
    // initialize and reset the model
    m_inst->init();
    reset();
    m_regCount = m_inst->TesterWrapper__io_regFileIF_regCount.to_ulong();
  }

  virtual void detach() { delete m_inst; }

  virtual void copyBufferHostToAccel(void * hostBuffer, void * accelBuffer, unsigned int numBytes) {
    uint64_t accelBufBase = (uint64_t) accelBuffer;

    if((numBytes % 8 == 0) && (accelBufBase % 8 == 0))
      alignedCopyBufferHostToAccel(hostBuffer, accelBuffer, numBytes);
    else {
      // align base and size
      uint64_t alignedBase = accelBufBase - (accelBufBase % 8);
      uint64_t startDiff = accelBufBase - alignedBase;
      unsigned int alignedSize = (startDiff + numBytes + 7) / 8 * 8;
      // copy containing block into host memory
      char * tmp = new char[alignedSize];
      alignedCopyBufferAccelToHost((void *)alignedBase, (void *) tmp, alignedSize);
      // do host-to-host unaligned copy
      memcpy((void *)&tmp[startDiff], hostBuffer, numBytes);
      // write containing block back to accel memory
      alignedCopyBufferHostToAccel((void *)tmp, (void *)alignedBase, alignedSize);
      delete [] tmp;
    }
  }

  virtual void copyBufferAccelToHost(void * accelBuffer, void * hostBuffer, unsigned int numBytes) {
    uint64_t accelBufBase = (uint64_t) accelBuffer;

    if((numBytes % 8 == 0) && (accelBufBase % 8 == 0))
      alignedCopyBufferAccelToHost(hostBuffer, accelBuffer, numBytes);
    else {
      // implement unaligned accel-to-host
      // align base and size
      uint64_t alignedBase = accelBufBase - (accelBufBase % 8);
      uint64_t startDiff = accelBufBase - alignedBase;
      unsigned int alignedSize = (startDiff + numBytes + 7) / 8 * 8;
      // copy containing block into host memory
      char * tmp = new char[alignedSize];
      alignedCopyBufferAccelToHost((void *)alignedBase, (void *) tmp, alignedSize);
      // do host-to-host unaligned copy
      memcpy(hostBuffer, (void *)&tmp[startDiff],numBytes);
      delete [] tmp;
    }
  }

  virtual void * allocAccelBuffer(unsigned int numBytes) {
    // all this assumes allocation and mem word size of 8 bytes
    // round requested size to nearest multiple of 8
    unsigned int actualAllocSize = numBytes + 7 / 8 * 8;
    void * accelBuf = (void *) m_freePtr;
    // update free pointer and sanity check
    m_freePtr += actualAllocSize;
    if(m_freePtr > m_memWords * 8)
      throw "Not enough memory in allocAccelBuffer";

    return accelBuf;
  }

  // register access methods for the platform wrapper
  virtual void writeReg(unsigned int regInd, AccelReg regValue) {
    __TESTERDRIVER_DEBUG("writeReg(" << regInd << ", " << regValue  << ") "<< endl);

    m_inst->TesterWrapper__io_regFileIF_cmd_bits_writeData = regValue;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_write  = 1;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_regID = regInd;
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 1;
    step();
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 0;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_write = 0;
    step(5);  // extra delay on write completion to be realistic
  }

  virtual AccelReg readReg(unsigned int regInd) {
    AccelReg ret;

    m_inst->TesterWrapper__io_regFileIF_cmd_bits_regID = regInd;
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 1;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_read = 1;
    step(); // don't actually need 1 cycle, regfile reads are combinational

    if(!m_inst->TesterWrapper__io_regFileIF_readData_valid.to_bool())
      throw "Could not read register";

    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 0;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_read = 0;

    ret = m_inst->TesterWrapper__io_regFileIF_readData_bits.to_ulong();

    __TESTERDRIVER_DEBUG("readReg(" << regInd << ") = " << ret << endl);

    step(5);  // extra delay on read completion to be realistic

    return ret;
  }

  void printAllRegs() {<commit_msg>more debug + bugfix in TesterDriver alloc alignment<commit_after>#ifndef TESTERDRIVER_H
#define TESTERDRIVER_H

#include <iostream>
#include <string.h>
using namespace std;
#include "wrapperregdriver.h"
#include "TesterWrapper.h"

// uncomment the second line here to enable verbose reg read/writes
//#define __TESTERDRIVER_DEBUG(x) (cout << x << endl)
#define __TESTERDRIVER_DEBUG(x) (0)

// register driver for the Tester platform, using the Chisel-generated C++ model to
// interface with the accelerator model
// note that TesterWrapper.h must be generated for each new accelerator, it is the
// model header not just for the wrapper, but the entire system (wrapper+accel)

class TesterRegDriver : public WrapperRegDriver {
public:
  TesterRegDriver() {m_freePtr = 0;}

  virtual void attach(const char * name) {
    m_inst = new TesterWrapper_t();
    // get # words in the memory
    m_memWords = m_inst->TesterWrapper__mem.length();
    // initialize and reset the model
    m_inst->init();
    reset();
    m_regCount = m_inst->TesterWrapper__io_regFileIF_regCount.to_ulong();
  }

  virtual void detach() { delete m_inst; }

  virtual void copyBufferHostToAccel(void * hostBuffer, void * accelBuffer, unsigned int numBytes) {
    uint64_t accelBufBase = (uint64_t) accelBuffer;
    __TESTERDRIVER_DEBUG("host2accel(" << (uint64_t) hostBuffer << " -> " << accelBufBase << " : " << numBytes << " bytes)");

    if((numBytes % 8 == 0) && (accelBufBase % 8 == 0))
      alignedCopyBufferHostToAccel(hostBuffer, accelBuffer, numBytes);
    else {
      // align base and size
      uint64_t alignedBase = accelBufBase - (accelBufBase % 8);
      uint64_t startDiff = accelBufBase - alignedBase;
      unsigned int alignedSize = (startDiff + numBytes + 7) / 8 * 8;
      // copy containing block into host memory
      char * tmp = new char[alignedSize];
      alignedCopyBufferAccelToHost((void *)alignedBase, (void *) tmp, alignedSize);
      // do host-to-host unaligned copy
      memcpy((void *)&tmp[startDiff], hostBuffer, numBytes);
      // write containing block back to accel memory
      alignedCopyBufferHostToAccel((void *)tmp, (void *)alignedBase, alignedSize);
      delete [] tmp;
    }
  }

  virtual void copyBufferAccelToHost(void * accelBuffer, void * hostBuffer, unsigned int numBytes) {
    uint64_t accelBufBase = (uint64_t) accelBuffer;
    __TESTERDRIVER_DEBUG("accel2host(" << accelBufBase << " -> " << (uint64_t) hostBuffer << " : " << numBytes << " bytes)");

    if((numBytes % 8 == 0) && (accelBufBase % 8 == 0))
      alignedCopyBufferAccelToHost(hostBuffer, accelBuffer, numBytes);
    else {
      // implement unaligned accel-to-host
      // align base and size
      uint64_t alignedBase = accelBufBase - (accelBufBase % 8);
      uint64_t startDiff = accelBufBase - alignedBase;
      unsigned int alignedSize = (startDiff + numBytes + 7) / 8 * 8;
      // copy containing block into host memory
      char * tmp = new char[alignedSize];
      alignedCopyBufferAccelToHost((void *)alignedBase, (void *) tmp, alignedSize);
      // do host-to-host unaligned copy
      memcpy(hostBuffer, (void *)&tmp[startDiff],numBytes);
      delete [] tmp;
    }
  }

  virtual void * allocAccelBuffer(unsigned int numBytes) {
    // all this assumes allocation and mem word size of 8 bytes
    // round requested size to nearest multiple of 8
    unsigned int actualAllocSize = (numBytes + 7) / 8 * 8;
    void * accelBuf = (void *) m_freePtr;
    // update free pointer and sanity check
    m_freePtr += actualAllocSize;
    if(m_freePtr > m_memWords * 8)
      throw "Not enough memory in allocAccelBuffer";
    __TESTERDRIVER_DEBUG("allocAccelBuffer(" << numBytes << ", alloc " << actualAllocSize <<") = " << (uint64_t) accelBuf);

    return accelBuf;
  }

  // register access methods for the platform wrapper
  virtual void writeReg(unsigned int regInd, AccelReg regValue) {
    __TESTERDRIVER_DEBUG("writeReg(" << regInd << ", " << regValue  << ") ");

    m_inst->TesterWrapper__io_regFileIF_cmd_bits_writeData = regValue;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_write  = 1;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_regID = regInd;
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 1;
    step();
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 0;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_write = 0;
    step(5);  // extra delay on write completion to be realistic
  }

  virtual AccelReg readReg(unsigned int regInd) {
    AccelReg ret;

    m_inst->TesterWrapper__io_regFileIF_cmd_bits_regID = regInd;
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 1;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_read = 1;
    step(); // don't actually need 1 cycle, regfile reads are combinational

    if(!m_inst->TesterWrapper__io_regFileIF_readData_valid.to_bool())
      throw "Could not read register";

    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 0;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_read = 0;

    ret = m_inst->TesterWrapper__io_regFileIF_readData_bits.to_ulong();

    __TESTERDRIVER_DEBUG("readReg(" << regInd << ") = " << ret);

    step(5);  // extra delay on read completion to be realistic

    return ret;
  }

  void printAllRegs() {
{'fraction_non_alphanumeric': 0.10199821055770951, 'fraction_numerical': 0.010935480664081917, 'mean_word_length': 3.749763928234183, 'pattern_counts': {'":': 0, '<': 79, '<?xml version=': 0, '>': 43, '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': '517368', 'n_tokens_mistral': 3312, 'n_tokens_neox': 3143, 'n_words': 841}