#include <stdio.h> #include <stdlib.h> #include <pthread.h> #define MAX_BURST 4 #define MAX_TEST_COT 3 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_ON_BUSY =0, BUS_OFF_BUSY =1, BUS_ON_LOCK =2, BUS_OFF_LOCK =3, }; 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, }; typedef struct Bus { int FmAddr; int ToAddr; int Data[MAX_BURST]; int Busy; int Lock; } Bus_Buf; Bus_Buf BusPtr; int TEST_COT=0; void Bus_Initial(){ BusPtr.Busy = BUS_OFF_BUSY; BusPtr.Lock = BUS_OFF_LOCK; } void *MASTER_1_Transmitter(void *t){ long my_id = (long)t; while( TEST_COT < MAX_TEST_COT ){ int cot =10; while( BusPtr.Busy == BUS_ON_BUSY ){ sleep(1); if( cot==0 ){ printf("Out-of-Time-Wait M1 Transmitter retry...\n"); break; } cot--; } if( cot>0 ){ printf("M1 Transmitter @ %d\n", TEST_COT); pthread_mutex_lock(&count_mutex); BusPtr.FmAddr = BUS_MASTER_1_ST; BusPtr.ToAddr = ( TEST_COT%2==0 )? BUS_SLAVE_1_ST: BUS_SLAVE_2_ST; BusPtr.Busy = BUS_ON_BUSY; pthread_mutex_unlock(&count_mutex); } else { sleep(2); } sleep(3); } pthread_exit(NULL); } void *MASTER_1_Receiver(void *t){ long my_id = (long)t; int cot =10; while( TEST_COT < MAX_TEST_COT ){ while( BusPtr.Busy == BUS_ON_BUSY && BusPtr.Lock == BUS_OFF_LOCK ){ sleep(1); if( cot==0 ){ printf("Out-of-Time wait M1 Receiver retry...\n"); break; } cot--; } int i; if( cot>0 && BUS_MASTER_1_ST <= BusPtr.FmAddr && BusPtr.FmAddr <= BUS_MASTER_1_ED ){ pthread_mutex_lock(&count_mutex); BusPtr.Busy = BUS_OFF_BUSY; BusPtr.Lock = BUS_OFF_LOCK; for(i=0; i<MAX_BURST; i++){ printf("M1 Receive Fm %d,%d,%d\n",BusPtr.ToAddr,i,BusPtr.Data[i]); } printf("M1 Reveive Done @ %d\n",TEST_COT); printf("\n"); TEST_COT++; pthread_mutex_unlock(&count_mutex); } else { sleep(2); } sleep(3); } pthread_exit(NULL); } void *SLAVE_1_DO(void *t){ long my_id = (long)t; while( TEST_COT < MAX_TEST_COT ){ while( BusPtr.Busy == BUS_OFF_BUSY ){ sleep(1); } int i; if( BUS_SLAVE_1_ST <= BusPtr.ToAddr && BusPtr.ToAddr <= BUS_SLAVE_1_ED ){ pthread_mutex_lock(&count_mutex); BusPtr.Lock = BUS_ON_LOCK; for(i=0; i<MAX_BURST; i++){ BusPtr.Data[i] = i+10; } pthread_mutex_unlock(&count_mutex); } else { sleep(3); } sleep(3); } pthread_exit(NULL); } void *SLAVE_2_DO(void *t){ long my_id = (long)t; while( TEST_COT < MAX_TEST_COT ){ while( BusPtr.Busy == BUS_OFF_BUSY ){ sleep(1); } int i; if( BUS_SLAVE_2_ST <= BusPtr.ToAddr && BusPtr.ToAddr <= BUS_SLAVE_2_ED ){ pthread_mutex_lock(&count_mutex); BusPtr.Lock = BUS_ON_LOCK; for(i=0; i<MAX_BURST; i++){ BusPtr.Data[i] = i+100; } pthread_mutex_unlock(&count_mutex); } else { sleep(3); } sleep(3); } pthread_exit(NULL); } int main(int argc,char* argv[]){ Bus_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 M1 Transmitter @ 0 M1 Receive Fm 256,0,10 M1 Receive Fm 256,1,11 M1 Receive Fm 256,2,12 M1 Receive Fm 256,3,13 M1 Reveive Done @ 0 M1 Transmitter @ 1 M1 Receive Fm 512,0,100 M1 Receive Fm 512,1,101 M1 Receive Fm 512,2,102 M1 Receive Fm 512,3,103 M1 Reveive Done @ 1 sample code download here Refs: ARM Technology 基于AMBA AXI总线的低功耗扩展设计 On Chip Communication Architectures AHB vs. AXI Burst. AHB Burst. Address and Data are locked together (single pipeline stage); HREADY controls intervals of address and data ...
2010年8月24日 星期二
AMBA 4.0 AXI Bus Pt1
在learning plus: AMBA 4 ARM ,learning plus: AHB Platform emulator @ SystemC,learning plus: ESL Design Flow 中我們有介紹 AMBA 2.0 AHB跟APB 的 Bus 架構,跟 SystemC Module @ AHB,APB 的 virtual platform .不過 ARM 在 AMBA 3.0之後為了要增加 Bus 的效能,而改變了先前 AMBA 2.0 的 protocol,主要在於 AMBA 2.0 採用的是 in-order 機制,就是Data傳輸完後 Bus 的使用權才會被Release.表示一組Transfer是不能被中斷的,相對的Bus會一值被Lock.導致整個系統的 performance會被慢速的 Transfer 給影響,所以在 AMBA 3.0 之後採用 out-of-order 的概念做不對等的傳輸方式,表示在每組 Transfer 可根據自己本身速度的快慢來 Access Bus.
Ex: AMBA 2.0 Burst(4) type M1@33Mhz, M2@66Mhz
SEQ : M1->M2
M1(0), M1(1), M1(2), M1(3), M2(0), M2(1), M2(2), M2(3)
要等 M1 完成, M2 才開始
Ex: AMBA >=3.0 Burst(4) type M1@33Mhz, M2@66Mhz
SEQ : M1->M2
M2(0), M2(1), M2(2), M2(3),M1(0),M1(1) M1(2), M2(3)
取決於 M1, M2 的速度,不必等 M1 完成, M2 即可開始
當然這除了硬體要支援sort跟reorder機制,跟 Address Phase 和 Data Phase 完全分開.
底下用sample code來模擬 in-order 跟 out-of-order的差別
in_order.c
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言