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, &copy_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, &copy_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, &copy_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, &copy_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, &copy_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, &copy_dbytrue1<DATAWORD>,
63813521Sgabeblack@google.com                       &copy_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, &copy_dbyb1<DATAWORD>,
64413521Sgabeblack@google.com                       &copy_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, &copy_b1<DATAWORD>,
70613521Sgabeblack@google.com                               &copy_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, &copy_d1<DATAWORD>,
72013521Sgabeblack@google.com                               &copy_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, &copy_db1<DATAWORD>,
72913521Sgabeblack@google.com                               &copy_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, &copy_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, &copy_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, &copy_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, &copy_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, &copy_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