protocol.h

Go to the documentation of this file.
00001 //    sampalib.org ESL library and tools
00002 //    Copyright (C) 2007  Thierry Grellier
00003 //
00004 //    This program is free software; you can redistribute it and/or modify
00005 //    it under the terms of the GNU General Public License version 2 as
00006 //    published by the Free Software Foundation.
00007 //
00008 //    This program is distributed in the hope that it will be useful,
00009 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 //    GNU General Public License for more details.
00012 //
00013 //    You should have received a copy of the GNU General Public License along
00014 //    with this program; if not, write to the Free Software Foundation, Inc.,
00015 //    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016 //
00017 //    contact: www.sampalib.org
00018 
00019 #ifndef SAMPA_PROTOCOL_H
00020 #define SAMPA_PROTOCOL_H
00021 
00022 #include "sampa/core/module.h"
00023 #include "sampa/core/gated.h"
00024 #include "sampa/core/clock.h"
00025 #include "sampa/core/call.h"
00026 #include "sampa/core/address.h"
00027 
00028 namespace Sampa {
00029 
00113   typedef unsigned short     Burst;
00114   typedef unsigned short     ThreadId;
00115   typedef unsigned short     ByteEnable;
00116   typedef unsigned long long Data;
00117   enum Command     { CMD_IDLE, CMD_READ, CMD_WRITE, CMD_NUM   };
00118   enum AddressMode { ADDR_INCR, ADDR_WRAP, NUM_ADDR_MODE_KIND };
00119 
00120 
00124   class SAMPA_PERSISTENT_CLASS(Transaction) {
00125     SAMPA_PERSISTENT(Transaction);
00126   public:
00127     struct SAMPA_PERSISTENT_CLASS(Payload) {
00128       Payload(DefaultCtrTag);
00129       virtual ~Payload(); // enable dynamic cast 
00130       Command     m_command; //: 3
00131       Burst       m_burst; //:  8
00132       Address     m_address; //: 32
00133       ThreadId    m_threadid;// : 16
00134       bool        m_last;// : 1
00135       bool        m_srmd;// : 1
00136       AddressMode m_address_mode;// : 2
00137       ByteEnable  m_byte_enable;// : 16
00138       Data        m_data;// : 64
00139     protected:
00140       int         m_num_ref;
00141       Payload*    m_next;
00142       SAMPA_PERSISTENT(Payload);
00143       friend class Transaction;
00144       friend class FactoryBase;
00145     };
00146 
00147     class SAMPA_PERSISTENT_CLASS(FactoryBase) {
00148       SAMPA_PERSISTENT(FactoryBase);
00149     public:
00150       FactoryBase(DefaultCtrTag);
00151 
00152       Payload*   allocate();
00153       Payload*   clone(Payload* src);
00154       void free(Payload* p);
00155      
00156       virtual Payload* create();
00157       virtual Payload* create(Payload* p);
00158       virtual void reset(Payload* p, Payload* src); 
00159 
00160       Payload* m_first;
00161       Payload* m_default_payload;
00162 
00163       static FactoryBase* M_inst;
00164     };
00165 
00166     Transaction(DefaultCtrTag);
00167     Transaction(const Transaction& req);
00168     Transaction(Command command, Burst burst);
00169     ~Transaction();
00170 
00171     const Payload& rd() const { return *m_payload; }
00172     Payload& wr()             { return *copy_on_write(); }
00173     Payload& mwr()            { return *m_payload; }
00174    
00175     Address      get_address() const                  { return m_payload->m_address;      }    
00176     AddressMode  get_address_mode() const             { return m_payload->m_address_mode; }    
00177     Command      get_command() const                  { return m_payload->m_command;      }
00178     ByteEnable   get_byte_enable() const              { return m_payload->m_byte_enable;  }
00179     Burst        get_burst() const                    { return m_payload->m_burst;        }       
00180     Data         get_data() const                     { return m_payload->m_data;         }
00181     bool         is_last() const                      { return m_payload->m_last;         }
00182     bool         is_srmd() const                      { return m_payload->m_srmd;         }
00183     ThreadId     get_threadid() const                 { return m_payload->m_threadid;     }
00184 
00185     void toggle_srmd()                                { copy_on_write()->m_srmd        ^= m_payload->m_srmd; } 
00186     void set_srmd(bool srmd)                          { copy_on_write()->m_srmd         = srmd;           } 
00187     void set_command(Command command)                 { copy_on_write()->m_command      = command;        }  
00188     void set_address_mode(AddressMode address_mode)   { copy_on_write()->m_address_mode = address_mode;   }  
00189     void set_burst(Burst   burst)                     { copy_on_write()->m_burst        = burst;          }
00190     void set_byte_enable(ByteEnable byte_enable)      { copy_on_write()->m_byte_enable  = byte_enable;    }
00191     void set_data(Data data)                          { copy_on_write()->m_data         = data;           }
00192     void toggle_last()                                { copy_on_write()->m_last        ^= m_payload->m_last; } 
00193     void set_last(bool last)                          { copy_on_write()->m_last         = last;           } 
00194     void set_address(Address address)                 { copy_on_write()->m_address      = address;        }
00195     void set_threadid(ThreadId threadid)              { copy_on_write()->m_threadid     = threadid;       }
00196 
00197     void qtoggle_srmd()                               { m_payload->m_srmd        ^= m_payload->m_srmd; } 
00198     void qset_srmd(bool srmd)                         { m_payload->m_srmd         = srmd;           } 
00199     void qset_command(Command command)                { m_payload->m_command      = command;        }  
00200     void qset_address_mode(AddressMode address_mode)  { m_payload->m_address_mode = address_mode;   }  
00201     void qset_burst(Burst   burst)                    { m_payload->m_burst        = burst;          }
00202     void qset_byte_enable(ByteEnable byte_enable)     { m_payload->m_byte_enable  = byte_enable;    }
00203     void qset_data(Data data)                         { m_payload->m_data         = data;           }
00204     void qtoggle_last()                               { m_payload->m_last        ^= m_payload->m_last; } 
00205     void qset_last(bool last)                         { m_payload->m_last         = last;           } 
00206     void qset_address(Address address)                { m_payload->m_address      = address;        }
00207     void qset_threadid(ThreadId threadid)             { m_payload->m_threadid     = threadid;       }
00208 
00209     Transaction& operator=(const Transaction& o) { assign(o); return *this; }
00210 
00211 //    void dump(ostream& os) const { m_payload->dump(os); }
00212   protected: 
00213     Payload* assign(const Transaction& o);
00214     Payload* copy_on_write();
00215     Payload* m_payload;
00216   };
00217 
00218 
00219   class Nil {};
00220 
00221   template<typename H, typename T>
00222   struct TL {
00223     typedef H Head;
00224     typedef T Tail;
00225   };
00226 
00227 # define Ext1(c1) Sampa::TL<c1,Sampa::Nil>
00228 # define Ext2(c1, c2) Sampa::TL<c1,Ext1(c2)>
00229 # define Ext3(c1, c2, c3) Sampa::TL<c1,Ext2(c2, c3)>
00230 # define Ext4(c1, c2, c3, c4) Sampa::TL<c1,Ext3(c2, c3, c4)>
00231 # define Ext5(c1, c2, c3, c4, c5) Sampa::TL<c1,Ext4(c2, c3, c4, c5)>
00232 # define Ext6(c1, c2, c3, c4, c5, c6) Sampa::TL<c1,Ext4(c2, c3, c4, c5, c6)>
00233 # define Ext7(c1, c2, c3, c4, c5, c6, c7) Sampa::TL<c1,Ext4(c2, c3, c4, c5, c6, c7)>
00234 # define Ext8(c1, c2, c3, c4, c5, c6, c7, c8) Sampa::TL<c1,Ext4(c2, c3, c4, c5, c6, c7, c8)>
00235 # define Ext9(c1, c2, c3, c4, c5, c6, c7, c8, c9) Sampa::TL<c1,Ext4(c2, c3, c4, c5, c6, c7, c8, c9)>
00236 
00237   template <class Ext> struct ExtPayload : Ext::Head, ExtPayload<typename Ext::Tail> {
00238     ExtPayload(DefaultCtrTag tag) : Ext::Head(tag), ExtPayload<typename Ext::Tail>(tag) { }
00239   };
00240   template < > struct ExtPayload<Nil> : public Transaction::Payload { 
00241     ExtPayload(DefaultCtrTag tag) : Transaction::Payload(tag) { }
00242   };
00243 
00244   template <class Ext>
00245   class Factory : public Transaction::FactoryBase {
00246     SAMPA_PERSISTENT(Factory);
00247   public:
00248     typedef ExtPayload<Ext> Payload;
00249     Factory(DefaultCtrTag tag) : FactoryBase(tag) { m_default_payload = pnew(Payload)(DEFAULT_CTR); }
00250   protected:
00251     Transaction::Payload* create()
00252     { return pnew(Payload)(DEFAULT_CTR); }
00253     Transaction::Payload* create(Payload* p) 
00254     { return pnew(Payload)(*static_cast<Payload*>(p)); }
00255     void reset(Transaction::Payload* p, Transaction::Payload* src) 
00256     { *static_cast<Payload*>(p) = *static_cast<Payload*>(src); }
00257   };
00258 
00259   template<int n>
00260   class NthElem{};
00261 
00262   template<class TL, int n>
00263   struct NthType {
00264     typedef typename NthType<typename TL::Tail, n-1>::Ret Ret;
00265   };
00266 
00267   template<class TL>
00268   struct NthType<TL, 1> {
00269     typedef typename TL::Head Ret;
00270   };
00271 
00272 
00273   template <class Ext>
00274   class Tx : public Tx<typename Ext::Tail> {
00275     typedef Tx<typename Ext::Tail> Base;
00276     typedef typename Ext::Head E;
00277   public:
00278     using Transaction::m_payload;
00279     using Transaction::assign;
00280     using Transaction::copy_on_write;
00281     using Transaction::wr;
00282     using Transaction::rd;
00283     using Transaction::mwr;
00284 
00285     Tx(DefaultCtrTag tag) : Base(tag)    { m_cached = dynamic_cast<E*>(m_payload); }
00286     Tx(const Transaction& tx) : Base(tx) { m_cached = dynamic_cast<E*>(m_payload); }
00287 
00288     Tx& operator=(const Transaction& tx) {
00289       Transaction::Payload* pl = m_payload; 
00290       if (assign(tx) != pl) update(); 
00291       return *this; 
00292     }
00293 
00294     void update() {
00295       m_cached = dynamic_cast<E*>(m_payload);
00296       Base::update();
00297     }
00298 
00299 //    void dump(ostream& os) const { 
00300 //      cached->dump(os);
00301 //      Base::dump(os);
00302 //    }
00303 
00304     // Get function for the nth element.
00305     template<int m>
00306     const typename NthType<Ext, m>::Ret&
00307     rd() const
00308     { return UglyRd(NthElem<m>()); };
00309 
00310     template<int m>
00311     const typename NthType<Ext, m>::Ret&
00312     UglyRd(NthElem<m>) const
00313     { return Base::UglyRd(NthElem<m-1>()); }
00314 
00315     const E& UglyRd(NthElem<1>) const
00316     { return *m_cached; }
00317 
00318     template<int m>
00319     typename NthType<Ext, m>::Ret&
00320     mwr()
00321     { return UglyMwr(NthElem<m>()); }
00322 
00323     template<int m>
00324     typename NthType<Ext, m>::Ret&
00325     UglyMwr(NthElem<m>)
00326     { return Base::UglyMwr(NthElem<m-1>()); }
00327 
00328     E& UglyMwr(NthElem<1>)
00329     { return *m_cached; }
00330 
00331     template<int m>
00332     typename NthType<Ext, m>::Ret&
00333     wr()
00334     { return UglyWr(NthElem<m>()); }
00335 
00336     template<int m>
00337     typename NthType<Ext, m>::Ret&
00338     UglyWr(NthElem<m>)
00339     { return Base::UglyWr(NthElem<m-1>()); }
00340 
00341     E& UglyWr(NthElem<1>)
00342     { 
00343       Transaction::Payload* pl = m_payload; 
00344       if (copy_on_write() != pl) update();
00345       return *m_cached; 
00346     }
00347 
00348 #if SAMPA_CONFIG_COLD_RESTART == SAMPA_ENABLED
00349     static void constructor(object* ptr) { new (ptr) Tx; }
00350     static class_descriptor self_class;
00351     Tx() {
00352       int sp = 0; 
00353       gc_segment* const gc_stack = storage::gc_stack;
00354       long const shift = storage::base_address_shift;
00355       if (gc_stack != NULL) { REF(m_cached) storage::gc_stack=&gc_stack[sp]; }
00356       else if (shift != 0) { REF(m_cached) } 
00357     }
00358 #else
00359     Tx() {}
00360 #endif
00361 
00362     E* m_cached;
00363   };
00364 
00365   template <>
00366   class Tx<Nil> : public Transaction {
00367     typedef Transaction Base;
00368   public:
00369     Tx(DefaultCtrTag tag) : Transaction(tag) {}
00370     Tx(const Transaction& tx) : Base(tx) {}
00371     void update() {}
00372     SAMPA_PERSISTENT(Tx);
00373   };
00374 
00378   typedef Transaction Request;
00379 
00383   typedef Request Response;
00384 
00388   struct TargetRequestInterface {
00389     virtual bool recieve_request(const Request&) = 0;
00390   };
00391    
00395   struct InitiatorResponseInterface {
00396     virtual bool recieve_response(const Response&) = 0;
00397   };
00398 
00399   class Target;
00400   
00404   class Initiator : public ContainerObject {
00405   public:
00406     Initiator(const Name&, InitiatorResponseInterface* initiator = 0);    
00407     void bind_target(Target* target);
00408     void bind_clock(Clock* clock);
00409     Initiator* operator->()  
00410       { return this; }
00411     bool is_dont_trace() const
00412       { return !m_trace; }
00413     InitiatorResponseInterface* get_initiator() const 
00414       { return p_initiator; }
00415     EventListener& get_request_accepted_event()
00416       { return e_request_accepted; }
00417     EventListener& get_response_accepted_event()
00418       { return e_response_accepted; }
00419     bool send_request(const Request& request);
00420     bool has_pending_request() const
00421       { return m_request_pending; }
00422     bool accept_response();    
00423     void cancel_accept_response();
00424   
00425   private:
00426     friend class Target;
00427     bool send_response(const Response& response);
00428     bool has_pending_response() const
00429       { return m_response_pending; }
00430     bool accept_request();
00431     void cancel_accept_request();
00432 
00433     BoolParameter               m_trace;
00434     InitiatorResponseInterface* p_initiator;
00435     TargetRequestInterface*     p_target;
00436     ClockedEvent                e_request_accepted;
00437     Gated<bool>                 m_request_pending;
00438     ClockedEvent                e_response_accepted;
00439     Gated<bool>                 m_response_pending;
00440     SAMPA_PERSISTENT(Initiator);
00441   };
00442   
00446   class Target : public ContainerObject {
00447   public:
00448     Target(const Name& name, TargetRequestInterface* target = 0);
00449     void bind_initiator(Initiator* initiator)
00450       { p_initiator = initiator; }
00451     TargetRequestInterface* get_target() const 
00452       { return p_target; }
00453     void bind_clock(Clock* clock);
00454     Clock* get_clock() const 
00455       { return p_clock; }
00456     Target* operator->() 
00457       { return this; }
00458     bool send_response(const Response& response) 
00459       { return p_initiator->send_response(response); }
00460     bool has_pending_response() const 
00461       { return p_initiator->has_pending_response(); }
00462     EventListener& get_response_accepted_event() 
00463       { return p_initiator->get_response_accepted_event(); }
00464     EventListener& get_request_accepted_event() 
00465       { return p_initiator->get_request_accepted_event(); }
00466     bool accept_request() 
00467       { return p_initiator->accept_request(); }
00468     void cancel_accept_request() 
00469       { p_initiator->cancel_accept_request(); }
00470   private:
00471     Initiator*              p_initiator;
00472     TargetRequestInterface* p_target;
00473     Clock*                  p_clock;
00474     SAMPA_PERSISTENT(Target);
00475   };
00476 
00477   template <class Adapted>
00478   class AdaptingInitiator : public Initiator, public InitiatorResponseInterface {
00479     SAMPA_PERSISTENT(AdaptingInitiator);
00480   public:
00481     typedef bool (Adapted::*RecieveResponseFunc)(const Response&);
00482     AdaptingInitiator(const Name& nm, RecieveResponseFunc callback);
00483     void complete_restart(RecieveResponseFunc callback);
00484     bool recieve_response(const Response& response);
00485     Adapted*            m_module;
00486     RecieveResponseFunc m_callback;
00487   };
00488   
00489   template <class Adapted>
00490   class AdaptingTarget : public Target, public TargetRequestInterface {
00491     SAMPA_PERSISTENT(AdaptingTarget);
00492   public:
00493     typedef bool (Adapted::*RecieveRequestFunc)(const Request&);
00494     AdaptingTarget(const Name& nm, RecieveRequestFunc callback);
00495     void complete_restart(RecieveRequestFunc callback);
00496     bool recieve_request(const Request& response);
00497     Adapted*           m_module;
00498     RecieveRequestFunc m_callback;
00499   };
00500 
00502 }
00503 
00504 #endif

Generated on Sat Feb 16 16:23:15 2008 for Sampa by  doxygen 1.5.3