tlm_endian_conv.h revision 12027
112027Sjungma@eit.uni-kl.de/***************************************************************************** 212027Sjungma@eit.uni-kl.de 312027Sjungma@eit.uni-kl.de Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 412027Sjungma@eit.uni-kl.de more contributor license agreements. See the NOTICE file distributed 512027Sjungma@eit.uni-kl.de with this work for additional information regarding copyright ownership. 612027Sjungma@eit.uni-kl.de Accellera licenses this file to you under the Apache License, Version 2.0 712027Sjungma@eit.uni-kl.de (the "License"); you may not use this file except in compliance with the 812027Sjungma@eit.uni-kl.de License. You may obtain a copy of the License at 912027Sjungma@eit.uni-kl.de 1012027Sjungma@eit.uni-kl.de http://www.apache.org/licenses/LICENSE-2.0 1112027Sjungma@eit.uni-kl.de 1212027Sjungma@eit.uni-kl.de Unless required by applicable law or agreed to in writing, software 1312027Sjungma@eit.uni-kl.de distributed under the License is distributed on an "AS IS" BASIS, 1412027Sjungma@eit.uni-kl.de WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 1512027Sjungma@eit.uni-kl.de implied. See the License for the specific language governing 1612027Sjungma@eit.uni-kl.de permissions and limitations under the License. 1712027Sjungma@eit.uni-kl.de 1812027Sjungma@eit.uni-kl.de *****************************************************************************/ 1912027Sjungma@eit.uni-kl.de 2012027Sjungma@eit.uni-kl.de 2112027Sjungma@eit.uni-kl.de#ifndef __TLM_ENDIAN_CONV_H__ 2212027Sjungma@eit.uni-kl.de#define __TLM_ENDIAN_CONV_H__ 2312027Sjungma@eit.uni-kl.de 2412027Sjungma@eit.uni-kl.de#include <systemc> 2512027Sjungma@eit.uni-kl.de#include "tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h" 2612027Sjungma@eit.uni-kl.de 2712027Sjungma@eit.uni-kl.de 2812027Sjungma@eit.uni-kl.denamespace tlm { 2912027Sjungma@eit.uni-kl.de 3012027Sjungma@eit.uni-kl.de 3112027Sjungma@eit.uni-kl.de/* 3212027Sjungma@eit.uni-kl.deTranaction-Level Modelling 3312027Sjungma@eit.uni-kl.deEndianness Helper Functions 3412027Sjungma@eit.uni-kl.de 3512027Sjungma@eit.uni-kl.deDESCRIPTION 3612027Sjungma@eit.uni-kl.deA set of functions for helping users to get the endianness 3712027Sjungma@eit.uni-kl.deright in their TLM models of system initiators. These functions are 3812027Sjungma@eit.uni-kl.defor use within an initiator. They can not be used as-is outside 3912027Sjungma@eit.uni-kl.dean initiator because the extension used to store context will not work 4012027Sjungma@eit.uni-kl.deif cascaded, and they do not respect the generic payload mutability 4112027Sjungma@eit.uni-kl.derules. However this code may be easily copied and adapted for use 4212027Sjungma@eit.uni-kl.dein bridges, etc.. 4312027Sjungma@eit.uni-kl.de 4412027Sjungma@eit.uni-kl.deThese functions are not compulsory. There are other legitimate ways to 4512027Sjungma@eit.uni-kl.deachieve the same functionality. If extra information is available at 4612027Sjungma@eit.uni-kl.decompile time about the nature of an initiator's transactions, this can 4712027Sjungma@eit.uni-kl.debe exploited to accelerate simulations by creating further functions 4812027Sjungma@eit.uni-kl.desimilar to those in this file. In general a functional transaction can be 4912027Sjungma@eit.uni-kl.dedescribed in more than one way by a TLM-2 GP object. 5012027Sjungma@eit.uni-kl.de 5112027Sjungma@eit.uni-kl.deThe functions convert the endianness of a GP object, either on request or 5212027Sjungma@eit.uni-kl.deresponse. They should only be used when the initiator's endianness 5312027Sjungma@eit.uni-kl.dedoes not match the host's endianness. They assume 'arithmetic mode' 5412027Sjungma@eit.uni-kl.demeaning that within a data word the byte order is always host-endian. 5512027Sjungma@eit.uni-kl.deFor non-arithmetic mode initiators they can be used with a data word 5612027Sjungma@eit.uni-kl.desize of 1 byte. 5712027Sjungma@eit.uni-kl.de 5812027Sjungma@eit.uni-kl.deAll the functions are templates, for example: 5912027Sjungma@eit.uni-kl.de 6012027Sjungma@eit.uni-kl.detemplate<class DATAWORD> inline void 6112027Sjungma@eit.uni-kl.de to_hostendian_generic(tlm_generic_payload *txn, int sizeof_databus) 6212027Sjungma@eit.uni-kl.de 6312027Sjungma@eit.uni-kl.deThe template parameter provides the data word width. Having this as a class 6412027Sjungma@eit.uni-kl.demakes it easy to use it for copy and swap operations within the functions. 6512027Sjungma@eit.uni-kl.deIf the assignment operator for this class is overloaded, the endianness 6612027Sjungma@eit.uni-kl.deconversion function may not have the desired effect. 6712027Sjungma@eit.uni-kl.de 6812027Sjungma@eit.uni-kl.deAll the functions have the same signature except for different names. 6912027Sjungma@eit.uni-kl.de 7012027Sjungma@eit.uni-kl.deThe principle is that a function to_hostendian_convtype() is called when the 7112027Sjungma@eit.uni-kl.deinitiator-endian transaction is created, and the matching function 7212027Sjungma@eit.uni-kl.defrom_hostendian_convtype() is called when the transaction is completed, for 7312027Sjungma@eit.uni-kl.deexample before read data can be used. In some cases the from_ function is 7412027Sjungma@eit.uni-kl.deredundant but an empty function is provided anyway. It is strongly 7512027Sjungma@eit.uni-kl.derecommended that the from_ function is called, in case it ceases to be 7612027Sjungma@eit.uni-kl.deredundant in future versions of this code. 7712027Sjungma@eit.uni-kl.de 7812027Sjungma@eit.uni-kl.deNo context needs to be managed outside the two functions, except that they 7912027Sjungma@eit.uni-kl.demust be called with the same template parameter and the same bus width. 8012027Sjungma@eit.uni-kl.de 8112027Sjungma@eit.uni-kl.deFor initiator models that can not easily manage this context information, 8212027Sjungma@eit.uni-kl.dea single entry point for the from_ function is provided, which will be 8312027Sjungma@eit.uni-kl.dea little slower than calling the correct from_ function directly, as 8412027Sjungma@eit.uni-kl.deit can not be inlined. 8512027Sjungma@eit.uni-kl.de 8612027Sjungma@eit.uni-kl.deAll functions assume power-of-2 bus and data word widths. 8712027Sjungma@eit.uni-kl.de 8812027Sjungma@eit.uni-kl.deFunctions offered: 8912027Sjungma@eit.uni-kl.de 9012027Sjungma@eit.uni-kl.de0) A pair of functions that work for almost all TLM2 GP transactions. The 9112027Sjungma@eit.uni-kl.deonly limitations are that data and bus widths should be powers of 2, and that 9212027Sjungma@eit.uni-kl.dethe data length should be an integer number of streaming widths and that the 9312027Sjungma@eit.uni-kl.destreaming width should be an integer number of data words. 9412027Sjungma@eit.uni-kl.deThese functions always allocate new data and byte enable buffers and copy 9512027Sjungma@eit.uni-kl.dedata one byte at a time. 9612027Sjungma@eit.uni-kl.de tlm_to_hostendian_generic(tlm_generic_payload *txn, int sizeof_databus) 9712027Sjungma@eit.uni-kl.de tlm_from_hostendian_generic(tlm_generic_payload *txn, int sizeof_databus) 9812027Sjungma@eit.uni-kl.de 9912027Sjungma@eit.uni-kl.de1) A pair of functions that work for all transactions regardless of data and 10012027Sjungma@eit.uni-kl.debus data sizes and address alignment except for the the following 10112027Sjungma@eit.uni-kl.delimitations: 10212027Sjungma@eit.uni-kl.de- byte-enables are supported only when byte-enable granularity is no finer 10312027Sjungma@eit.uni-kl.dethan the data word (every data word is wholly enabled or wholly disabled) 10412027Sjungma@eit.uni-kl.de- byte-enable-length is not supported (if byte enables are present, the byte 10512027Sjungma@eit.uni-kl.deenable length must be equal to the data length). 10612027Sjungma@eit.uni-kl.de- streaming width is not supported 10712027Sjungma@eit.uni-kl.de- data word wider than bus word is not supported 10812027Sjungma@eit.uni-kl.deA new data buffer and a new byte enable buffer are always allocated. Byte 10912027Sjungma@eit.uni-kl.deenables are assumed to be needed even if not required for the original 11012027Sjungma@eit.uni-kl.de(unconverted) transaction. Data is copied to the new buffer on request 11112027Sjungma@eit.uni-kl.de(for writes) or on response (for reads). Copies are done word-by-word 11212027Sjungma@eit.uni-kl.dewhere possible. 11312027Sjungma@eit.uni-kl.de tlm_to_hostendian_word(tlm_generic_payload *txn, int sizeof_databus) 11412027Sjungma@eit.uni-kl.de tlm_from_hostendian_word(tlm_generic_payload *txn, int sizeof_databus) 11512027Sjungma@eit.uni-kl.de 11612027Sjungma@eit.uni-kl.de2) If the original transaction is both word and bus-aligned then this pair of 11712027Sjungma@eit.uni-kl.defunctions can be used. It will complete faster than the generic function 11812027Sjungma@eit.uni-kl.debecause the data reordering function is much simpler and no address 11912027Sjungma@eit.uni-kl.deconversion is required. 12012027Sjungma@eit.uni-kl.deThe following limitations apply: 12112027Sjungma@eit.uni-kl.de- byte-enables are supported only when byte-enable granularity is no finer 12212027Sjungma@eit.uni-kl.dethan the data word (every data word is wholly enabled or wholly disabled) 12312027Sjungma@eit.uni-kl.de- byte-enable-length is not supported (if byte enables are present, the byte 12412027Sjungma@eit.uni-kl.deenable length must be equal to the data length). 12512027Sjungma@eit.uni-kl.de- streaming width is not supported 12612027Sjungma@eit.uni-kl.de- data word wider than bus word is not supported 12712027Sjungma@eit.uni-kl.de- the transaction must be an integer number of bus words 12812027Sjungma@eit.uni-kl.de- the address must be aligned to the bus width 12912027Sjungma@eit.uni-kl.de tlm_to_hostendian_aligned(tlm_generic_payload *txn, int sizeof_databus) 13012027Sjungma@eit.uni-kl.de tlm_from_hostendian_aligned(tlm_generic_payload *txn, int sizeof_databus) 13112027Sjungma@eit.uni-kl.de 13212027Sjungma@eit.uni-kl.de3) For single word transactions that don't cross a bus word boundary it 13312027Sjungma@eit.uni-kl.deis always safe to work in-place and the conversion is very simple. Again, 13412027Sjungma@eit.uni-kl.destreaming width and byte-enable length are not supported, and byte-enables 13512027Sjungma@eit.uni-kl.demay not changes within a data word. 13612027Sjungma@eit.uni-kl.de tlm_to_hostendian_single(tlm_generic_payload *txn, int sizeof_databus) 13712027Sjungma@eit.uni-kl.de tlm_from_hostendian_single(tlm_generic_payload *txn, int sizeof_databus) 13812027Sjungma@eit.uni-kl.de 13912027Sjungma@eit.uni-kl.de4) A single entry point for accessing the correct from_ function without 14012027Sjungma@eit.uni-kl.deneeding to store context. 14112027Sjungma@eit.uni-kl.de tlm_from_hostendian(tlm_generic_payload *txn) 14212027Sjungma@eit.uni-kl.de*/ 14312027Sjungma@eit.uni-kl.de 14412027Sjungma@eit.uni-kl.de 14512027Sjungma@eit.uni-kl.de 14612027Sjungma@eit.uni-kl.de#ifndef uchar 14712027Sjungma@eit.uni-kl.de#define uchar unsigned char 14812027Sjungma@eit.uni-kl.de#else 14912027Sjungma@eit.uni-kl.de#define TLM_END_CONV_DONT_UNDEF_UCHAR 15012027Sjungma@eit.uni-kl.de#endif 15112027Sjungma@eit.uni-kl.de 15212027Sjungma@eit.uni-kl.de 15312027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////////////////////////////// 15412027Sjungma@eit.uni-kl.de// Generic Utilities 15512027Sjungma@eit.uni-kl.de 15612027Sjungma@eit.uni-kl.declass tlm_endian_context; 15712027Sjungma@eit.uni-kl.declass tlm_endian_context_pool { 15812027Sjungma@eit.uni-kl.de public: 15912027Sjungma@eit.uni-kl.de tlm_endian_context *first; 16012027Sjungma@eit.uni-kl.de inline tlm_endian_context_pool(); 16112027Sjungma@eit.uni-kl.de inline ~tlm_endian_context_pool(); 16212027Sjungma@eit.uni-kl.de inline tlm_endian_context *pop(); 16312027Sjungma@eit.uni-kl.de inline void push(tlm_endian_context *c); 16412027Sjungma@eit.uni-kl.de}; 16512027Sjungma@eit.uni-kl.destatic tlm_endian_context_pool global_tlm_endian_context_pool; 16612027Sjungma@eit.uni-kl.de 16712027Sjungma@eit.uni-kl.de// an extension to keep the information needed for reconversion of response 16812027Sjungma@eit.uni-kl.declass tlm_endian_context : public tlm_extension<tlm_endian_context> { 16912027Sjungma@eit.uni-kl.de public: 17012027Sjungma@eit.uni-kl.de tlm_endian_context() : dbuf_size(0), bebuf_size(0) {} 17112027Sjungma@eit.uni-kl.de ~tlm_endian_context() { 17212027Sjungma@eit.uni-kl.de if(dbuf_size > 0) delete [] new_dbuf; 17312027Sjungma@eit.uni-kl.de if(bebuf_size > 0) delete [] new_bebuf; 17412027Sjungma@eit.uni-kl.de } 17512027Sjungma@eit.uni-kl.de 17612027Sjungma@eit.uni-kl.de sc_dt::uint64 address; // used by generic, word 17712027Sjungma@eit.uni-kl.de sc_dt::uint64 new_address; // used by generic 17812027Sjungma@eit.uni-kl.de uchar *data_ptr; // used by generic, word, aligned 17912027Sjungma@eit.uni-kl.de uchar *byte_enable; // used by word 18012027Sjungma@eit.uni-kl.de int length; // used by generic, word 18112027Sjungma@eit.uni-kl.de int stream_width; // used by generic 18212027Sjungma@eit.uni-kl.de 18312027Sjungma@eit.uni-kl.de // used by common entry point on response 18412027Sjungma@eit.uni-kl.de void (*from_f)(tlm_generic_payload *txn, unsigned int sizeof_databus); 18512027Sjungma@eit.uni-kl.de int sizeof_databus; 18612027Sjungma@eit.uni-kl.de 18712027Sjungma@eit.uni-kl.de // reordering buffers for data and byte-enables 18812027Sjungma@eit.uni-kl.de uchar *new_dbuf, *new_bebuf; 18912027Sjungma@eit.uni-kl.de int dbuf_size, bebuf_size; 19012027Sjungma@eit.uni-kl.de void establish_dbuf(int len) { 19112027Sjungma@eit.uni-kl.de if(len <= dbuf_size) return; 19212027Sjungma@eit.uni-kl.de if(dbuf_size > 0) delete [] new_dbuf; 19312027Sjungma@eit.uni-kl.de new_dbuf = new uchar[len]; 19412027Sjungma@eit.uni-kl.de dbuf_size = len; 19512027Sjungma@eit.uni-kl.de } 19612027Sjungma@eit.uni-kl.de void establish_bebuf(int len) { 19712027Sjungma@eit.uni-kl.de if(len <= bebuf_size) return; 19812027Sjungma@eit.uni-kl.de if(bebuf_size > 0) delete [] new_bebuf; 19912027Sjungma@eit.uni-kl.de new_bebuf = new uchar[len]; 20012027Sjungma@eit.uni-kl.de bebuf_size = len; 20112027Sjungma@eit.uni-kl.de } 20212027Sjungma@eit.uni-kl.de 20312027Sjungma@eit.uni-kl.de // required for extension management 20412027Sjungma@eit.uni-kl.de void free() { 20512027Sjungma@eit.uni-kl.de global_tlm_endian_context_pool.push(this); 20612027Sjungma@eit.uni-kl.de } 20712027Sjungma@eit.uni-kl.de tlm_extension_base* clone() const {return 0;} 20812027Sjungma@eit.uni-kl.de void copy_from(tlm_extension_base const &) {return;} 20912027Sjungma@eit.uni-kl.de 21012027Sjungma@eit.uni-kl.de // for pooling 21112027Sjungma@eit.uni-kl.de tlm_endian_context *next; 21212027Sjungma@eit.uni-kl.de}; 21312027Sjungma@eit.uni-kl.de// Assumptions about transaction contexts: 21412027Sjungma@eit.uni-kl.de// 1) only the address attribute of a transaction 21512027Sjungma@eit.uni-kl.de// is mutable. all other attributes are unchanged from the request to 21612027Sjungma@eit.uni-kl.de// response side conversion. 21712027Sjungma@eit.uni-kl.de// 2) the conversion functions in this file do not respect the mutability 21812027Sjungma@eit.uni-kl.de// rules and do not put the transaction back into its original state after 21912027Sjungma@eit.uni-kl.de// completion. so if the initiator has any cleaning up to do (eg of byte 22012027Sjungma@eit.uni-kl.de// enable buffers), it needs to store its own context. the transaction 22112027Sjungma@eit.uni-kl.de// returned to the initiator may contain pointers to data and byte enable 22212027Sjungma@eit.uni-kl.de// that can/must not be deleted. 22312027Sjungma@eit.uni-kl.de// 3) the conversion functions in this file use an extension to store 22412027Sjungma@eit.uni-kl.de// context information. they do not remove this extension. the initiator 22512027Sjungma@eit.uni-kl.de// should not remove it unless it deletes the generic payload 22612027Sjungma@eit.uni-kl.de// object. 22712027Sjungma@eit.uni-kl.de 22812027Sjungma@eit.uni-kl.deinline tlm_endian_context *establish_context(tlm_generic_payload *txn) { 22912027Sjungma@eit.uni-kl.de tlm_endian_context *tc = txn->get_extension<tlm_endian_context>(); 23012027Sjungma@eit.uni-kl.de if(tc == 0) { 23112027Sjungma@eit.uni-kl.de tc = global_tlm_endian_context_pool.pop(); 23212027Sjungma@eit.uni-kl.de txn->set_extension(tc); 23312027Sjungma@eit.uni-kl.de } 23412027Sjungma@eit.uni-kl.de return tc; 23512027Sjungma@eit.uni-kl.de} 23612027Sjungma@eit.uni-kl.de 23712027Sjungma@eit.uni-kl.deinline tlm_endian_context_pool::tlm_endian_context_pool() : first(0) {} 23812027Sjungma@eit.uni-kl.de 23912027Sjungma@eit.uni-kl.deinline tlm_endian_context_pool::~tlm_endian_context_pool() { 24012027Sjungma@eit.uni-kl.de while(first != 0) { 24112027Sjungma@eit.uni-kl.de tlm_endian_context *next = first->next; 24212027Sjungma@eit.uni-kl.de delete first; 24312027Sjungma@eit.uni-kl.de first = next; 24412027Sjungma@eit.uni-kl.de } 24512027Sjungma@eit.uni-kl.de} 24612027Sjungma@eit.uni-kl.de 24712027Sjungma@eit.uni-kl.detlm_endian_context *tlm_endian_context_pool::pop() { 24812027Sjungma@eit.uni-kl.de if(first == 0) return new tlm_endian_context; 24912027Sjungma@eit.uni-kl.de tlm_endian_context *r = first; 25012027Sjungma@eit.uni-kl.de first = first->next; 25112027Sjungma@eit.uni-kl.de return r; 25212027Sjungma@eit.uni-kl.de} 25312027Sjungma@eit.uni-kl.de 25412027Sjungma@eit.uni-kl.devoid tlm_endian_context_pool::push(tlm_endian_context *c) { 25512027Sjungma@eit.uni-kl.de c->next = first; 25612027Sjungma@eit.uni-kl.de first = c; 25712027Sjungma@eit.uni-kl.de} 25812027Sjungma@eit.uni-kl.de 25912027Sjungma@eit.uni-kl.de 26012027Sjungma@eit.uni-kl.de// a set of constants for efficient filling of byte enables 26112027Sjungma@eit.uni-kl.detemplate<class D> class tlm_bool { 26212027Sjungma@eit.uni-kl.de public: 26312027Sjungma@eit.uni-kl.de static D TLM_TRUE; 26412027Sjungma@eit.uni-kl.de static D TLM_FALSE; 26512027Sjungma@eit.uni-kl.de static D make_uchar_array(uchar c) { 26612027Sjungma@eit.uni-kl.de D d; 26712027Sjungma@eit.uni-kl.de uchar *tmp = (uchar *)(&d); 26812027Sjungma@eit.uni-kl.de for(ptrdiff_t i=0; i!=sizeof(D); i++) tmp[i] = c; // 64BITFIX negligable risk but easy fix // 26912027Sjungma@eit.uni-kl.de return d; 27012027Sjungma@eit.uni-kl.de } 27112027Sjungma@eit.uni-kl.de // also provides an syntax-efficient tester, using a 27212027Sjungma@eit.uni-kl.de // copy constuctor and an implicit cast to boolean 27312027Sjungma@eit.uni-kl.de tlm_bool(D &d) : b(*((uchar*)&d) != TLM_BYTE_DISABLED) {} 27412027Sjungma@eit.uni-kl.de operator bool() const {return b;} 27512027Sjungma@eit.uni-kl.de private: 27612027Sjungma@eit.uni-kl.de bool b; 27712027Sjungma@eit.uni-kl.de}; 27812027Sjungma@eit.uni-kl.de 27912027Sjungma@eit.uni-kl.detemplate<class D> D tlm_bool<D>::TLM_TRUE 28012027Sjungma@eit.uni-kl.de = tlm_bool<D>::make_uchar_array(TLM_BYTE_ENABLED); 28112027Sjungma@eit.uni-kl.detemplate<class D> D tlm_bool<D>::TLM_FALSE 28212027Sjungma@eit.uni-kl.de = tlm_bool<D>::make_uchar_array(TLM_BYTE_DISABLED); 28312027Sjungma@eit.uni-kl.de 28412027Sjungma@eit.uni-kl.de 28512027Sjungma@eit.uni-kl.de 28612027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////////////////////////////// 28712027Sjungma@eit.uni-kl.de// function set (0): Utilities 28812027Sjungma@eit.uni-kl.deinline void copy_db0(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { 28912027Sjungma@eit.uni-kl.de *dest1 = *src1; 29012027Sjungma@eit.uni-kl.de *dest2 = *src2; 29112027Sjungma@eit.uni-kl.de} 29212027Sjungma@eit.uni-kl.de 29312027Sjungma@eit.uni-kl.deinline void copy_dbtrue0(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { 29412027Sjungma@eit.uni-kl.de *dest1 = *src1; 29512027Sjungma@eit.uni-kl.de *dest2 = TLM_BYTE_ENABLED; 29612027Sjungma@eit.uni-kl.de} 29712027Sjungma@eit.uni-kl.de 29812027Sjungma@eit.uni-kl.deinline void copy_btrue0(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { 29912027Sjungma@eit.uni-kl.de *dest2 = TLM_BYTE_ENABLED; 30012027Sjungma@eit.uni-kl.de} 30112027Sjungma@eit.uni-kl.de 30212027Sjungma@eit.uni-kl.deinline void copy_b0(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { 30312027Sjungma@eit.uni-kl.de *dest2 = *src2; 30412027Sjungma@eit.uni-kl.de} 30512027Sjungma@eit.uni-kl.de 30612027Sjungma@eit.uni-kl.deinline void copy_dbyb0(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { 30712027Sjungma@eit.uni-kl.de if(*dest2 == TLM_BYTE_ENABLED) *src1 = *dest1; 30812027Sjungma@eit.uni-kl.de} 30912027Sjungma@eit.uni-kl.de 31012027Sjungma@eit.uni-kl.de 31112027Sjungma@eit.uni-kl.detemplate<class D, 31212027Sjungma@eit.uni-kl.de void COPY(uchar *he_d, uchar *he_b, uchar *ie_d, uchar *ie_b)> 31312027Sjungma@eit.uni-kl.deinline void loop_generic0(int new_len, int new_stream_width, 31412027Sjungma@eit.uni-kl.de int orig_stream_width, int sizeof_databus, 31512027Sjungma@eit.uni-kl.de sc_dt::uint64 orig_start_address, sc_dt::uint64 new_start_address, int be_length, 31612027Sjungma@eit.uni-kl.de uchar *ie_data, uchar *ie_be, uchar *he_data, uchar *he_be) { 31712027Sjungma@eit.uni-kl.de 31812027Sjungma@eit.uni-kl.de for(int orig_sword = 0, new_sword = 0; new_sword < new_len; 31912027Sjungma@eit.uni-kl.de new_sword += new_stream_width, orig_sword += orig_stream_width) { 32012027Sjungma@eit.uni-kl.de 32112027Sjungma@eit.uni-kl.de sc_dt::uint64 ie_addr = orig_start_address; 32212027Sjungma@eit.uni-kl.de for(int orig_dword = orig_sword; 32312027Sjungma@eit.uni-kl.de orig_dword < orig_sword + orig_stream_width; orig_dword += sizeof(D)) { 32412027Sjungma@eit.uni-kl.de 32512027Sjungma@eit.uni-kl.de for(int curr_byte = orig_dword + sizeof(D) - 1; 32612027Sjungma@eit.uni-kl.de curr_byte >= orig_dword; curr_byte--) { 32712027Sjungma@eit.uni-kl.de 32812027Sjungma@eit.uni-kl.de ptrdiff_t he_index = ((ie_addr++) ^ (sizeof_databus - 1)) 32912027Sjungma@eit.uni-kl.de - new_start_address + new_sword; // 64BITFIX // 33012027Sjungma@eit.uni-kl.de COPY(ie_data+curr_byte, 33112027Sjungma@eit.uni-kl.de ie_be+(curr_byte % be_length), // 64BITRISK no risk of overflow, always positive // 33212027Sjungma@eit.uni-kl.de he_data+he_index, he_be+he_index); 33312027Sjungma@eit.uni-kl.de } 33412027Sjungma@eit.uni-kl.de } 33512027Sjungma@eit.uni-kl.de } 33612027Sjungma@eit.uni-kl.de} 33712027Sjungma@eit.uni-kl.de 33812027Sjungma@eit.uni-kl.de 33912027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////////////////////////////// 34012027Sjungma@eit.uni-kl.de// function set (0): Response 34112027Sjungma@eit.uni-kl.detemplate<class DATAWORD> inline void 34212027Sjungma@eit.uni-kl.detlm_from_hostendian_generic(tlm_generic_payload *txn, unsigned int sizeof_databus) { 34312027Sjungma@eit.uni-kl.de if(txn->is_read()) { 34412027Sjungma@eit.uni-kl.de tlm_endian_context *tc = txn->template get_extension<tlm_endian_context>(); 34512027Sjungma@eit.uni-kl.de loop_generic0<DATAWORD, ©_dbyb0>(txn->get_data_length(), 34612027Sjungma@eit.uni-kl.de txn->get_streaming_width(), tc->stream_width, sizeof_databus, tc->address, 34712027Sjungma@eit.uni-kl.de tc->new_address, txn->get_data_length(), tc->data_ptr, 0, txn->get_data_ptr(), 34812027Sjungma@eit.uni-kl.de txn->get_byte_enable_ptr()); 34912027Sjungma@eit.uni-kl.de } 35012027Sjungma@eit.uni-kl.de} 35112027Sjungma@eit.uni-kl.de 35212027Sjungma@eit.uni-kl.de 35312027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////////////////////////////// 35412027Sjungma@eit.uni-kl.de// function set (0): Request 35512027Sjungma@eit.uni-kl.detemplate<class DATAWORD> inline void 35612027Sjungma@eit.uni-kl.detlm_to_hostendian_generic(tlm_generic_payload *txn, unsigned int sizeof_databus) { 35712027Sjungma@eit.uni-kl.de tlm_endian_context *tc = establish_context(txn); 35812027Sjungma@eit.uni-kl.de tc->from_f = &(tlm_from_hostendian_generic<DATAWORD>); 35912027Sjungma@eit.uni-kl.de tc->sizeof_databus = sizeof_databus; 36012027Sjungma@eit.uni-kl.de 36112027Sjungma@eit.uni-kl.de // calculate new size: nr stream words multiplied by big enough stream width 36212027Sjungma@eit.uni-kl.de int s_width = txn->get_streaming_width(); 36312027Sjungma@eit.uni-kl.de int length = txn->get_data_length(); 36412027Sjungma@eit.uni-kl.de if(s_width >= length) s_width = length; 36512027Sjungma@eit.uni-kl.de int nr_stream_words = length/s_width; 36612027Sjungma@eit.uni-kl.de 36712027Sjungma@eit.uni-kl.de // find out in which bus word the stream word starts and ends 36812027Sjungma@eit.uni-kl.de sc_dt::uint64 new_address = (txn->get_address() & ~(sizeof_databus - 1)); 36912027Sjungma@eit.uni-kl.de sc_dt::uint64 end_address = ((txn->get_address() + s_width - 1) 37012027Sjungma@eit.uni-kl.de & ~(sizeof_databus - 1)); 37112027Sjungma@eit.uni-kl.de 37212027Sjungma@eit.uni-kl.de int new_stream_width = end_address - new_address + sizeof_databus; 37312027Sjungma@eit.uni-kl.de int new_length = new_stream_width * nr_stream_words; 37412027Sjungma@eit.uni-kl.de 37512027Sjungma@eit.uni-kl.de // store context 37612027Sjungma@eit.uni-kl.de tc->data_ptr = txn->get_data_ptr(); 37712027Sjungma@eit.uni-kl.de tc->address = txn->get_address(); 37812027Sjungma@eit.uni-kl.de tc->new_address = new_address; 37912027Sjungma@eit.uni-kl.de tc->stream_width = s_width; 38012027Sjungma@eit.uni-kl.de uchar *orig_be = txn->get_byte_enable_ptr(); 38112027Sjungma@eit.uni-kl.de int orig_be_length = txn->get_byte_enable_length(); 38212027Sjungma@eit.uni-kl.de 38312027Sjungma@eit.uni-kl.de // create data and byte-enable buffers 38412027Sjungma@eit.uni-kl.de txn->set_address(new_address); 38512027Sjungma@eit.uni-kl.de tc->establish_dbuf(new_length); 38612027Sjungma@eit.uni-kl.de txn->set_data_ptr(tc->new_dbuf); 38712027Sjungma@eit.uni-kl.de tc->establish_bebuf(new_length); 38812027Sjungma@eit.uni-kl.de txn->set_byte_enable_ptr(tc->new_bebuf); 38912027Sjungma@eit.uni-kl.de memset(txn->get_byte_enable_ptr(), TLM_BYTE_DISABLED, new_length); 39012027Sjungma@eit.uni-kl.de txn->set_streaming_width(new_stream_width); 39112027Sjungma@eit.uni-kl.de txn->set_data_length(new_length); 39212027Sjungma@eit.uni-kl.de txn->set_byte_enable_length(new_length); 39312027Sjungma@eit.uni-kl.de 39412027Sjungma@eit.uni-kl.de // copy data and/or byte enables 39512027Sjungma@eit.uni-kl.de if(txn->is_write()) { 39612027Sjungma@eit.uni-kl.de if(orig_be == 0) { 39712027Sjungma@eit.uni-kl.de loop_generic0<DATAWORD, ©_dbtrue0>(new_length, 39812027Sjungma@eit.uni-kl.de new_stream_width, s_width, sizeof_databus, tc->address, 39912027Sjungma@eit.uni-kl.de new_address, new_length, tc->data_ptr, 0, txn->get_data_ptr(), 40012027Sjungma@eit.uni-kl.de txn->get_byte_enable_ptr()); 40112027Sjungma@eit.uni-kl.de } else { 40212027Sjungma@eit.uni-kl.de loop_generic0<DATAWORD, ©_db0>(new_length, 40312027Sjungma@eit.uni-kl.de new_stream_width, s_width, sizeof_databus, tc->address, 40412027Sjungma@eit.uni-kl.de new_address, orig_be_length, tc->data_ptr, orig_be, txn->get_data_ptr(), 40512027Sjungma@eit.uni-kl.de txn->get_byte_enable_ptr()); 40612027Sjungma@eit.uni-kl.de } 40712027Sjungma@eit.uni-kl.de } else { // read transaction 40812027Sjungma@eit.uni-kl.de if(orig_be == 0) { 40912027Sjungma@eit.uni-kl.de loop_generic0<DATAWORD, ©_btrue0>(new_length, 41012027Sjungma@eit.uni-kl.de new_stream_width, s_width, sizeof_databus, tc->address, 41112027Sjungma@eit.uni-kl.de new_address, new_length, tc->data_ptr, 0, txn->get_data_ptr(), 41212027Sjungma@eit.uni-kl.de txn->get_byte_enable_ptr()); 41312027Sjungma@eit.uni-kl.de } else { 41412027Sjungma@eit.uni-kl.de loop_generic0<DATAWORD, ©_b0>(new_length, 41512027Sjungma@eit.uni-kl.de new_stream_width, s_width, sizeof_databus, tc->address, 41612027Sjungma@eit.uni-kl.de new_address, orig_be_length, tc->data_ptr, orig_be, txn->get_data_ptr(), 41712027Sjungma@eit.uni-kl.de txn->get_byte_enable_ptr()); 41812027Sjungma@eit.uni-kl.de } 41912027Sjungma@eit.uni-kl.de } 42012027Sjungma@eit.uni-kl.de} 42112027Sjungma@eit.uni-kl.de 42212027Sjungma@eit.uni-kl.de 42312027Sjungma@eit.uni-kl.de 42412027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////////////////////////////// 42512027Sjungma@eit.uni-kl.de// function set (1): Utilities 42612027Sjungma@eit.uni-kl.detemplate<class D> 42712027Sjungma@eit.uni-kl.deinline void copy_d1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { 42812027Sjungma@eit.uni-kl.de *((D *)dest1) = *((D *)src1); 42912027Sjungma@eit.uni-kl.de *((D *)dest2) = tlm_bool<D>::TLM_TRUE; 43012027Sjungma@eit.uni-kl.de} 43112027Sjungma@eit.uni-kl.de 43212027Sjungma@eit.uni-kl.detemplate<class D> 43312027Sjungma@eit.uni-kl.deinline void copy_db1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { 43412027Sjungma@eit.uni-kl.de *((D *)dest1) = *((D *)src1); 43512027Sjungma@eit.uni-kl.de *((D *)dest2) = *((D *)src2); 43612027Sjungma@eit.uni-kl.de} 43712027Sjungma@eit.uni-kl.de 43812027Sjungma@eit.uni-kl.detemplate<class D> 43912027Sjungma@eit.uni-kl.deinline void true_b1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { 44012027Sjungma@eit.uni-kl.de *((D *)dest2) = tlm_bool<D>::TLM_TRUE; 44112027Sjungma@eit.uni-kl.de} 44212027Sjungma@eit.uni-kl.de 44312027Sjungma@eit.uni-kl.detemplate<class D> 44412027Sjungma@eit.uni-kl.deinline void copy_b1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { 44512027Sjungma@eit.uni-kl.de *((D *)dest2) = *((D *)src2); 44612027Sjungma@eit.uni-kl.de} 44712027Sjungma@eit.uni-kl.de 44812027Sjungma@eit.uni-kl.detemplate<class D> 44912027Sjungma@eit.uni-kl.deinline void copy_dbyb1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { 45012027Sjungma@eit.uni-kl.de if(*src2 != TLM_BYTE_DISABLED) *((D *)src1) = *((D *)dest1); 45112027Sjungma@eit.uni-kl.de} 45212027Sjungma@eit.uni-kl.de 45312027Sjungma@eit.uni-kl.detemplate<class D> 45412027Sjungma@eit.uni-kl.deinline void copy_dbytrue1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { 45512027Sjungma@eit.uni-kl.de *((D *)src1) = *((D *)dest1); 45612027Sjungma@eit.uni-kl.de} 45712027Sjungma@eit.uni-kl.de 45812027Sjungma@eit.uni-kl.detemplate<class D> inline void false_b1(uchar *dest1) { 45912027Sjungma@eit.uni-kl.de *((D *)dest1) = tlm_bool<D>::TLM_FALSE; 46012027Sjungma@eit.uni-kl.de} 46112027Sjungma@eit.uni-kl.de 46212027Sjungma@eit.uni-kl.detemplate<class D> inline void no_b1(uchar *dest1) { 46312027Sjungma@eit.uni-kl.de} 46412027Sjungma@eit.uni-kl.de 46512027Sjungma@eit.uni-kl.detemplate<class D, 46612027Sjungma@eit.uni-kl.de void COPY(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2), 46712027Sjungma@eit.uni-kl.de void COPYuchar(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2), 46812027Sjungma@eit.uni-kl.de void FILLFALSE(uchar *dest1), void FILLFALSEuchar(uchar *dest1)> 46912027Sjungma@eit.uni-kl.deinline int loop_word1( 47012027Sjungma@eit.uni-kl.de int bytes_left, int len0, int lenN, int sizeof_databus, 47112027Sjungma@eit.uni-kl.de uchar *start, uchar *end, uchar *src, uchar *bsrc, uchar *dest, uchar *bdest) { 47212027Sjungma@eit.uni-kl.de ptrdiff_t d2b_src = bsrc - src; // 64BITFIX was int // 47312027Sjungma@eit.uni-kl.de ptrdiff_t d2b_dest = bdest - dest; // 64BITFIX was int // 47412027Sjungma@eit.uni-kl.de uchar *original_dest = dest; 47512027Sjungma@eit.uni-kl.de 47612027Sjungma@eit.uni-kl.de while(true) { 47712027Sjungma@eit.uni-kl.de // len0 bytes at start of a bus word 47812027Sjungma@eit.uni-kl.de if((src >= start) && (src < end)) { 47912027Sjungma@eit.uni-kl.de for(int i=0; i<len0; i++) { 48012027Sjungma@eit.uni-kl.de COPYuchar(src, src+d2b_src, dest, dest+d2b_dest); 48112027Sjungma@eit.uni-kl.de src++; 48212027Sjungma@eit.uni-kl.de dest++; 48312027Sjungma@eit.uni-kl.de } 48412027Sjungma@eit.uni-kl.de bytes_left -= len0; 48512027Sjungma@eit.uni-kl.de if(bytes_left <= 0) return int(dest - original_dest); 48612027Sjungma@eit.uni-kl.de } else { 48712027Sjungma@eit.uni-kl.de for(int i=0; i<len0; i++) { 48812027Sjungma@eit.uni-kl.de FILLFALSEuchar(dest+d2b_dest); 48912027Sjungma@eit.uni-kl.de src++; 49012027Sjungma@eit.uni-kl.de dest++; 49112027Sjungma@eit.uni-kl.de } 49212027Sjungma@eit.uni-kl.de } 49312027Sjungma@eit.uni-kl.de src -= 2 * sizeof(D); 49412027Sjungma@eit.uni-kl.de 49512027Sjungma@eit.uni-kl.de // sequence of full data word fragments 49612027Sjungma@eit.uni-kl.de for(unsigned int i=1; i<sizeof_databus/sizeof(D); i++) { 49712027Sjungma@eit.uni-kl.de if((src >= start) && (src < end)) { 49812027Sjungma@eit.uni-kl.de COPY(src, src+d2b_src, dest, dest+d2b_dest); 49912027Sjungma@eit.uni-kl.de bytes_left -= sizeof(D); 50012027Sjungma@eit.uni-kl.de } else { 50112027Sjungma@eit.uni-kl.de FILLFALSE(dest+d2b_dest); 50212027Sjungma@eit.uni-kl.de } 50312027Sjungma@eit.uni-kl.de dest += sizeof(D); 50412027Sjungma@eit.uni-kl.de if(bytes_left <= 0) return int(dest - original_dest); 50512027Sjungma@eit.uni-kl.de src -= sizeof(D); 50612027Sjungma@eit.uni-kl.de } 50712027Sjungma@eit.uni-kl.de 50812027Sjungma@eit.uni-kl.de // lenN bytes at end of bus word 50912027Sjungma@eit.uni-kl.de if((src >= start) && (src < end)) { 51012027Sjungma@eit.uni-kl.de for(int i=0; i<lenN; i++) { 51112027Sjungma@eit.uni-kl.de COPYuchar(src, src+d2b_src, dest, dest+d2b_dest); 51212027Sjungma@eit.uni-kl.de src++; 51312027Sjungma@eit.uni-kl.de dest++; 51412027Sjungma@eit.uni-kl.de } 51512027Sjungma@eit.uni-kl.de bytes_left -= lenN; 51612027Sjungma@eit.uni-kl.de if(bytes_left <= 0) return int(dest - original_dest); 51712027Sjungma@eit.uni-kl.de } else { 51812027Sjungma@eit.uni-kl.de for(int i=0; i<lenN; i++) { 51912027Sjungma@eit.uni-kl.de FILLFALSEuchar(dest+d2b_dest); 52012027Sjungma@eit.uni-kl.de src++; 52112027Sjungma@eit.uni-kl.de dest++; 52212027Sjungma@eit.uni-kl.de } 52312027Sjungma@eit.uni-kl.de } 52412027Sjungma@eit.uni-kl.de src += 2 * sizeof_databus; 52512027Sjungma@eit.uni-kl.de } 52612027Sjungma@eit.uni-kl.de} 52712027Sjungma@eit.uni-kl.de 52812027Sjungma@eit.uni-kl.de 52912027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////////////////////////////// 53012027Sjungma@eit.uni-kl.de// function set (1): Response 53112027Sjungma@eit.uni-kl.detemplate<class DATAWORD> inline void 53212027Sjungma@eit.uni-kl.detlm_from_hostendian_word(tlm_generic_payload *txn, unsigned int sizeof_databus) { 53312027Sjungma@eit.uni-kl.de if(txn->is_read()) { 53412027Sjungma@eit.uni-kl.de tlm_endian_context *tc = txn->template get_extension<tlm_endian_context>(); 53512027Sjungma@eit.uni-kl.de sc_dt::uint64 b_mask = sizeof_databus - 1; 53612027Sjungma@eit.uni-kl.de int d_mask = sizeof(DATAWORD) - 1; 53712027Sjungma@eit.uni-kl.de int a_offset = static_cast<int>(tc->address & b_mask); 53812027Sjungma@eit.uni-kl.de int len0 = (sizeof_databus - a_offset) & d_mask; 53912027Sjungma@eit.uni-kl.de int lenN = sizeof(DATAWORD) - len0; 54012027Sjungma@eit.uni-kl.de uchar *d_start = tc->data_ptr; 54112027Sjungma@eit.uni-kl.de uchar *d_end = ptrdiff_t(tc->length) + d_start; // 64BITFIX probably redundant // 54212027Sjungma@eit.uni-kl.de uchar *d = ptrdiff_t(((sizeof_databus - a_offset) & ~d_mask) + lenN) + d_start; // 64BITFIX probably redundant // 54312027Sjungma@eit.uni-kl.de 54412027Sjungma@eit.uni-kl.de // iterate over transaction copying data qualified by byte-enables 54512027Sjungma@eit.uni-kl.de if(tc->byte_enable == 0) { 54612027Sjungma@eit.uni-kl.de loop_word1<DATAWORD, ©_dbytrue1<DATAWORD>, 54712027Sjungma@eit.uni-kl.de ©_dbytrue1<uchar>, &no_b1<DATAWORD>, &no_b1<uchar> >( 54812027Sjungma@eit.uni-kl.de tc->length, len0, lenN, sizeof_databus, d_start, d_end, d, 54912027Sjungma@eit.uni-kl.de 0, txn->get_data_ptr(), 0); 55012027Sjungma@eit.uni-kl.de } else { 55112027Sjungma@eit.uni-kl.de loop_word1<DATAWORD, ©_dbyb1<DATAWORD>, 55212027Sjungma@eit.uni-kl.de ©_dbyb1<uchar>, &no_b1<DATAWORD>, &no_b1<uchar> >( 55312027Sjungma@eit.uni-kl.de tc->length, len0, lenN, sizeof_databus, d_start, d_end, d, 55412027Sjungma@eit.uni-kl.de tc->byte_enable - d_start + d, txn->get_data_ptr(), 0); 55512027Sjungma@eit.uni-kl.de } 55612027Sjungma@eit.uni-kl.de } 55712027Sjungma@eit.uni-kl.de} 55812027Sjungma@eit.uni-kl.de 55912027Sjungma@eit.uni-kl.de 56012027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////////////////////////////// 56112027Sjungma@eit.uni-kl.de// function set (1): Request 56212027Sjungma@eit.uni-kl.detemplate<class DATAWORD> inline void 56312027Sjungma@eit.uni-kl.detlm_to_hostendian_word(tlm_generic_payload *txn, unsigned int sizeof_databus) { 56412027Sjungma@eit.uni-kl.de tlm_endian_context *tc = establish_context(txn); 56512027Sjungma@eit.uni-kl.de tc->from_f = &(tlm_from_hostendian_word<DATAWORD>); 56612027Sjungma@eit.uni-kl.de tc->sizeof_databus = sizeof_databus; 56712027Sjungma@eit.uni-kl.de 56812027Sjungma@eit.uni-kl.de sc_dt::uint64 b_mask = sizeof_databus - 1; 56912027Sjungma@eit.uni-kl.de int d_mask = sizeof(DATAWORD) - 1; 57012027Sjungma@eit.uni-kl.de sc_dt::uint64 a_aligned = txn->get_address() & ~b_mask; 57112027Sjungma@eit.uni-kl.de int a_offset = static_cast<int>(txn->get_address() & b_mask); 57212027Sjungma@eit.uni-kl.de int len0 = (sizeof_databus - a_offset) & d_mask; 57312027Sjungma@eit.uni-kl.de int lenN = sizeof(DATAWORD) - len0; 57412027Sjungma@eit.uni-kl.de uchar *d_start = txn->get_data_ptr(); 57512027Sjungma@eit.uni-kl.de uchar *d_end = ptrdiff_t(txn->get_data_length()) + d_start; // 64BITFIX probably redundant // 57612027Sjungma@eit.uni-kl.de uchar *d = ptrdiff_t(((sizeof_databus - a_offset) & ~d_mask) + lenN) + d_start; // 64BITFIX probably redundant // 57712027Sjungma@eit.uni-kl.de 57812027Sjungma@eit.uni-kl.de // create new data and byte enable buffers 57912027Sjungma@eit.uni-kl.de int long_enough = txn->get_data_length() + 2 * sizeof_databus; 58012027Sjungma@eit.uni-kl.de tc->establish_dbuf(long_enough); 58112027Sjungma@eit.uni-kl.de uchar *new_data = tc->new_dbuf; 58212027Sjungma@eit.uni-kl.de tc->establish_bebuf(long_enough); 58312027Sjungma@eit.uni-kl.de uchar *new_be = tc->new_bebuf; 58412027Sjungma@eit.uni-kl.de 58512027Sjungma@eit.uni-kl.de if(txn->is_read()) { 58612027Sjungma@eit.uni-kl.de tc->data_ptr = d_start; 58712027Sjungma@eit.uni-kl.de tc->address = txn->get_address(); 58812027Sjungma@eit.uni-kl.de tc->byte_enable = txn->get_byte_enable_ptr(); 58912027Sjungma@eit.uni-kl.de tc->length = txn->get_data_length(); 59012027Sjungma@eit.uni-kl.de if(txn->get_byte_enable_ptr() == 0) { 59112027Sjungma@eit.uni-kl.de // iterate over transaction creating new byte enables from all-true 59212027Sjungma@eit.uni-kl.de txn->set_data_length(loop_word1<DATAWORD, &true_b1<DATAWORD>, 59312027Sjungma@eit.uni-kl.de &true_b1<uchar>, &false_b1<DATAWORD>, &false_b1<uchar> >( 59412027Sjungma@eit.uni-kl.de txn->get_data_length(), len0, lenN, sizeof_databus, 59512027Sjungma@eit.uni-kl.de d_start, d_end, d, 0, new_data, new_be)); 59612027Sjungma@eit.uni-kl.de } else { 59712027Sjungma@eit.uni-kl.de // iterate over transaction copying byte enables 59812027Sjungma@eit.uni-kl.de txn->set_data_length(loop_word1<DATAWORD, ©_b1<DATAWORD>, 59912027Sjungma@eit.uni-kl.de ©_b1<uchar>, &false_b1<DATAWORD>, &false_b1<uchar> >( 60012027Sjungma@eit.uni-kl.de txn->get_data_length(), len0, lenN, sizeof_databus, d_start, d_end, 60112027Sjungma@eit.uni-kl.de d, txn->get_byte_enable_ptr() - d_start + d, new_data, new_be)); 60212027Sjungma@eit.uni-kl.de } 60312027Sjungma@eit.uni-kl.de } else { 60412027Sjungma@eit.uni-kl.de // WRITE 60512027Sjungma@eit.uni-kl.de if(txn->get_byte_enable_ptr() == 0) { 60612027Sjungma@eit.uni-kl.de // iterate over transaction copying data and creating new byte-enables 60712027Sjungma@eit.uni-kl.de txn->set_data_length(loop_word1<DATAWORD, ©_d1<DATAWORD>, 60812027Sjungma@eit.uni-kl.de ©_d1<uchar>, &false_b1<DATAWORD>, &false_b1<uchar> >( 60912027Sjungma@eit.uni-kl.de txn->get_data_length(), len0, lenN, sizeof_databus, 61012027Sjungma@eit.uni-kl.de d_start, d_end, d, 0, new_data, new_be)); 61112027Sjungma@eit.uni-kl.de } else { 61212027Sjungma@eit.uni-kl.de // iterate over transaction copying data and byte-enables 61312027Sjungma@eit.uni-kl.de txn->set_data_length(loop_word1<DATAWORD, ©_db1<DATAWORD>, 61412027Sjungma@eit.uni-kl.de ©_db1<uchar>, &false_b1<DATAWORD>, &false_b1<uchar> >( 61512027Sjungma@eit.uni-kl.de txn->get_data_length(), len0, lenN, sizeof_databus, d_start, d_end, 61612027Sjungma@eit.uni-kl.de d, txn->get_byte_enable_ptr() - d_start + d, new_data, new_be)); 61712027Sjungma@eit.uni-kl.de } 61812027Sjungma@eit.uni-kl.de } 61912027Sjungma@eit.uni-kl.de txn->set_byte_enable_length(txn->get_data_length()); 62012027Sjungma@eit.uni-kl.de txn->set_streaming_width(txn->get_data_length()); 62112027Sjungma@eit.uni-kl.de txn->set_data_ptr(new_data); 62212027Sjungma@eit.uni-kl.de txn->set_byte_enable_ptr(new_be); 62312027Sjungma@eit.uni-kl.de txn->set_address(a_aligned); 62412027Sjungma@eit.uni-kl.de} 62512027Sjungma@eit.uni-kl.de 62612027Sjungma@eit.uni-kl.de 62712027Sjungma@eit.uni-kl.de 62812027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////////////////////////////// 62912027Sjungma@eit.uni-kl.de// function set (2): Utilities 63012027Sjungma@eit.uni-kl.detemplate<class D> inline void copy_d2(D *src1, D *src2, D *dest1, D *dest2) { 63112027Sjungma@eit.uni-kl.de *dest1 = *src1; 63212027Sjungma@eit.uni-kl.de} 63312027Sjungma@eit.uni-kl.de 63412027Sjungma@eit.uni-kl.detemplate<class D> inline void copy_db2(D *src1, D *src2, D *dest1, D *dest2) { 63512027Sjungma@eit.uni-kl.de *dest1 = *src1; 63612027Sjungma@eit.uni-kl.de *dest2 = *src2; 63712027Sjungma@eit.uni-kl.de} 63812027Sjungma@eit.uni-kl.de 63912027Sjungma@eit.uni-kl.detemplate<class D> 64012027Sjungma@eit.uni-kl.deinline void copy_dbyb2(D *src1, D *src2, D *dest1, D *dest2) { 64112027Sjungma@eit.uni-kl.de if(tlm_bool<D>(*src2)) *dest1 = *src1; 64212027Sjungma@eit.uni-kl.de} 64312027Sjungma@eit.uni-kl.de 64412027Sjungma@eit.uni-kl.detemplate<class D, void COPY(D *src1, D *src2, D *dest1, D *dest2)> 64512027Sjungma@eit.uni-kl.deinline void loop_aligned2(D *src1, D *src2, D *dest1, D *dest2, 64612027Sjungma@eit.uni-kl.de int words, int words_per_bus) { 64712027Sjungma@eit.uni-kl.de ptrdiff_t src1to2 = (char *)src2 - (char *)src1; // 64BITFIX was int and operands were cast to int // 64812027Sjungma@eit.uni-kl.de ptrdiff_t dest1to2 = (char *)dest2 - (char *)dest1; // 64BITFIX was int and operands were cast to int // 64912027Sjungma@eit.uni-kl.de 65012027Sjungma@eit.uni-kl.de D *done = src1 + ptrdiff_t(words); // 64BITFIX // 65112027Sjungma@eit.uni-kl.de D *bus_start = src1; 65212027Sjungma@eit.uni-kl.de src1 += ptrdiff_t(words_per_bus - 1); // 64BITFIX // 65312027Sjungma@eit.uni-kl.de 65412027Sjungma@eit.uni-kl.de while(true) { 65512027Sjungma@eit.uni-kl.de COPY(src1, (D *)(src1to2+(char *)src1), dest1, (D *)(dest1to2+(char *)dest1)); // 64BITFIX // 65612027Sjungma@eit.uni-kl.de dest1++; 65712027Sjungma@eit.uni-kl.de if((--src1) < bus_start) { 65812027Sjungma@eit.uni-kl.de bus_start += ptrdiff_t(words_per_bus); // 64BITFIX // 65912027Sjungma@eit.uni-kl.de if(bus_start == done) break; 66012027Sjungma@eit.uni-kl.de src1 = bus_start + ptrdiff_t(words_per_bus - 1); // 64BITFIX // 66112027Sjungma@eit.uni-kl.de } 66212027Sjungma@eit.uni-kl.de } 66312027Sjungma@eit.uni-kl.de} 66412027Sjungma@eit.uni-kl.de 66512027Sjungma@eit.uni-kl.de 66612027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////////////////////////////// 66712027Sjungma@eit.uni-kl.de// function set (2): Response 66812027Sjungma@eit.uni-kl.detemplate<class DATAWORD> inline void 66912027Sjungma@eit.uni-kl.detlm_from_hostendian_aligned(tlm_generic_payload *txn, unsigned int sizeof_databus) { 67012027Sjungma@eit.uni-kl.de int words_per_bus = sizeof_databus/sizeof(DATAWORD); 67112027Sjungma@eit.uni-kl.de if(words_per_bus == 1) return; 67212027Sjungma@eit.uni-kl.de int words = (txn->get_data_length())/sizeof(DATAWORD); 67312027Sjungma@eit.uni-kl.de tlm_endian_context *tc = txn->template get_extension<tlm_endian_context>(); 67412027Sjungma@eit.uni-kl.de 67512027Sjungma@eit.uni-kl.de if(txn->get_byte_enable_ptr() == 0) { 67612027Sjungma@eit.uni-kl.de // no byte enables 67712027Sjungma@eit.uni-kl.de if(txn->is_read()) { 67812027Sjungma@eit.uni-kl.de // RD without byte enables. Copy data to original buffer 67912027Sjungma@eit.uni-kl.de loop_aligned2<DATAWORD, ©_d2<DATAWORD> >( 68012027Sjungma@eit.uni-kl.de (DATAWORD *)(txn->get_data_ptr()), 68112027Sjungma@eit.uni-kl.de 0, (DATAWORD *)(tc->data_ptr), 0, words, words_per_bus); 68212027Sjungma@eit.uni-kl.de } 68312027Sjungma@eit.uni-kl.de } else { 68412027Sjungma@eit.uni-kl.de // byte enables present 68512027Sjungma@eit.uni-kl.de if(txn->is_read()) { 68612027Sjungma@eit.uni-kl.de // RD with byte enables. Copy data qualified by byte-enables 68712027Sjungma@eit.uni-kl.de loop_aligned2<DATAWORD, ©_dbyb2<DATAWORD> >( 68812027Sjungma@eit.uni-kl.de (DATAWORD *)(txn->get_data_ptr()), 68912027Sjungma@eit.uni-kl.de (DATAWORD *)(txn->get_byte_enable_ptr()), 69012027Sjungma@eit.uni-kl.de (DATAWORD *)(tc->data_ptr), 0, words, words_per_bus); 69112027Sjungma@eit.uni-kl.de } 69212027Sjungma@eit.uni-kl.de } 69312027Sjungma@eit.uni-kl.de} 69412027Sjungma@eit.uni-kl.de 69512027Sjungma@eit.uni-kl.de 69612027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////////////////////////////// 69712027Sjungma@eit.uni-kl.de// function set (2): Request 69812027Sjungma@eit.uni-kl.detemplate<class DATAWORD> inline void 69912027Sjungma@eit.uni-kl.detlm_to_hostendian_aligned(tlm_generic_payload *txn, unsigned int sizeof_databus) { 70012027Sjungma@eit.uni-kl.de tlm_endian_context *tc = establish_context(txn); 70112027Sjungma@eit.uni-kl.de tc->from_f = &(tlm_from_hostendian_aligned<DATAWORD>); 70212027Sjungma@eit.uni-kl.de tc->sizeof_databus = sizeof_databus; 70312027Sjungma@eit.uni-kl.de 70412027Sjungma@eit.uni-kl.de int words_per_bus = sizeof_databus/sizeof(DATAWORD); 70512027Sjungma@eit.uni-kl.de if(words_per_bus == 1) return; 70612027Sjungma@eit.uni-kl.de int words = (txn->get_data_length())/sizeof(DATAWORD); 70712027Sjungma@eit.uni-kl.de 70812027Sjungma@eit.uni-kl.de DATAWORD *original_be = (DATAWORD *)(txn->get_byte_enable_ptr()); 70912027Sjungma@eit.uni-kl.de DATAWORD *original_data = (DATAWORD *)(txn->get_data_ptr()); 71012027Sjungma@eit.uni-kl.de 71112027Sjungma@eit.uni-kl.de // always allocate a new data buffer 71212027Sjungma@eit.uni-kl.de tc->establish_dbuf(txn->get_data_length()); 71312027Sjungma@eit.uni-kl.de txn->set_data_ptr(tc->new_dbuf); 71412027Sjungma@eit.uni-kl.de 71512027Sjungma@eit.uni-kl.de if(original_be == 0) { 71612027Sjungma@eit.uni-kl.de // no byte enables 71712027Sjungma@eit.uni-kl.de if(txn->is_write()) { 71812027Sjungma@eit.uni-kl.de // WR no byte enables. Copy data 71912027Sjungma@eit.uni-kl.de loop_aligned2<DATAWORD, ©_d2<DATAWORD> >(original_data, 0, 72012027Sjungma@eit.uni-kl.de (DATAWORD *)(txn->get_data_ptr()), 0, 72112027Sjungma@eit.uni-kl.de words, words_per_bus); 72212027Sjungma@eit.uni-kl.de } else { 72312027Sjungma@eit.uni-kl.de // RD no byte enables. Save original data pointer 72412027Sjungma@eit.uni-kl.de tc->data_ptr = (uchar *)original_data; 72512027Sjungma@eit.uni-kl.de } 72612027Sjungma@eit.uni-kl.de } else { 72712027Sjungma@eit.uni-kl.de // byte enables present 72812027Sjungma@eit.uni-kl.de // allocate a new buffer for them 72912027Sjungma@eit.uni-kl.de tc->establish_bebuf(txn->get_data_length()); 73012027Sjungma@eit.uni-kl.de txn->set_byte_enable_ptr(tc->new_bebuf); 73112027Sjungma@eit.uni-kl.de txn->set_byte_enable_length(txn->get_data_length()); 73212027Sjungma@eit.uni-kl.de 73312027Sjungma@eit.uni-kl.de if(txn->is_write()) { 73412027Sjungma@eit.uni-kl.de // WR with byte enables. Copy data and BEs 73512027Sjungma@eit.uni-kl.de loop_aligned2<DATAWORD, ©_db2<DATAWORD> >(original_data, original_be, 73612027Sjungma@eit.uni-kl.de (DATAWORD *)(txn->get_data_ptr()), 73712027Sjungma@eit.uni-kl.de (DATAWORD *)(txn->get_byte_enable_ptr()), words, words_per_bus); 73812027Sjungma@eit.uni-kl.de } else { 73912027Sjungma@eit.uni-kl.de // RD with byte enables. Save original data pointer 74012027Sjungma@eit.uni-kl.de tc->data_ptr = (uchar *)original_data; 74112027Sjungma@eit.uni-kl.de // Copy byte enables to new buffer 74212027Sjungma@eit.uni-kl.de loop_aligned2<DATAWORD, ©_d2<DATAWORD> >(original_be, 0, 74312027Sjungma@eit.uni-kl.de (DATAWORD *)(txn->get_byte_enable_ptr()), 0, 74412027Sjungma@eit.uni-kl.de words, words_per_bus); 74512027Sjungma@eit.uni-kl.de } 74612027Sjungma@eit.uni-kl.de } 74712027Sjungma@eit.uni-kl.de} 74812027Sjungma@eit.uni-kl.de 74912027Sjungma@eit.uni-kl.de 75012027Sjungma@eit.uni-kl.de 75112027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////////////////////////////// 75212027Sjungma@eit.uni-kl.de// function set (3): Response 75312027Sjungma@eit.uni-kl.detemplate<class DATAWORD> inline void 75412027Sjungma@eit.uni-kl.detlm_from_hostendian_single(tlm_generic_payload *txn, unsigned int sizeof_databus) { 75512027Sjungma@eit.uni-kl.de // nothing needs to be done here 75612027Sjungma@eit.uni-kl.de} 75712027Sjungma@eit.uni-kl.de 75812027Sjungma@eit.uni-kl.de 75912027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////////////////////////////// 76012027Sjungma@eit.uni-kl.de// function set (3): Request 76112027Sjungma@eit.uni-kl.detemplate<class DATAWORD> inline void 76212027Sjungma@eit.uni-kl.detlm_to_hostendian_single(tlm_generic_payload *txn, unsigned int sizeof_databus) { 76312027Sjungma@eit.uni-kl.de tlm_endian_context *tc = establish_context(txn); 76412027Sjungma@eit.uni-kl.de tc->from_f = &(tlm_from_hostendian_single<DATAWORD>); 76512027Sjungma@eit.uni-kl.de tc->sizeof_databus = sizeof_databus; 76612027Sjungma@eit.uni-kl.de 76712027Sjungma@eit.uni-kl.de // only need to change the address, always safe to work in-place 76812027Sjungma@eit.uni-kl.de sc_dt::uint64 mask = sizeof_databus-1; 76912027Sjungma@eit.uni-kl.de sc_dt::uint64 a = txn->get_address(); 77012027Sjungma@eit.uni-kl.de txn->set_address((a & ~mask) | 77112027Sjungma@eit.uni-kl.de (sizeof_databus - (a & mask) - sizeof(DATAWORD))); 77212027Sjungma@eit.uni-kl.de} 77312027Sjungma@eit.uni-kl.de 77412027Sjungma@eit.uni-kl.de 77512027Sjungma@eit.uni-kl.de 77612027Sjungma@eit.uni-kl.de/////////////////////////////////////////////////////////////////////////////// 77712027Sjungma@eit.uni-kl.de// helper function which works for all responses 77812027Sjungma@eit.uni-kl.deinline void tlm_from_hostendian(tlm_generic_payload *txn) { 77912027Sjungma@eit.uni-kl.de tlm_endian_context *tc = txn->get_extension<tlm_endian_context>(); 78012027Sjungma@eit.uni-kl.de (*(tc->from_f))(txn, tc->sizeof_databus); 78112027Sjungma@eit.uni-kl.de} 78212027Sjungma@eit.uni-kl.de 78312027Sjungma@eit.uni-kl.de 78412027Sjungma@eit.uni-kl.de#ifndef TLM_END_CONV_DONT_UNDEF_UCHAR 78512027Sjungma@eit.uni-kl.de#undef uchar 78612027Sjungma@eit.uni-kl.de#endif 78712027Sjungma@eit.uni-kl.de 78812027Sjungma@eit.uni-kl.de} // namespace tlm 78912027Sjungma@eit.uni-kl.de 79012027Sjungma@eit.uni-kl.de 79112027Sjungma@eit.uni-kl.de#endif // multiple-inclusion protection 79212027Sjungma@eit.uni-kl.de 793