00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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();
00130 Command m_command;
00131 Burst m_burst;
00132 Address m_address;
00133 ThreadId m_threadid;
00134 bool m_last;
00135 bool m_srmd;
00136 AddressMode m_address_mode;
00137 ByteEnable m_byte_enable;
00138 Data m_data;
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
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
00300
00301
00302
00303
00304
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