ImplementationIdeas

Some thoughts about the implementation of GreenBus

If we manage to have just one type of transaction for ALL protocols, then there will be less copies when transforming a transaction from one protocol to another. This transaction must give the user access to data in different bus-sizes, and timing should be completely separated from the transaction structure, so the same structure is used in any abstraction level.

The transaction

My suggestion for this transaction structure is to be as simple as:

  1. struct transaction
  2. {
  3.   // Each protocol defines their commands as an enum
  4.   //   then one can use: trans.cmd = OCP::READ;
  5.   int cmd;
  6.  
  7.   // Set the maximum data size in bytes (the maximum burst possible)
  8.   //   I don't know this number, it is just a guess
  9.   static const unsigned int data_size = 1024;
  10.  
  11.   // Data can be accessed in many bus-sizes
  12.   //   example for the third phase of dada handshake in 16bit bus:
  13.   //   trans.data.as16bit[2] = /*whatever*/;
  14.   union {
  15.     uint8  as8bit [data_size];
  16.     uint16 as16bit[data_size/2];
  17.     uint32 as32bit[data_size/4];
  18.   } data;
  19.  
  20.   // Maybe address quark should use the same technique as data
  21.   //   so we don't fix and address type/size
  22.   union {/*...*/} addr;
  23.  
  24. };

The atom

Anything related to timing (phases of the protocol) or error handling should be in a separate structure, the atom! Note that, following this idea, an atom is not inside the transaction anymore. So, it breaks the TAC figure.

  1. struct atom
  2. {
  3.   // Each protocol defines their own phases (atoms?) as an enum
  4.   //   there should be different sets of phases for different
  5.   //   levels of abstraction, so a master in a higher level of
  6.   //   abstraction can talk with a slave that accepts many levels
  7.   //   of abstraction
  8.   int phase;
  9.  
  10.   // Error is also a protocol-specific enum
  11.   int error;
  12.  
  13. };

The protocol

Then protocols are just a structure defining the enum's:

  1. struct my_protocol {
  2.  
  3.   enum command {READ, WRITE};
  4.  
  5.   // Maybe the phases are just the "master view", like
  6.   //   mini-transactions
  7.   enum phase {
  8.     PV_req,      /* PV  level */
  9.     PVT_lock,    /* PVT level (burst) */
  10.     PVT_req,
  11.     PVT_data1,
  12.     PVT_data2,
  13.     PVT_finish
  14.   };
  15.  
  16.   enum error {ADDR_INVALID, LOCK_FAIL, /*...*/};
  17.  
  18. };

Dealing with multiple transactions

The router or bridge could have a map (master,transaction id). Then, after an answer from a slave, the router/bridge can route the transaction back to the originating master. I'm not sure: may the master initiate another transaction before the completion of a previous one? If true, then it would be a list of transactions associated with a master. The slave may be always chosen by the address of the transaction (or maybe the command), right?

The router

It may convert the address for the slave, removing the slave-selection part of the address. When returning a transaction to master, it returns the address to the original value, so another phase of the protocol can be done (with the same slave).

The bridge

It knows to convert atoms from one protocol to another. I'm not sure it it's necessary to recover the original atom when returning the transaction to master.

Identifying the correct protocol

This operation should be done in elaboration time. There must be some way to do this when ports binds... but I didn't have time to study this yet. Checking it in simulation run-time it to time-consuming!