gp.cc revision 13516
113516Sgabeblack@google.com/***************************************************************************** 213516Sgabeblack@google.com 313516Sgabeblack@google.com Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 413516Sgabeblack@google.com more contributor license agreements. See the NOTICE file distributed 513516Sgabeblack@google.com with this work for additional information regarding copyright ownership. 613516Sgabeblack@google.com Accellera licenses this file to you under the Apache License, Version 2.0 713516Sgabeblack@google.com (the "License"); you may not use this file except in compliance with the 813516Sgabeblack@google.com License. You may obtain a copy of the License at 913516Sgabeblack@google.com 1013516Sgabeblack@google.com http://www.apache.org/licenses/LICENSE-2.0 1113516Sgabeblack@google.com 1213516Sgabeblack@google.com Unless required by applicable law or agreed to in writing, software 1313516Sgabeblack@google.com distributed under the License is distributed on an "AS IS" BASIS, 1413516Sgabeblack@google.com WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 1513516Sgabeblack@google.com implied. See the License for the specific language governing 1613516Sgabeblack@google.com permissions and limitations under the License. 1713516Sgabeblack@google.com 1813516Sgabeblack@google.com *****************************************************************************/ 1913516Sgabeblack@google.com 2013516Sgabeblack@google.com#include <cstring> // std::memcpy et.al. 2113516Sgabeblack@google.com#include <map> 2213516Sgabeblack@google.com#include <systemc> 2313516Sgabeblack@google.com#include <tlm> 2413516Sgabeblack@google.com 2513516Sgabeblack@google.comusing sc_core::sc_type_index; 2613516Sgabeblack@google.com 2713516Sgabeblack@google.comnamespace tlm 2813516Sgabeblack@google.com{ 2913516Sgabeblack@google.com 3013516Sgabeblack@google.comtemplate class tlm_array<tlm_extension_base *>; 3113516Sgabeblack@google.com 3213516Sgabeblack@google.com//--------------------------------------------------------------------------- 3313516Sgabeblack@google.com// Classes for the extension mechanism 3413516Sgabeblack@google.com//--------------------------------------------------------------------------- 3513516Sgabeblack@google.com 3613516Sgabeblack@google.comnamespace 3713516Sgabeblack@google.com{ 3813516Sgabeblack@google.com 3913516Sgabeblack@google.comclass tlm_extension_registry 4013516Sgabeblack@google.com{ 4113516Sgabeblack@google.com typedef unsigned int key_type; 4213516Sgabeblack@google.com typedef std::map<sc_core::sc_type_index, key_type> type_map; 4313516Sgabeblack@google.com public: 4413516Sgabeblack@google.com static tlm_extension_registry & 4513516Sgabeblack@google.com instance() 4613516Sgabeblack@google.com { 4713516Sgabeblack@google.com if (!instance_) { 4813516Sgabeblack@google.com // Don't cleanup registry. 4913516Sgabeblack@google.com instance_ = new tlm_extension_registry(); 5013516Sgabeblack@google.com } 5113516Sgabeblack@google.com return *instance_; 5213516Sgabeblack@google.com } 5313516Sgabeblack@google.com 5413516Sgabeblack@google.com unsigned int 5513516Sgabeblack@google.com register_extension(sc_type_index type) 5613516Sgabeblack@google.com { 5713516Sgabeblack@google.com type_map::const_iterator it = ids_.find(type); 5813516Sgabeblack@google.com 5913516Sgabeblack@google.com if (it == ids_.end()) { 6013516Sgabeblack@google.com // New extension - generate/store ID. 6113516Sgabeblack@google.com type_map::value_type v(type, static_cast<key_type>(ids_.size())); 6213516Sgabeblack@google.com ids_.insert(v); 6313516Sgabeblack@google.com return v.second; 6413516Sgabeblack@google.com } 6513516Sgabeblack@google.com return it->second; 6613516Sgabeblack@google.com } 6713516Sgabeblack@google.com 6813516Sgabeblack@google.com static unsigned int 6913516Sgabeblack@google.com max_num_extensions() 7013516Sgabeblack@google.com { 7113516Sgabeblack@google.com return (instance_) ? instance().ids_.size() : 0; 7213516Sgabeblack@google.com } 7313516Sgabeblack@google.com 7413516Sgabeblack@google.com private: 7513516Sgabeblack@google.com static tlm_extension_registry *instance_; 7613516Sgabeblack@google.com type_map ids_; 7713516Sgabeblack@google.com tlm_extension_registry() {} 7813516Sgabeblack@google.com 7913516Sgabeblack@google.com}; 8013516Sgabeblack@google.com 8113516Sgabeblack@google.comtlm_extension_registry *tlm_extension_registry::instance_ = NULL; 8213516Sgabeblack@google.com 8313516Sgabeblack@google.com} // anonymous namespace 8413516Sgabeblack@google.com 8513516Sgabeblack@google.comunsigned int 8613516Sgabeblack@google.commax_num_extensions() 8713516Sgabeblack@google.com{ 8813516Sgabeblack@google.com return tlm_extension_registry::max_num_extensions(); 8913516Sgabeblack@google.com} 9013516Sgabeblack@google.com 9113516Sgabeblack@google.comunsigned int 9213516Sgabeblack@google.comtlm_extension_base::register_extension(const std::type_info &type) 9313516Sgabeblack@google.com{ 9413516Sgabeblack@google.com return tlm_extension_registry::instance().register_extension(type); 9513516Sgabeblack@google.com} 9613516Sgabeblack@google.com 9713516Sgabeblack@google.com//--------------------------------------------------------------------------- 9813516Sgabeblack@google.com// The generic payload class: 9913516Sgabeblack@google.com//--------------------------------------------------------------------------- 10013516Sgabeblack@google.com 10113516Sgabeblack@google.comtlm_generic_payload::tlm_generic_payload() : m_address(0), 10213516Sgabeblack@google.com m_command(TLM_IGNORE_COMMAND), m_data(0), m_length(0), 10313516Sgabeblack@google.com m_response_status(TLM_INCOMPLETE_RESPONSE), m_dmi(false), m_byte_enable(0), 10413516Sgabeblack@google.com m_byte_enable_length(0), m_streaming_width(0), 10513516Sgabeblack@google.com m_gp_option(TLM_MIN_PAYLOAD), m_extensions(max_num_extensions()), m_mm(0), 10613516Sgabeblack@google.com m_ref_count(0) 10713516Sgabeblack@google.com{} 10813516Sgabeblack@google.com 10913516Sgabeblack@google.comtlm_generic_payload::tlm_generic_payload(tlm_mm_interface *mm): m_address(0), 11013516Sgabeblack@google.com m_command(TLM_IGNORE_COMMAND), m_data(0), m_length(0), 11113516Sgabeblack@google.com m_response_status(TLM_INCOMPLETE_RESPONSE), m_dmi(false), m_byte_enable(0), 11213516Sgabeblack@google.com m_byte_enable_length(0), m_streaming_width(0), 11313516Sgabeblack@google.com m_gp_option(TLM_MIN_PAYLOAD), m_extensions(max_num_extensions()), m_mm(mm), 11413516Sgabeblack@google.com m_ref_count(0) 11513516Sgabeblack@google.com{} 11613516Sgabeblack@google.com 11713516Sgabeblack@google.comvoid 11813516Sgabeblack@google.comtlm_generic_payload::reset() 11913516Sgabeblack@google.com{ 12013516Sgabeblack@google.com // Should the other members be reset too? 12113516Sgabeblack@google.com m_gp_option = TLM_MIN_PAYLOAD; 12213516Sgabeblack@google.com m_extensions.free_entire_cache(); 12313516Sgabeblack@google.com}; 12413516Sgabeblack@google.com 12513516Sgabeblack@google.com// Non-virtual deep-copying of the object. 12613516Sgabeblack@google.comvoid 12713516Sgabeblack@google.comtlm_generic_payload::deep_copy_from(const tlm_generic_payload &other) 12813516Sgabeblack@google.com{ 12913516Sgabeblack@google.com m_command = other.get_command(); 13013516Sgabeblack@google.com m_address = other.get_address(); 13113516Sgabeblack@google.com m_length = other.get_data_length(); 13213516Sgabeblack@google.com m_response_status = other.get_response_status(); 13313516Sgabeblack@google.com m_byte_enable_length = other.get_byte_enable_length(); 13413516Sgabeblack@google.com m_streaming_width = other.get_streaming_width(); 13513516Sgabeblack@google.com m_gp_option = other.get_gp_option(); 13613516Sgabeblack@google.com m_dmi = other.is_dmi_allowed(); 13713516Sgabeblack@google.com 13813516Sgabeblack@google.com // Deep copy data. 13913516Sgabeblack@google.com // There must be enough space in the target transaction! 14013516Sgabeblack@google.com if (m_data && other.m_data) { 14113516Sgabeblack@google.com std::memcpy(m_data, other.m_data, m_length); 14213516Sgabeblack@google.com } 14313516Sgabeblack@google.com // Deep copy byte enables. 14413516Sgabeblack@google.com // There must be enough space in the target transaction! 14513516Sgabeblack@google.com if (m_byte_enable && other.m_byte_enable) { 14613516Sgabeblack@google.com std::memcpy(m_byte_enable, other.m_byte_enable, m_byte_enable_length); 14713516Sgabeblack@google.com } 14813516Sgabeblack@google.com // Deep copy extensions (sticky and non-sticky). 14913516Sgabeblack@google.com if (m_extensions.size() < other.m_extensions.size()) { 15013516Sgabeblack@google.com m_extensions.expand(other.m_extensions.size()); 15113516Sgabeblack@google.com } 15213516Sgabeblack@google.com for (unsigned int i = 0; i < other.m_extensions.size(); i++) { 15313516Sgabeblack@google.com if (other.m_extensions[i]) { 15413516Sgabeblack@google.com // Original has extension i. 15513516Sgabeblack@google.com if (!m_extensions[i]) { 15613516Sgabeblack@google.com // We don't: clone. 15713516Sgabeblack@google.com tlm_extension_base *ext = other.m_extensions[i]->clone(); 15813516Sgabeblack@google.com if (ext) { // Extension may not be clonable. 15913516Sgabeblack@google.com if (has_mm()) { 16013516Sgabeblack@google.com // mm can take care of removing cloned extensions. 16113516Sgabeblack@google.com set_auto_extension(i, ext); 16213516Sgabeblack@google.com } else { 16313516Sgabeblack@google.com // no mm, user will call free_all_extensions(). 16413516Sgabeblack@google.com set_extension(i, ext); 16513516Sgabeblack@google.com } 16613516Sgabeblack@google.com } 16713516Sgabeblack@google.com } else { 16813516Sgabeblack@google.com // We already have such extension. Copy original over it. 16913516Sgabeblack@google.com m_extensions[i]->copy_from(*other.m_extensions[i]); 17013516Sgabeblack@google.com } 17113516Sgabeblack@google.com } 17213516Sgabeblack@google.com } 17313516Sgabeblack@google.com} 17413516Sgabeblack@google.com 17513516Sgabeblack@google.com// To update the state of the original generic payload from a deep copy. 17613516Sgabeblack@google.com// Assumes that "other" was created from the original by calling 17713516Sgabeblack@google.com// deep_copy_from. Argument use_byte_enable_on_read determines whether to use 17813516Sgabeblack@google.com// or ignores byte enables when copying back the data array on a read command. 17913516Sgabeblack@google.com 18013516Sgabeblack@google.comvoid 18113516Sgabeblack@google.comtlm_generic_payload::update_original_from( 18213516Sgabeblack@google.com const tlm_generic_payload &other, bool use_byte_enable_on_read) 18313516Sgabeblack@google.com{ 18413516Sgabeblack@google.com // Copy back extensions that are present on the original. 18513516Sgabeblack@google.com update_extensions_from(other); 18613516Sgabeblack@google.com 18713516Sgabeblack@google.com // Copy back the response status and DMI hint attributes. 18813516Sgabeblack@google.com m_response_status = other.get_response_status(); 18913516Sgabeblack@google.com m_dmi = other.is_dmi_allowed(); 19013516Sgabeblack@google.com 19113516Sgabeblack@google.com // Copy back the data array for a read command only deep_copy_from allowed 19213516Sgabeblack@google.com // null pointers, and so will we. 19313516Sgabeblack@google.com // We assume the arrays are the same size. 19413516Sgabeblack@google.com // We test for equal pointers in case the original and the copy share the 19513516Sgabeblack@google.com // same array. 19613516Sgabeblack@google.com 19713516Sgabeblack@google.com if (is_read() && m_data && other.m_data && m_data != other.m_data) { 19813516Sgabeblack@google.com if (m_byte_enable && use_byte_enable_on_read) { 19913516Sgabeblack@google.com if (m_byte_enable_length == 8 && m_length % 8 == 0) { 20013516Sgabeblack@google.com // Optimized implementation copies 64-bit words by masking. 20113516Sgabeblack@google.com for (unsigned int i = 0; i < m_length; i += 8) { 20213516Sgabeblack@google.com typedef sc_dt::uint64 *u; 20313516Sgabeblack@google.com *reinterpret_cast<u>(&m_data[i]) &= 20413516Sgabeblack@google.com ~*reinterpret_cast<u>(m_byte_enable); 20513516Sgabeblack@google.com *reinterpret_cast<u>(&m_data[i]) |= 20613516Sgabeblack@google.com *reinterpret_cast<u>(&other.m_data[i]) & 20713516Sgabeblack@google.com *reinterpret_cast<u>(m_byte_enable); 20813516Sgabeblack@google.com } 20913516Sgabeblack@google.com } else if (m_byte_enable_length == 4 && m_length % 4 == 0) { 21013516Sgabeblack@google.com // Optimized implementation copies 32-bit words by masking. 21113516Sgabeblack@google.com for (unsigned int i = 0; i < m_length; i += 4) { 21213516Sgabeblack@google.com typedef unsigned int *u; 21313516Sgabeblack@google.com *reinterpret_cast<u>(&m_data[i]) &= 21413516Sgabeblack@google.com ~*reinterpret_cast<u>(m_byte_enable); 21513516Sgabeblack@google.com *reinterpret_cast<u>(&m_data[i]) |= 21613516Sgabeblack@google.com *reinterpret_cast<u>(&other.m_data[i]) & 21713516Sgabeblack@google.com *reinterpret_cast<u>(m_byte_enable); 21813516Sgabeblack@google.com } 21913516Sgabeblack@google.com } else { 22013516Sgabeblack@google.com // Unoptimized implementation. 22113516Sgabeblack@google.com for (unsigned int i = 0; i < m_length; i++) { 22213516Sgabeblack@google.com if (m_byte_enable[i % m_byte_enable_length]) 22313516Sgabeblack@google.com m_data[i] = other.m_data[i]; 22413516Sgabeblack@google.com } 22513516Sgabeblack@google.com } 22613516Sgabeblack@google.com } else { 22713516Sgabeblack@google.com std::memcpy(m_data, other.m_data, m_length); 22813516Sgabeblack@google.com } 22913516Sgabeblack@google.com } 23013516Sgabeblack@google.com} 23113516Sgabeblack@google.com 23213516Sgabeblack@google.comvoid 23313516Sgabeblack@google.comtlm_generic_payload::update_extensions_from(const tlm_generic_payload &other) 23413516Sgabeblack@google.com{ 23513516Sgabeblack@google.com // Deep copy extensions that are already present. 23613516Sgabeblack@google.com sc_assert(m_extensions.size() <= other.m_extensions.size()); 23713516Sgabeblack@google.com for (unsigned int i = 0; i < m_extensions.size(); i++) { 23813516Sgabeblack@google.com if (other.m_extensions[i]) { 23913516Sgabeblack@google.com // Original has extension i. 24013516Sgabeblack@google.com if (m_extensions[i]) { 24113516Sgabeblack@google.com // We have it too. Copy. 24213516Sgabeblack@google.com m_extensions[i]->copy_from(*other.m_extensions[i]); 24313516Sgabeblack@google.com } 24413516Sgabeblack@google.com } 24513516Sgabeblack@google.com } 24613516Sgabeblack@google.com} 24713516Sgabeblack@google.com 24813516Sgabeblack@google.com// Free all extensions. Useful when reusing a cloned transaction that doesn't 24913516Sgabeblack@google.com// have memory manager. Normal and sticky extensions are freed and extension 25013516Sgabeblack@google.com// array cleared. 25113516Sgabeblack@google.comvoid 25213516Sgabeblack@google.comtlm_generic_payload::free_all_extensions() 25313516Sgabeblack@google.com{ 25413516Sgabeblack@google.com m_extensions.free_entire_cache(); 25513516Sgabeblack@google.com for (unsigned int i = 0; i < m_extensions.size(); i++) { 25613516Sgabeblack@google.com if (m_extensions[i]) { 25713516Sgabeblack@google.com m_extensions[i]->free(); 25813516Sgabeblack@google.com m_extensions[i] = 0; 25913516Sgabeblack@google.com } 26013516Sgabeblack@google.com } 26113516Sgabeblack@google.com} 26213516Sgabeblack@google.com 26313516Sgabeblack@google.comtlm_generic_payload::~tlm_generic_payload() 26413516Sgabeblack@google.com{ 26513516Sgabeblack@google.com for (unsigned int i = 0; i < m_extensions.size(); i++) { 26613516Sgabeblack@google.com if (m_extensions[i]) 26713516Sgabeblack@google.com m_extensions[i]->free(); 26813516Sgabeblack@google.com } 26913516Sgabeblack@google.com} 27013516Sgabeblack@google.com 27113516Sgabeblack@google.com//---------------- 27213516Sgabeblack@google.com// API (including setters & getters) 27313516Sgabeblack@google.com//--------------- 27413516Sgabeblack@google.com 27513516Sgabeblack@google.comstd::string 27613516Sgabeblack@google.comtlm_generic_payload::get_response_string() const 27713516Sgabeblack@google.com{ 27813516Sgabeblack@google.com switch (m_response_status) { 27913516Sgabeblack@google.com case TLM_OK_RESPONSE: 28013516Sgabeblack@google.com return "TLM_OK_RESPONSE"; 28113516Sgabeblack@google.com case TLM_INCOMPLETE_RESPONSE: 28213516Sgabeblack@google.com return "TLM_INCOMPLETE_RESPONSE"; 28313516Sgabeblack@google.com case TLM_GENERIC_ERROR_RESPONSE: 28413516Sgabeblack@google.com return "TLM_GENERIC_ERROR_RESPONSE"; 28513516Sgabeblack@google.com case TLM_ADDRESS_ERROR_RESPONSE: 28613516Sgabeblack@google.com return "TLM_ADDRESS_ERROR_RESPONSE"; 28713516Sgabeblack@google.com case TLM_COMMAND_ERROR_RESPONSE: 28813516Sgabeblack@google.com return "TLM_COMMAND_ERROR_RESPONSE"; 28913516Sgabeblack@google.com case TLM_BURST_ERROR_RESPONSE: 29013516Sgabeblack@google.com return "TLM_BURST_ERROR_RESPONSE"; 29113516Sgabeblack@google.com case TLM_BYTE_ENABLE_ERROR_RESPONSE: 29213516Sgabeblack@google.com return "TLM_BYTE_ENABLE_ERROR_RESPONSE"; 29313516Sgabeblack@google.com } 29413516Sgabeblack@google.com return "TLM_UNKNOWN_RESPONSE"; 29513516Sgabeblack@google.com} 29613516Sgabeblack@google.com 29713516Sgabeblack@google.com/* --------------------------------------------------------------------- */ 29813516Sgabeblack@google.com/* Dynamic extension mechanism: */ 29913516Sgabeblack@google.com/* --------------------------------------------------------------------- */ 30013516Sgabeblack@google.com 30113516Sgabeblack@google.comtlm_extension_base * 30213516Sgabeblack@google.comtlm_generic_payload::set_extension(unsigned int index, tlm_extension_base *ext) 30313516Sgabeblack@google.com{ 30413516Sgabeblack@google.com sc_assert(index < m_extensions.size()); 30513516Sgabeblack@google.com tlm_extension_base *tmp = m_extensions[index]; 30613516Sgabeblack@google.com m_extensions[index] = ext; 30713516Sgabeblack@google.com return tmp; 30813516Sgabeblack@google.com} 30913516Sgabeblack@google.com 31013516Sgabeblack@google.comtlm_extension_base * 31113516Sgabeblack@google.comtlm_generic_payload::set_auto_extension( 31213516Sgabeblack@google.com unsigned int index, tlm_extension_base *ext) 31313516Sgabeblack@google.com{ 31413516Sgabeblack@google.com sc_assert(index < m_extensions.size()); 31513516Sgabeblack@google.com tlm_extension_base *tmp = m_extensions[index]; 31613516Sgabeblack@google.com m_extensions[index] = ext; 31713516Sgabeblack@google.com if (!tmp) 31813516Sgabeblack@google.com m_extensions.insert_in_cache(&m_extensions[index]); 31913516Sgabeblack@google.com sc_assert(m_mm != 0); 32013516Sgabeblack@google.com return tmp; 32113516Sgabeblack@google.com} 32213516Sgabeblack@google.com 32313516Sgabeblack@google.comtlm_extension_base * 32413516Sgabeblack@google.comtlm_generic_payload::get_extension(unsigned int index) const 32513516Sgabeblack@google.com{ 32613516Sgabeblack@google.com sc_assert(index < m_extensions.size()); 32713516Sgabeblack@google.com return m_extensions[index]; 32813516Sgabeblack@google.com} 32913516Sgabeblack@google.com 33013516Sgabeblack@google.comvoid 33113516Sgabeblack@google.comtlm_generic_payload::clear_extension(unsigned int index) 33213516Sgabeblack@google.com{ 33313516Sgabeblack@google.com sc_assert(index < m_extensions.size()); 33413516Sgabeblack@google.com m_extensions[index] = static_cast<tlm_extension_base *>(0); 33513516Sgabeblack@google.com} 33613516Sgabeblack@google.com 33713516Sgabeblack@google.comvoid 33813516Sgabeblack@google.comtlm_generic_payload::release_extension(unsigned int index) 33913516Sgabeblack@google.com{ 34013516Sgabeblack@google.com sc_assert(index < m_extensions.size()); 34113516Sgabeblack@google.com if (m_mm) { 34213516Sgabeblack@google.com m_extensions.insert_in_cache(&m_extensions[index]); 34313516Sgabeblack@google.com } else { 34413516Sgabeblack@google.com m_extensions[index]->free(); 34513516Sgabeblack@google.com m_extensions[index] = static_cast<tlm_extension_base *>(nullptr); 34613516Sgabeblack@google.com } 34713516Sgabeblack@google.com} 34813516Sgabeblack@google.com 34913516Sgabeblack@google.comvoid 35013516Sgabeblack@google.comtlm_generic_payload::resize_extensions() 35113516Sgabeblack@google.com{ 35213516Sgabeblack@google.com m_extensions.expand(max_num_extensions()); 35313516Sgabeblack@google.com} 35413516Sgabeblack@google.com 35513516Sgabeblack@google.com} // namespace tlm 356