113521Sgabeblack@google.com/***************************************************************************** 213521Sgabeblack@google.com 313521Sgabeblack@google.com Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 413521Sgabeblack@google.com more contributor license agreements. See the NOTICE file distributed 513521Sgabeblack@google.com with this work for additional information regarding copyright ownership. 613521Sgabeblack@google.com Accellera licenses this file to you under the Apache License, Version 2.0 713521Sgabeblack@google.com (the "License"); you may not use this file except in compliance with the 813521Sgabeblack@google.com License. You may obtain a copy of the License at 913521Sgabeblack@google.com 1013521Sgabeblack@google.com http://www.apache.org/licenses/LICENSE-2.0 1113521Sgabeblack@google.com 1213521Sgabeblack@google.com Unless required by applicable law or agreed to in writing, software 1313521Sgabeblack@google.com distributed under the License is distributed on an "AS IS" BASIS, 1413521Sgabeblack@google.com WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 1513521Sgabeblack@google.com implied. See the License for the specific language governing 1613521Sgabeblack@google.com permissions and limitations under the License. 1713521Sgabeblack@google.com 1813521Sgabeblack@google.com *****************************************************************************/ 1913521Sgabeblack@google.com 2013521Sgabeblack@google.com 2113521Sgabeblack@google.com#ifndef __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_ENDIAN_CONV_HH__ 2213521Sgabeblack@google.com#define __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_ENDIAN_CONV_HH__ 2313521Sgabeblack@google.com 2413521Sgabeblack@google.com#include <cstring> // std::memset 2513521Sgabeblack@google.com 2613586Sgabeblack@google.com#include "gp.hh" 2713521Sgabeblack@google.com 2813521Sgabeblack@google.comnamespace tlm 2913521Sgabeblack@google.com{ 3013521Sgabeblack@google.com 3113521Sgabeblack@google.com/* 3213521Sgabeblack@google.comTranaction-Level Modelling 3313521Sgabeblack@google.comEndianness Helper Functions 3413521Sgabeblack@google.com 3513521Sgabeblack@google.comDESCRIPTION 3613521Sgabeblack@google.comA set of functions for helping users to get the endianness 3713521Sgabeblack@google.comright in their TLM models of system initiators. These functions are 3813521Sgabeblack@google.comfor use within an initiator. They can not be used as-is outside 3913521Sgabeblack@google.coman initiator because the extension used to store context will not work 4013521Sgabeblack@google.comif cascaded, and they do not respect the generic payload mutability 4113521Sgabeblack@google.comrules. However this code may be easily copied and adapted for use 4213521Sgabeblack@google.comin bridges, etc.. 4313521Sgabeblack@google.com 4413521Sgabeblack@google.comThese functions are not compulsory. There are other legitimate ways to 4513521Sgabeblack@google.comachieve the same functionality. If extra information is available at 4613521Sgabeblack@google.comcompile time about the nature of an initiator's transactions, this can 4713521Sgabeblack@google.combe exploited to accelerate simulations by creating further functions 4813521Sgabeblack@google.comsimilar to those in this file. In general a functional transaction can be 4913521Sgabeblack@google.comdescribed in more than one way by a TLM-2 GP object. 5013521Sgabeblack@google.com 5113521Sgabeblack@google.comThe functions convert the endianness of a GP object, either on request or 5213521Sgabeblack@google.comresponse. They should only be used when the initiator's endianness 5313521Sgabeblack@google.comdoes not match the host's endianness. They assume 'arithmetic mode' 5413521Sgabeblack@google.commeaning that within a data word the byte order is always host-endian. 5513521Sgabeblack@google.comFor non-arithmetic mode initiators they can be used with a data word 5613521Sgabeblack@google.comsize of 1 byte. 5713521Sgabeblack@google.com 5813521Sgabeblack@google.comAll the functions are templates, for example: 5913521Sgabeblack@google.com 6013521Sgabeblack@google.comtemplate<class DATAWORD> inline void 6113521Sgabeblack@google.com to_hostendian_generic(tlm_generic_payload *txn, int sizeof_databus) 6213521Sgabeblack@google.com 6313521Sgabeblack@google.comThe template parameter provides the data word width. Having this as a class 6413521Sgabeblack@google.commakes it easy to use it for copy and swap operations within the functions. 6513521Sgabeblack@google.comIf the assignment operator for this class is overloaded, the endianness 6613521Sgabeblack@google.comconversion function may not have the desired effect. 6713521Sgabeblack@google.com 6813521Sgabeblack@google.comAll the functions have the same signature except for different names. 6913521Sgabeblack@google.com 7013521Sgabeblack@google.comThe principle is that a function to_hostendian_convtype() is called when the 7113521Sgabeblack@google.cominitiator-endian transaction is created, and the matching function 7213521Sgabeblack@google.comfrom_hostendian_convtype() is called when the transaction is completed, for 7313521Sgabeblack@google.comexample before read data can be used. In some cases the from_ function is 7413521Sgabeblack@google.comredundant but an empty function is provided anyway. It is strongly 7513521Sgabeblack@google.comrecommended that the from_ function is called, in case it ceases to be 7613521Sgabeblack@google.comredundant in future versions of this code. 7713521Sgabeblack@google.com 7813521Sgabeblack@google.comNo context needs to be managed outside the two functions, except that they 7913521Sgabeblack@google.commust be called with the same template parameter and the same bus width. 8013521Sgabeblack@google.com 8113521Sgabeblack@google.comFor initiator models that can not easily manage this context information, 8213521Sgabeblack@google.coma single entry point for the from_ function is provided, which will be 8313521Sgabeblack@google.coma little slower than calling the correct from_ function directly, as 8413521Sgabeblack@google.comit can not be inlined. 8513521Sgabeblack@google.com 8613521Sgabeblack@google.comAll functions assume power-of-2 bus and data word widths. 8713521Sgabeblack@google.com 8813521Sgabeblack@google.comFunctions offered: 8913521Sgabeblack@google.com 9013521Sgabeblack@google.com0) A pair of functions that work for almost all TLM2 GP transactions. The 9113521Sgabeblack@google.comonly limitations are that data and bus widths should be powers of 2, and that 9213521Sgabeblack@google.comthe data length should be an integer number of streaming widths and that the 9313521Sgabeblack@google.comstreaming width should be an integer number of data words. 9413521Sgabeblack@google.comThese functions always allocate new data and byte enable buffers and copy 9513521Sgabeblack@google.comdata one byte at a time. 9613521Sgabeblack@google.com tlm_to_hostendian_generic(tlm_generic_payload *txn, int sizeof_databus) 9713521Sgabeblack@google.com tlm_from_hostendian_generic(tlm_generic_payload *txn, int sizeof_databus) 9813521Sgabeblack@google.com 9913521Sgabeblack@google.com1) A pair of functions that work for all transactions regardless of data and 10013521Sgabeblack@google.combus data sizes and address alignment except for the the following 10113521Sgabeblack@google.comlimitations: 10213521Sgabeblack@google.com- byte-enables are supported only when byte-enable granularity is no finer 10313521Sgabeblack@google.comthan the data word (every data word is wholly enabled or wholly disabled) 10413521Sgabeblack@google.com- byte-enable-length is not supported (if byte enables are present, the byte 10513521Sgabeblack@google.comenable length must be equal to the data length). 10613521Sgabeblack@google.com- streaming width is not supported 10713521Sgabeblack@google.com- data word wider than bus word is not supported 10813521Sgabeblack@google.comA new data buffer and a new byte enable buffer are always allocated. Byte 10913521Sgabeblack@google.comenables are assumed to be needed even if not required for the original 11013521Sgabeblack@google.com(unconverted) transaction. Data is copied to the new buffer on request 11113521Sgabeblack@google.com(for writes) or on response (for reads). Copies are done word-by-word 11213521Sgabeblack@google.comwhere possible. 11313521Sgabeblack@google.com tlm_to_hostendian_word(tlm_generic_payload *txn, int sizeof_databus) 11413521Sgabeblack@google.com tlm_from_hostendian_word(tlm_generic_payload *txn, int sizeof_databus) 11513521Sgabeblack@google.com 11613521Sgabeblack@google.com2) If the original transaction is both word and bus-aligned then this pair of 11713521Sgabeblack@google.comfunctions can be used. It will complete faster than the generic function 11813521Sgabeblack@google.combecause the data reordering function is much simpler and no address 11913521Sgabeblack@google.comconversion is required. 12013521Sgabeblack@google.comThe following limitations apply: 12113521Sgabeblack@google.com- byte-enables are supported only when byte-enable granularity is no finer 12213521Sgabeblack@google.comthan the data word (every data word is wholly enabled or wholly disabled) 12313521Sgabeblack@google.com- byte-enable-length is not supported (if byte enables are present, the byte 12413521Sgabeblack@google.comenable length must be equal to the data length). 12513521Sgabeblack@google.com- streaming width is not supported 12613521Sgabeblack@google.com- data word wider than bus word is not supported 12713521Sgabeblack@google.com- the transaction must be an integer number of bus words 12813521Sgabeblack@google.com- the address must be aligned to the bus width 12913521Sgabeblack@google.com tlm_to_hostendian_aligned(tlm_generic_payload *txn, int sizeof_databus) 13013521Sgabeblack@google.com tlm_from_hostendian_aligned(tlm_generic_payload *txn, int sizeof_databus) 13113521Sgabeblack@google.com 13213521Sgabeblack@google.com3) For single word transactions that don't cross a bus word boundary it 13313521Sgabeblack@google.comis always safe to work in-place and the conversion is very simple. Again, 13413521Sgabeblack@google.comstreaming width and byte-enable length are not supported, and byte-enables 13513521Sgabeblack@google.commay not changes within a data word. 13613521Sgabeblack@google.com tlm_to_hostendian_single(tlm_generic_payload *txn, int sizeof_databus) 13713521Sgabeblack@google.com tlm_from_hostendian_single(tlm_generic_payload *txn, int sizeof_databus) 13813521Sgabeblack@google.com 13913521Sgabeblack@google.com4) A single entry point for accessing the correct from_ function without 14013521Sgabeblack@google.comneeding to store context. 14113521Sgabeblack@google.com tlm_from_hostendian(tlm_generic_payload *txn) 14213521Sgabeblack@google.com*/ 14313521Sgabeblack@google.com 14413521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 14513521Sgabeblack@google.com// Generic Utilities 14613521Sgabeblack@google.com 14713521Sgabeblack@google.comclass tlm_endian_context; 14813521Sgabeblack@google.com 14913521Sgabeblack@google.comclass tlm_endian_context_pool 15013521Sgabeblack@google.com{ 15113521Sgabeblack@google.com public: 15213521Sgabeblack@google.com tlm_endian_context *first; 15313521Sgabeblack@google.com inline tlm_endian_context_pool(); 15413521Sgabeblack@google.com inline ~tlm_endian_context_pool(); 15513521Sgabeblack@google.com inline tlm_endian_context *pop(); 15613521Sgabeblack@google.com inline void push(tlm_endian_context *c); 15713521Sgabeblack@google.com}; 15813521Sgabeblack@google.com 15913521Sgabeblack@google.comstatic tlm_endian_context_pool global_tlm_endian_context_pool; 16013521Sgabeblack@google.com 16113521Sgabeblack@google.com// an extension to keep the information needed for reconversion of response 16213521Sgabeblack@google.comclass tlm_endian_context : public tlm_extension<tlm_endian_context> 16313521Sgabeblack@google.com{ 16413521Sgabeblack@google.com public: 16513521Sgabeblack@google.com tlm_endian_context() : dbuf_size(0), bebuf_size(0) {} 16613521Sgabeblack@google.com 16713521Sgabeblack@google.com ~tlm_endian_context() { 16813521Sgabeblack@google.com if (dbuf_size > 0) 16913521Sgabeblack@google.com delete [] new_dbuf; 17013521Sgabeblack@google.com if (bebuf_size > 0) 17113521Sgabeblack@google.com delete [] new_bebuf; 17213521Sgabeblack@google.com } 17313521Sgabeblack@google.com 17413521Sgabeblack@google.com sc_dt::uint64 address; // Used by generic, word. 17513521Sgabeblack@google.com sc_dt::uint64 new_address; // Used by generic. 17613521Sgabeblack@google.com unsigned char *data_ptr; // Used by generic, word, aligned. 17713521Sgabeblack@google.com unsigned char *byte_enable; // Used by word. 17813521Sgabeblack@google.com int length; // Used by generic, word. 17913521Sgabeblack@google.com int stream_width; // Used by generic. 18013521Sgabeblack@google.com 18113521Sgabeblack@google.com // Used by common entry point on response. 18213521Sgabeblack@google.com void (*from_f)(tlm_generic_payload *txn, unsigned int sizeof_databus); 18313521Sgabeblack@google.com int sizeof_databus; 18413521Sgabeblack@google.com 18513521Sgabeblack@google.com // Reordering buffers for data and byte-enables. 18613521Sgabeblack@google.com unsigned char *new_dbuf, *new_bebuf; 18713521Sgabeblack@google.com int dbuf_size, bebuf_size; 18813521Sgabeblack@google.com 18913521Sgabeblack@google.com void 19013521Sgabeblack@google.com establish_dbuf(int len) 19113521Sgabeblack@google.com { 19213521Sgabeblack@google.com if (len <= dbuf_size) 19313521Sgabeblack@google.com return; 19413521Sgabeblack@google.com if (dbuf_size > 0) 19513521Sgabeblack@google.com delete [] new_dbuf; 19613521Sgabeblack@google.com new_dbuf = new unsigned char[len]; 19713521Sgabeblack@google.com dbuf_size = len; 19813521Sgabeblack@google.com } 19913521Sgabeblack@google.com 20013521Sgabeblack@google.com void 20113521Sgabeblack@google.com establish_bebuf(int len) 20213521Sgabeblack@google.com { 20313521Sgabeblack@google.com if (len <= bebuf_size) 20413521Sgabeblack@google.com return; 20513521Sgabeblack@google.com if (bebuf_size > 0) 20613521Sgabeblack@google.com delete [] new_bebuf; 20713521Sgabeblack@google.com new_bebuf = new unsigned char[len]; 20813521Sgabeblack@google.com bebuf_size = len; 20913521Sgabeblack@google.com } 21013521Sgabeblack@google.com 21113521Sgabeblack@google.com // Required for extension management. 21213521Sgabeblack@google.com void free() { global_tlm_endian_context_pool.push(this); } 21313521Sgabeblack@google.com tlm_extension_base *clone() const { return 0; } 21413521Sgabeblack@google.com void copy_from(tlm_extension_base const &) { return; } 21513521Sgabeblack@google.com 21613521Sgabeblack@google.com // For pooling. 21713521Sgabeblack@google.com tlm_endian_context *next; 21813521Sgabeblack@google.com}; 21913521Sgabeblack@google.com 22013521Sgabeblack@google.com// Assumptions about transaction contexts: 22113521Sgabeblack@google.com// 1) only the address attribute of a transaction 22213521Sgabeblack@google.com// is mutable. all other attributes are unchanged from the request to 22313521Sgabeblack@google.com// response side conversion. 22413521Sgabeblack@google.com// 2) the conversion functions in this file do not respect the mutability 22513521Sgabeblack@google.com// rules and do not put the transaction back into its original state after 22613521Sgabeblack@google.com// completion. so if the initiator has any cleaning up to do (eg of byte 22713521Sgabeblack@google.com// enable buffers), it needs to store its own context. the transaction 22813521Sgabeblack@google.com// returned to the initiator may contain pointers to data and byte enable 22913521Sgabeblack@google.com// that can/must not be deleted. 23013521Sgabeblack@google.com// 3) the conversion functions in this file use an extension to store 23113521Sgabeblack@google.com// context information. they do not remove this extension. the initiator 23213521Sgabeblack@google.com// should not remove it unless it deletes the generic payload 23313521Sgabeblack@google.com// object. 23413521Sgabeblack@google.com 23513521Sgabeblack@google.cominline tlm_endian_context * 23613521Sgabeblack@google.comestablish_context(tlm_generic_payload *txn) 23713521Sgabeblack@google.com{ 23813521Sgabeblack@google.com tlm_endian_context *tc = txn->get_extension<tlm_endian_context>(); 23913521Sgabeblack@google.com if (tc == 0) { 24013521Sgabeblack@google.com tc = global_tlm_endian_context_pool.pop(); 24113521Sgabeblack@google.com txn->set_extension(tc); 24213521Sgabeblack@google.com } 24313521Sgabeblack@google.com return tc; 24413521Sgabeblack@google.com} 24513521Sgabeblack@google.com 24613521Sgabeblack@google.cominline tlm_endian_context_pool::tlm_endian_context_pool() : first(0) {} 24713521Sgabeblack@google.com 24813521Sgabeblack@google.cominline tlm_endian_context_pool::~tlm_endian_context_pool() 24913521Sgabeblack@google.com{ 25013521Sgabeblack@google.com while (first != 0) { 25113521Sgabeblack@google.com tlm_endian_context *next = first->next; 25213521Sgabeblack@google.com delete first; 25313521Sgabeblack@google.com first = next; 25413521Sgabeblack@google.com } 25513521Sgabeblack@google.com} 25613521Sgabeblack@google.com 25713521Sgabeblack@google.comtlm_endian_context * 25813521Sgabeblack@google.comtlm_endian_context_pool::pop() 25913521Sgabeblack@google.com{ 26013521Sgabeblack@google.com if (first == 0) 26113521Sgabeblack@google.com return new tlm_endian_context; 26213521Sgabeblack@google.com tlm_endian_context *r = first; 26313521Sgabeblack@google.com first = first->next; 26413521Sgabeblack@google.com return r; 26513521Sgabeblack@google.com} 26613521Sgabeblack@google.com 26713521Sgabeblack@google.comvoid tlm_endian_context_pool::push(tlm_endian_context *c) 26813521Sgabeblack@google.com{ 26913521Sgabeblack@google.com c->next = first; 27013521Sgabeblack@google.com first = c; 27113521Sgabeblack@google.com} 27213521Sgabeblack@google.com 27313521Sgabeblack@google.com 27413521Sgabeblack@google.com// A set of constants for efficient filling of byte enables. 27513521Sgabeblack@google.comtemplate <class D> 27613521Sgabeblack@google.comclass tlm_bool 27713521Sgabeblack@google.com{ 27813521Sgabeblack@google.com public: 27913521Sgabeblack@google.com static D TLM_TRUE; 28013521Sgabeblack@google.com static D TLM_FALSE; 28113521Sgabeblack@google.com static D 28213521Sgabeblack@google.com make_uchar_array(unsigned char c) 28313521Sgabeblack@google.com { 28413521Sgabeblack@google.com D d; 28513521Sgabeblack@google.com unsigned char *tmp = (unsigned char *)(&d); 28613521Sgabeblack@google.com for (ptrdiff_t i = 0; i != sizeof(D); i++) 28713521Sgabeblack@google.com tmp[i] = c; // 64BITFIX negligable risk but easy fix. 28813521Sgabeblack@google.com return d; 28913521Sgabeblack@google.com } 29013521Sgabeblack@google.com 29113521Sgabeblack@google.com // Also provides an syntax-efficient tester, using a 29213521Sgabeblack@google.com // copy constuctor and an implicit cast to boolean. 29313521Sgabeblack@google.com tlm_bool(D &d) : b(*((unsigned char *)&d) != TLM_BYTE_DISABLED) {} 29413521Sgabeblack@google.com operator bool() const { return b; } 29513521Sgabeblack@google.com private: 29613521Sgabeblack@google.com bool b; 29713521Sgabeblack@google.com}; 29813521Sgabeblack@google.com 29913521Sgabeblack@google.comtemplate<class D> 30013521Sgabeblack@google.comD tlm_bool<D>::TLM_TRUE = tlm_bool<D>::make_uchar_array(TLM_BYTE_ENABLED); 30113521Sgabeblack@google.comtemplate<class D> 30213521Sgabeblack@google.comD tlm_bool<D>::TLM_FALSE = tlm_bool<D>::make_uchar_array(TLM_BYTE_DISABLED); 30313521Sgabeblack@google.com 30413521Sgabeblack@google.com 30513521Sgabeblack@google.com 30613521Sgabeblack@google.cominline void 30713521Sgabeblack@google.comcopy_db0(unsigned char *src1, unsigned char *src2, 30813521Sgabeblack@google.com unsigned char *dest1, unsigned char *dest2) 30913521Sgabeblack@google.com{ 31013521Sgabeblack@google.com *dest1 = *src1; 31113521Sgabeblack@google.com *dest2 = *src2; 31213521Sgabeblack@google.com} 31313521Sgabeblack@google.com 31413521Sgabeblack@google.cominline void 31513521Sgabeblack@google.comcopy_dbtrue0(unsigned char *src1, unsigned char * /* src2 */, 31613521Sgabeblack@google.com unsigned char *dest1, unsigned char *dest2) 31713521Sgabeblack@google.com{ 31813521Sgabeblack@google.com *dest1 = *src1; 31913521Sgabeblack@google.com *dest2 = TLM_BYTE_ENABLED; 32013521Sgabeblack@google.com} 32113521Sgabeblack@google.com 32213521Sgabeblack@google.cominline void 32313521Sgabeblack@google.comcopy_btrue0(unsigned char * /* src1 */, unsigned char * /* src2 */, 32413521Sgabeblack@google.com unsigned char * /* dest1 */, unsigned char *dest2) 32513521Sgabeblack@google.com{ 32613521Sgabeblack@google.com *dest2 = TLM_BYTE_ENABLED; 32713521Sgabeblack@google.com} 32813521Sgabeblack@google.com 32913521Sgabeblack@google.cominline void 33013521Sgabeblack@google.comcopy_b0(unsigned char * /* src1 */, unsigned char *src2, 33113521Sgabeblack@google.com unsigned char * /* dest1 */, unsigned char *dest2) 33213521Sgabeblack@google.com{ 33313521Sgabeblack@google.com *dest2 = *src2; 33413521Sgabeblack@google.com} 33513521Sgabeblack@google.com 33613521Sgabeblack@google.cominline void 33713521Sgabeblack@google.comcopy_dbyb0(unsigned char *src1, unsigned char * /* src2 */, 33813521Sgabeblack@google.com unsigned char *dest1, unsigned char *dest2) 33913521Sgabeblack@google.com{ 34013521Sgabeblack@google.com if (*dest2 == TLM_BYTE_ENABLED) 34113521Sgabeblack@google.com *src1 = *dest1; 34213521Sgabeblack@google.com} 34313521Sgabeblack@google.com 34413521Sgabeblack@google.com 34513521Sgabeblack@google.comtemplate <class D, 34613521Sgabeblack@google.com void COPY(unsigned char *he_d, unsigned char *he_b, 34713521Sgabeblack@google.com unsigned char *ie_d, unsigned char *ie_b)> 34813521Sgabeblack@google.cominline void 34913521Sgabeblack@google.comloop_generic0(int new_len, int new_stream_width, int orig_stream_width, 35013521Sgabeblack@google.com int sizeof_databus, sc_dt::uint64 orig_start_address, 35113521Sgabeblack@google.com sc_dt::uint64 new_start_address, int be_length, 35213521Sgabeblack@google.com unsigned char *ie_data, unsigned char *ie_be, 35313521Sgabeblack@google.com unsigned char *he_data, unsigned char *he_be) 35413521Sgabeblack@google.com{ 35513521Sgabeblack@google.com for (int orig_sword = 0, new_sword = 0; new_sword < new_len; 35613521Sgabeblack@google.com new_sword += new_stream_width, orig_sword += orig_stream_width) { 35713521Sgabeblack@google.com sc_dt::uint64 ie_addr = orig_start_address; 35813521Sgabeblack@google.com for (int orig_dword = orig_sword; 35913521Sgabeblack@google.com orig_dword < orig_sword + orig_stream_width; 36013521Sgabeblack@google.com orig_dword += sizeof(D)) { 36113521Sgabeblack@google.com for (int curr_byte = orig_dword + sizeof(D) - 1; 36213521Sgabeblack@google.com curr_byte >= orig_dword; curr_byte--) { 36313521Sgabeblack@google.com ptrdiff_t he_index = ((ie_addr++) ^ (sizeof_databus - 1)) - 36413521Sgabeblack@google.com new_start_address + new_sword; // 64BITFIX 36513521Sgabeblack@google.com COPY(ie_data + curr_byte, 36613521Sgabeblack@google.com // 64BITRISK no risk of overflow, always positive. 36713521Sgabeblack@google.com ie_be + (curr_byte % be_length), 36813521Sgabeblack@google.com he_data + he_index, he_be + he_index); 36913521Sgabeblack@google.com } 37013521Sgabeblack@google.com } 37113521Sgabeblack@google.com } 37213521Sgabeblack@google.com} 37313521Sgabeblack@google.com 37413521Sgabeblack@google.com 37513521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 37613521Sgabeblack@google.com// function set (0): Response 37713521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 37813521Sgabeblack@google.com 37913521Sgabeblack@google.comtemplate <class DATAWORD> 38013521Sgabeblack@google.cominline void 38113521Sgabeblack@google.comtlm_from_hostendian_generic(tlm_generic_payload *txn, 38213521Sgabeblack@google.com unsigned int sizeof_databus) 38313521Sgabeblack@google.com{ 38413521Sgabeblack@google.com if (txn->is_read()) { 38513521Sgabeblack@google.com tlm_endian_context *tc = 38613521Sgabeblack@google.com txn->template get_extension<tlm_endian_context>(); 38713521Sgabeblack@google.com loop_generic0<DATAWORD, ©_dbyb0>(txn->get_data_length(), 38813521Sgabeblack@google.com txn->get_streaming_width(), tc->stream_width, sizeof_databus, 38913521Sgabeblack@google.com tc->address, tc->new_address, txn->get_data_length(), 39013521Sgabeblack@google.com tc->data_ptr, 0, txn->get_data_ptr(), 39113521Sgabeblack@google.com txn->get_byte_enable_ptr()); 39213521Sgabeblack@google.com } 39313521Sgabeblack@google.com} 39413521Sgabeblack@google.com 39513521Sgabeblack@google.com 39613521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 39713521Sgabeblack@google.com// function set (0): Request 39813521Sgabeblack@google.comtemplate <class DATAWORD> 39913521Sgabeblack@google.cominline void 40013521Sgabeblack@google.comtlm_to_hostendian_generic(tlm_generic_payload *txn, 40113521Sgabeblack@google.com unsigned int sizeof_databus) 40213521Sgabeblack@google.com{ 40313521Sgabeblack@google.com tlm_endian_context *tc = establish_context(txn); 40413521Sgabeblack@google.com tc->from_f = &(tlm_from_hostendian_generic<DATAWORD>); 40513521Sgabeblack@google.com tc->sizeof_databus = sizeof_databus; 40613521Sgabeblack@google.com 40713521Sgabeblack@google.com // Calculate new size: nr stream words multiplied by big enough stream 40813521Sgabeblack@google.com // width. 40913521Sgabeblack@google.com int s_width = txn->get_streaming_width(); 41013521Sgabeblack@google.com int length = txn->get_data_length(); 41113521Sgabeblack@google.com if (s_width >= length) 41213521Sgabeblack@google.com s_width = length; 41313521Sgabeblack@google.com int nr_stream_words = length / s_width; 41413521Sgabeblack@google.com 41513521Sgabeblack@google.com // Find out in which bus word the stream word starts and ends. 41613521Sgabeblack@google.com sc_dt::uint64 new_address = (txn->get_address() & ~(sizeof_databus - 1)); 41713521Sgabeblack@google.com sc_dt::uint64 end_address = ((txn->get_address() + s_width - 1) & 41813521Sgabeblack@google.com ~(sizeof_databus - 1)); 41913521Sgabeblack@google.com 42013521Sgabeblack@google.com int new_stream_width = end_address - new_address + sizeof_databus; 42113521Sgabeblack@google.com int new_length = new_stream_width * nr_stream_words; 42213521Sgabeblack@google.com 42313521Sgabeblack@google.com // Store context. 42413521Sgabeblack@google.com tc->data_ptr = txn->get_data_ptr(); 42513521Sgabeblack@google.com tc->address = txn->get_address(); 42613521Sgabeblack@google.com tc->new_address = new_address; 42713521Sgabeblack@google.com tc->stream_width = s_width; 42813521Sgabeblack@google.com unsigned char *orig_be = txn->get_byte_enable_ptr(); 42913521Sgabeblack@google.com int orig_be_length = txn->get_byte_enable_length(); 43013521Sgabeblack@google.com 43113521Sgabeblack@google.com // Create data and byte-enable buffers. 43213521Sgabeblack@google.com txn->set_address(new_address); 43313521Sgabeblack@google.com tc->establish_dbuf(new_length); 43413521Sgabeblack@google.com txn->set_data_ptr(tc->new_dbuf); 43513521Sgabeblack@google.com tc->establish_bebuf(new_length); 43613521Sgabeblack@google.com txn->set_byte_enable_ptr(tc->new_bebuf); 43713521Sgabeblack@google.com std::memset(txn->get_byte_enable_ptr(), TLM_BYTE_DISABLED, new_length); 43813521Sgabeblack@google.com txn->set_streaming_width(new_stream_width); 43913521Sgabeblack@google.com txn->set_data_length(new_length); 44013521Sgabeblack@google.com txn->set_byte_enable_length(new_length); 44113521Sgabeblack@google.com 44213521Sgabeblack@google.com // Copy data and/or byte enables. 44313521Sgabeblack@google.com if (txn->is_write()) { 44413521Sgabeblack@google.com if (orig_be == 0) { 44513521Sgabeblack@google.com loop_generic0<DATAWORD, ©_dbtrue0>( 44613521Sgabeblack@google.com new_length, new_stream_width, s_width, sizeof_databus, 44713521Sgabeblack@google.com tc->address, new_address, new_length, tc->data_ptr, 0, 44813521Sgabeblack@google.com txn->get_data_ptr(), txn->get_byte_enable_ptr()); 44913521Sgabeblack@google.com } else { 45013521Sgabeblack@google.com loop_generic0<DATAWORD, ©_db0>(new_length, new_stream_width, 45113521Sgabeblack@google.com s_width, sizeof_databus, tc->address, new_address, 45213521Sgabeblack@google.com orig_be_length, tc->data_ptr, orig_be, 45313521Sgabeblack@google.com txn->get_data_ptr(), txn->get_byte_enable_ptr()); 45413521Sgabeblack@google.com } 45513521Sgabeblack@google.com } else { 45613521Sgabeblack@google.com // Read transaction. 45713521Sgabeblack@google.com if (orig_be == 0) { 45813521Sgabeblack@google.com loop_generic0<DATAWORD, ©_btrue0>(new_length, 45913521Sgabeblack@google.com new_stream_width, s_width, sizeof_databus, tc->address, 46013521Sgabeblack@google.com new_address, new_length, tc->data_ptr, 0, 46113521Sgabeblack@google.com txn->get_data_ptr(), txn->get_byte_enable_ptr()); 46213521Sgabeblack@google.com } else { 46313521Sgabeblack@google.com loop_generic0<DATAWORD, ©_b0>(new_length, new_stream_width, 46413521Sgabeblack@google.com s_width, sizeof_databus, tc->address, new_address, 46513521Sgabeblack@google.com orig_be_length, tc->data_ptr, orig_be, 46613521Sgabeblack@google.com txn->get_data_ptr(), txn->get_byte_enable_ptr()); 46713521Sgabeblack@google.com } 46813521Sgabeblack@google.com } 46913521Sgabeblack@google.com} 47013521Sgabeblack@google.com 47113521Sgabeblack@google.com 47213521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 47313521Sgabeblack@google.com// function set (1): Utilities 47413521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 47513521Sgabeblack@google.com 47613521Sgabeblack@google.comtemplate <class D> 47713521Sgabeblack@google.cominline void 47813521Sgabeblack@google.comcopy_d1(unsigned char *src1, unsigned char *src2, 47913521Sgabeblack@google.com unsigned char *dest1, unsigned char *dest2) 48013521Sgabeblack@google.com{ 48113521Sgabeblack@google.com *((D *)dest1) = *((D *)src1); 48213521Sgabeblack@google.com *((D *)dest2) = tlm_bool<D>::TLM_TRUE; 48313521Sgabeblack@google.com} 48413521Sgabeblack@google.com 48513521Sgabeblack@google.comtemplate <class D> 48613521Sgabeblack@google.cominline void 48713521Sgabeblack@google.comcopy_db1(unsigned char *src1, unsigned char *src2, 48813521Sgabeblack@google.com unsigned char *dest1, unsigned char *dest2) 48913521Sgabeblack@google.com{ 49013521Sgabeblack@google.com *((D *)dest1) = *((D *)src1); 49113521Sgabeblack@google.com *((D *)dest2) = *((D *)src2); 49213521Sgabeblack@google.com} 49313521Sgabeblack@google.com 49413521Sgabeblack@google.comtemplate <class D> 49513521Sgabeblack@google.cominline void 49613521Sgabeblack@google.comtrue_b1(unsigned char *src1, unsigned char *src2, 49713521Sgabeblack@google.com unsigned char *dest1, unsigned char *dest2) 49813521Sgabeblack@google.com{ 49913521Sgabeblack@google.com *((D *)dest2) = tlm_bool<D>::TLM_TRUE; 50013521Sgabeblack@google.com} 50113521Sgabeblack@google.com 50213521Sgabeblack@google.comtemplate <class D> 50313521Sgabeblack@google.cominline void 50413521Sgabeblack@google.comcopy_b1(unsigned char *src1, unsigned char *src2, 50513521Sgabeblack@google.com unsigned char *dest1, unsigned char *dest2) 50613521Sgabeblack@google.com{ 50713521Sgabeblack@google.com *((D *)dest2) = *((D *)src2); 50813521Sgabeblack@google.com} 50913521Sgabeblack@google.com 51013521Sgabeblack@google.comtemplate <class D> 51113521Sgabeblack@google.cominline void 51213521Sgabeblack@google.comcopy_dbyb1(unsigned char *src1, unsigned char *src2, 51313521Sgabeblack@google.com unsigned char *dest1, unsigned char *dest2) 51413521Sgabeblack@google.com{ 51513521Sgabeblack@google.com if (*src2 != TLM_BYTE_DISABLED) 51613521Sgabeblack@google.com *((D *)src1) = *((D *)dest1); 51713521Sgabeblack@google.com} 51813521Sgabeblack@google.com 51913521Sgabeblack@google.comtemplate <class D> 52013521Sgabeblack@google.cominline void 52113521Sgabeblack@google.comcopy_dbytrue1(unsigned char *src1, unsigned char *src2, 52213521Sgabeblack@google.com unsigned char *dest1, unsigned char *dest2) 52313521Sgabeblack@google.com{ 52413521Sgabeblack@google.com *((D *)src1) = *((D *)dest1); 52513521Sgabeblack@google.com} 52613521Sgabeblack@google.com 52713521Sgabeblack@google.comtemplate<class D> 52813521Sgabeblack@google.cominline void 52913521Sgabeblack@google.comfalse_b1(unsigned char *dest1) 53013521Sgabeblack@google.com{ 53113521Sgabeblack@google.com *((D *)dest1) = tlm_bool<D>::TLM_FALSE; 53213521Sgabeblack@google.com} 53313521Sgabeblack@google.com 53413521Sgabeblack@google.comtemplate<class D> 53513521Sgabeblack@google.cominline void 53613521Sgabeblack@google.comno_b1(unsigned char *dest1) 53713521Sgabeblack@google.com{} 53813521Sgabeblack@google.com 53913521Sgabeblack@google.comtemplate<class D, 54013521Sgabeblack@google.com void COPY(unsigned char *src1, unsigned char *src2, 54113521Sgabeblack@google.com unsigned char *dest1, unsigned char *dest2), 54213521Sgabeblack@google.com void COPYuchar(unsigned char *src1, unsigned char *src2, 54313521Sgabeblack@google.com unsigned char *dest1, unsigned char *dest2), 54413521Sgabeblack@google.com void FILLFALSE(unsigned char *dest1), 54513521Sgabeblack@google.com void FILLFALSEuchar(unsigned char *dest1)> 54613521Sgabeblack@google.cominline int 54713521Sgabeblack@google.comloop_word1(int bytes_left, int len0, int lenN, int sizeof_databus, 54813521Sgabeblack@google.com unsigned char *start, unsigned char *end, 54913521Sgabeblack@google.com unsigned char *src, unsigned char *bsrc, 55013521Sgabeblack@google.com unsigned char *dest, unsigned char *bdest) 55113521Sgabeblack@google.com{ 55213521Sgabeblack@google.com ptrdiff_t d2b_src = bsrc - src; // 64BITFIX was int 55313521Sgabeblack@google.com ptrdiff_t d2b_dest = bdest - dest; // 64BITFIX was int 55413521Sgabeblack@google.com unsigned char *original_dest = dest; 55513521Sgabeblack@google.com 55613521Sgabeblack@google.com while (true) { 55713521Sgabeblack@google.com // len0 bytes at start of a bus word. 55813521Sgabeblack@google.com if ((src >= start) && (src < end)) { 55913521Sgabeblack@google.com for (int i = 0; i < len0; i++) { 56013521Sgabeblack@google.com COPYuchar(src, src + d2b_src, dest, dest + d2b_dest); 56113521Sgabeblack@google.com src++; 56213521Sgabeblack@google.com dest++; 56313521Sgabeblack@google.com } 56413521Sgabeblack@google.com bytes_left -= len0; 56513521Sgabeblack@google.com if (bytes_left <= 0) 56613521Sgabeblack@google.com return int(dest - original_dest); 56713521Sgabeblack@google.com } else { 56813521Sgabeblack@google.com for (int i = 0; i < len0; i++) { 56913521Sgabeblack@google.com FILLFALSEuchar(dest + d2b_dest); 57013521Sgabeblack@google.com src++; 57113521Sgabeblack@google.com dest++; 57213521Sgabeblack@google.com } 57313521Sgabeblack@google.com } 57413521Sgabeblack@google.com src -= 2 * sizeof(D); 57513521Sgabeblack@google.com 57613521Sgabeblack@google.com // Sequence of full data word fragments. 57713521Sgabeblack@google.com for (unsigned int i = 1; i < sizeof_databus / sizeof(D); i++) { 57813521Sgabeblack@google.com if ((src >= start) && (src < end)) { 57913521Sgabeblack@google.com COPY(src, src + d2b_src, dest, dest + d2b_dest); 58013521Sgabeblack@google.com bytes_left -= sizeof(D); 58113521Sgabeblack@google.com } else { 58213521Sgabeblack@google.com FILLFALSE(dest + d2b_dest); 58313521Sgabeblack@google.com } 58413521Sgabeblack@google.com dest += sizeof(D); 58513521Sgabeblack@google.com if (bytes_left <= 0) 58613521Sgabeblack@google.com return int(dest - original_dest); 58713521Sgabeblack@google.com src -= sizeof(D); 58813521Sgabeblack@google.com } 58913521Sgabeblack@google.com 59013521Sgabeblack@google.com // lenN bytes at end of bus word. 59113521Sgabeblack@google.com if ((src >= start) && (src < end)) { 59213521Sgabeblack@google.com for (int i = 0; i < lenN; i++) { 59313521Sgabeblack@google.com COPYuchar(src, src + d2b_src, dest, dest + d2b_dest); 59413521Sgabeblack@google.com src++; 59513521Sgabeblack@google.com dest++; 59613521Sgabeblack@google.com } 59713521Sgabeblack@google.com bytes_left -= lenN; 59813521Sgabeblack@google.com if (bytes_left <= 0) 59913521Sgabeblack@google.com return int(dest - original_dest); 60013521Sgabeblack@google.com } else { 60113521Sgabeblack@google.com for (int i = 0; i < lenN; i++) { 60213521Sgabeblack@google.com FILLFALSEuchar(dest + d2b_dest); 60313521Sgabeblack@google.com src++; 60413521Sgabeblack@google.com dest++; 60513521Sgabeblack@google.com } 60613521Sgabeblack@google.com } 60713521Sgabeblack@google.com src += 2 * sizeof_databus; 60813521Sgabeblack@google.com } 60913521Sgabeblack@google.com} 61013521Sgabeblack@google.com 61113521Sgabeblack@google.com 61213521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 61313521Sgabeblack@google.com// function set (1): Response 61413521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 61513521Sgabeblack@google.com 61613521Sgabeblack@google.comtemplate <class DATAWORD> 61713521Sgabeblack@google.cominline void 61813521Sgabeblack@google.comtlm_from_hostendian_word(tlm_generic_payload *txn, unsigned int sizeof_databus) 61913521Sgabeblack@google.com{ 62013521Sgabeblack@google.com if (txn->is_read()) { 62113521Sgabeblack@google.com tlm_endian_context *tc = 62213521Sgabeblack@google.com txn->template get_extension<tlm_endian_context>(); 62313521Sgabeblack@google.com sc_dt::uint64 b_mask = sizeof_databus - 1; 62413521Sgabeblack@google.com int d_mask = sizeof(DATAWORD) - 1; 62513521Sgabeblack@google.com int a_offset = static_cast<int>(tc->address & b_mask); 62613521Sgabeblack@google.com int len0 = (sizeof_databus - a_offset) & d_mask; 62713521Sgabeblack@google.com int lenN = sizeof(DATAWORD) - len0; 62813521Sgabeblack@google.com unsigned char *d_start = tc->data_ptr; 62913521Sgabeblack@google.com unsigned char *d_end = 63013521Sgabeblack@google.com ptrdiff_t(tc->length) + d_start; // 64BITFIX probably redundant 63113521Sgabeblack@google.com unsigned char *d = 63213521Sgabeblack@google.com ptrdiff_t(((sizeof_databus - a_offset) & ~d_mask) + lenN) + 63313521Sgabeblack@google.com d_start; // 64BITFIX probably redundant 63413521Sgabeblack@google.com 63513521Sgabeblack@google.com // Iterate over transaction copying data qualified by byte-enables. 63613521Sgabeblack@google.com if (tc->byte_enable == 0) { 63713521Sgabeblack@google.com loop_word1<DATAWORD, ©_dbytrue1<DATAWORD>, 63813521Sgabeblack@google.com ©_dbytrue1<unsigned char>, &no_b1<DATAWORD>, 63913521Sgabeblack@google.com &no_b1<unsigned char>>( 64013521Sgabeblack@google.com tc->length, len0, lenN, sizeof_databus, 64113521Sgabeblack@google.com d_start, d_end, d, 0, txn->get_data_ptr(), 0); 64213521Sgabeblack@google.com } else { 64313521Sgabeblack@google.com loop_word1<DATAWORD, ©_dbyb1<DATAWORD>, 64413521Sgabeblack@google.com ©_dbyb1<unsigned char>, &no_b1<DATAWORD>, 64513521Sgabeblack@google.com &no_b1<unsigned char>>( 64613521Sgabeblack@google.com tc->length, len0, lenN, sizeof_databus, 64713521Sgabeblack@google.com d_start, d_end, d, 64813521Sgabeblack@google.com tc->byte_enable - d_start + d, 64913521Sgabeblack@google.com txn->get_data_ptr(), 0); 65013521Sgabeblack@google.com } 65113521Sgabeblack@google.com } 65213521Sgabeblack@google.com} 65313521Sgabeblack@google.com 65413521Sgabeblack@google.com 65513521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 65613521Sgabeblack@google.com// function set (1): Request 65713521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 65813521Sgabeblack@google.com 65913521Sgabeblack@google.comtemplate <class DATAWORD> 66013521Sgabeblack@google.cominline void 66113521Sgabeblack@google.comtlm_to_hostendian_word(tlm_generic_payload *txn, unsigned int sizeof_databus) 66213521Sgabeblack@google.com{ 66313521Sgabeblack@google.com tlm_endian_context *tc = establish_context(txn); 66413521Sgabeblack@google.com tc->from_f = &(tlm_from_hostendian_word<DATAWORD>); 66513521Sgabeblack@google.com tc->sizeof_databus = sizeof_databus; 66613521Sgabeblack@google.com 66713521Sgabeblack@google.com sc_dt::uint64 b_mask = sizeof_databus - 1; 66813521Sgabeblack@google.com int d_mask = sizeof(DATAWORD) - 1; 66913521Sgabeblack@google.com sc_dt::uint64 a_aligned = txn->get_address() & ~b_mask; 67013521Sgabeblack@google.com int a_offset = static_cast<int>(txn->get_address() & b_mask); 67113521Sgabeblack@google.com int len0 = (sizeof_databus - a_offset) & d_mask; 67213521Sgabeblack@google.com int lenN = sizeof(DATAWORD) - len0; 67313521Sgabeblack@google.com unsigned char *d_start = txn->get_data_ptr(); 67413521Sgabeblack@google.com unsigned char *d_end = 67513521Sgabeblack@google.com ptrdiff_t(txn->get_data_length()) + d_start; 67613521Sgabeblack@google.com // 64BITFIX probably redundant. 67713521Sgabeblack@google.com unsigned char *d = 67813521Sgabeblack@google.com ptrdiff_t(((sizeof_databus - a_offset) & ~d_mask) + lenN) + d_start; 67913521Sgabeblack@google.com // 64BITFIX probably redundant. 68013521Sgabeblack@google.com 68113521Sgabeblack@google.com // Create new data and byte enable buffers. 68213521Sgabeblack@google.com int long_enough = txn->get_data_length() + 2 * sizeof_databus; 68313521Sgabeblack@google.com tc->establish_dbuf(long_enough); 68413521Sgabeblack@google.com unsigned char *new_data = tc->new_dbuf; 68513521Sgabeblack@google.com tc->establish_bebuf(long_enough); 68613521Sgabeblack@google.com unsigned char *new_be = tc->new_bebuf; 68713521Sgabeblack@google.com 68813521Sgabeblack@google.com if (txn->is_read()) { 68913521Sgabeblack@google.com tc->data_ptr = d_start; 69013521Sgabeblack@google.com tc->address = txn->get_address(); 69113521Sgabeblack@google.com tc->byte_enable = txn->get_byte_enable_ptr(); 69213521Sgabeblack@google.com tc->length = txn->get_data_length(); 69313521Sgabeblack@google.com if (txn->get_byte_enable_ptr() == 0) { 69413521Sgabeblack@google.com // Iterate over transaction creating new byte enables from all-true 69513521Sgabeblack@google.com txn->set_data_length( 69613521Sgabeblack@google.com loop_word1<DATAWORD, &true_b1<DATAWORD>, 69713521Sgabeblack@google.com &true_b1<unsigned char>, &false_b1<DATAWORD>, 69813521Sgabeblack@google.com &false_b1<unsigned char>>( 69913521Sgabeblack@google.com txn->get_data_length(), len0, lenN, 70013521Sgabeblack@google.com sizeof_databus, d_start, d_end, d, 0, 70113521Sgabeblack@google.com new_data, new_be)); 70213521Sgabeblack@google.com } else { 70313521Sgabeblack@google.com // iterate over transaction copying byte enables 70413521Sgabeblack@google.com txn->set_data_length( 70513521Sgabeblack@google.com loop_word1<DATAWORD, ©_b1<DATAWORD>, 70613521Sgabeblack@google.com ©_b1<unsigned char>, &false_b1<DATAWORD>, 70713521Sgabeblack@google.com &false_b1<unsigned char>>( 70813521Sgabeblack@google.com txn->get_data_length(), len0, lenN, 70913521Sgabeblack@google.com sizeof_databus, d_start, d_end, d, 71013521Sgabeblack@google.com txn->get_byte_enable_ptr() - d_start + d, 71113521Sgabeblack@google.com new_data, new_be)); 71213521Sgabeblack@google.com } 71313521Sgabeblack@google.com } else { 71413521Sgabeblack@google.com // WRITE 71513521Sgabeblack@google.com if (txn->get_byte_enable_ptr() == 0) { 71613521Sgabeblack@google.com // Iterate over transaction copying data and creating new 71713521Sgabeblack@google.com // byte-enables. 71813521Sgabeblack@google.com txn->set_data_length( 71913521Sgabeblack@google.com loop_word1<DATAWORD, ©_d1<DATAWORD>, 72013521Sgabeblack@google.com ©_d1<unsigned char>, &false_b1<DATAWORD>, 72113521Sgabeblack@google.com &false_b1<unsigned char>>( 72213521Sgabeblack@google.com txn->get_data_length(), len0, lenN, 72313521Sgabeblack@google.com sizeof_databus, d_start, d_end, d, 0, 72413521Sgabeblack@google.com new_data, new_be)); 72513521Sgabeblack@google.com } else { 72613521Sgabeblack@google.com // Iterate over transaction copying data and byte-enables. 72713521Sgabeblack@google.com txn->set_data_length( 72813521Sgabeblack@google.com loop_word1<DATAWORD, ©_db1<DATAWORD>, 72913521Sgabeblack@google.com ©_db1<unsigned char>, &false_b1<DATAWORD>, 73013521Sgabeblack@google.com &false_b1<unsigned char>>( 73113521Sgabeblack@google.com txn->get_data_length(), len0, lenN, 73213521Sgabeblack@google.com sizeof_databus, d_start, d_end, d, 73313521Sgabeblack@google.com txn->get_byte_enable_ptr() - d_start + d, 73413521Sgabeblack@google.com new_data, new_be)); 73513521Sgabeblack@google.com } 73613521Sgabeblack@google.com } 73713521Sgabeblack@google.com txn->set_byte_enable_length(txn->get_data_length()); 73813521Sgabeblack@google.com txn->set_streaming_width(txn->get_data_length()); 73913521Sgabeblack@google.com txn->set_data_ptr(new_data); 74013521Sgabeblack@google.com txn->set_byte_enable_ptr(new_be); 74113521Sgabeblack@google.com txn->set_address(a_aligned); 74213521Sgabeblack@google.com} 74313521Sgabeblack@google.com 74413521Sgabeblack@google.com 74513521Sgabeblack@google.com 74613521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 74713521Sgabeblack@google.com// function set (2): Utilities 74813521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 74913521Sgabeblack@google.com 75013521Sgabeblack@google.comtemplate <class D> 75113521Sgabeblack@google.cominline void copy_d2(D *src1, D *src2, D *dest1, D *dest2) { *dest1 = *src1; } 75213521Sgabeblack@google.com 75313521Sgabeblack@google.comtemplate <class D> 75413521Sgabeblack@google.cominline void 75513521Sgabeblack@google.comcopy_db2(D *src1, D *src2, D *dest1, D *dest2) 75613521Sgabeblack@google.com{ 75713521Sgabeblack@google.com *dest1 = *src1; 75813521Sgabeblack@google.com *dest2 = *src2; 75913521Sgabeblack@google.com} 76013521Sgabeblack@google.com 76113521Sgabeblack@google.comtemplate <class D> 76213521Sgabeblack@google.cominline void 76313521Sgabeblack@google.comcopy_dbyb2(D *src1, D *src2, D *dest1, D *dest2) 76413521Sgabeblack@google.com{ 76513521Sgabeblack@google.com if (tlm_bool<D>(*src2)) 76613521Sgabeblack@google.com *dest1 = *src1; 76713521Sgabeblack@google.com} 76813521Sgabeblack@google.com 76913521Sgabeblack@google.comtemplate <class D, void COPY(D *src1, D *src2, D *dest1, D *dest2)> 77013521Sgabeblack@google.cominline void 77113521Sgabeblack@google.comloop_aligned2(D *src1, D *src2, D *dest1, D *dest2, int words, 77213521Sgabeblack@google.com int words_per_bus) 77313521Sgabeblack@google.com{ 77413521Sgabeblack@google.com // 64BITFIX was int and operands were cast to int. 77513521Sgabeblack@google.com ptrdiff_t src1to2 = (char *)src2 - (char *)src1; 77613521Sgabeblack@google.com // 64BITFIX was int and operands were cast to int. 77713521Sgabeblack@google.com ptrdiff_t dest1to2 = (char *)dest2 - (char *)dest1; 77813521Sgabeblack@google.com 77913521Sgabeblack@google.com D *done = src1 + ptrdiff_t(words); // 64BITFIX. 78013521Sgabeblack@google.com D *bus_start = src1; 78113521Sgabeblack@google.com src1 += ptrdiff_t(words_per_bus - 1); // 64BITFIX. 78213521Sgabeblack@google.com 78313521Sgabeblack@google.com while (true) { 78413521Sgabeblack@google.com COPY(src1, (D *)(src1to2 + (char *)src1), dest1, 78513521Sgabeblack@google.com (D *)(dest1to2 + (char *)dest1)); // 64BITFIX. 78613521Sgabeblack@google.com dest1++; 78713521Sgabeblack@google.com if ((--src1) < bus_start) { 78813521Sgabeblack@google.com bus_start += ptrdiff_t(words_per_bus); // 64BITFIX. 78913521Sgabeblack@google.com if (bus_start == done) 79013521Sgabeblack@google.com break; 79113521Sgabeblack@google.com src1 = bus_start + ptrdiff_t(words_per_bus - 1); // 64BITFIX. 79213521Sgabeblack@google.com } 79313521Sgabeblack@google.com } 79413521Sgabeblack@google.com} 79513521Sgabeblack@google.com 79613521Sgabeblack@google.com 79713521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 79813521Sgabeblack@google.com// function set (2): Response 79913521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 80013521Sgabeblack@google.com 80113521Sgabeblack@google.comtemplate <class DATAWORD> 80213521Sgabeblack@google.cominline void 80313521Sgabeblack@google.comtlm_from_hostendian_aligned( 80413521Sgabeblack@google.com tlm_generic_payload *txn, unsigned int sizeof_databus) 80513521Sgabeblack@google.com{ 80613521Sgabeblack@google.com int words_per_bus = sizeof_databus / sizeof(DATAWORD); 80713521Sgabeblack@google.com if (words_per_bus == 1) 80813521Sgabeblack@google.com return; 80913521Sgabeblack@google.com int words = (txn->get_data_length()) / sizeof(DATAWORD); 81013521Sgabeblack@google.com tlm_endian_context *tc = txn->template get_extension<tlm_endian_context>(); 81113521Sgabeblack@google.com 81213521Sgabeblack@google.com if (txn->get_byte_enable_ptr() == 0) { 81313521Sgabeblack@google.com // no byte enables 81413521Sgabeblack@google.com if (txn->is_read()) { 81513521Sgabeblack@google.com // RD without byte enables. Copy data to original buffer. 81613521Sgabeblack@google.com loop_aligned2<DATAWORD, ©_d2<DATAWORD>>( 81713521Sgabeblack@google.com (DATAWORD *)(txn->get_data_ptr()), 0, 81813521Sgabeblack@google.com (DATAWORD *)(tc->data_ptr), 0, words, words_per_bus); 81913521Sgabeblack@google.com } 82013521Sgabeblack@google.com } else { 82113521Sgabeblack@google.com // byte enables present 82213521Sgabeblack@google.com if (txn->is_read()) { 82313521Sgabeblack@google.com // RD with byte enables. Copy data qualified by byte-enables. 82413521Sgabeblack@google.com loop_aligned2<DATAWORD, ©_dbyb2<DATAWORD>>( 82513521Sgabeblack@google.com (DATAWORD *)(txn->get_data_ptr()), 82613521Sgabeblack@google.com (DATAWORD *)(txn->get_byte_enable_ptr()), 82713521Sgabeblack@google.com (DATAWORD *)(tc->data_ptr), 0, words, words_per_bus); 82813521Sgabeblack@google.com } 82913521Sgabeblack@google.com } 83013521Sgabeblack@google.com} 83113521Sgabeblack@google.com 83213521Sgabeblack@google.com 83313521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 83413521Sgabeblack@google.com// function set (2): Request 83513521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 83613521Sgabeblack@google.com 83713521Sgabeblack@google.comtemplate <class DATAWORD> 83813521Sgabeblack@google.cominline void 83913521Sgabeblack@google.comtlm_to_hostendian_aligned( 84013521Sgabeblack@google.com tlm_generic_payload *txn, unsigned int sizeof_databus) 84113521Sgabeblack@google.com{ 84213521Sgabeblack@google.com tlm_endian_context *tc = establish_context(txn); 84313521Sgabeblack@google.com tc->from_f = &(tlm_from_hostendian_aligned<DATAWORD>); 84413521Sgabeblack@google.com tc->sizeof_databus = sizeof_databus; 84513521Sgabeblack@google.com 84613521Sgabeblack@google.com int words_per_bus = sizeof_databus / sizeof(DATAWORD); 84713521Sgabeblack@google.com if (words_per_bus == 1) 84813521Sgabeblack@google.com return; 84913521Sgabeblack@google.com int words = (txn->get_data_length()) / sizeof(DATAWORD); 85013521Sgabeblack@google.com 85113521Sgabeblack@google.com DATAWORD *original_be = (DATAWORD *)(txn->get_byte_enable_ptr()); 85213521Sgabeblack@google.com DATAWORD *original_data = (DATAWORD *)(txn->get_data_ptr()); 85313521Sgabeblack@google.com 85413521Sgabeblack@google.com // Always allocate a new data buffer. 85513521Sgabeblack@google.com tc->establish_dbuf(txn->get_data_length()); 85613521Sgabeblack@google.com txn->set_data_ptr(tc->new_dbuf); 85713521Sgabeblack@google.com 85813521Sgabeblack@google.com if (original_be == 0) { 85913521Sgabeblack@google.com // No byte enables. 86013521Sgabeblack@google.com if (txn->is_write()) { 86113521Sgabeblack@google.com // WR no byte enables. Copy data. 86213521Sgabeblack@google.com loop_aligned2<DATAWORD, ©_d2<DATAWORD>>( 86313521Sgabeblack@google.com original_data, 0, (DATAWORD *)(txn->get_data_ptr()), 0, 86413521Sgabeblack@google.com words, words_per_bus); 86513521Sgabeblack@google.com } else { 86613521Sgabeblack@google.com // RD no byte enables. Save original data pointer. 86713521Sgabeblack@google.com tc->data_ptr = (unsigned char *)original_data; 86813521Sgabeblack@google.com } 86913521Sgabeblack@google.com } else { 87013521Sgabeblack@google.com // Byte enables present. 87113521Sgabeblack@google.com // Allocate a new buffer for them. 87213521Sgabeblack@google.com tc->establish_bebuf(txn->get_data_length()); 87313521Sgabeblack@google.com txn->set_byte_enable_ptr(tc->new_bebuf); 87413521Sgabeblack@google.com txn->set_byte_enable_length(txn->get_data_length()); 87513521Sgabeblack@google.com 87613521Sgabeblack@google.com if (txn->is_write()) { 87713521Sgabeblack@google.com // WR with byte enables. Copy data and BEs. 87813521Sgabeblack@google.com loop_aligned2<DATAWORD, ©_db2<DATAWORD>>( 87913521Sgabeblack@google.com original_data, original_be, 88013521Sgabeblack@google.com (DATAWORD *)(txn->get_data_ptr()), 88113521Sgabeblack@google.com (DATAWORD *)(txn->get_byte_enable_ptr()), 88213521Sgabeblack@google.com words, words_per_bus); 88313521Sgabeblack@google.com } else { 88413521Sgabeblack@google.com // RD with byte enables. Save original data pointer. 88513521Sgabeblack@google.com tc->data_ptr = (unsigned char *)original_data; 88613521Sgabeblack@google.com // Copy byte enables to new buffer. 88713521Sgabeblack@google.com loop_aligned2<DATAWORD, ©_d2<DATAWORD>>( 88813521Sgabeblack@google.com original_be, 0, (DATAWORD *)(txn->get_byte_enable_ptr()), 88913521Sgabeblack@google.com 0, words, words_per_bus); 89013521Sgabeblack@google.com } 89113521Sgabeblack@google.com } 89213521Sgabeblack@google.com} 89313521Sgabeblack@google.com 89413521Sgabeblack@google.com 89513521Sgabeblack@google.com 89613521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 89713521Sgabeblack@google.com// function set (3): Response 89813521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 89913521Sgabeblack@google.com 90013521Sgabeblack@google.comtemplate <class DATAWORD> 90113521Sgabeblack@google.cominline void 90213521Sgabeblack@google.comtlm_from_hostendian_single( 90313521Sgabeblack@google.com tlm_generic_payload *txn, unsigned int sizeof_databus) 90413521Sgabeblack@google.com{} 90513521Sgabeblack@google.com 90613521Sgabeblack@google.com 90713521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 90813521Sgabeblack@google.com// function set (3): Request 90913521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 91013521Sgabeblack@google.com 91113521Sgabeblack@google.comtemplate <class DATAWORD> 91213521Sgabeblack@google.cominline void 91313521Sgabeblack@google.comtlm_to_hostendian_single(tlm_generic_payload *txn, unsigned int sizeof_databus) 91413521Sgabeblack@google.com{ 91513521Sgabeblack@google.com tlm_endian_context *tc = establish_context(txn); 91613521Sgabeblack@google.com tc->from_f = &(tlm_from_hostendian_single<DATAWORD>); 91713521Sgabeblack@google.com tc->sizeof_databus = sizeof_databus; 91813521Sgabeblack@google.com 91913521Sgabeblack@google.com // Only need to change the address, always safe to work in-place. 92013521Sgabeblack@google.com sc_dt::uint64 mask = sizeof_databus - 1; 92113521Sgabeblack@google.com sc_dt::uint64 a = txn->get_address(); 92213521Sgabeblack@google.com txn->set_address((a & ~mask) | 92313521Sgabeblack@google.com (sizeof_databus - (a & mask) - sizeof(DATAWORD))); 92413521Sgabeblack@google.com} 92513521Sgabeblack@google.com 92613521Sgabeblack@google.com 92713521Sgabeblack@google.com 92813521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 92913521Sgabeblack@google.com// helper function which works for all responses 93013521Sgabeblack@google.com/////////////////////////////////////////////////////////////////////////////// 93113521Sgabeblack@google.com 93213521Sgabeblack@google.cominline void 93313521Sgabeblack@google.comtlm_from_hostendian(tlm_generic_payload *txn) 93413521Sgabeblack@google.com{ 93513521Sgabeblack@google.com tlm_endian_context *tc = txn->get_extension<tlm_endian_context>(); 93613521Sgabeblack@google.com (*(tc->from_f))(txn, tc->sizeof_databus); 93713521Sgabeblack@google.com} 93813521Sgabeblack@google.com 93913521Sgabeblack@google.com} // namespace tlm 94013521Sgabeblack@google.com 94113521Sgabeblack@google.com#endif /* __SYSTEMC_EXT_TLM_CORE_2_GENERIC_PAYLOAD_ENDIAN_CONV_HH__ */ 942