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