tlm_endian_conv.h

来自「SystemC Transaction Level Modelling. 是基于」· C头文件 代码 · 共 786 行 · 第 1/2 页

H
786
字号
        txn->get_byte_enable_ptr());    }  } else { // read transaction    if(orig_be == 0) {      loop_generic0<DATAWORD, &copy_btrue0>(new_length,        new_stream_width, s_width, sizeof_databus, tc->address,        new_address, new_length, tc->data_ptr, 0, txn->get_data_ptr(),        txn->get_byte_enable_ptr());    } else {      loop_generic0<DATAWORD, &copy_b0>(new_length,        new_stream_width, s_width, sizeof_databus, tc->address,        new_address, orig_be_length, tc->data_ptr, orig_be, txn->get_data_ptr(),        txn->get_byte_enable_ptr());    }  }}///////////////////////////////////////////////////////////////////////////////// function set (1): Utilitiestemplate<class D>inline void copy_d1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) {  *((D *)dest1) = *((D *)src1);  *((D *)dest2) = tlm_bool<D>::TLM_TRUE;}template<class D>inline void copy_db1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) {  *((D *)dest1) = *((D *)src1);  *((D *)dest2) = *((D *)src2);}template<class D>inline void true_b1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) {  *((D *)dest2) = tlm_bool<D>::TLM_TRUE;}template<class D>inline void copy_b1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) {  *((D *)dest2) = *((D *)src2);}template<class D>inline void copy_dbyb1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) {  if(*src2 != TLM_BYTE_DISABLED)  *((D *)src1) = *((D *)dest1);}template<class D>inline void copy_dbytrue1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) {  *((D *)src1) = *((D *)dest1);}template<class D> inline void false_b1(uchar *dest1) {  *((D *)dest1) = tlm_bool<D>::TLM_FALSE;}template<class D> inline void no_b1(uchar *dest1) {}template<class D,         void COPY(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2),         void COPYuchar(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2),         void FILLFALSE(uchar *dest1), void FILLFALSEuchar(uchar *dest1)>inline int loop_word1(  int bytes_left, int len0, int lenN, int sizeof_databus,  uchar *start, uchar *end, uchar *src, uchar *bsrc, uchar *dest, uchar *bdest) {  int d2b_src = bsrc - src;  int d2b_dest = bdest - dest;  uchar *original_dest = dest;  while(true) {    // len0 bytes at start of a bus word    if((src >= start) && (src < end)) {      for(int i=0; i<len0; i++) {        COPYuchar(src, src+d2b_src, dest, dest+d2b_dest);        src++;        dest++;      }      bytes_left -= len0;      if(bytes_left <= 0) return int(dest - original_dest);    } else {      for(int i=0; i<len0; i++) {        FILLFALSEuchar(dest+d2b_dest);        src++;        dest++;      }    }    src -= 2 * sizeof(D);    // sequence of full data word fragments    for(unsigned int i=1; i<sizeof_databus/sizeof(D); i++) {      if((src >= start) && (src < end)) {        COPY(src, src+d2b_src, dest, dest+d2b_dest);        bytes_left -= sizeof(D);      } else {        FILLFALSE(dest+d2b_dest);      }      dest += sizeof(D);      if(bytes_left <= 0) return int(dest - original_dest);      src -= sizeof(D);    }    // lenN bytes at end of bus word    if((src >= start) && (src < end)) {      for(int i=0; i<lenN; i++) {        COPYuchar(src, src+d2b_src, dest, dest+d2b_dest);        src++;        dest++;      }      bytes_left -= lenN;      if(bytes_left <= 0) return int(dest - original_dest);    } else {      for(int i=0; i<lenN; i++) {        FILLFALSEuchar(dest+d2b_dest);        src++;        dest++;      }    }    src += 2 * sizeof_databus;  }}///////////////////////////////////////////////////////////////////////////////// function set (1): Responsetemplate<class DATAWORD> inline voidtlm_from_hostendian_word(tlm_generic_payload *txn, unsigned int sizeof_databus) {  if(txn->is_read()) {    tlm_endian_context *tc = txn->template get_extension<tlm_endian_context>();    sc_dt::uint64 b_mask = sizeof_databus - 1;    int d_mask = sizeof(DATAWORD) - 1;    int a_offset = tc->address & b_mask;    int len0 = (sizeof_databus - a_offset) & d_mask;    int lenN = sizeof(DATAWORD) - len0;    uchar *d_start = tc->data_ptr;    uchar *d_end = tc->length + d_start;    uchar *d = ((sizeof_databus - a_offset) & ~d_mask) + lenN + d_start;    // iterate over transaction copying data qualified by byte-enables    if(tc->byte_enable == 0) {      loop_word1<DATAWORD, &copy_dbytrue1<DATAWORD>,        &copy_dbytrue1<uchar>, &no_b1<DATAWORD>, &no_b1<uchar> >(        tc->length, len0, lenN, sizeof_databus, d_start, d_end, d,        0, txn->get_data_ptr(), 0);    } else {      loop_word1<DATAWORD, &copy_dbyb1<DATAWORD>,        &copy_dbyb1<uchar>, &no_b1<DATAWORD>, &no_b1<uchar> >(        tc->length, len0, lenN, sizeof_databus, d_start, d_end, d,        tc->byte_enable - d_start + d, txn->get_data_ptr(), 0);    }  }  local_buffer_pool.return_buffer(txn->get_byte_enable_ptr());  local_buffer_pool.return_buffer(txn->get_data_ptr());}///////////////////////////////////////////////////////////////////////////////// function set (1): Requesttemplate<class DATAWORD> inline voidtlm_to_hostendian_word(tlm_generic_payload *txn, unsigned int sizeof_databus) {  tlm_endian_context *tc = establish_context(txn);  tc->from_f = &(tlm_from_hostendian_word<DATAWORD>);  tc->sizeof_databus = sizeof_databus;  sc_dt::uint64 b_mask = sizeof_databus - 1;  int d_mask = sizeof(DATAWORD) - 1;  sc_dt::uint64 a_aligned = txn->get_address() & ~b_mask;  int a_offset = txn->get_address() & b_mask;  int len0 = (sizeof_databus - a_offset) & d_mask;  int lenN = sizeof(DATAWORD) - len0;  uchar *d_start = txn->get_data_ptr();  uchar *d_end = txn->get_data_length() + d_start;  uchar *d = ((sizeof_databus - a_offset) & ~d_mask) + lenN + d_start;  // create new data and byte enable buffers  int long_enough = txn->get_data_length() + 2 * sizeof_databus;  uchar *new_data = local_buffer_pool.get_a_buffer(long_enough);  uchar *new_be = local_buffer_pool.get_a_buffer(long_enough);  if(txn->is_read()) {    tc->data_ptr = d_start;    tc->address = txn->get_address();    tc->byte_enable = txn->get_byte_enable_ptr();    tc->length = txn->get_data_length();    if(txn->get_byte_enable_ptr() == 0) {      // iterate over transaction creating new byte enables from all-true      txn->set_data_length(loop_word1<DATAWORD, &true_b1<DATAWORD>,        &true_b1<uchar>, &false_b1<DATAWORD>, &false_b1<uchar> >(        txn->get_data_length(), len0, lenN, sizeof_databus,        d_start, d_end, d, 0, new_data, new_be));    } else {      // iterate over transaction copying byte enables      txn->set_data_length(loop_word1<DATAWORD, &copy_b1<DATAWORD>,        &copy_b1<uchar>, &false_b1<DATAWORD>, &false_b1<uchar> >(        txn->get_data_length(), len0, lenN, sizeof_databus, d_start, d_end,        d, txn->get_byte_enable_ptr() - d_start + d, new_data, new_be));    }  } else {    // WRITE    if(txn->get_byte_enable_ptr() == 0) {      // iterate over transaction copying data and creating new byte-enables      txn->set_data_length(loop_word1<DATAWORD, &copy_d1<DATAWORD>,        &copy_d1<uchar>, &false_b1<DATAWORD>, &false_b1<uchar> >(        txn->get_data_length(), len0, lenN, sizeof_databus,        d_start, d_end, d, 0, new_data, new_be));    } else {      // iterate over transaction copying data and byte-enables      txn->set_data_length(loop_word1<DATAWORD, &copy_db1<DATAWORD>,        &copy_db1<uchar>, &false_b1<DATAWORD>, &false_b1<uchar> >(        txn->get_data_length(), len0, lenN, sizeof_databus, d_start, d_end,        d, txn->get_byte_enable_ptr() - d_start + d, new_data, new_be));    }  }  txn->set_byte_enable_length(txn->get_data_length());  txn->set_streaming_width(txn->get_data_length());  txn->set_data_ptr(new_data);  txn->set_byte_enable_ptr(new_be);  txn->set_address(a_aligned);}///////////////////////////////////////////////////////////////////////////////// function set (2): Utilitiestemplate<class D> inline void copy_d2(D *src1, D *src2, D *dest1, D *dest2) {  *dest1 = *src1;}template<class D> inline void copy_db2(D *src1, D *src2, D *dest1, D *dest2) {  *dest1 = *src1;  *dest2 = *src2;}template<class D>inline void copy_dbyb2(D *src1, D *src2, D *dest1, D *dest2) {  if(tlm_bool<D>(*src2)) *dest1 = *src1;}template<class D, void COPY(D *src1, D *src2, D *dest1, D *dest2)>inline void loop_aligned2(D *src1, D *src2, D *dest1, D *dest2,    int words, int words_per_bus) {  int src1to2 = int(src2) - int(src1);  int dest1to2 = int(dest2) - int(dest1);  D *done = src1 + words;  D *bus_start = src1;  src1 += words_per_bus - 1;  while(true) {    COPY(src1, (D *)(int(src1)+src1to2), dest1, (D *)(int(dest1)+dest1to2));    dest1++;    if((--src1) < bus_start) {      bus_start += words_per_bus;      if(bus_start == done) break;      src1 = bus_start + words_per_bus - 1;    }  }}///////////////////////////////////////////////////////////////////////////////// function set (2): Responsetemplate<class DATAWORD> inline voidtlm_from_hostendian_aligned(tlm_generic_payload *txn, unsigned int sizeof_databus) {  int words_per_bus = sizeof_databus/sizeof(DATAWORD);  if(words_per_bus == 1) return;  int words = (txn->get_data_length())/sizeof(DATAWORD);  if(txn->get_byte_enable_ptr() == 0) {    // no byte enables    if(txn->is_read()) {      // RD without byte enables.  Copy data to original buffer      tlm_endian_context *tc = txn->template get_extension<tlm_endian_context>();      loop_aligned2<DATAWORD, &copy_d2<DATAWORD> >(        (DATAWORD *)(txn->get_data_ptr()),        0, (DATAWORD *)(tc->data_ptr), 0, words, words_per_bus);    }  } else {    // byte enables present    if(txn->is_read()) {      // RD with byte enables.  Copy data qualified by byte-enables      tlm_endian_context *tc = txn->template get_extension<tlm_endian_context>();      loop_aligned2<DATAWORD, &copy_dbyb2<DATAWORD> >(        (DATAWORD *)(txn->get_data_ptr()),        (DATAWORD *)(txn->get_byte_enable_ptr()),        (DATAWORD *)(tc->data_ptr), 0, words, words_per_bus);    }    local_buffer_pool.return_buffer(txn->get_byte_enable_ptr());  }  // in all cases free the new data buffer  local_buffer_pool.return_buffer(txn->get_data_ptr());}///////////////////////////////////////////////////////////////////////////////// function set (2): Requesttemplate<class DATAWORD> inline voidtlm_to_hostendian_aligned(tlm_generic_payload *txn, unsigned int sizeof_databus) {  tlm_endian_context *tc = establish_context(txn);  tc->from_f = &(tlm_from_hostendian_aligned<DATAWORD>);  tc->sizeof_databus = sizeof_databus;  int words_per_bus = sizeof_databus/sizeof(DATAWORD);  if(words_per_bus == 1) return;  int words = (txn->get_data_length())/sizeof(DATAWORD);  DATAWORD *original_be = (DATAWORD *)(txn->get_byte_enable_ptr());  DATAWORD *original_data = (DATAWORD *)(txn->get_data_ptr());  // always allocate a new data buffer  txn->set_data_ptr(local_buffer_pool.get_a_buffer(txn->get_data_length()));  if(original_be == 0) {    // no byte enables    if(txn->is_write()) {      // WR no byte enables.  Copy data      loop_aligned2<DATAWORD, &copy_d2<DATAWORD> >(original_data, 0,        (DATAWORD *)(txn->get_data_ptr()), 0,        words, words_per_bus);    } else {      // RD no byte enables.  Save original data pointer      tc->data_ptr = (uchar *)original_data;    }  } else {    // byte enables present    // allocate a new buffer for them    txn->set_byte_enable_ptr(      local_buffer_pool.get_a_buffer(txn->get_data_length()));    txn->set_byte_enable_length(txn->get_data_length());    if(txn->is_write()) {      // WR with byte enables.  Copy data and BEs      loop_aligned2<DATAWORD, &copy_db2<DATAWORD> >(original_data, original_be,        (DATAWORD *)(txn->get_data_ptr()),        (DATAWORD *)(txn->get_byte_enable_ptr()), words, words_per_bus);    } else {      // RD with byte enables.  Save original data pointer      tc->data_ptr = (uchar *)original_data;      // Copy byte enables to new buffer      loop_aligned2<DATAWORD, &copy_d2<DATAWORD> >(original_be, 0,        (DATAWORD *)(txn->get_byte_enable_ptr()), 0,        words, words_per_bus);    }  }}///////////////////////////////////////////////////////////////////////////////// function set (3): Responsetemplate<class DATAWORD> inline voidtlm_from_hostendian_single(tlm_generic_payload *txn, unsigned int sizeof_databus) {  // nothing needs to be done here}///////////////////////////////////////////////////////////////////////////////// function set (3): Requesttemplate<class DATAWORD> inline voidtlm_to_hostendian_single(tlm_generic_payload *txn, unsigned int sizeof_databus) {  tlm_endian_context *tc = establish_context(txn);  tc->from_f = &(tlm_from_hostendian_single<DATAWORD>);  tc->sizeof_databus = sizeof_databus;  // only need to change the address, always safe to work in-place  sc_dt::uint64 mask = sizeof_databus-1;  sc_dt::uint64 a = txn->get_address();  txn->set_address((a & ~mask) |    (sizeof_databus - (a & mask) - sizeof(DATAWORD)));}///////////////////////////////////////////////////////////////////////////////// helper function which works for all responsesinline void tlm_from_hostendian(tlm_generic_payload *txn) {  tlm_endian_context *tc = txn->get_extension<tlm_endian_context>();  (*(tc->from_f))(txn, tc->sizeof_databus);}#ifndef TLM_END_CONV_DONT_UNDEF_UCHAR#undef uchar#endif}  // namespace tlm#endif  // multiple-inclusion protection

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?