1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * Register Table Generator File: makereg.c 5 * 6 * Author: Mitch Lichtenberg 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 <ctype.h> 52#include <stdio.h> 53#include <string.h> 54#include <malloc.h> 55#include <stdlib.h> 56 57#if defined(_MSC_VER) || defined(__CYGWIN__) 58#define TEXTMODE "t" 59#else 60#define TEXTMODE "" 61#endif 62 63#define FALSE 0 64#define TRUE 1 65 66typedef struct Cons { 67 char *str; 68 int num; 69} CONS; 70 71typedef struct RegInfo { 72 unsigned int reg_mask; 73 char *reg_agent; 74 int reg_agentidx; 75 char *reg_addr; 76 char *reg_inst; 77 char *reg_subinst; 78 char *reg_printfunc; 79 char *reg_description; 80} REGINFO; 81 82typedef struct ConstInfo { 83 char *name; 84 unsigned int value; 85} CONSTINFO; 86 87#define MAXCONST 256 88CONSTINFO constants[MAXCONST]; 89int constcnt = 0; 90 91#define MAXREGS 5000 92REGINFO allregs[MAXREGS]; 93int regcnt = 0; 94 95int maskcnt = 0; 96 97#define MAXAGENTS 64 98char *agentnames[MAXAGENTS]; 99int agentcnt; 100 101#define CMD_AGENT 1 102#define CMD_ENDAGENT 2 103#define CMD_AGENT_NOMASK 3 104 105CONS commands[] = { 106 {"!agent",CMD_AGENT}, 107 {"!agent_nomask",CMD_AGENT_NOMASK}, 108 {"!endagent",CMD_ENDAGENT}, 109 {NULL,0}}; 110 111static int assoc(CONS *list,char *str) 112{ 113 while (list->str) { 114 if (strcmp(list->str,str) == 0) return list->num; 115 list++; 116 } 117 118 return -1; 119} 120 121static char *gettoken(char **ptr) 122{ 123 char *p = *ptr; 124 char *ret; 125 126 /* skip white space */ 127 128 while (*p && isspace(*p)) p++; 129 ret = p; 130 131 /* check for end of string */ 132 133 if (!*p) { 134 *ptr = p; 135 return NULL; 136 } 137 138 /* skip non-whitespace */ 139 140 while (*p) { 141 if (isspace(*p)) break; 142 143 /* do quoted strings */ 144 145 if (*p == '"') { 146 p++; 147 ret = p; 148 while (*p && (*p != '"')) p++; 149 if (*p == '"') *p = '\0'; 150 } 151 152 p++; 153 154 } 155 156 if (*p) { 157 *p++ = '\0'; 158 } 159 *ptr = p; 160 161 return ret; 162} 163 164static int readline(FILE *str,char *dest,int destlen) 165{ 166 char *x; 167 168 for (;;) { 169 if (!fgets(dest,destlen,str)) return -1; 170 if ((x = strchr(dest,'\n')) != NULL) *x = '\0'; 171 if (dest[0] == '\0') continue; 172 if (dest[0] == ';') continue; 173 break; 174 } 175 176 return 0; 177} 178 179 180static void fatal(char *str,char *val) 181{ 182 fprintf(stderr,"fatal error: %s %s\n",str,val ? val : ""); 183 exit(1); 184} 185 186static unsigned int newmask(void) 187{ 188 int res; 189 190 res = maskcnt; 191 192 if (maskcnt == 32) { 193 fatal("Out of mask bits",NULL); 194 } 195 196 maskcnt++; 197 198 return 1<<res; 199} 200 201static void addconst(char *name,unsigned int val) 202{ 203 if (constcnt == MAXCONST) { 204 fatal("Out of constant space",NULL); 205 } 206 207 constants[constcnt].name = strdup(name); 208 constants[constcnt].value = val; 209 210 constcnt++; 211} 212 213static void addreg( 214 char *agentname, 215 int agentidx, 216 unsigned long mask, 217 char *addr, 218 char *inst, 219 char *subinst, 220 char *printfunc, 221 char *description) 222{ 223 allregs[regcnt].reg_mask = mask; 224 allregs[regcnt].reg_addr = strdup(addr); 225 allregs[regcnt].reg_agent = strdup(agentname); 226 allregs[regcnt].reg_agentidx = agentidx; 227 allregs[regcnt].reg_inst = strdup(inst); 228 allregs[regcnt].reg_subinst = strdup(subinst); 229 allregs[regcnt].reg_printfunc = strdup(printfunc); 230 allregs[regcnt].reg_description = strdup(description); 231 regcnt++; 232} 233 234 235static void macroexpand(char *instr,char *exp,char *outstr) 236{ 237 while (*instr) { 238 if (*instr == '$') { 239 strcpy(outstr,exp); 240 outstr += strlen(outstr); 241 instr++; 242 } 243 else { 244 *outstr++ = *instr++; 245 } 246 } 247 248 *outstr = '\0'; 249} 250 251 252static void doagentcmd(FILE *str,char *line,int nomask) 253{ 254 char *agentname; 255 char *instances; 256 char *inst; 257 char *ptr; 258 char regline[500]; 259 char cumlname[100]; 260 REGINFO regs[100]; 261 char temp[20]; 262 int rmax = 0; 263 int idx; 264 unsigned int cumlmask; 265 int agentidx; 266 267 agentname = gettoken(&line); 268 instances = gettoken(&line); 269 if (!instances) { 270 strcpy(temp,"*"); 271 instances = temp; 272 } 273 274 fprintf(stderr,"Agent %s Instances %s\n",agentname,instances); 275 276 if (agentcnt == MAXAGENTS) { 277 fatal("Out of agent slots\n",NULL); 278 } 279 280 agentnames[agentcnt] = strdup(agentname); 281 agentidx = agentcnt; 282 agentcnt++; 283 284 regline[0] = '\0'; 285 286 while ((readline(str,regline,sizeof(regline)) >= 0) && (rmax < 100)) { 287 char *atext,*subinst,*pfunc,*descr; 288 289 if (regline[0] == '!') break; 290 291 ptr = regline; 292 atext = gettoken(&ptr); 293 subinst = gettoken(&ptr); 294 pfunc = gettoken(&ptr); 295 descr = gettoken(&ptr); 296 297 if (!descr) { 298 fatal("Missing fields for ",atext); 299 } 300 301 regs[rmax].reg_addr = strdup(atext); 302 regs[rmax].reg_subinst = strdup(subinst); 303 regs[rmax].reg_printfunc = strdup(pfunc); 304 regs[rmax].reg_description = strdup(descr); 305 regs[rmax].reg_mask = 0; 306 rmax++; 307 } 308 309 if (rmax == 100) fatal("Too many registers in section ",agentname); 310 311 inst = strtok(instances,","); 312 313 cumlmask = 0; 314 while (inst) { 315 char defname[100]; 316 unsigned int curmask; 317 318 sprintf(defname,"SOC_AGENT_%s%s", 319 agentname,inst[0] == '*' ? "" : inst); 320 321 if (nomask) { 322 curmask = 0; 323 } 324 else { 325 curmask = newmask(); 326 cumlmask |= curmask; 327 } 328 329 addconst(defname,curmask); 330 331 for (idx = 0; idx < rmax; idx++) { 332 char descr[100]; 333 char atext[200]; 334 335 macroexpand(regs[idx].reg_addr,inst,atext); 336#if 0 337 strcpy(descr,agentname); 338 if (inst[0] != '*') { 339 strcat(descr,inst); 340 } 341 strcat(descr," "); 342 if (regs[idx].reg_subinst[0] != '*') { 343 strcat(descr,regs[idx].reg_subinst); 344 strcat(descr," "); 345 } 346 strcat(descr,regs[idx].reg_description); 347#else 348 strcpy(descr,regs[idx].reg_description); 349#endif 350 351 addreg(agentname, 352 agentidx, 353 curmask, 354 atext, 355 inst, 356 regs[idx].reg_subinst, 357 regs[idx].reg_printfunc, 358 descr); 359 } 360 inst = strtok(NULL,","); 361 } 362 363 if (instances[0] != '*') { 364 sprintf(cumlname,"SOC_AGENT_%s",agentname); 365 addconst(cumlname,cumlmask); 366 } 367} 368 369static void docommand(FILE *str,char *line) 370{ 371 char *cmd; 372 373 cmd = gettoken(&line); 374 if (!cmd) return; 375 376 switch (assoc(commands,cmd)) { 377 case CMD_AGENT: 378 doagentcmd(str,line,FALSE); 379 break; 380 case CMD_AGENT_NOMASK: 381 doagentcmd(str,line,TRUE); 382 break; 383 default: 384 fatal("Invalid command",cmd); 385 break; 386 } 387 388} 389 390static void ingestfile(FILE *str) 391{ 392 char line[500]; 393 394 while (readline(str,line,sizeof(line)) >= 0) { 395 if (line[0] == '!') { 396 docommand(str,line); 397 } 398 else { 399 fatal("Command string required before register data",NULL); 400 } 401 } 402} 403 404 405static void saveincfile(char *fname, char *header) 406{ 407 FILE *str; 408 int idx; 409 410 str = fopen(fname,"w" TEXTMODE); 411 if (!str) { 412 perror(fname); 413 exit(1); 414 } 415 416 fprintf(str,"\n\n"); 417 418 if (header != NULL) { 419 fprintf(str, "#include \"%s\"\n", header); 420 fprintf(str,"\n\n"); 421 } 422 423 fprintf(str,"#ifndef %s\n",constants[0].name); 424 for (idx = 0; idx < constcnt; idx++) { 425 fprintf(str,"#define %s 0x%08X\n",constants[idx].name, 426 constants[idx].value); 427 } 428 fprintf(str,"#endif\n"); 429 430 fprintf(str,"\n\n"); 431 432 fprintf(str,"#ifdef _CFE_\n"); 433 fprintf(str,"#ifdef __ASSEMBLER__\n"); 434 fprintf(str,"\t.globl socstatetable\n"); 435 fprintf(str,"socstatetable:\n"); 436 for (idx = 0; idx < regcnt; idx++) { 437 fprintf(str,"\t\t.word 0x%08X,%s\n", 438 allregs[idx].reg_mask,allregs[idx].reg_addr); 439 } 440 fprintf(str,"\t\t.word 0,0\n"); 441 fprintf(str,"#endif\n"); 442 443 fprintf(str,"\n\n"); 444 fprintf(str,"#ifndef __ASSEMBLER__\n"); 445 446 /* Addr Agent Inst Subinst Mask Printfunc Descr */ 447 448 fprintf(str,"char *socagents[] = {\n"); 449 for (idx = 0; idx < agentcnt; idx++) { 450 fprintf(str,"\t\"%s\",\n",agentnames[idx]); 451 } 452 fprintf(str,"\tNULL};\n\n"); 453 454 fprintf(str,"const socreg_t socregs[] = {\n"); 455 for (idx = 0; idx < regcnt; idx++) { 456 fprintf(str," {%s,%d,\"%s\",\"%s\",\n 0x%08X,%s,\"%s\"},\n", 457 allregs[idx].reg_addr, 458 allregs[idx].reg_agentidx, 459 allregs[idx].reg_inst, 460 allregs[idx].reg_subinst, 461 allregs[idx].reg_mask, 462 allregs[idx].reg_printfunc, 463 allregs[idx].reg_description); 464 } 465 fprintf(str," {0,0,NULL,NULL,0,NULL,NULL}};\n\n"); 466 467 fprintf(str,"#endif\n"); 468 fprintf(str,"#endif\n"); 469 fclose(str); 470} 471 472int main(int argc,char *argv[]) 473{ 474 FILE *str; 475 476 if (argc != 3 && argc != 4) { 477 fprintf(stderr,"usage: makereg inputfile outputfile [header]\n"); 478 exit(1); 479 } 480 481 str = fopen(argv[1],"r" TEXTMODE); 482 483 if (!str) { 484 perror(argv[1]); 485 exit(1); 486 } 487 488 ingestfile(str); 489 490 fclose(str); 491 492 fprintf(stderr,"Total registers: %d\n",regcnt); 493 494 saveincfile(argv[2], argc > 3 ? argv[3] : NULL); 495 496 exit(0); 497 return 0; 498} 499