qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [CONFIGURATION METHOD] A proposal


From: Salvatore Lionetti
Subject: [Qemu-devel] [CONFIGURATION METHOD] A proposal
Date: Fri, 28 Nov 2008 00:55:22 +0000 (GMT)

Hi,

i'm working a little on ppc405 emulation and.
Instead of
- overload method with many parameter,
- putting interface definition in the same implementation module,
- duplicate lot of code between similar board,

i've elaborated a first draft, compiled and working, of configuration 
component: see the comment on the head of file.

Thanks for eventually feedback (information, comment, proposal)

1,528d0
< /* Configuration object
<  * ====================
<  * 
<  * Every object:
<  * - is identified by a string (es '/walnut/cpu/mal/txeobisr')
<  * - is tagged with a type (es 'INT' 'STRING' 'PTR' 'FILE' 'CALLBACK')
<  * - have a value, which can be {set,get}ted.
<  * Es "/walnut/cpu/mal/txeobisr INT 0"
<  *
<  * Collection of objects is readed from a char* variable, 
<  * so can be acquired both from configuration file and code.
<  *
<  * Every sw entity can intercept a value set over an object.
<  * Co-relation take place in the context of set operation.
<  *
<  * As special case, sharing a pointer ex toward a variable,
<  * no code change is required after registering it.
<  *
<  * Ascii representation has some constrain:
<  * - start a line with a number of space equal to level number,
<  * - every object name have to start with '/'.
<  * - multivalue have to follow strictly this format: last/{a INT 0, b INT 1, 
...}
<  * 
<  * Some example:
< # Some comment
< /cpu
<  # That can be inserted
<  /emac
<   # At any level
<   /txeobisr INT 0
<  /iic/eeprom/{address INT 0x56, image FILE pid.bin}
<  /serial
<   /serial0/{base PTR 0x300, intr INT 0}
<   /serial1/{base PTR 0x400, intr INT 1, filename STRING "tcp:..."}
<  *
<  * Common interface or inheritance relation should be supported
<  * Not in this release
<  * Some example:
<  *
< eeprom{address INT, image FILE}
<  
< /cpu_meta
<  /emac
<   /txeobisr INT 0
<  /iic/eeprom
< 
< /cpu0(cpu_meta)
< /cpu1(cpu_meta)
<  *
<  * Configuration is totally dinamic so assertion about missing definition of 
an object (es no value during get())
<  * take place only when needed, like pure virtual function call in C++.
<  */
< 
< #include <assert.h>
< #define TEST
< #ifndef TEST
< #include "qemu-common.h"
< #include "hw.h"
< #else
< #define qemu_malloc malloc 
< #include <string.h>
< #include <stdio.h>
< #include <fcntl.h>
< #include <malloc.h>
< #include <sys/mman.h>
< /* Configuration object is a 3-ple:
<  * "/name/of/object", type, value
<  * Every function return <0 on error.
<  */
< enum hw_conf_basicT {
<       HW_CONF_NOTYPE,
<       HW_CONF_INT,
<       HW_CONF_STRING,
<       HW_CONF_PTR,
<       HW_CONF_FUNC,
< };
< #define HW_CONF_GET(name, val) hw_conf_get(name, (void**)&val)
< #define HW_CONF_SET(name, val) hw_conf_set(name, (void*)val)
< /* 0 let change happen, 1 deny current change (a voting alg) */
< typedef int (HWConf_corelateFunc)(void *opaque, const char* name, void* newv);
< 
< /* Return number of object successfully parsed. Value is only an opaque of 
type void* */
< int hw_conf_parsefrom(const char* str, int sz);
< int hw_conf_get(const char* name, void** val);
< int hw_conf_set(const char* name, void* val);
< void hw_conf_corelatewith(const char* str, HWConf_corelateFunc f, void* 
opaque);
< #endif
< struct hw_conf_corelateT {
<       HWConf_corelateFunc* f;
<       void* opaque;
< };
< struct hw_conf_nodeT {
<       /* Three related */
<       struct hw_conf_nodeT* nextH;
<       struct hw_conf_nodeT* nextV;
<       struct hw_conf_nodeT* prevV;
< 
<       char* id;
<       /* Data contents */
<       enum hw_conf_basicT type;
<       void* opaque;
< 
<       /* Communique with the world */
<       struct hw_conf_corelateT core[10];
< };
< 
< static struct hw_conf_nodeT hw_conf_root;
< static int hw_conf_haveroot = 0;
< 
< static void hw_conf_nodeinit(struct hw_conf_nodeT* n) {
<       int l;
< 
<       assert(n);
<       n->nextH = n->nextV = n->prevV = NULL;
<       n->id = NULL;
<       for (l=0; l<sizeof(n->core)/sizeof(n->core[0]); l++) {
<               n->core[l].f = NULL;
<               n->core[l].opaque = NULL;
<       }
< }
< 
< static void hw_conf_skipword(const char** s0, int n) {
<       const char* s = *s0;
<       while (*s && (s-*s0)<n) {
<               /* Until a char [^0-9xa-zA-Z_'"'"] */
<               if (!((*s>='0' && *s<='9') || (*s>='a' && *s<='z') || (*s>='A' 
&& *s<='Z')/*|| *s=='\'' || *s=='\"'*/)) {
<                       break;
<               }
<               s++;
<       }
<       *s0 = s;
< }
< 
< /* Return 0 => root */
< static int hw_conf_getLevel(struct hw_conf_nodeT* n) {
<       int ret = 0;
<       while (n->prevV != &hw_conf_root) {
<               n = n->prevV;
<               ret++;
<       }
<       return ret;
< }
< static struct hw_conf_nodeT* hw_conf_find(struct hw_conf_nodeT* n0, const 
char** id, int create) {
<       char haveMultiValue;
<       struct hw_conf_nodeT* n, *nKm1;
<       struct hw_conf_nodeT* ret = NULL;
<       if (n0 == NULL || id == NULL || *id==NULL)
<               return ret;
< 
<       (*id)++;
<       if ((*id)[0]=='{')
<               (*id)++;
<       /* Root initialize */
<       if (hw_conf_haveroot == 0) {
<               hw_conf_nodeinit(&hw_conf_root);
<               hw_conf_haveroot = 1;
<       }
<       
<       haveMultiValue = 0;
<       /* Down one level, then loop trow node */
<       nKm1 = n = n0->nextV;
<       while (n && !ret) {
<               if (strstr(*id, n->id)) {
<                       *id+=strlen(n->id);
<                       switch (*id[0]) {
<                               case '/':
<                                       ret = hw_conf_find(n, id, create);
<                                       break;
<                               case '\x0':
<                                       ret = n;
<                                       break;
<                               default:
<                                       break;
<                       }
<               }
<               nKm1 = n;
<               n = n->nextH;
<       }
<       if (!ret && create) {
<               struct hw_conf_nodeT* newn = (struct hw_conf_nodeT*) 
qemu_malloc(sizeof(struct hw_conf_nodeT));
<               const char* eon;
<               int len;
< 
<               eon = *id;
<               hw_conf_skipword(&eon, 255);
< 
<               len = eon-*id;
<               hw_conf_nodeinit(newn);
<               newn->id = qemu_malloc(len+1);
<               memcpy(newn->id, *id, len);
<               newn->id[len] = '\x0';
< 
<               /* 
<                * on new node:
<                * nextH: NULL (we add to the tail)
<                * nextV: NULL (no child when create)
<                * prevV: n0   (always have a node of level-1)
<                */
<               newn->prevV = n0;
<               if (n0->nextV) {
<                       /* Link to last in this level */
<                       assert(nKm1->nextH==NULL);
<                       nKm1->nextH = newn;
<               } else {
<                       /* First item on this level */
<                       n0->nextV = newn;
<               }
< 
<               *id=eon;
<               ret = *eon!='/' ? newn : hw_conf_find(newn, id, create);
<       }
<       if (ret) {
<               switch (ret->type) {
<                       case HW_CONF_INT:
<                       case HW_CONF_STRING:
<                       case HW_CONF_PTR:
<                       case HW_CONF_FUNC:
<                       case HW_CONF_NOTYPE:
<                               break;
<                       default:
<                               assert("Find a node with unmanaged type!");
<                               break;
<               }
<       }
<       return ret;
< }
< 
< char* hw_conf_getTypeDes(enum hw_conf_basicT t) {
<       char* ret = NULL;
<       switch (t) {
<               case HW_CONF_INT:       ret = "INT"; break;
<               case HW_CONF_STRING:    ret = "STRING"; break;
<               case HW_CONF_PTR:       ret = "PTR"; break;
<               case HW_CONF_FUNC:      ret = "FUNC"; break;
<               case HW_CONF_NOTYPE:    ret = "NOTYPE"; break;
<               default:                ret = "UNKTYPE"; break;
<       }
<       return ret;
< }
< 
< enum hw_conf_basicT hw_conf_parseType(const char** s, int n) {
<       enum hw_conf_basicT ret = HW_CONF_NOTYPE;
<       if (s==NULL || *s==NULL || n==0)
<               return ret;
< 
<              if (strncmp(*s, "INT ", n>4?4:n)==0) {
<               (*s)+=4;
<               ret = HW_CONF_INT;
<       } else if (strncmp(*s, "STRING ", n>7?7:n)==0) {
<               (*s)+=7;
<               ret = HW_CONF_STRING;
<       } else if (strncmp(*s, "PTR ", n>4?4:n)==0) {
<               (*s)+=4;
<               ret = HW_CONF_PTR;
<       } else if (strncmp(*s, "FUNC ", n>5?5:n)==0) {
<               (*s)+=5;
<               ret = HW_CONF_FUNC;
<       }
<       return ret;
< }
< int hw_conf_parseValue(const char** s0, int n, enum hw_conf_basicT t, void** 
o) {
<       int ret=0;
<       if (s0 && *s0 && n) {
<               const char* s = *s0;
<               switch (t) {
<                       case HW_CONF_INT:
<                       case HW_CONF_PTR:
<                               hw_conf_skipword(&s, n);
<                               if (sscanf(*s0, "0x%x", (int*)o)==1 || 
sscanf(*s0, "%d", (int*)o)==1)
<                                       ret = 1;
<                               break;
<                       case HW_CONF_STRING:
<                       case HW_CONF_FUNC:
<                       {
<                               if (**s0=='\'' || **s0=='\"') {
<                                       char* tmp;
<                                       s++;
<                                       while (n-(*s0-s)>0 && (*s!='\'' && 
*s!='\"')) {
<                                               s++;
<                                       }
<                                       tmp = qemu_malloc(s-*s0);
<                                       memcpy(tmp, *s0+1, s-*s0-1);
<                                       tmp[s-*s0-1] = '\x0';
<                                       *o = (void*) tmp;
<                                               
<                                       ret = 1;
<                               }
<                               break;
<                       }
<               }
<               if (ret==1) {
<                       *s0 = s;
<               }
<       }
<       return ret;
< }
< 
< /* Elaborate until eof | eos */
< int hw_conf_parsefrom(const char* name, int sz) {
<       enum {HW_CONF_READING_LEVEL, HW_CONF_READING_NAME, HW_CONF_READED_NAME, 
HW_CONF_READING_TYPE, HW_CONF_READING_VALUE, HW_CONF_READING_DONE} state;
<       enum hw_conf_basicT t;
<       void *o;
<       char nlev, nlevKm1, comment;
<       int nobj;
<       const char* n = name;
<       struct hw_conf_nodeT* node;
< 
<       printf("len %d\n", sz);
<       state = HW_CONF_READING_LEVEL;
<       t = HW_CONF_NOTYPE;
<       nlev = nlevKm1 = comment = 0;
<       nobj = 0;
<       if (name==NULL)
<               return nobj;
<       if (sz == 0)
<               sz = strlen(name);
<       while ((n-name)<sz && *n) {
<               if (comment==0 || *n==0xa) {
<               switch (*n) {
<                       case ' ':
<                               if (state == HW_CONF_READED_NAME) {
<                                       state = HW_CONF_READING_TYPE;
<                               }
<                               if (state == HW_CONF_READING_LEVEL) {
<                                       nlev++;
<                               }
<                               break;
<                       case ',':
<                               /* Multi value line */
<                               if (state == HW_CONF_READING_DONE) {
<                                       state = HW_CONF_READING_NAME;
<                                       nlev--;
<                                       node = node->prevV;
<                                       n++; /* Skip ',' */
<                               } else {
<                                       break;
<                               }
<                       case '/':
<                               if (state <= HW_CONF_READING_NAME) {
<                                       if (nlev>nlevKm1) {
<                                               assert((nlev - nlevKm1) == 1);
<                                       }
<                                       while (nlev && nlev<=nlevKm1) {
<                                               node = node->prevV;
<                                               nlevKm1--;
<                                       }
<                                       if (nlev == 0) {
<                                               node = &hw_conf_root;
<                                       }
<                                       node = hw_conf_find(node, &n, 1);
<                                       nlev = hw_conf_getLevel(node);
<                                       state=HW_CONF_READED_NAME;
<                                       n--;
<                               }
<                               break;
<                       case '}':
<                               nlev--;
<                               node = node->prevV;
<                               break;
<                       case 0xa:
<                               if (comment) {
<                                       nlev = 0;
<                               }
<                               comment = 0;
<                               if (state != HW_CONF_READING_LEVEL) {
<                                       state = HW_CONF_READING_LEVEL;
<                                       nlevKm1 = nlev;
<                                       nlev = 0;
<                               }
<                               break;
<                       case '#':
<                               comment = 1;
<                               break;
<                       default:
<                               switch (state) {
<                                       case HW_CONF_READING_TYPE:
<                                               if ((t = hw_conf_parseType(&n, 
sz-(n-name)))!=HW_CONF_NOTYPE) {
<                                                       state = 
HW_CONF_READING_VALUE;
<                                                       n--;
<                                               }
<                                               break;
<                                       case HW_CONF_READING_VALUE:
<                                               if (hw_conf_parseValue(&n, 
sz-(n-name), t, &o)) {
<                                                       node->type = t;
<                                                       node->opaque = o;
<                                                       state = 
HW_CONF_READING_DONE;
<                                                       nobj++;
<                                                       n--;
<                                               }
<                                       default:
<                                               break;
<                               }
<                               break;
<               } /* switch */
<               } /* if */
<               n++;
< 
<       }
<       return nobj;
< }
< int hw_conf_get(const char* name, void** val) {
<       struct hw_conf_nodeT *ret = hw_conf_find(&hw_conf_root, &name, 0);
<       if (ret)
<               *val = ret->opaque;
<       return ret!=NULL;
< }
< int hw_conf_set(const char* name, void* val) {
<       const char* orign = name;
<       struct hw_conf_nodeT *ret = hw_conf_find(&hw_conf_root, &name, 0);
<       if (ret) {
<               /* Inform the world */
<               int i, l;
<               l = 0;
<               for (i=0; i<sizeof(ret->core)/sizeof(ret->core[0]); i++)
<                       if (ret->core[i].f)
<                               l += ret->core[i].f(ret->core[i].opaque, orign, 
val);
< 
<               if (l==0)
<                       ret->opaque = val;
<       }
<       return ret!=NULL;
< }
< void hw_conf_corelatewith(const char* name, HWConf_corelateFunc f, void* 
opaque) {
<       struct hw_conf_nodeT *ret = hw_conf_find(&hw_conf_root, &name, 0);
<       if (ret) {
<               int i;
<               for (i=0; i<sizeof(ret->core)/sizeof(ret->core[0]); i++)
<                       if (ret->core[i].f==NULL && ret->core[i].opaque==NULL) {
<                               ret->core[i].f = f;
<                               ret->core[i].opaque = opaque;
<                               break;
<                       }
<               if (i == sizeof(ret->core)/sizeof(ret->core[0])) {
<                       assert("Not enough space for store corelation 
information!");
<               }
<       } else {
<               assert("Corelation with non existent object");
<       }
< }
< /* scende & stampa con nextV
<  * sale con prevV e segue nextH
<  * sale con prevV
<  * fino ad n0
<  */
< int hw_conf_printfrom(struct hw_conf_nodeT* n0) {
<       struct hw_conf_nodeT *n;
<       int nlev, nlevKm1, lastWasUp;
<       int nobj = 0;
<       if (n0==NULL || n0->nextV==NULL)
<               return nobj;
<       n = n0->nextV;
<       nlev = lastWasUp = 0;
<       while (n != n0) {
<               if (!lastWasUp) {
<               int i;
<               for (i=0; i<nlev; i++)
<                       printf(" ");
<               printf("/%s", n->id);
<               if (n->type!=HW_CONF_NOTYPE) {
<                       printf(" %s ", hw_conf_getTypeDes(n->type));
<                       if (n->type == HW_CONF_STRING) {
<                               printf("'%s'", (char*) n->opaque);
<                       } else {
<                               printf("0x%x", n->opaque);
<                       }
<               }
<               printf("\n");
<               }
<               if (n->nextV && !lastWasUp) {
<                       nlev++;
<                       n = n->nextV;
<               /* Are on leaf: 1) Try same level, then go up */
<               } else {
<                       if (n->nextH) {
<                               n = n->nextH;
<                               lastWasUp = 0;
<                       } else {
<                               nlev--;
<                               n = n->prevV;
<                               lastWasUp = 1;
<                       }
<               }
<       }
<       return nobj;
< }
< 
< char* open_mmap(char* fn, int* len) {
<       int fd;
<       char* ret = NULL;
<       fd = open(fn, O_RDONLY);
<       if (fd>0) {
<               *len = lseek(fd, 0, SEEK_END);
<               printf("File lungo %d bytes\n", *len);
<               ret=mmap(NULL, *len, PROT_READ, MAP_SHARED, fd, 0);
<               if (ret==MAP_FAILED)
<                       ret = NULL;
<       }
<       return ret;
< }
< #ifdef TEST
< int core(void *opaque, const char* name, void* newv) {
<       printf("Co-relation(this=0x%x) %s now %x\n", opaque, name, newv);
<       return 0;
< }
< int main(int argc, char* argv[]) {
<       char tmp[256];
<       char* tmp1=NULL;
<       int len;
<       void* serial_base;
<       char* info = "\
< /cpu\n\
<  /serial\n\
<   /base PTR 0x500\n\
<   /intr STRING '0'\n\
<  /emac/txeobisr INT 0\n\
< /iic/eeprom\n\
<   /address INT 0x56\n\
<   /image STRING 'pid.bin'";
<       len = 0;
<       tmp1 = open_mmap("hw_conf.txt", &len);
<       printf("parse = %d\n", hw_conf_parsefrom(tmp1, len));
<       hw_conf_printfrom(&hw_conf_root);
<       hw_conf_get("/cpu/serial/base", &serial_base);
<       printf("get serial_base 0x%x\n", serial_base);
<       hw_conf_corelatewith("/cpu/serial/base", core, (void*)4);
<       serial_base++;
<       hw_conf_set("/cpu/serial/base", serial_base);
<       serial_base=0;
<       hw_conf_get("/cpu/serial/base", &serial_base);
<       printf("get serial_base 0x%x\n", serial_base);
< }
< #endif







reply via email to

[Prev in Thread] Current Thread [Next in Thread]