112027Sjungma@eit.uni-kl.de/***************************************************************************** 212027Sjungma@eit.uni-kl.de 312027Sjungma@eit.uni-kl.de Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 412027Sjungma@eit.uni-kl.de more contributor license agreements. See the NOTICE file distributed 512027Sjungma@eit.uni-kl.de with this work for additional information regarding copyright ownership. 612027Sjungma@eit.uni-kl.de Accellera licenses this file to you under the Apache License, Version 2.0 712027Sjungma@eit.uni-kl.de (the "License"); you may not use this file except in compliance with the 812027Sjungma@eit.uni-kl.de License. You may obtain a copy of the License at 912027Sjungma@eit.uni-kl.de 1012027Sjungma@eit.uni-kl.de http://www.apache.org/licenses/LICENSE-2.0 1112027Sjungma@eit.uni-kl.de 1212027Sjungma@eit.uni-kl.de Unless required by applicable law or agreed to in writing, software 1312027Sjungma@eit.uni-kl.de distributed under the License is distributed on an "AS IS" BASIS, 1412027Sjungma@eit.uni-kl.de WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 1512027Sjungma@eit.uni-kl.de implied. See the License for the specific language governing 1612027Sjungma@eit.uni-kl.de permissions and limitations under the License. 1712027Sjungma@eit.uni-kl.de 1812027Sjungma@eit.uni-kl.de *****************************************************************************/ 1912027Sjungma@eit.uni-kl.de 2012027Sjungma@eit.uni-kl.de/* 2112027Sjungma@eit.uni-kl.deInstance specific extensions, are extension that only a single instance of a module 2212027Sjungma@eit.uni-kl.demay access. They are invisible to all other modules; they are private to this 2312027Sjungma@eit.uni-kl.deinstance so to speak. 2412027Sjungma@eit.uni-kl.de 2512027Sjungma@eit.uni-kl.deAs they are only of value to a certain instance, this instance knows very well 2612027Sjungma@eit.uni-kl.dewhen it needs them and when it does not need them any longer (usually when 2712027Sjungma@eit.uni-kl.dea transaction passes through a module for the last time). 2812027Sjungma@eit.uni-kl.deIt does not have to care if anyone else in the system may still have a 2912027Sjungma@eit.uni-kl.dereference to the transaction as this one is not able to access the extension 3012027Sjungma@eit.uni-kl.deanyway. 3112027Sjungma@eit.uni-kl.deTherefore the instance is obliged to call set_extension when it wants to add a 3212027Sjungma@eit.uni-kl.deprivate extension and clear_extension when it does not need it any more. 3312027Sjungma@eit.uni-kl.de 3412027Sjungma@eit.uni-kl.deTo get access to an instance specifc extension the module must own a so called 3512027Sjungma@eit.uni-kl.deinstance_specific_extension_accessor that provides the exclusive access rights. 3612027Sjungma@eit.uni-kl.deAssuming the instance_specific_extension_accessor of a given module is called m_accessor 3712027Sjungma@eit.uni-kl.deand the transaction of which the private extension is about to be accessed 3812027Sjungma@eit.uni-kl.deis called txn, then the calls have to be 3912027Sjungma@eit.uni-kl.de 4012027Sjungma@eit.uni-kl.dem_accessor(txn).set_extension(...); 4112027Sjungma@eit.uni-kl.deor 4212027Sjungma@eit.uni-kl.dem_accessor(txn).clear_extension(...); 4312027Sjungma@eit.uni-kl.de 4412027Sjungma@eit.uni-kl.deThe owner of the private extension is responsible to allocate/deallocate 4512027Sjungma@eit.uni-kl.dethe extension before/after setting/clearing the extension. 4612027Sjungma@eit.uni-kl.de*/ 4712027Sjungma@eit.uni-kl.de 4812027Sjungma@eit.uni-kl.de#ifndef __INSTANCE_SPECIFIC_EXTENSIONS_H__ 4912027Sjungma@eit.uni-kl.de#define __INSTANCE_SPECIFIC_EXTENSIONS_H__ 5012027Sjungma@eit.uni-kl.de 5112027Sjungma@eit.uni-kl.de#include <tlm> 5212027Sjungma@eit.uni-kl.de 5312027Sjungma@eit.uni-kl.denamespace tlm_utils { 5412027Sjungma@eit.uni-kl.de 5512027Sjungma@eit.uni-kl.de//Helper to do the numbering of private extension accessors 5612027Sjungma@eit.uni-kl.deinline unsigned int max_num_ispex_accessors(bool increment=false) 5712027Sjungma@eit.uni-kl.de{ 5812027Sjungma@eit.uni-kl.de static unsigned int max_num = 0; 5912027Sjungma@eit.uni-kl.de if (increment) ++max_num; 6012027Sjungma@eit.uni-kl.de return max_num; 6112027Sjungma@eit.uni-kl.de} 6212027Sjungma@eit.uni-kl.de 6312027Sjungma@eit.uni-kl.de//Helper to do the index generation for private extensions 6412027Sjungma@eit.uni-kl.deinline unsigned int max_num_ispex(bool increment=false) 6512027Sjungma@eit.uni-kl.de{ 6612027Sjungma@eit.uni-kl.de static unsigned int max_num = 0; 6712027Sjungma@eit.uni-kl.de if (increment) ++max_num; 6812027Sjungma@eit.uni-kl.de return max_num; 6912027Sjungma@eit.uni-kl.de} 7012027Sjungma@eit.uni-kl.de 7112027Sjungma@eit.uni-kl.de//The private extension base. Similar to normal extension base, but without clone and free 7212027Sjungma@eit.uni-kl.declass ispex_base 7312027Sjungma@eit.uni-kl.de{ 7412027Sjungma@eit.uni-kl.depublic: 7512027Sjungma@eit.uni-kl.de virtual ~ispex_base() {} 7612027Sjungma@eit.uni-kl.deprotected: 7712027Sjungma@eit.uni-kl.de static unsigned int register_private_extension() 7812027Sjungma@eit.uni-kl.de { 7912027Sjungma@eit.uni-kl.de return (max_num_ispex(true) - 1); 8012027Sjungma@eit.uni-kl.de }; 8112027Sjungma@eit.uni-kl.de}; 8212027Sjungma@eit.uni-kl.de 8312027Sjungma@eit.uni-kl.de//The templated private extension. Similar to normal extension 8412027Sjungma@eit.uni-kl.detemplate <typename T> 8512027Sjungma@eit.uni-kl.declass 8612027Sjungma@eit.uni-kl.deinstance_specific_extension : public ispex_base{ 8712027Sjungma@eit.uni-kl.depublic: 8812027Sjungma@eit.uni-kl.de virtual ~instance_specific_extension() {} 8912027Sjungma@eit.uni-kl.de const static unsigned int priv_id; 9012027Sjungma@eit.uni-kl.de}; 9112027Sjungma@eit.uni-kl.de 9212027Sjungma@eit.uni-kl.detemplate <typename T> 9312027Sjungma@eit.uni-kl.deconst 9412027Sjungma@eit.uni-kl.deunsigned int instance_specific_extension<T>::priv_id = ispex_base::register_private_extension(); 9512027Sjungma@eit.uni-kl.de 9612027Sjungma@eit.uni-kl.de 9712027Sjungma@eit.uni-kl.de//this thing is basically a snippet of the generic_payload 9812027Sjungma@eit.uni-kl.de// it contains all the extension specific code (the extension API so to speak) 9912027Sjungma@eit.uni-kl.de// the differences are: 10012027Sjungma@eit.uni-kl.de// - it calls back to its owner whenever a real (==non-NULL) extension gets set for the first time 10112027Sjungma@eit.uni-kl.de// - it calls back to its owner whenever a living (==non-NULL) extension gets cleared 10212027Sjungma@eit.uni-kl.detemplate<typename U> 10312027Sjungma@eit.uni-kl.declass instance_specific_extensions_per_accessor{ 10412027Sjungma@eit.uni-kl.depublic: 10512027Sjungma@eit.uni-kl.de 10612027Sjungma@eit.uni-kl.de typedef void (U::*cb)(); 10712027Sjungma@eit.uni-kl.de 10812027Sjungma@eit.uni-kl.de instance_specific_extensions_per_accessor(U* container, cb inc, cb dec): m_container(container), m_inc(inc), m_dec(dec){ 10912027Sjungma@eit.uni-kl.de } 11012027Sjungma@eit.uni-kl.de 11112027Sjungma@eit.uni-kl.de template <typename T> T* set_extension(T* ext) 11212027Sjungma@eit.uni-kl.de { 11312027Sjungma@eit.uni-kl.de resize_extensions(); 11412027Sjungma@eit.uni-kl.de T* tmp = static_cast<T*>(m_extensions[T::priv_id]); 11512027Sjungma@eit.uni-kl.de m_extensions[T::priv_id] = static_cast<ispex_base*>(ext); 11612027Sjungma@eit.uni-kl.de if (!tmp && ext) (m_container->*m_inc)(); 11712027Sjungma@eit.uni-kl.de return tmp; 11812027Sjungma@eit.uni-kl.de } 11912027Sjungma@eit.uni-kl.de // non-templatized version with manual index: 12012027Sjungma@eit.uni-kl.de ispex_base* set_extension(unsigned int index, 12112027Sjungma@eit.uni-kl.de ispex_base* ext) 12212027Sjungma@eit.uni-kl.de { 12312027Sjungma@eit.uni-kl.de resize_extensions(); 12412027Sjungma@eit.uni-kl.de ispex_base* tmp = m_extensions[index]; 12512027Sjungma@eit.uni-kl.de m_extensions[index] = ext; 12612027Sjungma@eit.uni-kl.de if (!tmp && ext) (m_container->*m_inc)(); 12712027Sjungma@eit.uni-kl.de return tmp; 12812027Sjungma@eit.uni-kl.de } 12912027Sjungma@eit.uni-kl.de 13012027Sjungma@eit.uni-kl.de // Check for an extension, ext will point to 0 if not present 13112027Sjungma@eit.uni-kl.de template <typename T> void get_extension(T*& ext) const 13212027Sjungma@eit.uni-kl.de { 13312027Sjungma@eit.uni-kl.de ext = static_cast<T*>(m_extensions[T::priv_id]); 13412027Sjungma@eit.uni-kl.de } 13512027Sjungma@eit.uni-kl.de // Non-templatized version: 13612027Sjungma@eit.uni-kl.de ispex_base* get_extension(unsigned int index) const 13712027Sjungma@eit.uni-kl.de { 13812027Sjungma@eit.uni-kl.de return m_extensions[index]; 13912027Sjungma@eit.uni-kl.de } 14012027Sjungma@eit.uni-kl.de 14112027Sjungma@eit.uni-kl.de // Clear extension, the argument is needed to find the right index: 14212027Sjungma@eit.uni-kl.de template <typename T> void clear_extension(const T* ext) 14312027Sjungma@eit.uni-kl.de { 14412027Sjungma@eit.uni-kl.de resize_extensions(); 14512027Sjungma@eit.uni-kl.de if (m_extensions[T::priv_id]) (m_container->*m_dec)(); 14612027Sjungma@eit.uni-kl.de m_extensions[T::priv_id] = static_cast<ispex_base*>(0); 14712027Sjungma@eit.uni-kl.de } 14812027Sjungma@eit.uni-kl.de // Non-templatized version with manual index 14912027Sjungma@eit.uni-kl.de void clear_extension(unsigned int index) 15012027Sjungma@eit.uni-kl.de { 15112027Sjungma@eit.uni-kl.de if (index < m_extensions.size()) 15212027Sjungma@eit.uni-kl.de { 15312027Sjungma@eit.uni-kl.de if (m_extensions[index]) (m_container->*m_dec)(); 15412027Sjungma@eit.uni-kl.de m_extensions[index] = static_cast<ispex_base*>(0); 15512027Sjungma@eit.uni-kl.de } 15612027Sjungma@eit.uni-kl.de } 15712027Sjungma@eit.uni-kl.de 15812027Sjungma@eit.uni-kl.de // Make sure the extension array is large enough. Can be called once by 15912027Sjungma@eit.uni-kl.de // an initiator module (before issuing the first transaction) to make 16012027Sjungma@eit.uni-kl.de // sure that the extension array is of correct size. This is only needed 16112027Sjungma@eit.uni-kl.de // if the initiator cannot guarantee that the generic payload object is 16212027Sjungma@eit.uni-kl.de // allocated after C++ static construction time. 16312027Sjungma@eit.uni-kl.de void resize_extensions() 16412027Sjungma@eit.uni-kl.de { 16512027Sjungma@eit.uni-kl.de m_extensions.expand(max_num_ispex()); 16612027Sjungma@eit.uni-kl.de } 16712027Sjungma@eit.uni-kl.de 16812027Sjungma@eit.uni-kl.deprivate: 16912027Sjungma@eit.uni-kl.de tlm::tlm_array<ispex_base*> m_extensions; 17012027Sjungma@eit.uni-kl.de U* m_container; 17112027Sjungma@eit.uni-kl.de cb m_inc, m_dec; 17212027Sjungma@eit.uni-kl.de 17312027Sjungma@eit.uni-kl.de}; 17412027Sjungma@eit.uni-kl.de 17512027Sjungma@eit.uni-kl.declass instance_specific_extension_container; 17612027Sjungma@eit.uni-kl.de 17712027Sjungma@eit.uni-kl.de 17812027Sjungma@eit.uni-kl.de//the pool for the container, plain as can be 17912027Sjungma@eit.uni-kl.declass instance_specific_extension_container_pool{ 18012027Sjungma@eit.uni-kl.de friend class instance_specific_extension_carrier; 18112027Sjungma@eit.uni-kl.de friend class instance_specific_extension_container; 18212027Sjungma@eit.uni-kl.de instance_specific_extension_container_pool() : unused(NULL){} 18312027Sjungma@eit.uni-kl.de inline ~instance_specific_extension_container_pool(); 18412027Sjungma@eit.uni-kl.de inline static instance_specific_extension_container_pool& get_ispexcont_pool(){ static instance_specific_extension_container_pool tmp; return tmp;} 18512027Sjungma@eit.uni-kl.de inline instance_specific_extension_container* create(); 18612027Sjungma@eit.uni-kl.de inline void free(instance_specific_extension_container*); 18712027Sjungma@eit.uni-kl.de 18812027Sjungma@eit.uni-kl.de instance_specific_extension_container* unused; 18912027Sjungma@eit.uni-kl.de}; 19012027Sjungma@eit.uni-kl.de 19112027Sjungma@eit.uni-kl.declass instance_specific_extension_carrier; 19212027Sjungma@eit.uni-kl.de 19312027Sjungma@eit.uni-kl.de//this thing contains the vector of extensions per accessor 19412027Sjungma@eit.uni-kl.de//which can be really large so this one should be pool allocated 19512027Sjungma@eit.uni-kl.de// therefore it keeps a use_count of itself to automatically free itself 19612027Sjungma@eit.uni-kl.de// - to this end it provides callbacks to the extensions per accessor 19712027Sjungma@eit.uni-kl.de// to increment and decrement the use_count 19812027Sjungma@eit.uni-kl.declass instance_specific_extension_container{ 19912027Sjungma@eit.uni-kl.de friend class instance_specific_extension_container_pool; 20012027Sjungma@eit.uni-kl.de friend class instance_specific_extension_accessor; 20112027Sjungma@eit.uni-kl.de friend class instance_specific_extension_carrier; 20212027Sjungma@eit.uni-kl.de 20312027Sjungma@eit.uni-kl.de instance_specific_extension_container(): use_count(0), next(NULL){resize();} 20412027Sjungma@eit.uni-kl.de 20512027Sjungma@eit.uni-kl.de void resize(){ 20612027Sjungma@eit.uni-kl.de m_ispex_per_accessor.resize(max_num_ispex_accessors()); 20712027Sjungma@eit.uni-kl.de for (unsigned int i=0; i<m_ispex_per_accessor.size(); i++) { 20812027Sjungma@eit.uni-kl.de m_ispex_per_accessor[i]=new instance_specific_extensions_per_accessor<instance_specific_extension_container>(this, 20912027Sjungma@eit.uni-kl.de &instance_specific_extension_container::inc_use_count, 21012027Sjungma@eit.uni-kl.de &instance_specific_extension_container::dec_use_count 21112027Sjungma@eit.uni-kl.de ); 21212027Sjungma@eit.uni-kl.de m_ispex_per_accessor[i]->resize_extensions(); 21312027Sjungma@eit.uni-kl.de } 21412027Sjungma@eit.uni-kl.de } 21512027Sjungma@eit.uni-kl.de 21612027Sjungma@eit.uni-kl.de ~instance_specific_extension_container(){ 21712027Sjungma@eit.uni-kl.de for (unsigned int i=0; i<m_ispex_per_accessor.size(); i++) delete m_ispex_per_accessor[i]; 21812027Sjungma@eit.uni-kl.de } 21912027Sjungma@eit.uni-kl.de 22012027Sjungma@eit.uni-kl.de void inc_use_count(){use_count++;} 22112027Sjungma@eit.uni-kl.de inline void dec_use_count(); 22212027Sjungma@eit.uni-kl.de 22312027Sjungma@eit.uni-kl.de std::vector<instance_specific_extensions_per_accessor<instance_specific_extension_container>* > m_ispex_per_accessor; 22412027Sjungma@eit.uni-kl.de unsigned int use_count; 22512027Sjungma@eit.uni-kl.de tlm::tlm_generic_payload* my_txn; 22612027Sjungma@eit.uni-kl.de instance_specific_extension_carrier* my_carrier; 22712027Sjungma@eit.uni-kl.de instance_specific_extension_container* next; //for pooling 22812027Sjungma@eit.uni-kl.de}; 22912027Sjungma@eit.uni-kl.de 23012027Sjungma@eit.uni-kl.de 23112027Sjungma@eit.uni-kl.deinline instance_specific_extension_container_pool::~instance_specific_extension_container_pool(){ 23212027Sjungma@eit.uni-kl.de while(unused) { instance_specific_extension_container* tmp=unused; unused=unused->next; delete tmp;} 23312027Sjungma@eit.uni-kl.de} 23412027Sjungma@eit.uni-kl.de 23512027Sjungma@eit.uni-kl.deinstance_specific_extension_container* instance_specific_extension_container_pool::create(){ 23612027Sjungma@eit.uni-kl.de if (!unused) {unused=new instance_specific_extension_container();} 23712027Sjungma@eit.uni-kl.de instance_specific_extension_container* tmp=unused; 23812027Sjungma@eit.uni-kl.de unused=unused->next; 23912027Sjungma@eit.uni-kl.de return tmp; 24012027Sjungma@eit.uni-kl.de} 24112027Sjungma@eit.uni-kl.de 24212027Sjungma@eit.uni-kl.devoid instance_specific_extension_container_pool::free(instance_specific_extension_container* cont){ 24312027Sjungma@eit.uni-kl.de cont->next=unused; 24412027Sjungma@eit.uni-kl.de unused=cont; 24512027Sjungma@eit.uni-kl.de} 24612027Sjungma@eit.uni-kl.de 24712027Sjungma@eit.uni-kl.de//This is the class that actually sits in the extension array 24812027Sjungma@eit.uni-kl.de//we keep this small since that one gets allocated and deallocated all the times 24912027Sjungma@eit.uni-kl.declass instance_specific_extension_carrier: public tlm::tlm_extension<instance_specific_extension_carrier>{ 25012027Sjungma@eit.uni-kl.de friend class instance_specific_extension_accessor; 25112027Sjungma@eit.uni-kl.de 25212027Sjungma@eit.uni-kl.depublic: 25312027Sjungma@eit.uni-kl.de instance_specific_extension_carrier(){ 25412027Sjungma@eit.uni-kl.de m_container=instance_specific_extension_container_pool::get_ispexcont_pool().create(); 25512027Sjungma@eit.uni-kl.de m_container->my_carrier=this; 25612027Sjungma@eit.uni-kl.de } 25712027Sjungma@eit.uni-kl.de 25812027Sjungma@eit.uni-kl.de virtual tlm::tlm_extension_base* clone() const { 25912027Sjungma@eit.uni-kl.de //we don't clone since private info is instance specific and associated to a given txn (the original) 26012027Sjungma@eit.uni-kl.de //so the deep copied txn will be virgin in terms of private info 26112027Sjungma@eit.uni-kl.de return NULL; 26212027Sjungma@eit.uni-kl.de } 26312027Sjungma@eit.uni-kl.de void copy_from(tlm::tlm_extension_base const &){return;} 26412027Sjungma@eit.uni-kl.de void free(){return;} 26512027Sjungma@eit.uni-kl.deprivate: 26612027Sjungma@eit.uni-kl.de instance_specific_extension_container* m_container; 26712027Sjungma@eit.uni-kl.de}; 26812027Sjungma@eit.uni-kl.de 26912027Sjungma@eit.uni-kl.deinline void instance_specific_extension_container::dec_use_count(){ 27012027Sjungma@eit.uni-kl.de if ((--use_count)==0) { //if this container isn't used any more 27112027Sjungma@eit.uni-kl.de instance_specific_extension_container_pool::get_ispexcont_pool().free(this); //we send it back to our pool 27212027Sjungma@eit.uni-kl.de //we have to do that manually, as we cannot rely on the fact that there is MM in the txn 27312027Sjungma@eit.uni-kl.de my_txn->clear_extension(my_carrier); //and remove it from the transaction's extension array 27412027Sjungma@eit.uni-kl.de delete my_carrier; 27512027Sjungma@eit.uni-kl.de } 27612027Sjungma@eit.uni-kl.de} 27712027Sjungma@eit.uni-kl.de 27812027Sjungma@eit.uni-kl.de 27912027Sjungma@eit.uni-kl.de//This class 'hides' all the instance specific extension stuff from the user 28012027Sjungma@eit.uni-kl.de// he instantiates one of those (e.g. instance_specific_extension_accessor extAcc;) and can then access 28112027Sjungma@eit.uni-kl.de// the private extensions 28212027Sjungma@eit.uni-kl.de// extAcc(txn).extensionAPIFnCall() 28312027Sjungma@eit.uni-kl.de// where extensionAPIFnCall is set_extension, get_extension, clear_extension,... 28412027Sjungma@eit.uni-kl.declass instance_specific_extension_accessor{ 28512027Sjungma@eit.uni-kl.depublic: 28612027Sjungma@eit.uni-kl.de instance_specific_extension_accessor(): m_index(max_num_ispex_accessors(true)-1){} 28712027Sjungma@eit.uni-kl.de 28812027Sjungma@eit.uni-kl.de template<typename T> 28912027Sjungma@eit.uni-kl.de inline instance_specific_extensions_per_accessor<instance_specific_extension_container>& operator()(T& txn){ 29012027Sjungma@eit.uni-kl.de instance_specific_extension_carrier* carrier; 29112027Sjungma@eit.uni-kl.de txn.get_extension(carrier); 29212027Sjungma@eit.uni-kl.de if (!carrier){ 29312027Sjungma@eit.uni-kl.de carrier=new instance_specific_extension_carrier(); 29412027Sjungma@eit.uni-kl.de carrier->m_container->my_txn=&txn; 29512027Sjungma@eit.uni-kl.de txn.set_extension(carrier); 29612027Sjungma@eit.uni-kl.de } 29712027Sjungma@eit.uni-kl.de return *(carrier->m_container->m_ispex_per_accessor[m_index]); 29812027Sjungma@eit.uni-kl.de } 29912027Sjungma@eit.uni-kl.de 30012027Sjungma@eit.uni-kl.deprotected: 30112027Sjungma@eit.uni-kl.de unsigned int m_index; 30212027Sjungma@eit.uni-kl.de}; 30312027Sjungma@eit.uni-kl.de 30412027Sjungma@eit.uni-kl.de} 30512027Sjungma@eit.uni-kl.de 30612027Sjungma@eit.uni-kl.de#endif 307