From eba0ab506bfa33e7810163bc255d0af4a14ac8db Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 15 Jun 2018 20:02:54 -0700 Subject: systemc: Add some common test include files. These are "common" in the sense that they're not in a particular test directory, but I think they're only used by one test. Change-Id: I4ffd209d04ed0e5253085810913827b87412b302 Reviewed-on: https://gem5-review.googlesource.com/11272 Reviewed-by: Gabe Black Maintainer: Gabe Black --- src/systemc/tests/include/SimpleBusLT.h | 193 ++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 src/systemc/tests/include/SimpleBusLT.h (limited to 'src/systemc/tests/include/SimpleBusLT.h') diff --git a/src/systemc/tests/include/SimpleBusLT.h b/src/systemc/tests/include/SimpleBusLT.h new file mode 100644 index 000000000..a2e71d866 --- /dev/null +++ b/src/systemc/tests/include/SimpleBusLT.h @@ -0,0 +1,193 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +#ifndef __SIMPLEBUSLT_H__ +#define __SIMPLEBUSLT_H__ + +//#include +#include "tlm.h" + +#include "tlm_utils/simple_target_socket.h" +#include "tlm_utils/simple_initiator_socket.h" + +template +class SimpleBusLT : public sc_core::sc_module +{ +public: + typedef tlm::tlm_generic_payload transaction_type; + typedef tlm::tlm_phase phase_type; + typedef tlm::tlm_sync_enum sync_enum_type; + typedef tlm_utils::simple_target_socket_tagged target_socket_type; + typedef tlm_utils::simple_initiator_socket_tagged initiator_socket_type; + +public: + target_socket_type target_socket[NR_OF_INITIATORS]; + initiator_socket_type initiator_socket[NR_OF_TARGETS]; + +public: + SC_HAS_PROCESS(SimpleBusLT); + SimpleBusLT(sc_core::sc_module_name name) : + sc_core::sc_module(name) + { + for (unsigned int i = 0; i < NR_OF_INITIATORS; ++i) { + target_socket[i].register_b_transport(this, &SimpleBusLT::initiatorBTransport, i); + target_socket[i].register_transport_dbg(this, &SimpleBusLT::transportDebug, i); + target_socket[i].register_get_direct_mem_ptr(this, &SimpleBusLT::getDMIPointer, i); + } + for (unsigned int i = 0; i < NR_OF_TARGETS; ++i) { + initiator_socket[i].register_invalidate_direct_mem_ptr(this, &SimpleBusLT::invalidateDMIPointers, i); + } + } + + // + // Dummy decoder: + // - address[31-28]: portId + // - address[27-0]: masked address + // + + unsigned int getPortId(const sc_dt::uint64& address) + { + return (unsigned int)address >> 28; + } + + sc_dt::uint64 getAddressOffset(unsigned int portId) + { + return portId << 28; + } + + sc_dt::uint64 getAddressMask(unsigned int portId) + { + return 0xfffffff; + } + + unsigned int decode(const sc_dt::uint64& address) + { + // decode address: + // - return initiator socket id + + return getPortId(address); + } + + // + // interface methods + // + + // + // LT protocol + // - forward each call to the target/initiator + // + void initiatorBTransport(int SocketId, + transaction_type& trans, + sc_core::sc_time& t) + { + initiator_socket_type* decodeSocket; + unsigned int portId = decode(trans.get_address()); + assert(portId < NR_OF_TARGETS); + decodeSocket = &initiator_socket[portId]; + trans.set_address(trans.get_address() & getAddressMask(portId)); + + (*decodeSocket)->b_transport(trans, t); + } + + unsigned int transportDebug(int SocketId, + transaction_type& trans) + { + unsigned int portId = decode(trans.get_address()); + assert(portId < NR_OF_TARGETS); + initiator_socket_type* decodeSocket = &initiator_socket[portId]; + trans.set_address( trans.get_address() & getAddressMask(portId) ); + + return (*decodeSocket)->transport_dbg(trans); + } + + bool limitRange(unsigned int portId, sc_dt::uint64& low, sc_dt::uint64& high) + { + sc_dt::uint64 addressOffset = getAddressOffset(portId); + sc_dt::uint64 addressMask = getAddressMask(portId); + + if (low > addressMask) { + // Range does not overlap with addressrange for this target + return false; + } + + low += addressOffset; + if (high > addressMask) { + high = addressOffset + addressMask; + + } else { + high += addressOffset; + } + return true; + } + + bool getDMIPointer(int SocketId, + transaction_type& trans, + tlm::tlm_dmi& dmi_data) + { + sc_dt::uint64 address = trans.get_address(); + + unsigned int portId = decode(address); + assert(portId < NR_OF_TARGETS); + initiator_socket_type* decodeSocket = &initiator_socket[portId]; + sc_dt::uint64 maskedAddress = address & getAddressMask(portId); + + trans.set_address(maskedAddress); + + bool result = + (*decodeSocket)->get_direct_mem_ptr(trans, dmi_data); + + if (result) + { + // Range must contain address + assert(dmi_data.get_start_address() <= maskedAddress); + assert(dmi_data.get_end_address() >= maskedAddress); + } + + // Should always succeed + sc_dt::uint64 start, end; + start = dmi_data.get_start_address(); + end = dmi_data.get_end_address(); + + limitRange(portId, start, end); + + dmi_data.set_start_address(start); + dmi_data.set_end_address(end); + + return result; + } + + void invalidateDMIPointers(int port_id, + sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + // FIXME: probably faster to always invalidate everything? + + if (!limitRange(port_id, start_range, end_range)) { + // Range does not fall into address range of target + return; + } + + for (unsigned int i = 0; i < NR_OF_INITIATORS; ++i) { + (target_socket[i])->invalidate_direct_mem_ptr(start_range, end_range); + } + } + +}; + +#endif -- cgit v1.2.3