112922Sgabeblack@google.com/*****************************************************************************
212922Sgabeblack@google.com
312922Sgabeblack@google.com  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
412922Sgabeblack@google.com  more contributor license agreements.  See the NOTICE file distributed
512922Sgabeblack@google.com  with this work for additional information regarding copyright ownership.
612922Sgabeblack@google.com  Accellera licenses this file to you under the Apache License, Version 2.0
712922Sgabeblack@google.com  (the "License"); you may not use this file except in compliance with the
812922Sgabeblack@google.com  License.  You may obtain a copy of the License at
912922Sgabeblack@google.com
1012922Sgabeblack@google.com    http://www.apache.org/licenses/LICENSE-2.0
1112922Sgabeblack@google.com
1212922Sgabeblack@google.com  Unless required by applicable law or agreed to in writing, software
1312922Sgabeblack@google.com  distributed under the License is distributed on an "AS IS" BASIS,
1412922Sgabeblack@google.com  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1512922Sgabeblack@google.com  implied.  See the License for the specific language governing
1612922Sgabeblack@google.com  permissions and limitations under the License.
1712922Sgabeblack@google.com
1812922Sgabeblack@google.com *****************************************************************************/
1912922Sgabeblack@google.com
2012922Sgabeblack@google.com#ifndef __SIMPLEBUSLT_H__
2112922Sgabeblack@google.com#define __SIMPLEBUSLT_H__
2212922Sgabeblack@google.com
2312922Sgabeblack@google.com//#include <systemc>
2412922Sgabeblack@google.com#include "tlm.h"
2512922Sgabeblack@google.com
2612922Sgabeblack@google.com#include "tlm_utils/simple_target_socket.h"
2712922Sgabeblack@google.com#include "tlm_utils/simple_initiator_socket.h"
2812922Sgabeblack@google.com
2912922Sgabeblack@google.comtemplate <int NR_OF_INITIATORS, int NR_OF_TARGETS>
3012922Sgabeblack@google.comclass SimpleBusLT : public sc_core::sc_module
3112922Sgabeblack@google.com{
3212922Sgabeblack@google.compublic:
3312922Sgabeblack@google.com  typedef tlm::tlm_generic_payload                 transaction_type;
3412922Sgabeblack@google.com  typedef tlm::tlm_phase                           phase_type;
3512922Sgabeblack@google.com  typedef tlm::tlm_sync_enum                       sync_enum_type;
3612922Sgabeblack@google.com  typedef tlm_utils::simple_target_socket_tagged<SimpleBusLT>    target_socket_type;
3712922Sgabeblack@google.com  typedef tlm_utils::simple_initiator_socket_tagged<SimpleBusLT> initiator_socket_type;
3812922Sgabeblack@google.com
3912922Sgabeblack@google.compublic:
4012922Sgabeblack@google.com  target_socket_type target_socket[NR_OF_INITIATORS];
4112922Sgabeblack@google.com  initiator_socket_type initiator_socket[NR_OF_TARGETS];
4212922Sgabeblack@google.com
4312922Sgabeblack@google.compublic:
4412922Sgabeblack@google.com  SC_HAS_PROCESS(SimpleBusLT);
4512922Sgabeblack@google.com  SimpleBusLT(sc_core::sc_module_name name) :
4612922Sgabeblack@google.com    sc_core::sc_module(name)
4712922Sgabeblack@google.com  {
4812922Sgabeblack@google.com    for (unsigned int i = 0; i < NR_OF_INITIATORS; ++i) {
4912922Sgabeblack@google.com      target_socket[i].register_b_transport(this, &SimpleBusLT::initiatorBTransport, i);
5012922Sgabeblack@google.com      target_socket[i].register_transport_dbg(this, &SimpleBusLT::transportDebug, i);
5112922Sgabeblack@google.com      target_socket[i].register_get_direct_mem_ptr(this, &SimpleBusLT::getDMIPointer, i);
5212922Sgabeblack@google.com    }
5312922Sgabeblack@google.com    for (unsigned int i = 0; i < NR_OF_TARGETS; ++i) {
5412922Sgabeblack@google.com      initiator_socket[i].register_invalidate_direct_mem_ptr(this, &SimpleBusLT::invalidateDMIPointers, i);
5512922Sgabeblack@google.com    }
5612922Sgabeblack@google.com  }
5712922Sgabeblack@google.com
5812922Sgabeblack@google.com  //
5912922Sgabeblack@google.com  // Dummy decoder:
6012922Sgabeblack@google.com  // - address[31-28]: portId
6112922Sgabeblack@google.com  // - address[27-0]: masked address
6212922Sgabeblack@google.com  //
6312922Sgabeblack@google.com
6412922Sgabeblack@google.com  unsigned int getPortId(const sc_dt::uint64& address)
6512922Sgabeblack@google.com  {
6612922Sgabeblack@google.com    return (unsigned int)address >> 28;
6712922Sgabeblack@google.com  }
6812922Sgabeblack@google.com
6912922Sgabeblack@google.com  sc_dt::uint64 getAddressOffset(unsigned int portId)
7012922Sgabeblack@google.com  {
7112922Sgabeblack@google.com    return portId << 28;
7212922Sgabeblack@google.com  }
7312922Sgabeblack@google.com
7412922Sgabeblack@google.com  sc_dt::uint64 getAddressMask(unsigned int portId)
7512922Sgabeblack@google.com  {
7612922Sgabeblack@google.com    return 0xfffffff;
7712922Sgabeblack@google.com  }
7812922Sgabeblack@google.com
7912922Sgabeblack@google.com  unsigned int decode(const sc_dt::uint64& address)
8012922Sgabeblack@google.com  {
8112922Sgabeblack@google.com    // decode address:
8212922Sgabeblack@google.com    // - return initiator socket id
8312922Sgabeblack@google.com
8412922Sgabeblack@google.com    return getPortId(address);
8512922Sgabeblack@google.com  }
8612922Sgabeblack@google.com
8712922Sgabeblack@google.com  //
8812922Sgabeblack@google.com  // interface methods
8912922Sgabeblack@google.com  //
9012922Sgabeblack@google.com
9112922Sgabeblack@google.com  //
9212922Sgabeblack@google.com  // LT protocol
9312922Sgabeblack@google.com  // - forward each call to the target/initiator
9412922Sgabeblack@google.com  //
9512922Sgabeblack@google.com  void initiatorBTransport(int SocketId,
9612922Sgabeblack@google.com                           transaction_type& trans,
9712922Sgabeblack@google.com                           sc_core::sc_time& t)
9812922Sgabeblack@google.com  {
9912922Sgabeblack@google.com    initiator_socket_type* decodeSocket;
10012922Sgabeblack@google.com    unsigned int portId = decode(trans.get_address());
10112922Sgabeblack@google.com    assert(portId < NR_OF_TARGETS);
10212922Sgabeblack@google.com    decodeSocket = &initiator_socket[portId];
10312922Sgabeblack@google.com    trans.set_address(trans.get_address() & getAddressMask(portId));
10412922Sgabeblack@google.com
10512922Sgabeblack@google.com    (*decodeSocket)->b_transport(trans, t);
10612922Sgabeblack@google.com  }
10712922Sgabeblack@google.com
10812922Sgabeblack@google.com  unsigned int transportDebug(int SocketId,
10912922Sgabeblack@google.com                              transaction_type& trans)
11012922Sgabeblack@google.com  {
11112922Sgabeblack@google.com    unsigned int portId = decode(trans.get_address());
11212922Sgabeblack@google.com    assert(portId < NR_OF_TARGETS);
11312922Sgabeblack@google.com    initiator_socket_type* decodeSocket = &initiator_socket[portId];
11412922Sgabeblack@google.com    trans.set_address( trans.get_address() & getAddressMask(portId) );
11512922Sgabeblack@google.com
11612922Sgabeblack@google.com    return (*decodeSocket)->transport_dbg(trans);
11712922Sgabeblack@google.com  }
11812922Sgabeblack@google.com
11912922Sgabeblack@google.com  bool limitRange(unsigned int portId, sc_dt::uint64& low, sc_dt::uint64& high)
12012922Sgabeblack@google.com  {
12112922Sgabeblack@google.com    sc_dt::uint64 addressOffset = getAddressOffset(portId);
12212922Sgabeblack@google.com    sc_dt::uint64 addressMask = getAddressMask(portId);
12312922Sgabeblack@google.com
12412922Sgabeblack@google.com    if (low > addressMask) {
12512922Sgabeblack@google.com      // Range does not overlap with addressrange for this target
12612922Sgabeblack@google.com      return false;
12712922Sgabeblack@google.com    }
12812922Sgabeblack@google.com
12912922Sgabeblack@google.com    low += addressOffset;
13012922Sgabeblack@google.com    if (high > addressMask) {
13112922Sgabeblack@google.com      high = addressOffset + addressMask;
13212922Sgabeblack@google.com
13312922Sgabeblack@google.com    } else {
13412922Sgabeblack@google.com      high += addressOffset;
13512922Sgabeblack@google.com    }
13612922Sgabeblack@google.com    return true;
13712922Sgabeblack@google.com  }
13812922Sgabeblack@google.com
13912922Sgabeblack@google.com  bool getDMIPointer(int SocketId,
14012922Sgabeblack@google.com                     transaction_type& trans,
14112922Sgabeblack@google.com                     tlm::tlm_dmi&  dmi_data)
14212922Sgabeblack@google.com  {
14312922Sgabeblack@google.com    sc_dt::uint64 address = trans.get_address();
14412922Sgabeblack@google.com
14512922Sgabeblack@google.com    unsigned int portId = decode(address);
14612922Sgabeblack@google.com    assert(portId < NR_OF_TARGETS);
14712922Sgabeblack@google.com    initiator_socket_type* decodeSocket = &initiator_socket[portId];
14812922Sgabeblack@google.com    sc_dt::uint64 maskedAddress = address & getAddressMask(portId);
14912922Sgabeblack@google.com
15012922Sgabeblack@google.com    trans.set_address(maskedAddress);
15112922Sgabeblack@google.com
15212922Sgabeblack@google.com    bool result =
15312922Sgabeblack@google.com      (*decodeSocket)->get_direct_mem_ptr(trans, dmi_data);
15412922Sgabeblack@google.com
15512922Sgabeblack@google.com    if (result)
15612922Sgabeblack@google.com    {
15712922Sgabeblack@google.com      // Range must contain address
15812922Sgabeblack@google.com      assert(dmi_data.get_start_address() <= maskedAddress);
15912922Sgabeblack@google.com      assert(dmi_data.get_end_address() >= maskedAddress);
16012922Sgabeblack@google.com    }
16112922Sgabeblack@google.com
16212922Sgabeblack@google.com    // Should always succeed
16312922Sgabeblack@google.com	sc_dt::uint64 start, end;
16412922Sgabeblack@google.com	start = dmi_data.get_start_address();
16512922Sgabeblack@google.com	end = dmi_data.get_end_address();
16612922Sgabeblack@google.com
16712922Sgabeblack@google.com	limitRange(portId, start, end);
16812922Sgabeblack@google.com
16912922Sgabeblack@google.com	dmi_data.set_start_address(start);
17012922Sgabeblack@google.com	dmi_data.set_end_address(end);
17112922Sgabeblack@google.com
17212922Sgabeblack@google.com    return result;
17312922Sgabeblack@google.com  }
17412922Sgabeblack@google.com
17512922Sgabeblack@google.com  void invalidateDMIPointers(int port_id,
17612922Sgabeblack@google.com                             sc_dt::uint64 start_range,
17712922Sgabeblack@google.com                             sc_dt::uint64 end_range)
17812922Sgabeblack@google.com  {
17912922Sgabeblack@google.com    // FIXME: probably faster to always invalidate everything?
18012922Sgabeblack@google.com
18112922Sgabeblack@google.com    if (!limitRange(port_id, start_range, end_range)) {
18212922Sgabeblack@google.com      // Range does not fall into address range of target
18312922Sgabeblack@google.com      return;
18412922Sgabeblack@google.com    }
18512922Sgabeblack@google.com
18612922Sgabeblack@google.com    for (unsigned int i = 0; i < NR_OF_INITIATORS; ++i) {
18712922Sgabeblack@google.com      (target_socket[i])->invalidate_direct_mem_ptr(start_range, end_range);
18812922Sgabeblack@google.com    }
18912922Sgabeblack@google.com  }
19012922Sgabeblack@google.com
19112922Sgabeblack@google.com};
19212922Sgabeblack@google.com
19312922Sgabeblack@google.com#endif
194