1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * Register Table Generator File: makereg.c 5 * 6 * Author: Mitch Lichtenberg (mpl@broadcom.com) 7 * 8 * Warning: don't eat your lunch before reading this program. 9 * It's nasty! 10 * 11 * This program generates tables of SOC registers and values 12 * that are easy for us to display. 13 * 14 ********************************************************************* 15 * 16 * Copyright 2000,2001,2002,2003 17 * Broadcom Corporation. All rights reserved. 18 * 19 * This software is furnished under license and may be used and 20 * copied only in accordance with the following terms and 21 * conditions. Subject to these conditions, you may download, 22 * copy, install, use, modify and distribute modified or unmodified 23 * copies of this software in source and/or binary form. No title 24 * or ownership is transferred hereby. 25 * 26 * 1) Any source code used, modified or distributed must reproduce 27 * and retain this copyright notice and list of conditions 28 * as they appear in the source file. 29 * 30 * 2) No right is granted to use any trade name, trademark, or 31 * logo of Broadcom Corporation. The "Broadcom Corporation" 32 * name may not be used to endorse or promote products derived 33 * from this software without the prior written permission of 34 * Broadcom Corporation. 35 * 36 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 37 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 38 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 39 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 40 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 41 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 42 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 43 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 44 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 45 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 46 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 47 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 48 * THE POSSIBILITY OF SUCH DAMAGE. 49 ********************************************************************* */ 50 51#include <stdio.h> 52#include <string.h> 53#include <malloc.h> 54#include <stdlib.h> 55 56#if defined(_MSC_VER) || defined(__CYGWIN__) 57#define TEXTMODE "t" 58#else 59#define TEXTMODE "" 60#endif 61 62typedef struct Cons { 63 char *str; 64 int num; 65} CONS; 66 67typedef struct RegInfo { 68 unsigned long reg_mask; 69 char *reg_agent; 70 int reg_agentidx; 71 char *reg_addr; 72 char *reg_inst; 73 char *reg_subinst; 74 char *reg_printfunc; 75 char *reg_description; 76} REGINFO; 77 78typedef struct ConstInfo { 79 char *name; 80 unsigned int value; 81} CONSTINFO; 82 83#define MAXCONST 64 84CONSTINFO constants[MAXCONST]; 85int constcnt = 0; 86 87#define MAXREGS 2000 88REGINFO allregs[MAXREGS]; 89int regcnt = 0; 90 91int maskcnt = 0; 92 93#define MAXAGENTS 32 94char *agentnames[MAXAGENTS]; 95int agentcnt; 96 97#define CMD_AGENT 1 98#define CMD_ENDAGENT 2 99 100CONS commands[] = { 101 {"!agent",CMD_AGENT}, 102 {"!endagent",CMD_ENDAGENT}, 103 {NULL,0}}; 104 105 106int assoc(CONS *list,char *str) 107{ 108 while (list->str) { 109 if (strcmp(list->str,str) == 0) return list->num; 110 list++; 111 } 112 113 return -1; 114} 115 116char *gettoken(char **ptr) 117{ 118 char *p = *ptr; 119 char *ret; 120 121 /* skip white space */ 122 123 while (*p && isspace(*p)) p++; 124 ret = p; 125 126 /* check for end of string */ 127 128 if (!*p) { 129 *ptr = p; 130 return NULL; 131 } 132 133 /* skip non-whitespace */ 134 135 while (*p) { 136 if (isspace(*p)) break; 137 138 /* do quoted strings */ 139 140 if (*p == '"') { 141 p++; 142 ret = p; 143 while (*p && (*p != '"')) p++; 144 if (*p == '"') *p = '\0'; 145 } 146 147 p++; 148 149 } 150 151 if (*p) { 152 *p++ = '\0'; 153 } 154 *ptr = p; 155 156 return ret; 157} 158 159static int readline(FILE *str,char *dest,int destlen) 160{ 161 char *x; 162 163 for (;;) { 164 if (!fgets(dest,destlen,str)) return -1; 165 if (x = strchr(dest,'\n')) *x = '\0'; 166 if (dest[0] == '\0') continue; 167 if (dest[0] == ';') continue; 168 break; 169 } 170 171 return 0; 172} 173 174 175static void fatal(char *str,char *val) 176{ 177 fprintf(stderr,"fatal error: %s %s\n",str,val ? val : ""); 178 exit(1); 179} 180 181static unsigned int newmask(void) 182{ 183 int res; 184 185 res = maskcnt; 186 187 if (maskcnt == 32) { 188 fatal("Out of mask bits",NULL); 189 } 190 191 maskcnt++; 192 193 return 1<<res; 194} 195 196static void addconst(char *name,unsigned int val) 197{ 198 if (constcnt == MAXCONST) { 199 fatal("Out of constant space",NULL); 200 } 201 202 constants[constcnt].name = strdup(name); 203 constants[constcnt].value = val; 204 205 constcnt++; 206} 207 208static void addreg( 209 char *agentname, 210 int agentidx, 211 unsigned long mask, 212 char *addr, 213 char *inst, 214 char *subinst, 215 char *printfunc, 216 char *description) 217{ 218 allregs[regcnt].reg_mask = mask; 219 allregs[regcnt].reg_addr = strdup(addr); 220 allregs[regcnt].reg_agent = strdup(agentname); 221 allregs[regcnt].reg_agentidx = agentidx; 222 allregs[regcnt].reg_inst = strdup(inst); 223 allregs[regcnt].reg_subinst = strdup(subinst); 224 allregs[regcnt].reg_printfunc = strdup(printfunc); 225 allregs[regcnt].reg_description = strdup(description); 226 regcnt++; 227} 228 229 230static void macroexpand(char *instr,char *exp,char *outstr) 231{ 232 while (*instr) { 233 if (*instr == '$') { 234 strcpy(outstr,exp); 235 outstr += strlen(outstr); 236 instr++; 237 } 238 else { 239 *outstr++ = *instr++; 240 } 241 } 242 243 *outstr = '\0'; 244} 245 246 247static void doagentcmd(FILE *str,char *line) 248{ 249 char *agentname; 250 char *instances; 251 char *inst; 252 char *ptr; 253 char regline[500]; 254 char cumlname[100]; 255 REGINFO regs[100]; 256 char temp[20]; 257 int rmax = 0; 258 int idx; 259 unsigned int cumlmask; 260 int agentidx; 261 262 agentname = gettoken(&line); 263 instances = gettoken(&line); 264 if (!instances) { 265 strcpy(temp,"*"); 266 instances = temp; 267 } 268 269 fprintf(stderr,"Agent %s Instances %s\n",agentname,instances); 270 271 if (agentcnt == MAXAGENTS) { 272 fatal("Out of agent slots\n",NULL); 273 } 274 275 agentnames[agentcnt] = strdup(agentname); 276 agentidx = agentcnt; 277 agentcnt++; 278 279 regline[0] = '\0'; 280 281 while ((readline(str,regline,sizeof(regline)) >= 0) && (rmax < 100)) { 282 char *atext,*subinst,*pfunc,*descr; 283 284 if (regline[0] == '!') break; 285 286 ptr = regline; 287 atext = gettoken(&ptr); 288 subinst = gettoken(&ptr); 289 pfunc = gettoken(&ptr); 290 descr = gettoken(&ptr); 291 292 if (!descr) { 293 fatal("Missing fields for ",atext); 294 } 295 296 regs[rmax].reg_addr = strdup(atext); 297 regs[rmax].reg_subinst = strdup(subinst); 298 regs[rmax].reg_printfunc = strdup(pfunc); 299 regs[rmax].reg_description = strdup(descr); 300 regs[rmax].reg_mask = 0; 301 rmax++; 302 } 303 304 if (rmax == 100) fatal("Too many registers in section ",agentname); 305 306 inst = strtok(instances,","); 307 308 cumlmask = 0; 309 while (inst) { 310 char defname[100]; 311 unsigned int curmask; 312 313 sprintf(defname,"SOC_AGENT_%s%s", 314 agentname,inst[0] == '*' ? "" : inst); 315 316 curmask = newmask(); 317 cumlmask |= curmask; 318 319 addconst(defname,curmask); 320 321 for (idx = 0; idx < rmax; idx++) { 322 char descr[100]; 323 char atext[200]; 324 325 macroexpand(regs[idx].reg_addr,inst,atext); 326 strcpy(descr,regs[idx].reg_description); 327 328 addreg(agentname, 329 agentidx, 330 curmask, 331 atext, 332 inst, 333 regs[idx].reg_subinst, 334 regs[idx].reg_printfunc, 335 descr); 336 } 337 inst = strtok(NULL,","); 338 } 339 340 if (instances[0] != '*') { 341 sprintf(cumlname,"SOC_AGENT_%s",agentname); 342 addconst(cumlname,cumlmask); 343 } 344} 345 346static void docommand(FILE *str,char *line) 347{ 348 char *cmd; 349 350 cmd = gettoken(&line); 351 if (!cmd) return; 352 353 switch (assoc(commands,cmd)) { 354 case CMD_AGENT: 355 doagentcmd(str,line); 356 break; 357 default: 358 fatal("Invalid command",cmd); 359 break; 360 } 361 362} 363 364static int ingestfile(FILE *str) 365{ 366 char line[500]; 367 368 while (readline(str,line,sizeof(line)) >= 0) { 369 if (line[0] == '!') { 370 docommand(str,line); 371 } 372 else { 373 fatal("Command string required before register data",NULL); 374 } 375 } 376} 377 378 379void saveincfile(char *fname) 380{ 381 FILE *str; 382 int idx; 383 384 str = fopen(fname,"w" TEXTMODE); 385 if (!str) { 386 perror(fname); 387 exit(1); 388 } 389 390 fprintf(str,"\n\n"); 391 392 fprintf(str,"#ifndef %s\n",constants[0].name); 393 for (idx = 0; idx < constcnt; idx++) { 394 fprintf(str,"#define %s 0x%08X\n",constants[idx].name, 395 constants[idx].value); 396 } 397 fprintf(str,"#endif\n"); 398 399 fprintf(str,"\n\n"); 400 401 fprintf(str,"#ifdef _CFE_\n"); 402 fprintf(str,"#ifdef __ASSEMBLER__\n"); 403 fprintf(str,"\t.globl socstatetable\n"); 404 fprintf(str,"socstatetable:\n"); 405 for (idx = 0; idx < regcnt; idx++) { 406 fprintf(str,"\t\t.word 0x%08X,%s\n", 407 allregs[idx].reg_mask,allregs[idx].reg_addr); 408 } 409 fprintf(str,"\t\t.word 0,0\n"); 410 fprintf(str,"#endif\n"); 411 412 fprintf(str,"\n\n"); 413 fprintf(str,"#ifndef __ASSEMBLER__\n"); 414 415 /* Addr Agent Inst Subinst Mask Printfunc Descr */ 416 417 fprintf(str,"char *socagents[] = {\n"); 418 for (idx = 0; idx < agentcnt; idx++) { 419 fprintf(str,"\t\"%s\",\n",agentnames[idx]); 420 } 421 fprintf(str,"\tNULL};\n\n"); 422 423 fprintf(str,"const socreg_t socregs[] = {\n"); 424 for (idx = 0; idx < regcnt; idx++) { 425 fprintf(str," {%s,%d,\"%s\",\"%s\",\n 0x%08X,%s,\"%s\"},\n", 426 allregs[idx].reg_addr, 427 allregs[idx].reg_agentidx, 428 allregs[idx].reg_inst, 429 allregs[idx].reg_subinst, 430 allregs[idx].reg_mask, 431 allregs[idx].reg_printfunc, 432 allregs[idx].reg_description); 433 } 434 fprintf(str," {0,0,NULL,NULL,0,NULL,NULL}};\n\n"); 435 436 fprintf(str,"#endif\n"); 437 fprintf(str,"#endif\n"); 438 fclose(str); 439} 440 441int main(int argc,char *argv[]) 442{ 443 FILE *str; 444 int idx; 445 446 if (argc != 3) { 447 fprintf(stderr,"usage: makereg inputfile outputfile\n"); 448 exit(1); 449 } 450 451 str = fopen(argv[1],"r" TEXTMODE); 452 453 if (!str) { 454 perror(argv[1]); 455 exit(1); 456 } 457 458 ingestfile(str); 459 460 fclose(str); 461 462 fprintf(stderr,"Total registers: %d\n",regcnt); 463 464 saveincfile(argv[2]); 465 466 exit(0); 467 return 0; 468} 469