SimpleBusLT.h revision 12922
112600Sodanrc@yahoo.com.br/*****************************************************************************
212600Sodanrc@yahoo.com.br
312600Sodanrc@yahoo.com.br  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
412600Sodanrc@yahoo.com.br  more contributor license agreements.  See the NOTICE file distributed
512600Sodanrc@yahoo.com.br  with this work for additional information regarding copyright ownership.
612600Sodanrc@yahoo.com.br  Accellera licenses this file to you under the Apache License, Version 2.0
712600Sodanrc@yahoo.com.br  (the "License"); you may not use this file except in compliance with the
812600Sodanrc@yahoo.com.br  License.  You may obtain a copy of the License at
912600Sodanrc@yahoo.com.br
1012600Sodanrc@yahoo.com.br    http://www.apache.org/licenses/LICENSE-2.0
1112600Sodanrc@yahoo.com.br
1212600Sodanrc@yahoo.com.br  Unless required by applicable law or agreed to in writing, software
1312600Sodanrc@yahoo.com.br  distributed under the License is distributed on an "AS IS" BASIS,
1412600Sodanrc@yahoo.com.br  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1512600Sodanrc@yahoo.com.br  implied.  See the License for the specific language governing
1612600Sodanrc@yahoo.com.br  permissions and limitations under the License.
1712600Sodanrc@yahoo.com.br
1812600Sodanrc@yahoo.com.br *****************************************************************************/
1912600Sodanrc@yahoo.com.br
2012600Sodanrc@yahoo.com.br#ifndef __SIMPLEBUSLT_H__
2112600Sodanrc@yahoo.com.br#define __SIMPLEBUSLT_H__
2212600Sodanrc@yahoo.com.br
2312600Sodanrc@yahoo.com.br//#include <systemc>
2412600Sodanrc@yahoo.com.br#include "tlm.h"
2512600Sodanrc@yahoo.com.br
2612600Sodanrc@yahoo.com.br#include "tlm_utils/simple_target_socket.h"
2712600Sodanrc@yahoo.com.br#include "tlm_utils/simple_initiator_socket.h"
2812600Sodanrc@yahoo.com.br
2912600Sodanrc@yahoo.com.brtemplate <int NR_OF_INITIATORS, int NR_OF_TARGETS>
3012600Sodanrc@yahoo.com.brclass SimpleBusLT : public sc_core::sc_module
3112600Sodanrc@yahoo.com.br{
3212600Sodanrc@yahoo.com.brpublic:
3312600Sodanrc@yahoo.com.br  typedef tlm::tlm_generic_payload                 transaction_type;
3412600Sodanrc@yahoo.com.br  typedef tlm::tlm_phase                           phase_type;
3512600Sodanrc@yahoo.com.br  typedef tlm::tlm_sync_enum                       sync_enum_type;
3612600Sodanrc@yahoo.com.br  typedef tlm_utils::simple_target_socket_tagged<SimpleBusLT>    target_socket_type;
3712600Sodanrc@yahoo.com.br  typedef tlm_utils::simple_initiator_socket_tagged<SimpleBusLT> initiator_socket_type;
3812607Sodanrc@yahoo.com.br
3912607Sodanrc@yahoo.com.brpublic:
4012607Sodanrc@yahoo.com.br  target_socket_type target_socket[NR_OF_INITIATORS];
4112607Sodanrc@yahoo.com.br  initiator_socket_type initiator_socket[NR_OF_TARGETS];
4212607Sodanrc@yahoo.com.br
4312600Sodanrc@yahoo.com.brpublic:
4412600Sodanrc@yahoo.com.br  SC_HAS_PROCESS(SimpleBusLT);
4512600Sodanrc@yahoo.com.br  SimpleBusLT(sc_core::sc_module_name name) :
4612600Sodanrc@yahoo.com.br    sc_core::sc_module(name)
4712600Sodanrc@yahoo.com.br  {
4812601Sodanrc@yahoo.com.br    for (unsigned int i = 0; i < NR_OF_INITIATORS; ++i) {
4912601Sodanrc@yahoo.com.br      target_socket[i].register_b_transport(this, &SimpleBusLT::initiatorBTransport, i);
5012601Sodanrc@yahoo.com.br      target_socket[i].register_transport_dbg(this, &SimpleBusLT::transportDebug, i);
5112601Sodanrc@yahoo.com.br      target_socket[i].register_get_direct_mem_ptr(this, &SimpleBusLT::getDMIPointer, i);
5212601Sodanrc@yahoo.com.br    }
5312600Sodanrc@yahoo.com.br    for (unsigned int i = 0; i < NR_OF_TARGETS; ++i) {
5412600Sodanrc@yahoo.com.br      initiator_socket[i].register_invalidate_direct_mem_ptr(this, &SimpleBusLT::invalidateDMIPointers, i);
5512600Sodanrc@yahoo.com.br    }
5612600Sodanrc@yahoo.com.br  }
5712626Sodanrc@yahoo.com.br
5812626Sodanrc@yahoo.com.br  //
5912626Sodanrc@yahoo.com.br  // Dummy decoder:
6012626Sodanrc@yahoo.com.br  // - address[31-28]: portId
6112626Sodanrc@yahoo.com.br  // - address[27-0]: masked address
6212626Sodanrc@yahoo.com.br  //
6312626Sodanrc@yahoo.com.br
6412626Sodanrc@yahoo.com.br  unsigned int getPortId(const sc_dt::uint64& address)
6512626Sodanrc@yahoo.com.br  {
6612626Sodanrc@yahoo.com.br    return (unsigned int)address >> 28;
6712627Sodanrc@yahoo.com.br  }
6812627Sodanrc@yahoo.com.br
6912627Sodanrc@yahoo.com.br  sc_dt::uint64 getAddressOffset(unsigned int portId)
70  {
71    return portId << 28;
72  }
73
74  sc_dt::uint64 getAddressMask(unsigned int portId)
75  {
76    return 0xfffffff;
77  }
78
79  unsigned int decode(const sc_dt::uint64& address)
80  {
81    // decode address:
82    // - return initiator socket id
83
84    return getPortId(address);
85  }
86
87  //
88  // interface methods
89  //
90
91  //
92  // LT protocol
93  // - forward each call to the target/initiator
94  //
95  void initiatorBTransport(int SocketId,
96                           transaction_type& trans,
97                           sc_core::sc_time& t)
98  {
99    initiator_socket_type* decodeSocket;
100    unsigned int portId = decode(trans.get_address());
101    assert(portId < NR_OF_TARGETS);
102    decodeSocket = &initiator_socket[portId];
103    trans.set_address(trans.get_address() & getAddressMask(portId));
104
105    (*decodeSocket)->b_transport(trans, t);
106  }
107
108  unsigned int transportDebug(int SocketId,
109                              transaction_type& trans)
110  {
111    unsigned int portId = decode(trans.get_address());
112    assert(portId < NR_OF_TARGETS);
113    initiator_socket_type* decodeSocket = &initiator_socket[portId];
114    trans.set_address( trans.get_address() & getAddressMask(portId) );
115
116    return (*decodeSocket)->transport_dbg(trans);
117  }
118
119  bool limitRange(unsigned int portId, sc_dt::uint64& low, sc_dt::uint64& high)
120  {
121    sc_dt::uint64 addressOffset = getAddressOffset(portId);
122    sc_dt::uint64 addressMask = getAddressMask(portId);
123
124    if (low > addressMask) {
125      // Range does not overlap with addressrange for this target
126      return false;
127    }
128
129    low += addressOffset;
130    if (high > addressMask) {
131      high = addressOffset + addressMask;
132
133    } else {
134      high += addressOffset;
135    }
136    return true;
137  }
138
139  bool getDMIPointer(int SocketId,
140                     transaction_type& trans,
141                     tlm::tlm_dmi&  dmi_data)
142  {
143    sc_dt::uint64 address = trans.get_address();
144
145    unsigned int portId = decode(address);
146    assert(portId < NR_OF_TARGETS);
147    initiator_socket_type* decodeSocket = &initiator_socket[portId];
148    sc_dt::uint64 maskedAddress = address & getAddressMask(portId);
149
150    trans.set_address(maskedAddress);
151
152    bool result =
153      (*decodeSocket)->get_direct_mem_ptr(trans, dmi_data);
154
155    if (result)
156    {
157      // Range must contain address
158      assert(dmi_data.get_start_address() <= maskedAddress);
159      assert(dmi_data.get_end_address() >= maskedAddress);
160    }
161
162    // Should always succeed
163	sc_dt::uint64 start, end;
164	start = dmi_data.get_start_address();
165	end = dmi_data.get_end_address();
166
167	limitRange(portId, start, end);
168
169	dmi_data.set_start_address(start);
170	dmi_data.set_end_address(end);
171
172    return result;
173  }
174
175  void invalidateDMIPointers(int port_id,
176                             sc_dt::uint64 start_range,
177                             sc_dt::uint64 end_range)
178  {
179    // FIXME: probably faster to always invalidate everything?
180
181    if (!limitRange(port_id, start_range, end_range)) {
182      // Range does not fall into address range of target
183      return;
184    }
185
186    for (unsigned int i = 0; i < NR_OF_INITIATORS; ++i) {
187      (target_socket[i])->invalidate_direct_mem_ptr(start_range, end_range);
188    }
189  }
190
191};
192
193#endif
194