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, ©_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, ©_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, ©_dbytrue1<DATAWORD>, ©_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, ©_dbyb1<DATAWORD>, ©_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, ©_b1<DATAWORD>, ©_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, ©_d1<DATAWORD>, ©_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, ©_db1<DATAWORD>, ©_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, ©_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, ©_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, ©_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, ©_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, ©_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 + -
显示快捷键?