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