SimpleBusLT.h revision 12922:a4f51f3405ac
1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20#ifndef __SIMPLEBUSLT_H__ 21#define __SIMPLEBUSLT_H__ 22 23//#include <systemc> 24#include "tlm.h" 25 26#include "tlm_utils/simple_target_socket.h" 27#include "tlm_utils/simple_initiator_socket.h" 28 29template <int NR_OF_INITIATORS, int NR_OF_TARGETS> 30class SimpleBusLT : public sc_core::sc_module 31{ 32public: 33 typedef tlm::tlm_generic_payload transaction_type; 34 typedef tlm::tlm_phase phase_type; 35 typedef tlm::tlm_sync_enum sync_enum_type; 36 typedef tlm_utils::simple_target_socket_tagged<SimpleBusLT> target_socket_type; 37 typedef tlm_utils::simple_initiator_socket_tagged<SimpleBusLT> initiator_socket_type; 38 39public: 40 target_socket_type target_socket[NR_OF_INITIATORS]; 41 initiator_socket_type initiator_socket[NR_OF_TARGETS]; 42 43public: 44 SC_HAS_PROCESS(SimpleBusLT); 45 SimpleBusLT(sc_core::sc_module_name name) : 46 sc_core::sc_module(name) 47 { 48 for (unsigned int i = 0; i < NR_OF_INITIATORS; ++i) { 49 target_socket[i].register_b_transport(this, &SimpleBusLT::initiatorBTransport, i); 50 target_socket[i].register_transport_dbg(this, &SimpleBusLT::transportDebug, i); 51 target_socket[i].register_get_direct_mem_ptr(this, &SimpleBusLT::getDMIPointer, i); 52 } 53 for (unsigned int i = 0; i < NR_OF_TARGETS; ++i) { 54 initiator_socket[i].register_invalidate_direct_mem_ptr(this, &SimpleBusLT::invalidateDMIPointers, i); 55 } 56 } 57 58 // 59 // Dummy decoder: 60 // - address[31-28]: portId 61 // - address[27-0]: masked address 62 // 63 64 unsigned int getPortId(const sc_dt::uint64& address) 65 { 66 return (unsigned int)address >> 28; 67 } 68 69 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