| /* |
| * Copyright 2019 Google, Inc. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer; |
| * redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution; |
| * neither the name of the copyright holders nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "arch/arm/fastmodel/amba_to_tlm_bridge.hh" |
| |
| #include "base/amo.hh" |
| #include "params/AmbaToTlmBridge64.hh" |
| #include "pv/FarAtomicService.h" |
| #include "pv_userpayload_extension.h" |
| #include "systemc/tlm_bridge/sc_ext.hh" |
| |
| namespace gem5 |
| { |
| |
| namespace { |
| |
| // According to AbstractMemory::access in mem/abstract_mem.cc, the gem5 memory |
| // model would set original data into the packet buffer. However, the TLM |
| // request with atomic operation doesn't carry a valid buffer because the |
| // resource is all allocated in atomic extension. Preventing from segmentation |
| // fault, we allocate a random buffer and share it with all atomic transactions |
| // since we don't really care about the content of it. |
| uint8_t dummy_buffer[64] = {}; |
| |
| struct FarAtomicOpFunctor : public AtomicOpFunctor |
| { |
| FarAtomicOpFunctor(far_atomic::FarAtomic *_fa) : fa(_fa) {} |
| |
| void |
| operator() (uint8_t *p) override |
| { |
| fa->serviceWasFound(); |
| fa->doAtomicOperation(p); |
| } |
| |
| AtomicOpFunctor * |
| clone() override |
| { |
| return new FarAtomicOpFunctor(*this); |
| } |
| |
| far_atomic::FarAtomic *fa; |
| }; |
| |
| } |
| |
| GEM5_DEPRECATED_NAMESPACE(FastModel, fastmodel); |
| namespace fastmodel |
| { |
| |
| AmbaToTlmBridge64::AmbaToTlmBridge64(const sc_core::sc_module_name& name) : |
| amba_pv::amba_pv_to_tlm_bridge<64>(name), |
| targetProxy("target_proxy"), |
| initiatorProxy("initiator_proxy"), |
| tlmWrapper(initiatorProxy, std::string(name) + ".tlm", -1), |
| ambaWrapper(amba_pv_s, std::string(name) + ".amba", -1) |
| { |
| targetProxy.register_b_transport(this, &AmbaToTlmBridge64::bTransport); |
| targetProxy.register_get_direct_mem_ptr( |
| this, &AmbaToTlmBridge64::getDirectMemPtr); |
| targetProxy.register_transport_dbg(this, &AmbaToTlmBridge64::transportDbg); |
| initiatorProxy.register_invalidate_direct_mem_ptr( |
| this, &AmbaToTlmBridge64::invalidateDirectMemPtr); |
| tlm_m(targetProxy); |
| } |
| |
| Port & |
| AmbaToTlmBridge64::gem5_getPort(const std::string &if_name, int idx) |
| { |
| if (if_name == "tlm") |
| return tlmWrapper; |
| else if (if_name == "amba") |
| return ambaWrapper; |
| else |
| return amba_pv::amba_pv_to_tlm_bridge<64>::gem5_getPort(if_name, idx); |
| } |
| |
| void |
| AmbaToTlmBridge64::bTransport(amba_pv::amba_pv_transaction &trans, |
| sc_core::sc_time &t) |
| { |
| maybeSetupAtomicExtension(trans); |
| return initiatorProxy->b_transport(trans, t); |
| } |
| |
| bool |
| AmbaToTlmBridge64::getDirectMemPtr(amba_pv::amba_pv_transaction &trans, |
| tlm::tlm_dmi &dmi_data) |
| { |
| return initiatorProxy->get_direct_mem_ptr(trans, dmi_data); |
| } |
| |
| unsigned int |
| AmbaToTlmBridge64::transportDbg(amba_pv::amba_pv_transaction &trans) |
| { |
| return initiatorProxy->transport_dbg(trans); |
| } |
| |
| void |
| AmbaToTlmBridge64::invalidateDirectMemPtr(sc_dt::uint64 start_range, |
| sc_dt::uint64 end_range) |
| { |
| targetProxy->invalidate_direct_mem_ptr(start_range, end_range); |
| } |
| |
| void |
| AmbaToTlmBridge64::maybeSetupAtomicExtension( |
| amba_pv::amba_pv_transaction &trans) |
| { |
| Gem5SystemC::AtomicExtension *atomic_ex = nullptr; |
| trans.get_extension(atomic_ex); |
| if (atomic_ex) |
| return; |
| |
| pv_userpayload_extension *user_ex = nullptr; |
| trans.get_extension(user_ex); |
| if (!user_ex) |
| return; |
| |
| pv::UserPayloadBase *upb = user_ex->get_user_payload(); |
| uint32_t appid = upb->get_appID(); |
| if (appid != pv::UserPayloadBase::SERVICE_REQUEST) |
| return; |
| |
| std::pair<void *, std::size_t> u_data = user_ex->get_user_data(); |
| far_atomic::FarAtomic *fa = static_cast<far_atomic::FarAtomic *>( |
| u_data.first); |
| |
| // Correct the request size manually and give it a dummy buffer preventing |
| // from segmentation fault. |
| fatal_if( |
| fa->getDataValueSizeInBytes() > sizeof(dummy_buffer), |
| "atomic operation(%d) is larger than dummy buffer(%d)", |
| fa->getDataValueSizeInBytes(), sizeof(dummy_buffer)); |
| trans.set_data_length(fa->getDataValueSizeInBytes()); |
| trans.set_data_ptr(dummy_buffer); |
| |
| // The return value would store in the extension. We don't need to specify |
| // need_return here. |
| atomic_ex = new Gem5SystemC::AtomicExtension( |
| std::make_shared<FarAtomicOpFunctor>(fa), false); |
| if (trans.has_mm()) |
| trans.set_auto_extension(atomic_ex); |
| else |
| trans.set_extension(atomic_ex); |
| } |
| |
| } // namespace fastmodel |
| |
| fastmodel::AmbaToTlmBridge64 * |
| AmbaToTlmBridge64Params::create() const |
| { |
| return new fastmodel::AmbaToTlmBridge64(name.c_str()); |
| } |
| |
| } // namespace gem5 |