2010年9月6日 星期一

LEX && YACC sample case pt1

早在 Lex & Yacc case study @ PLY 有提到 Lex && Yacc 的用法, 這邊用主要是透過 link-list 的方式把 Yacc 所建立的 Token 轉成 Node list 的方式存入,之後可以方便我們在內部做Scheduling 和 Mapping 的動作. tt.h

#ifndef TT_H
#define TT_H
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

enum TTType {
 TT_ADD =0,
 TT_SUB =1,
 TT_MUL =2,
 TT_DIV =3,
 TT_MOD =4,
 TT_SRC1 =5,
 TT_SRC2 =6,
 TT_DST =7,
};

typedef struct tt {
 int Id;
 char*  Nm;
 struct tt *Nxt;
} TT;

typedef struct list {
 int    Typ;
 int    OpId;
 struct TT *Parent;
 struct TT *Child;
 struct list *Nxt;
} LIST;


TT *set_TTNode(TT *p,int Id,char* Nm){

    TT *tPtr =  malloc(sizeof(TT));
    if( tPtr == NULL )
         return NULL;
   
     tPtr->Id = Id;
     tPtr->Nm = Nm;
     tPtr->Nxt = NULL;
     
    if( p == NULL ){
        p = tPtr;
    } else {
        tPtr->Nxt = p;
        p      = tPtr;
   }
 
return p;
}

TT *display_TTNode(TT *p){
   if(p!=NULL){
     printf("Id :: %3d,",p->Id);
     printf("Nm "" %3s\n",p->Nm);
   }
return p; 
}

TT *get_TTNode(TT *p,int Id){
    TT *tPtr = p;

    while(tPtr!=NULL){
      if( tPtr->Id == Id ){
           return tPtr; break;
      }
      tPtr = tPtr->Nxt;
   }

return NULL; 
}

LIST* set_Parent2List(LIST *l,int Id,char *Nm){
      
     if(l==NULL)
        return NULL;

     TT *tPtr  = (void *) l->Parent;
     tPtr      = set_TTNode(tPtr,Id,Nm);
     l->Parent = (void *)tPtr;

return l; 
}

LIST* set_List(LIST *l,int OpId,int Tp,char *src1,char *src2,char *dst){

    LIST *lPtr =  malloc(sizeof(LIST));
    if( lPtr == NULL )
         return NULL;
    
     lPtr      = set_Parent2List(lPtr,TT_SRC1,src1); 
     lPtr      = set_Parent2List(lPtr,TT_SRC2,src2); 
     lPtr->Typ = Tp;
     lPtr->OpId= OpId;
     lPtr->Nxt = NULL;

     if(l==NULL){
        l = lPtr;
     }else {
        lPtr->Nxt = l;  
        l         = lPtr;
 
    }

return l;
}

LIST* get_List(LIST *l,int OpId){

  LIST *lPtr = l;

  while(lPtr!=NULL){
        if(lPtr->OpId == OpId){ return lPtr; break; }
        lPtr = lPtr->Nxt;
  }

}
#endif
tt.c

#include "tt.h"

int main(){

int OpId =0;

LIST *lstr = NULL; //LIST list
TT   *tPtr = NULL; //TT   point
LIST *lPtr = NULL; //LIST point

lstr = set_List(lstr,OpId,TT_ADD,"a","b","c"); OpId++;
lstr = set_List(lstr,OpId,TT_ADD,"c","d","e"); OpId++;

if(lstr == NULL ){ printf("<E1> Initial List Error ...\n"); return -1; }
lPtr = get_List(lstr,0);

if(lPtr == NULL ){ printf("<E2> Get Ptr Error ...\n"); return -1; }
tPtr = (void *)lPtr->Parent;

if(tPtr == NULL ){ printf("<E3> Get Ptr->Parent Error ...\n"); return -1; }
tPtr = get_TTNode(tPtr,TT_SRC1);

if(tPtr == NULL ){ printf("<E4> Get Ptr->Parent->Src1 Error ...\n"); return -1; }
display_TTNode(tPtr);

return 0;
}
Results: Id :: 5,Nm a Refs: pointer 2 pointer memory map tPtr = (void *)lPtr->Parent;

2010年9月4日 星期六

SMP @ Linux Kernel case study

在多核心架構下,除了可以用 sched.h 底下的 CPU_SET 來指定 schedule list上的 schedule processor 要給那個CPU使用外.還要考慮CPU lock/schedule 的機制.一但多個CPU Access 相同的 Memory Address時,就需要 lock priority 來確保 Memory Address 不會被 overwrite. 在Linux kernel 上提供了 spinlock_trwlock(read write lock)的機制, 但在效能上 rwlock 要等lock被解鎖後才能動作,所以在 kernel 2.6 下加入了 RCU 的機制, 透過 COPY 的方式建立新的pointer, 不需要等lock解鎖就可執行,等執行完後在update 之前的pointer, 所以再效能上可降低 wait unlock 的時間. sample code 4 CPU_SET
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/sysinfo.h>
#include<unistd.h>

#define __USE_GNU
#include<sched.h>
#include<ctype.h>
#include<string.h>

int main(int argc, char* argv[])
{
        int num = sysconf(_SC_NPROCESSORS_CONF);
        int created_thread = 0;
        int myid;
        int i;
        int j = 0;

        cpu_set_t mask;
        cpu_set_t get;

        if (argc != 2)
        {
                printf("usage : ./cpu num\n");
                exit(1);
        }

        myid = atoi(argv[1]);

        printf("system has %i processor(s). \n", num);

        CPU_ZERO(&mask);
        CPU_SET(myid, &mask);

        if (sched_setaffinity(0, sizeof(mask), &mask) == -1)
        {
                printf("warning: could not set CPU affinity, continuing...\n");
        }
        while (1)
        {

                CPU_ZERO(&get);
                if (sched_getaffinity(0, sizeof(get), &get) == -1)
                {
                        printf("warning: cound not get cpu affinity, continuing...\n");
                }
                for (i = 0; i < num; i++)
                {
                        if (CPU_ISSET(i, &get))
                        {
                                printf("this process %d is running processor : %d\n",getpid(), i);
                        }
                }
        }
        return 0;
}
code reference [精彩] 发一个多CPU中进程与CPU绑定的例子 Refs: Linux RCU机制详解 Read-copy-update

2010年9月1日 星期三

NetWork on Chip @ c emulator

Hi all, We write a sample NOC emulator @ pthread c code. it support the multi tasks,such as Receiver and Transmitter at each Net-Nodes, and we add some ideas from AXI Bus. we use two channels Design to handle the Address and Data Phase,that can increase the performance and reduce power consumed. But in current version we only support the Address Phase,you can add the Data phase detection in it.thx 1.NOC flow chart Architecture. Define the Architecture set(Map Table),it includes the connection of Net-Nodes and each Nodes information(FIFO INDEX, EMPTY, FULL)... Task List Define how many jobs should do..,and it includes our definition tags. Node Trace Tracing the next node and detecting finish or not. NOC Architecture view parts of network.c
void *SetAddrInf2NetNodeId_0(void *t){
     int NodeId = (int)t;
     int cot;

while( CheckOwnTaskListAddrDone(NodeId) == NET_FALSE ){
    cot =3;
     while( NetNode[NodeId].Addr_FULL == NET_TRUE ){
            sleep( NetNode[NodeId].Addr_DELAY );
            if( cot== 0 ){ printf("Out-of-Time Wait 4 NetNode Set Addr Phase @ %d \n",NodeId); break; }
            cot--;
     }

     if( cot >0 ){
        pthread_mutex_lock(&count_mutex);
        if ( CheckTaskListAndSetAddrInf2NetNode(NodeId) == NET_OK_TASK ){
                printf("Set TaskList 2 NetNode Ok @ %d \n",NodeId);
                if(NET_DEBUG==0){ DisplayMapTable4NetNode();}
        }
        pthread_mutex_unlock(&count_mutex);
     } else {
           sleep( NetNode[NodeId].Addr_DELAY );
    }

    sleep( NetNode[NodeId].Addr_DELAY );
 }
 pthread_exit(NULL);
}

void *GetAddrInf2NetNodeId_0(void *t){
     int NodeId = (int)t;
     int cot;

while( CheckOwnTaskListAddrDone(NodeId) == NET_FALSE ){
    cot =3;
    while( NetNode[NodeId].Addr_EMPTY == NET_TRUE ){
           sleep( NetNode[NodeId].Addr_DELAY );
           if( cot== 0){ printf("Out-of-Time Wait 4 NetNode Get Addr Phase @ %d \n",NodeId); break; }
           cot--;
   }

   if( cot >0 ){
        pthread_mutex_lock(&count_mutex);
        if (CheckAddrInfNetNode2TaskList(NodeId) == NET_OK_TASK ){
               printf("Get NetNode 2 TaskList Ok @ %d\n",NodeId);
               if(NET_DEBUG==0 ){ DisplayMapTable4NetNode(); }
               if(TASK_DEBUG==0){ DisplayTaskList();         }
        }
        pthread_mutex_unlock(&count_mutex);

  } else {
      sleep( NetNode[NodeId].Addr_DELAY );
  }

   sleep( NetNode[NodeId].Addr_DELAY );
 }

 pthread_exit(NULL);
}
Results Set TaskList 2 NetNode Ok @ 0 Get NetNode 2 TaskList Ok @ 0 TId :: 0,NId :: 4,FromAddr :: 400,ToAddr :: 400,RWType :: 5,DepTId :: -1,AddrDone :: 0 TId :: 1,NId :: 3,FromAddr :: 300,ToAddr :: 400,RWType :: 6,DepTId :: 0,AddrDone :: 1 TId :: 2,NId :: 7,FromAddr :: 700,ToAddr :: 800,RWType :: 6,DepTId :: -1,AddrDone :: 1 TId :: 3,NId :: 0,FromAddr :: 0,ToAddr :: 400,RWType :: 5,DepTId :: -1,AddrDone :: 1 --------------------------------------- Get NetNode 2 TaskList Ok @ 4 TId :: 0,NId :: 4,FromAddr :: 400,ToAddr :: 400,RWType :: 5,DepTId :: -1,AddrDone :: 0 TId :: 1,NId :: 3,FromAddr :: 300,ToAddr :: 400,RWType :: 6,DepTId :: 0,AddrDone :: 1 TId :: 2,NId :: 7,FromAddr :: 700,ToAddr :: 800,RWType :: 6,DepTId :: -1,AddrDone :: 1 TId :: 3,NId :: 0,FromAddr :: 0,ToAddr :: 400,RWType :: 5,DepTId :: -1,AddrDone :: 1 --------------------------------------- code download here... Refs: NetWork on Chip @c