2010年8月26日 星期四

AMBA 4.0 AXI Bus Pt2

接續 AMBA 4.0 AXI Bus Pt1, 底下用 @c code 來模擬 AMBA 4.0 out-of-order的形式. 主要區分成 Address Phase, Read-Data Phase. 透過 sleep delay 來模擬 Slave 快速跟慢速的 Response. out_of_order.c

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define MAX_BUFF_DEEP 4 
#define MAX_BURST 4 
#define MAX_TEST_COT 8 

pthread_mutex_t count_mutex     = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t condition_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  condition_cond  = PTHREAD_COND_INITIALIZER;

enum BUS_STATUS {
  BUS_TRUE        =0,
 BUS_FALSE =1,
};

enum BUS_ADDR_MAP {
 BUS_SLAVE_1_ST = 0x00000100,
 BUS_SLAVE_1_ED = 0x000001ff,
 BUS_SLAVE_2_ST = 0x00000200,
 BUS_SLAVE_2_ED = 0x000002ff,
 BUS_MASTER_1_ST = 0x00000300,
 BUS_MASTER_1_ED = 0x000003ff,
 BUS_MASTER_2_ST = 0x00000400,
 BUS_MASTER_2_ED = 0x000004ff,
};

typedef struct AddrBus {
 int FmAddr[MAX_BUFF_DEEP];
 int ToAddr[MAX_BUFF_DEEP];
 int INX;
 int FULL;
 int EMPTY;
} AddrBusBuf;

typedef struct RdData {
 int Data[MAX_BURST];
} RdDataBuf;


typedef struct RdDataBus {
 RdDataBuf   Data[MAX_BUFF_DEEP];
 int  FmAddr[MAX_BUFF_DEEP];
 int  INX;
 int  FULL;
 int  EMPTY; 
} RdDataBusBuf;

int TEST_COT=0;

AddrBusBuf AddrBusBufPtr;
RdDataBusBuf RdDataBusBufPtr;


void  AddrBusBuf_Initial(){
      AddrBusBufPtr.INX  =0;
      AddrBusBufPtr.FULL = BUS_FALSE;
      AddrBusBufPtr.EMPTY= BUS_TRUE;
}

void  RdDataBusBuf_Initial(){
      RdDataBusBufPtr.INX  =0;
      RdDataBusBufPtr.FULL = BUS_FALSE;
      RdDataBusBufPtr.EMPTY= BUS_TRUE;
}

void SetAddrBusBufStatus(int FmAddr,int ToAddr){
     int inx = AddrBusBufPtr.INX;
     AddrBusBufPtr.FmAddr[inx] =  FmAddr;
     AddrBusBufPtr.ToAddr[inx] =  ToAddr;
     inx++;
     AddrBusBufPtr.INX = inx;
}

void GetAddrBusBufStatus(){
     int inx = AddrBusBufPtr.INX;
     int i;     
    for( i=0; i<inx; i++){
      AddrBusBufPtr.FmAddr[i] = AddrBusBufPtr.FmAddr[i+1];
      AddrBusBufPtr.ToAddr[i] = AddrBusBufPtr.ToAddr[i+1];
   }
      inx--;
      AddrBusBufPtr.INX = inx;
}

void CheckAddrBusBufStatus(){
     AddrBusBufPtr.FULL = ( AddrBusBufPtr.INX==MAX_BUFF_DEEP )? BUS_TRUE : BUS_FALSE;
     AddrBusBufPtr.EMPTY= ( AddrBusBufPtr.INX==0             )? BUS_TRUE : BUS_FALSE;
}


void GetRdDataBusBufStatus(int n){
    int inx = RdDataBusBufPtr.INX;
    int i;
      printf("M%d Receive @ FmAdder: %x\n",n, RdDataBusBufPtr.FmAddr[0] ); 
 
   for( i=0; i<MAX_BURST; i++ ){
      printf("M%d Receive @ %d, %d\n",n, i, RdDataBusBufPtr.Data[0].Data[i] );
    }
   //update RdDataBusBuf 
   for( i=0; i<inx; i++){
       RdDataBusBufPtr.FmAddr[i] = RdDataBusBufPtr.FmAddr[i+1];
       RdDataBusBufPtr.Data[i]   = RdDataBusBufPtr.Data[i+1];
    }   
       inx--;
       RdDataBusBufPtr.INX = inx;
}

void SetRdDataBusBufStatus(int FmAddr,int n){
     int i;
     int inx = RdDataBusBufPtr.INX;
     
      for(i=0; i<MAX_BURST; i++){
             RdDataBusBufPtr.Data[inx].Data[i] = (n==1)? 10+i : 100+i;
       }
             RdDataBusBufPtr.FmAddr[inx] = FmAddr;
      inx++; 
      RdDataBusBufPtr.INX = inx;
}

 
void CheckRdDataBusBufStatus(){
     RdDataBusBufPtr.FULL = ( RdDataBusBufPtr.INX==MAX_BUFF_DEEP )? BUS_TRUE : BUS_FALSE;
     RdDataBusBufPtr.EMPTY= ( RdDataBusBufPtr.INX==0             )? BUS_TRUE : BUS_FALSE;
}


void *MASTER_1_Transmitter(void *t){
     long my_id = (long)t;
     int FmAddr,ToAddr;

     while(TEST_COT<MAX_TEST_COT){
      int cot =10;
          
         while( AddrBusBufPtr.FULL == BUS_TRUE ){
             sleep(1);
             if( cot==0 ){ printf("out-of-Time-Wait ... @ M1 Transmitter 4 Addr Phase\n"); break; }
             cot--;
         } 

         if( cot>0 ){
            pthread_mutex_lock(&count_mutex);
            FmAddr = BUS_MASTER_1_ST;
            ToAddr = ( TEST_COT%2==0 )? BUS_SLAVE_1_ST : BUS_SLAVE_2_ST;
            SetAddrBusBufStatus( FmAddr, ToAddr);
            CheckAddrBusBufStatus();
            printf("M1 Transmit @ FmAddr: %x, ToAddr %x\n", FmAddr, ToAddr);    
            pthread_mutex_unlock(&count_mutex);
         }

         sleep(1);
     }

pthread_exit(NULL);
}

void *MASTER_1_Receiver(void *t){
    long my_id = (long)t;
 
    while(TEST_COT<MAX_TEST_COT){
    int  cot   =10;
     
       while( RdDataBusBufPtr.EMPTY == BUS_TRUE ){
          sleep(1);
          if( cot==0 ){ printf("out-of-Time-Wait ... @ M1 Receiver 4 RdData Phase\n"); break; }
          cot--;  
     }
     
     int i,inx;
     if( cot>0 && BUS_MASTER_1_ST <= RdDataBusBufPtr.FmAddr[0] && RdDataBusBufPtr.FmAddr[0] <= BUS_MASTER_1_ED ){
         pthread_mutex_lock(&count_mutex);
         GetRdDataBusBufStatus(1);
         CheckRdDataBusBufStatus();
         TEST_COT++;
         pthread_mutex_unlock(&count_mutex);                
     }

     sleep(1);
   }
 
pthread_exit(NULL);
}


void *SLAVE_1_DO(void *t){
    long my_id = (long)t;
    int  FmAddr;
  
    while(TEST_COT<MAX_TEST_COT){
     int cot =10;

       while( RdDataBusBufPtr.FULL == BUS_TRUE && AddrBusBufPtr.EMPTY == BUS_TRUE ){
          sleep(2);
          if( cot==0 ){ printf("out-ot-Time-Wait ... @ S1 Receive 4 RdData/Addr Phase\n"); break; }
          cot --;
       }

       if( cot>0  && BUS_SLAVE_1_ST <= AddrBusBufPtr.ToAddr[0] && AddrBusBufPtr.ToAddr[0] <= BUS_SLAVE_1_ED ){
          pthread_mutex_lock(&count_mutex);
          FmAddr = AddrBusBufPtr.FmAddr[0]; 
          printf("S1 Receive Req @ FmAddr: %x\n", FmAddr);
          SetRdDataBusBufStatus( FmAddr, 1);
          GetAddrBusBufStatus();
          CheckAddrBusBufStatus();
          CheckRdDataBusBufStatus();
          pthread_mutex_unlock(&count_mutex);
      }

     sleep(3);  
   }
 pthread_exit(NULL);
}

void *SLAVE_2_DO(void *t){
    long my_id = (long)t;
    int  FmAddr;
  
    while(TEST_COT<MAX_TEST_COT){
     int cot =10;

       while( RdDataBusBufPtr.FULL == BUS_TRUE && AddrBusBufPtr.EMPTY == BUS_TRUE ){
          sleep(2);
          if( cot==0 ){ printf("out-ot-Time-Wait ... @ S2 Receive 4 RdData/Addr Phase\n"); break; }
          cot --;
       }

       if( cot>0  && BUS_SLAVE_2_ST <= AddrBusBufPtr.ToAddr[0] && AddrBusBufPtr.ToAddr[0] <= BUS_SLAVE_2_ED ){
          pthread_mutex_lock(&count_mutex);
          FmAddr = AddrBusBufPtr.FmAddr[0]; 
          printf("S2 Receive Req @ FmAddr: %x\n", FmAddr);
          SetRdDataBusBufStatus( FmAddr, 2);
          GetAddrBusBufStatus();
          CheckAddrBusBufStatus();
          CheckRdDataBusBufStatus();
          pthread_mutex_unlock(&count_mutex);
      }

     sleep(5);  
   }
 pthread_exit(NULL);
}

int main(int argc,char* argv[]){
 AddrBusBuf_Initial();
 RdDataBusBuf_Initial();
 
 pthread_t thread[4];

 pthread_create( &thread[0],NULL, MASTER_1_Transmitter, NULL);
 pthread_create( &thread[1],NULL, MASTER_1_Receiver, NULL);
 pthread_create( &thread[2],NULL, SLAVE_1_DO, NULL);
 pthread_create( &thread[3],NULL, SLAVE_2_DO, NULL);
                      
 pthread_join( thread[0],NULL);
 pthread_join( thread[1],NULL);
 pthread_join( thread[2],NULL);
 pthread_join( thread[3],NULL);

 pthread_exit(NULL);

return 0;
}
Results: root@sean-laptop:/home/sean/prj/SOC_c_model/out_of_order# ./a.out M1 Transmit @ FmAddr: 300, ToAddr 100 S1 Receive Req @ FmAddr: 300 M1 Transmit @ FmAddr: 300, ToAddr 100 M1 Receive @ FmAdder: 300 M1 Receive @ 0, 10 M1 Receive @ 1, 11 M1 Receive @ 2, 12 M1 Receive @ 3, 13 M1 Transmit @ FmAddr: 300, ToAddr 200 S1 Receive Req @ FmAddr: 300 M1 Receive @ FmAdder: 300 M1 Receive @ 0, 10 M1 Receive @ 1, 11 M1 Receive @ 2, 12 M1 Receive @ 3, 13 M1 Transmit @ FmAddr: 300, ToAddr 100 M1 Transmit @ FmAddr: 300, ToAddr 100 M1 Transmit @ FmAddr: 300, ToAddr 100 S2 Receive Req @ FmAddr: 300 M1 Receive @ FmAdder: 300 M1 Receive @ 0, 100 M1 Receive @ 1, 101 M1 Receive @ 2, 102 M1 Receive @ 3, 103 S1 Receive Req @ FmAddr: 300 M1 Transmit @ FmAddr: 300, ToAddr 200 M1 Receive @ FmAdder: 300 M1 Receive @ 0, 10 M1 Receive @ 1, 11 M1 Receive @ 2, 12 M1 Receive @ 3, 13 sample code download here Summary AXI vs AHB

沒有留言:

張貼留言