| 1 | """Utilities needed to emulate Python's interactive interpreter. |
| 2 | """ |
| 3 | # |
| 4 | # copied from RiesCode.py, for cosim & sam environment |
| 5 | # |
| 6 | |
| 7 | import os, re, string, sys, time, types |
| 8 | |
| 9 | from Pfe_Conversion import * |
| 10 | from Pfe_Assembler import * |
| 11 | |
| 12 | no_sam = 0 |
| 13 | try: |
| 14 | import sam |
| 15 | except: |
| 16 | no_sam = 1 |
| 17 | |
| 18 | import traceback |
| 19 | from codeop import CommandCompiler, compile_command |
| 20 | |
| 21 | __all__ = ["InteractiveInterpreter", "InteractiveConsole", "interact", |
| 22 | "compile_command"] |
| 23 | |
| 24 | # constants |
| 25 | PLI_RUN = 'pli-run' |
| 26 | QUIT = 'quit' |
| 27 | RUN_PYTHON_FILE = 'run-python-file' |
| 28 | |
| 29 | DONE = 1 |
| 30 | DONE_NOT = 0 |
| 31 | |
| 32 | # when 1, ignore any exception associated with a wrong python statement |
| 33 | IGNORE_EXCEPT = 0 |
| 34 | |
| 35 | SIM = 'sim' |
| 36 | RSYS = 'rsys' |
| 37 | CPU = 'cpu' |
| 38 | CORE = 'core' |
| 39 | UCORE = 'ucore' |
| 40 | STRAND = 'strand' |
| 41 | |
| 42 | # regular expression used to catch execfile() command |
| 43 | execfileRE = re.compile("^execfile(\s)*\([^\(\)]+\)$") |
| 44 | NEW_CMD_RE = re.compile('^@?new_command\s*\(') |
| 45 | DIGITAL_RE = re.compile('^[0-9]+$') |
| 46 | |
| 47 | RC_SYS_CONFIG_OBJ = 'config0' |
| 48 | RC_PROMPT = 'prompt' |
| 49 | RC_MEM_IMAGE = 'mem_image' |
| 50 | RC_COMMAND = 'command' |
| 51 | RC_COMMAND_EXT = 'command_ext' |
| 52 | RC_FUNC_DEF = 'func_def' |
| 53 | |
| 54 | |
| 55 | def softspace(file, newvalue): |
| 56 | oldvalue = 0 |
| 57 | try: |
| 58 | oldvalue = file.softspace |
| 59 | except AttributeError: |
| 60 | pass |
| 61 | try: |
| 62 | file.softspace = newvalue |
| 63 | except (AttributeError, TypeError): |
| 64 | # "attribute-less object" or "read-only attributes" |
| 65 | pass |
| 66 | return oldvalue |
| 67 | |
| 68 | class InteractiveInterpreter: |
| 69 | """Base class for InteractiveConsole. |
| 70 | |
| 71 | This class deals with parsing and interpreter state (the user's |
| 72 | namespace); it doesn't deal with input buffering or prompting or |
| 73 | input file naming (the filename is always passed in explicitly). |
| 74 | |
| 75 | """ |
| 76 | |
| 77 | def __init__(self, locals=None): |
| 78 | """Constructor. |
| 79 | |
| 80 | The optional 'locals' argument specifies the dictionary in |
| 81 | which code will be executed; it defaults to a newly created |
| 82 | dictionary with key "__name__" set to "__console__" and key |
| 83 | "__doc__" set to None. |
| 84 | |
| 85 | """ |
| 86 | if locals is None: |
| 87 | locals = {"__name__": "__console__", "__doc__": None} |
| 88 | self.locals = locals |
| 89 | self.compile = CommandCompiler() |
| 90 | |
| 91 | def runsource(self, source, filename="<input>", symbol="single"): |
| 92 | """Compile and run some source in the interpreter. |
| 93 | |
| 94 | Arguments are as for compile_command(). |
| 95 | |
| 96 | One several things can happen: |
| 97 | |
| 98 | 1) The input is incorrect; compile_command() raised an |
| 99 | exception (SyntaxError or OverflowError). A syntax traceback |
| 100 | will be printed by calling the showsyntaxerror() method. |
| 101 | |
| 102 | 2) The input is incomplete, and more input is required; |
| 103 | compile_command() returned None. Nothing happens. |
| 104 | |
| 105 | 3) The input is complete; compile_command() returned a code |
| 106 | object. The code is executed by calling self.runcode() (which |
| 107 | also handles run-time exceptions, except for SystemExit). |
| 108 | |
| 109 | The return value is 1 in case 2, 0 in the other cases (unless |
| 110 | an exception is raised). The return value can be used to |
| 111 | decide whether to use sys.ps1 or sys.ps2 to prompt the next |
| 112 | line. |
| 113 | |
| 114 | """ |
| 115 | global IGNORE_EXCEPT |
| 116 | |
| 117 | try: |
| 118 | code = self.compile(source, filename, symbol) |
| 119 | except (OverflowError, SyntaxError, ValueError): |
| 120 | # Case 1 |
| 121 | if IGNORE_EXCEPT != 1: |
| 122 | self.showsyntaxerror(filename) |
| 123 | else: |
| 124 | raise |
| 125 | return 0 |
| 126 | |
| 127 | if code is None: |
| 128 | # Case 2 |
| 129 | return 1 |
| 130 | |
| 131 | # Case 3 |
| 132 | self.runcode(code) |
| 133 | return 0 |
| 134 | |
| 135 | def runcode(self, code): |
| 136 | """Execute a code object. |
| 137 | |
| 138 | When an exception occurs, self.showtraceback() is called to |
| 139 | display a traceback. All exceptions are caught except |
| 140 | SystemExit, which is reraised. |
| 141 | |
| 142 | A note about KeyboardInterrupt: this exception may occur |
| 143 | elsewhere in this code, and may not always be caught. The |
| 144 | caller should be prepared to deal with it. |
| 145 | |
| 146 | """ |
| 147 | global IGNORE_EXCEPT |
| 148 | |
| 149 | try: |
| 150 | exec code in self.locals |
| 151 | except SystemExit: |
| 152 | sys.stderr.write("# %s: end riesling frontend\n" % (time.ctime())) |
| 153 | raise |
| 154 | ## except AttributeError: |
| 155 | ## raise |
| 156 | except: |
| 157 | if IGNORE_EXCEPT != 1: |
| 158 | self.showtraceback() |
| 159 | else: |
| 160 | raise |
| 161 | else: |
| 162 | if softspace(sys.stdout, 0): |
| 163 | print |
| 164 | |
| 165 | def showsyntaxerror(self, filename=None): |
| 166 | """Display the syntax error that just occurred. |
| 167 | |
| 168 | This doesn't display a stack trace because there isn't one. |
| 169 | |
| 170 | If a filename is given, it is stuffed in the exception instead |
| 171 | of what was there before (because Python's parser always uses |
| 172 | "<string>" when reading from a string). |
| 173 | |
| 174 | The output is written by self.write(), below. |
| 175 | |
| 176 | """ |
| 177 | type, value, sys.last_traceback = sys.exc_info() |
| 178 | sys.last_type = type |
| 179 | sys.last_value = value |
| 180 | if filename and type is SyntaxError: |
| 181 | # Work hard to stuff the correct filename in the exception |
| 182 | try: |
| 183 | msg, (dummy_filename, lineno, offset, line) = value |
| 184 | except: |
| 185 | # Not the format we expect; leave it alone |
| 186 | pass |
| 187 | else: |
| 188 | # Stuff in the right filename |
| 189 | try: |
| 190 | # Assume SyntaxError is a class exception |
| 191 | value = SyntaxError(msg, (filename, lineno, offset, line)) |
| 192 | except: |
| 193 | # If that failed, assume SyntaxError is a string |
| 194 | value = msg, (filename, lineno, offset, line) |
| 195 | sys.last_value = value |
| 196 | list = traceback.format_exception_only(type, value) |
| 197 | map(self.write, list) |
| 198 | |
| 199 | def showtraceback(self): |
| 200 | """Display the exception that just occurred. |
| 201 | |
| 202 | We remove the first stack item because it is our own code. |
| 203 | |
| 204 | The output is written by self.write(), below. |
| 205 | |
| 206 | """ |
| 207 | try: |
| 208 | type, value, tb = sys.exc_info() |
| 209 | sys.last_type = type |
| 210 | sys.last_value = value |
| 211 | sys.last_traceback = tb |
| 212 | tblist = traceback.extract_tb(tb) |
| 213 | del tblist[:1] |
| 214 | list = traceback.format_list(tblist) |
| 215 | if list: |
| 216 | list.insert(0, "Traceback (most recent call last):\n") |
| 217 | list[len(list):] = traceback.format_exception_only(type, value) |
| 218 | finally: |
| 219 | tblist = tb = None |
| 220 | map(self.write, list) |
| 221 | |
| 222 | def write(self, data): |
| 223 | """Write a string. |
| 224 | |
| 225 | The base implementation writes to sys.stderr; a subclass may |
| 226 | replace this with a different implementation. |
| 227 | |
| 228 | """ |
| 229 | sys.stderr.write(data) |
| 230 | |
| 231 | |
| 232 | class InteractiveConsole(InteractiveInterpreter): |
| 233 | """Closely emulate the behavior of the interactive Python interpreter. |
| 234 | |
| 235 | This class builds on InteractiveInterpreter and adds prompting |
| 236 | using the familiar sys.ps1 and sys.ps2, and input buffering. |
| 237 | |
| 238 | """ |
| 239 | |
| 240 | def __init__(self, locals=None, filename="<console>"): |
| 241 | """Constructor. |
| 242 | |
| 243 | The optional locals argument will be passed to the |
| 244 | InteractiveInterpreter base class. |
| 245 | |
| 246 | The optional filename argument should specify the (file)name |
| 247 | of the input stream; it will show up in tracebacks. |
| 248 | |
| 249 | """ |
| 250 | InteractiveInterpreter.__init__(self, locals) |
| 251 | self.filename = filename |
| 252 | self.resetbuffer() |
| 253 | |
| 254 | def resetbuffer(self): |
| 255 | """Reset the input buffer.""" |
| 256 | self.buffer = [] |
| 257 | |
| 258 | def interact(self, banner=None, **parms): |
| 259 | """Closely emulate the interactive Python console. |
| 260 | |
| 261 | The optional banner argument specify the banner to print |
| 262 | before the first interaction; by default it prints a banner |
| 263 | similar to the one printed by the real Python interpreter, |
| 264 | followed by the current class name in parentheses (so as not |
| 265 | to confuse this with the real interpreter -- since it's so |
| 266 | close!). |
| 267 | |
| 268 | """ |
| 269 | global optdir |
| 270 | global rcCmd |
| 271 | |
| 272 | #sys.stderr.write("#DBX %s: enter InteractiveConsole.interact()\n" % (time.ctime())) |
| 273 | |
| 274 | # connect to command parser |
| 275 | self.parser = parms['parser'] |
| 276 | |
| 277 | ## # if there are good_trap and/or bad_trap in symbol file, register |
| 278 | ## # those as breakpoints |
| 279 | ## # TODO by default, no breakpoint for good/bad_trap is set in sam, |
| 280 | ## # we need an option to allow setting of those breakpoints. |
| 281 | ## if parms['reposit'].symTable and not optdir.has_key('--blaze'): |
| 282 | ## trapList = parms['reposit'].symTable.getTraps() |
| 283 | ## for (trap,vaddr) in trapList: |
| 284 | ## cmd = 'break %#x' % (vaddr) |
| 285 | ## if self.parser.parseCmd(cmd, **parms): |
| 286 | ## sys.stderr.write('ERROR: un-expected return value from parseCmd()\n') |
| 287 | |
| 288 | # if there are command(s) specified in config, execute those first |
| 289 | _configRC = None |
| 290 | if parms.has_key('confRC'): |
| 291 | _configRC = parms['confRC'] |
| 292 | |
| 293 | tmp = '.rs_config_cmd' |
| 294 | fdtmp = open(tmp, 'w') |
| 295 | if _configRC: |
| 296 | if _configRC.getObjData(ReadConfigDiag.TYPE_SYS_CONFIG, RC_SYS_CONFIG_OBJ, RC_COMMAND, silent=1): |
| 297 | #sys.stderr.write("# %s: process config/init cmd\n" % (time.ctime())) |
| 298 | for cmd in _configRC.getObjData(ReadConfigDiag.TYPE_SYS_CONFIG, RC_SYS_CONFIG_OBJ, RC_COMMAND): |
| 299 | cmd = cmd.strip() |
| 300 | # if get_addr() is part of the command, better resolve |
| 301 | # that here, so we don't need to worry about that later |
| 302 | # when execute the command |
| 303 | index = cmd.find('get_addr') |
| 304 | if index > -1: |
| 305 | lop = cmd[:index] |
| 306 | rop = cmd[index:] |
| 307 | try: |
| 308 | cmd = '%s%s' % (lop, eval(rop)) |
| 309 | except: |
| 310 | pass |
| 311 | fdtmp.write('%s\n' % (cmd)) |
| 312 | |
| 313 | for cmd in rcCmd: |
| 314 | fdtmp.write('%s\n' % (cmd)) |
| 315 | |
| 316 | fdtmp.close() |
| 317 | # execute the commands specified in config file, if a command |
| 318 | # cannot be run, just ignore it. |
| 319 | self.parseExecfile('execfile("%s")' % (tmp), ignore=1, **parms) |
| 320 | #sys.stderr.write("# %s: DBX: done config/init cmd\n" % (time.ctime())) |
| 321 | |
| 322 | # set prompt symbol |
| 323 | if _configRC: |
| 324 | prompt = _configRC.getObjData(ReadConfigDiag.TYPE_SYS_CONFIG, RC_SYS_CONFIG_OBJ, RC_PROMPT) |
| 325 | else: |
| 326 | prompt = 'sam' |
| 327 | |
| 328 | parms['reposit'].prompt = prompt |
| 329 | |
| 330 | try: |
| 331 | sys.ps1 |
| 332 | except AttributeError: |
| 333 | sys.ps1 = "%s>>> " % (prompt) |
| 334 | |
| 335 | try: |
| 336 | sys.ps2 |
| 337 | except AttributeError: |
| 338 | sys.ps2 = "%s... " % (prompt) |
| 339 | |
| 340 | try: |
| 341 | sys.ps3 |
| 342 | except AttributeError: |
| 343 | sys.ps3 = "%s!!! " % (prompt) |
| 344 | |
| 345 | cprt = 'Type "copyright", "credits" or "license" for more information.' |
| 346 | if banner is None: |
| 347 | self.write("Python %s on %s\n%s\n(%s)\n" % |
| 348 | (sys.version, sys.platform, cprt, |
| 349 | self.__class__.__name__)) |
| 350 | else: |
| 351 | #self.write("# %s: %s\n" % (time.ctime(), str(banner))) |
| 352 | pass |
| 353 | |
| 354 | more = 0 |
| 355 | while 1: |
| 356 | try: |
| 357 | if more: |
| 358 | prompt = sys.ps2 |
| 359 | elif no_sam == 1: |
| 360 | prompt = sys.ps1 |
| 361 | elif (no_sam == 0) and sam.is_stopped(): |
| 362 | prompt = sys.ps1 |
| 363 | else: |
| 364 | prompt = sys.ps3 |
| 365 | |
| 366 | try: |
| 367 | line = self.raw_input(prompt) |
| 368 | except EOFError: |
| 369 | self.write("\n") |
| 370 | break |
| 371 | else: |
| 372 | line = self.parser.parseCmd(line, **parms) |
| 373 | if line != None: |
| 374 | # most excepts are handled by push() and its inner |
| 375 | # methods, so we won't see them here. |
| 376 | if re.match(execfileRE, line): |
| 377 | try: |
| 378 | more = self.parseExecfile(line, **parms) |
| 379 | except SystemExit: |
| 380 | raise |
| 381 | except: |
| 382 | more = self.push(line) |
| 383 | else: |
| 384 | more = self.push(line) |
| 385 | else: |
| 386 | # to play it safe, flush out buffer when parser returns |
| 387 | # None |
| 388 | self.resetbuffer() |
| 389 | more = 0 |
| 390 | |
| 391 | except KeyboardInterrupt: |
| 392 | self.write("\nKeyboardInterrupt\n") |
| 393 | self.resetbuffer() |
| 394 | more = 0 |
| 395 | |
| 396 | def push(self, line): |
| 397 | """Push a line to the interpreter. |
| 398 | |
| 399 | The line should not have a trailing newline; it may have |
| 400 | internal newlines. The line is appended to a buffer and the |
| 401 | interpreter's runsource() method is called with the |
| 402 | concatenated contents of the buffer as source. If this |
| 403 | indicates that the command was executed or invalid, the buffer |
| 404 | is reset; otherwise, the command is incomplete, and the buffer |
| 405 | is left as it was after the line was appended. The return |
| 406 | value is 1 if more input is required, 0 if the line was dealt |
| 407 | with in some way (this is the same as runsource()). |
| 408 | |
| 409 | """ |
| 410 | self.buffer.append(line) |
| 411 | source = "\n".join(self.buffer) |
| 412 | more = self.runsource(source, self.filename) |
| 413 | if not more: |
| 414 | self.resetbuffer() |
| 415 | return more |
| 416 | |
| 417 | def raw_input(self, prompt=""): |
| 418 | """Write a prompt and read a line. |
| 419 | |
| 420 | The returned line does not include the trailing newline. |
| 421 | When the user enters the EOF key sequence, EOFError is raised. |
| 422 | |
| 423 | The base implementation uses the built-in function |
| 424 | raw_input(); a subclass may replace this with a different |
| 425 | implementation. |
| 426 | |
| 427 | """ |
| 428 | #return raw_input(prompt) |
| 429 | line = raw_input(prompt) |
| 430 | if re.match(NEW_CMD_RE, line): |
| 431 | if line.startswith('@'): |
| 432 | line = line[1:] |
| 433 | newlist = [ line ] |
| 434 | if not line.strip().endswith(')'): |
| 435 | line = raw_input(prompt) |
| 436 | while line.strip() and not line.strip().endswith(')'): |
| 437 | newlist.append(line) |
| 438 | line = raw_input(prompt) |
| 439 | # remember to include the last line ending with ')' |
| 440 | newlist.append(line) |
| 441 | return ' '.join(newlist) |
| 442 | else: |
| 443 | return line |
| 444 | |
| 445 | |
| 446 | def parseExecfile (self, cmdLine, ignore=0, **parms): |
| 447 | """execfile() bypasses riesling cmd parser by default, so we have |
| 448 | to intercept the execfile() command, and process its content line |
| 449 | by line. |
| 450 | """ |
| 451 | global IGNORE_EXCEPT |
| 452 | |
| 453 | current_ignore_except = IGNORE_EXCEPT |
| 454 | IGNORE_EXCEPT = ignore |
| 455 | |
| 456 | try: |
| 457 | self._parseExecfile(cmdLine, ignore=ignore, **parms) |
| 458 | except SystemExit: |
| 459 | self.resetbuffer() |
| 460 | raise |
| 461 | except Exception, ex: |
| 462 | self.resetbuffer() |
| 463 | if ignore == 0: |
| 464 | raise |
| 465 | else: |
| 466 | #sys.stderr.write('DBX: RiesCodeN2::parseExecfile: ignore <%s>, ex=%s\n' % (cmdLine, ex)) |
| 467 | pass |
| 468 | |
| 469 | IGNORE_EXCEPT = current_ignore_except |
| 470 | |
| 471 | |
| 472 | def _parseExecfile (self, cmdLine, ignore=0, **parms): |
| 473 | """execfile() bypasses riesling cmd parser by default, so we have |
| 474 | to intercept the execfile() command, and process its content line |
| 475 | by line. |
| 476 | """ |
| 477 | global parser |
| 478 | |
| 479 | # the cmdLine is expected to be in the format of "execfile('zzz')" |
| 480 | lindex = cmdLine.find('(') |
| 481 | rindex = cmdLine.find(')') |
| 482 | filename = eval(cmdLine[lindex+1:rindex].strip()) |
| 483 | |
| 484 | fin = open(filename) |
| 485 | lineBuffer = [ ] |
| 486 | for line in fin.readlines(): |
| 487 | if line and line.startswith('def '): |
| 488 | # a new function definition |
| 489 | # CmdParserNi::registerDoc (self, key, fname, type, shortdoc, longdoc) |
| 490 | defline = line.strip() |
| 491 | ii = defline.rfind(':') |
| 492 | if ii > -1: |
| 493 | defline = defline[4:ii].strip() |
| 494 | defkey = defline |
| 495 | jj = defkey.find('(') |
| 496 | if jj > -1: |
| 497 | defkey = defkey[:jj].strip() |
| 498 | parser.registerDoc(defkey, defline, '@DEF', filename+' : @def '+defline, None) |
| 499 | # continue reading & concatenating line(s) until a complete |
| 500 | # expression is formed. Remember to remove trailing newline |
| 501 | if line[-1] == '\n': |
| 502 | line = line[:-1] |
| 503 | |
| 504 | if (line != '') and (line[-1] == "\\"): |
| 505 | # exclude the trailing "\" |
| 506 | lineBuffer.append(line[:-1]) |
| 507 | else: |
| 508 | if len(lineBuffer) > 0: |
| 509 | # make sure we include the last line of an expression |
| 510 | lineBuffer.append(line) |
| 511 | line = ' '.join(lineBuffer) |
| 512 | lineBuffer = [ ] |
| 513 | |
| 514 | # keep track of leading whitespace |
| 515 | i, n = 0, len(line) |
| 516 | while (i < n) and (line[i] in string.whitespace): |
| 517 | i = i + 1 |
| 518 | indent = line[:i] |
| 519 | cmd = line[i:] |
| 520 | # if see nested execfile(), handle that recursively |
| 521 | if re.match(execfileRE, cmd): |
| 522 | try: |
| 523 | self.parseExecfile(cmd, ignore=ignore, **parms) |
| 524 | except Exception, ex: |
| 525 | if ignore == 0: |
| 526 | more = self.push(cmd) |
| 527 | else: |
| 528 | #sys.stderr.write('DBX: RiesCodeN2::_parseExecfile: ignore <%s>, ex=%s\n' % (cmd, ex)) |
| 529 | self.resetbuffer() |
| 530 | else: |
| 531 | # if not an execfile(), parse the line, then add back the |
| 532 | # leading whitespace |
| 533 | try: |
| 534 | cmd = self.parser.parseCmd(cmd, **parms) |
| 535 | if cmd != None: |
| 536 | # for run-command-file and run-python-file |
| 537 | # commands, parser will return execfile(file-name), |
| 538 | # since the file may contains frontend commands, |
| 539 | # so we must pass them through parser line by line. |
| 540 | if re.match(execfileRE, cmd): |
| 541 | self.parseExecfile(cmd, ignore=ignore, **parms) |
| 542 | else: |
| 543 | newCmd = indent + cmd |
| 544 | more = self.push(newCmd) |
| 545 | else: |
| 546 | self.resetbuffer() |
| 547 | more = 0 |
| 548 | |
| 549 | except SystemExit: |
| 550 | # if it is an exit signal, go with it. |
| 551 | raise |
| 552 | except Exception, ex: |
| 553 | if ignore == 0: |
| 554 | # report the error |
| 555 | more = self.push(indent + 'raise') |
| 556 | else: |
| 557 | #sys.stderr.write('DBX: RiesCodeN2::_parseExecfile: ignore <%s>, ex2=%s\n' % (cmd, ex)) |
| 558 | self.resetbuffer() |
| 559 | |
| 560 | fin.close() |
| 561 | # send in an extra newline to close the last definition in the file. |
| 562 | more = self.push("\n") |
| 563 | |
| 564 | |
| 565 | def interact(banner=None, readfunc=None, local=None, **parms): |
| 566 | """Closely emulate the interactive Python interpreter. |
| 567 | |
| 568 | This is a backwards compatible interface to the InteractiveConsole |
| 569 | class. When readfunc is not specified, it attempts to import the |
| 570 | readline module to enable GNU readline if it is available. |
| 571 | |
| 572 | Arguments (all optional, all default to None): |
| 573 | |
| 574 | banner -- passed to InteractiveConsole.interact() |
| 575 | readfunc -- if not None, replaces InteractiveConsole.raw_input() |
| 576 | local -- passed to InteractiveInterpreter.__init__() |
| 577 | |
| 578 | """ |
| 579 | console = InteractiveConsole(local) |
| 580 | if readfunc is not None: |
| 581 | console.raw_input = readfunc |
| 582 | else: |
| 583 | try: |
| 584 | import readline |
| 585 | except: |
| 586 | pass |
| 587 | console.interact(banner, **parms) |
| 588 | |
| 589 | |
| 590 | def usage(): |
| 591 | """ |
| 592 | """ |
| 593 | print |
| 594 | print "usage: python %s [options]" % (sys.argv[0]) |
| 595 | print "options:" |
| 596 | print "\t -c conf-file # diag configuration file" |
| 597 | print "\t -h # this usage information" |
| 598 | #print "\t -s backend-config # riesling backend configuration file" |
| 599 | print "\t -x conf-file # riesling configuration file" |
| 600 | print "\t -p python-file # python configuration file to be executed at startup" |
| 601 | print "\t --blaze system # type of system, n2" |
| 602 | print "\t --blazeopt \"blaze options\" # blaze runtime options" |
| 603 | print "\t --ar system # type of system, n2, ignore if --blaze is used" |
| 604 | print "\t --rc riesling-rc # riesling config, a combination of -c & -x" |
| 605 | print |
| 606 | sys.exit() |
| 607 | |
| 608 | |
| 609 | def dbxTraceBack(): |
| 610 | """ |
| 611 | """ |
| 612 | try: |
| 613 | type, value, tb = sys.exc_info() |
| 614 | sys.last_type = type |
| 615 | sys.last_value = value |
| 616 | sys.last_traceback = tb |
| 617 | tblist = traceback.extract_tb(tb) |
| 618 | del tblist[:1] |
| 619 | list = traceback.format_list(tblist) |
| 620 | if list: |
| 621 | list.insert(0, "Traceback (most recent call last):\n") |
| 622 | list[len(list):] = traceback.format_exception_only(type, value) |
| 623 | finally: |
| 624 | tblist = tb = None |
| 625 | |
| 626 | for line in list: |
| 627 | sys.stderr.write('%s' % line) |
| 628 | |
| 629 | |
| 630 | def createSystem (optdir): |
| 631 | """invoke backend system constructor |
| 632 | """ |
| 633 | #sys.stderr.write("# %s: create riesling.sys\n" % (time.ctime())) |
| 634 | |
| 635 | global rsys |
| 636 | global sim |
| 637 | global ncpus |
| 638 | global ncores |
| 639 | global nucores |
| 640 | global nstrands |
| 641 | global nstrandObjs |
| 642 | |
| 643 | # if --blaze is specified, use that, otherwise use --ar |
| 644 | if optdir.has_key('--blaze'): |
| 645 | if optdir['--blaze'] == 'n2': |
| 646 | optdir['--ar'] = 'n2' |
| 647 | else: |
| 648 | sys.stderr.write('ERROR: unknown system %s\n' % (optdir['--blaze'])) |
| 649 | sys.exit() |
| 650 | |
| 651 | if optdir['--ar'] == 'n2': |
| 652 | initN2() |
| 653 | else: |
| 654 | sys.stderr.write('ERROR: unknown system %s\n' % (optdir['--ar'])) |
| 655 | sys.exit() |
| 656 | |
| 657 | if nucores == 0: |
| 658 | nstrandObjs = ncpus * ncores * nstrands |
| 659 | #sys.stderr.write('# %s: sys=%s=(cpu,core,strand)=(%d,%d,%d)\n' % (time.ctime(), optdir['--ar'].upper(), ncpus, ncores, nstrands)) |
| 660 | else: |
| 661 | nstrandObjs = ncpus * ncores * nucores * nstrands |
| 662 | #sys.stderr.write('# %s: sys=(cpu,core,ucore,strand)=(%d,%d,%d,%d)\n' % (time.ctime(), ncpus, ncores, nucores, nstrands)) |
| 663 | |
| 664 | #sys.stderr.write("# %s: done creating riesling.sys\n" % (time.ctime())) |
| 665 | |
| 666 | |
| 667 | def initN2 (): |
| 668 | """init N2 structure/variables |
| 669 | """ |
| 670 | #sys.stderr.write("#DBX %s: initN2\n" % (time.ctime())) |
| 671 | |
| 672 | global rsys |
| 673 | global sim |
| 674 | |
| 675 | sim = rsys |
| 676 | initGenericN2(rsys) |
| 677 | initN2_specific(rsys) |
| 678 | |
| 679 | |
| 680 | def initN2_specific(rsys): |
| 681 | """special setting for N2 |
| 682 | """ |
| 683 | #sys.stderr.write("#DBX %s: initN2_specific\n" % (time.ctime())) |
| 684 | |
| 685 | global optdir |
| 686 | global configRC |
| 687 | |
| 688 | # cmp infomration in .riesling.rc |
| 689 | ## OBJECT swvmem0 TYPE swerver-memory { |
| 690 | ## debug_level : 0 |
| 691 | ## ignore_sparc : ['1', '3', '4', '5', '6', '7'] |
| 692 | ## irq : irq0 |
| 693 | ## queue : th00 |
| 694 | ## snoop : 0 |
| 695 | ## thread_mask : 11xx11 |
| 696 | ## thread_status : 0x9a00000000 |
| 697 | ## threads : 110011 |
| 698 | ## tso_checker : 0 |
| 699 | ## } |
| 700 | |
| 701 | if configRC == None: |
| 702 | return |
| 703 | |
| 704 | # (1) use 'cpu' to determine the number of cpus, (2) if thread_maskN is |
| 705 | # available, use that to calculate CMP, (3) otherwise, use ignore_sparc |
| 706 | # and threadsN to calculate CMP, less desirable. |
| 707 | try: |
| 708 | numCpus = int(configRC.getData('swvmem0', 'cpu', silent=1)) |
| 709 | except: |
| 710 | numCpus = 1 |
| 711 | |
| 712 | if ((optdir['--ar'] == 'n2') and ((numCpus < 0) or (numCpus > 1))): |
| 713 | sys.stderr.write('ERROR: wrong number of %s cpus %d\n' % (optdir['--ar'].upper(), numCpus)) |
| 714 | sys.exit(-1) |
| 715 | |
| 716 | for ii in range(numCpus): |
| 717 | # set cmp init value, if any |
| 718 | coreAvailable = 0x0L |
| 719 | coreRunning = 0x0L |
| 720 | coresAndStrands = configRC.getData('swvmem0', 'thread_mask'+str(ii), silent=1) |
| 721 | if (not coresAndStrands) and (ii == 0): |
| 722 | # for backward compatible, we used to just use thread_mask, |
| 723 | # instead of thread_mask0 |
| 724 | coresAndStrands = configRC.getData('swvmem0', 'thread_mask', silent=1) |
| 725 | #sys.stderr.write('#DBX: use thread_mask%d=%s\n' % (ii, coresAndStrands)) |
| 726 | if coresAndStrands: |
| 727 | # if -sas_run_args=-DTHREAD_MASK is used, the value is stored in |
| 728 | # coresAndStrands, which alone handles both cores & strands status. |
| 729 | # this is the preferred option of specifying core/strand availability. |
| 730 | # e.g., -sas_run_args=-DTHREAD_MASK=11xx11, every 2 digits (from right |
| 731 | # to left) represents a core, 'xx' means disabled core. |
| 732 | coresAndStrands = coresAndStrands.lower() |
| 733 | tail = len(coresAndStrands) |
| 734 | i = 0 |
| 735 | firstCore = -1 |
| 736 | while tail >= 2: |
| 737 | core = coresAndStrands[tail-2:tail] |
| 738 | if core.find('x') == -1: |
| 739 | if firstCore == -1: |
| 740 | # record the lowest core that is available |
| 741 | firstCore = i |
| 742 | coreAvailable = coreAvailable | (0xffL << i*8) |
| 743 | coreRunning = coreRunning | (long(core, 16) << i*8) |
| 744 | tail -= 2 |
| 745 | i += 1 |
| 746 | if tail > 0: |
| 747 | # if the coresAndStrands string has odd digits, handle the last one |
| 748 | core = coresAndStrands[:tail] |
| 749 | if core.find('x') == -1: |
| 750 | coreAvailable = coreAvailable | (0xffL << i*8) |
| 751 | coreRunning = coreRunning | (long(core, 16) << i*8) |
| 752 | # if no core is available, make the lowest one available |
| 753 | if coreAvailable == 0x0: |
| 754 | coreAvailable = 0xffL |
| 755 | firstCore = 0 |
| 756 | # if o strand is running, make the lowest strand of the lowest |
| 757 | # available core running. |
| 758 | if coreRunning == 0x0: |
| 759 | coreRunning = 0x1L << (firstCore*8) |
| 760 | #sys.stderr.write('#DBX: 1 coreAvailable=%#x\n' % (coreAvailable)) |
| 761 | #sys.stderr.write('#DBX: 1 coreRunning=%#x\n' % (coreRunning)) |
| 762 | else: |
| 763 | # otherwise use the combination of cores & strands status |
| 764 | parkedCoreList = configRC.getData('swvmem0', 'ignore_sparc', silent=1) |
| 765 | if parkedCoreList != None: |
| 766 | firstCore = -1 |
| 767 | i = ii*8 |
| 768 | while i < (ii*8 + 8): |
| 769 | if not str(i) in parkedCoreList: |
| 770 | if firstCore == -1: |
| 771 | firstCore = i - (ii*8) |
| 772 | coreAvailable = coreAvailable | (0xffL << (i-ii*8)*8) |
| 773 | i += 1 |
| 774 | if coreAvailable == 0x0: |
| 775 | coreAvailable = 0xffL |
| 776 | firstCore = 0 |
| 777 | # check strands |
| 778 | if ii == 0: |
| 779 | # don't change existing variable |
| 780 | unparkedStrands = configRC.getData('swvmem0', 'threads', silent=1) |
| 781 | else: |
| 782 | unparkedStrands = configRC.getData('swvmem0', 'threads'+str(ii), silent=1) |
| 783 | if unparkedStrands != None: |
| 784 | # only strands in enabled cores can be running |
| 785 | coreRunning = long(unparkedStrands, 16) & coreAvailable |
| 786 | if coreRunning == 0x0: |
| 787 | coreRunning = 0x1L << (firstCore*8) |
| 788 | else: |
| 789 | # if no threads is specified, all strands in enabled cores |
| 790 | # are enabled |
| 791 | coreRunning = coreAvailable |
| 792 | #sys.stderr.write('#DBX: 2 coreAvailable=%#x\n' % (coreAvailable)) |
| 793 | #sys.stderr.write('#DBX: 2 coreRunning=%#x\n' % (coreRunning)) |
| 794 | |
| 795 | #sys.stderr.write('#DBX: 3 coreAvailable=%#x\n' % (coreAvailable)) |
| 796 | #sys.stderr.write('#DBX: 3 coreRunning=%#x\n' % (coreRunning)) |
| 797 | if coreAvailable != 0x0 and coreRunning != 0x0: |
| 798 | headStrand = ii * 64 |
| 799 | strands[headStrand].wrasi(0x41, 0x0L, coreAvailable) |
| 800 | #???strands[headStrand].wrasi(0x41, 0x10L, coreAvailable) |
| 801 | strands[headStrand].wrasi(0x41, 0x20L, coreAvailable) |
| 802 | |
| 803 | strands[headStrand].wrasi(0x41, 0x50L, coreRunning) |
| 804 | #???strands[headStrand].wrasi(0x41, 0x58L, coreRunning) |
| 805 | |
| 806 | |
| 807 | def initGenericNi (rsys): |
| 808 | """init generic Niagara structure |
| 809 | """ |
| 810 | #sys.stderr.write("#DBX %s: initGenericNi\n" % (time.ctime())) |
| 811 | |
| 812 | global ncpus |
| 813 | global ncores |
| 814 | global nstrands |
| 815 | global cpus |
| 816 | global cores |
| 817 | global strands |
| 818 | |
| 819 | #TODO need work |
| 820 | if not rsys.__create_cpu__(1): |
| 821 | print "Failed to create %d Ni cpu instance(s)" % 1 |
| 822 | sys.exit(-1) |
| 823 | |
| 824 | # system configuration XXX |
| 825 | ncpus = len(rsys.p) |
| 826 | ncores = 8 |
| 827 | nstrands = 4 |
| 828 | |
| 829 | for i in range(0,ncpus): |
| 830 | cpus[i] = rsys.p[i] |
| 831 | for j in range(0,8): |
| 832 | cores[i*8 + j] = rsys.p[i].c[j] |
| 833 | for k in range(0,4): |
| 834 | strands[i*8*4 + j*8 + k] = rsys.p[i].c[j].s[k] |
| 835 | |
| 836 | |
| 837 | def initGenericN2 (rsys): |
| 838 | """init generic Niagara structure |
| 839 | """ |
| 840 | #sys.stderr.write("#DBX %s: initGenericN2\n" % (time.ctime())) |
| 841 | |
| 842 | global ncpus |
| 843 | global ncores |
| 844 | global nstrands |
| 845 | global cpus |
| 846 | global cores |
| 847 | global strands |
| 848 | |
| 849 | # system configuration # |
| 850 | ncpus = len(rsys.p) |
| 851 | ncores = len(rsys.p0.c) |
| 852 | nstrands = len(rsys.p0.c0.s) |
| 853 | |
| 854 | for i in range(0,ncpus): |
| 855 | cpus[i] = rsys.p[i] |
| 856 | for j in range(0,ncores): |
| 857 | cores[i*ncores + j] = rsys.p[i].c[j] |
| 858 | for k in range(0,nstrands): |
| 859 | strands[i*ncores*nstrands + j*nstrands + k] = rsys.p[i].c[j].s[k] |
| 860 | |
| 861 | |
| 862 | def readConfig (optdir): |
| 863 | """read configuration data |
| 864 | """ |
| 865 | global NEW_CONFIG |
| 866 | global configRC |
| 867 | |
| 868 | #sys.stderr.write("#DBX %s: read config\n" % (time.ctime())) |
| 869 | configRies = None |
| 870 | configDiag = None |
| 871 | |
| 872 | # read -x config (diag.simics) |
| 873 | if optdir.has_key('-x'): |
| 874 | configRies = ReadConfigRies.ReadConfigRies() |
| 875 | configRies.readConfig(optdir['-x']) |
| 876 | #sys.stderr.write('DBX: configRies = %s\n' % (configRies)) |
| 877 | |
| 878 | if configRies and configRies.data.has_key(ReadConfigRies.DIAG_CONF): |
| 879 | # if DIAG_CONF is specified in -x, use that |
| 880 | configDiag = ReadConfigDiag.ReadConfigDiag() |
| 881 | configDiag.readConfig(configRies.data[ReadConfigRies.DIAG_CONF]) |
| 882 | #sys.stderr.write('DBX: configDiag = %s\n' % (configDiag)) |
| 883 | |
| 884 | if configRies == None or configDiag == None: |
| 885 | #sys.stderr.write('ERROR: no configuration data is given by either -c & -x, or --rc option\n') |
| 886 | #usage() |
| 887 | #sys.exit() |
| 888 | return |
| 889 | |
| 890 | # system config |
| 891 | try: |
| 892 | newline = '@conf.%s.%s = %s' % (RC_SYS_CONFIG_OBJ, RC_PROMPT, configRies.data[ReadConfigRies.PROMPT]) |
| 893 | except: |
| 894 | # default |
| 895 | newline = '@conf.%s.%s = ries' % (RC_SYS_CONFIG_OBJ, RC_PROMPT) |
| 896 | configDiag.setDataLine(newline) |
| 897 | |
| 898 | try: |
| 899 | newline = '@conf.%s.%s = %s' % (RC_SYS_CONFIG_OBJ, RC_MEM_IMAGE, RC_configRies.data[ReadConfigRies.MEM_IMAGE]) |
| 900 | except: |
| 901 | # default |
| 902 | newline = '@conf.%s.%s = mem.image' % (RC_SYS_CONFIG_OBJ, RC_MEM_IMAGE) |
| 903 | configDiag.setDataLine(newline) |
| 904 | |
| 905 | # process @def and def specified in config file |
| 906 | handleAtDef(configRies, configDiag) |
| 907 | # process @conf.zzz in configRies |
| 908 | handleAtConf(configRies, configDiag) |
| 909 | # process commands |
| 910 | if configRies.data.has_key(ReadConfigRies.CMD): |
| 911 | for cmd in configRies.data[ReadConfigRies.CMD]: |
| 912 | newline = '@conf.%s.%s =+ %s' % (RC_SYS_CONFIG_OBJ, RC_COMMAND, cmd) |
| 913 | configDiag.setDataLine(newline) |
| 914 | # handle new_command() --- python command extension |
| 915 | if configRies and configRies.data[ReadConfigRies.NEW_CMD] != {}: |
| 916 | for cmdkey in configRies.data[ReadConfigRies.NEW_CMD].keys(): |
| 917 | newline = '@conf.%s.%s =+ %s=%s' % (RC_SYS_CONFIG_OBJ, RC_COMMAND_EXT, cmdkey, configRies.data[ReadConfigRies.NEW_CMD][cmdkey]) |
| 918 | configDiag.setDataLine(newline) |
| 919 | |
| 920 | fdtmp = open(NEW_CONFIG, 'w') |
| 921 | fdtmp.write('%s\n' % (configDiag)) |
| 922 | fdtmp.close() |
| 923 | |
| 924 | # create the rc object to be used from now on |
| 925 | configRC = ReadConfigDiag.ReadConfigDiag() |
| 926 | configRC.readConfig(NEW_CONFIG) |
| 927 | |
| 928 | |
| 929 | def constructSystem (optdir): |
| 930 | """construct a backend system |
| 931 | """ |
| 932 | global rsys |
| 933 | global sysAddr |
| 934 | |
| 935 | #sys.stderr.write("#DBX %s: construct system\n" % (time.ctime())) |
| 936 | |
| 937 | # create backend system and get the sys object's address, to be passed |
| 938 | # to nasAPI or blaze. |
| 939 | try: |
| 940 | createSystem(optdir) |
| 941 | except: |
| 942 | dbxTraceBack() |
| 943 | |
| 944 | #sys.stderr.write('# %s: sys addr=%u\n' % (time.ctime(), sysAddr)) |
| 945 | |
| 946 | |
| 947 | #def handleAtDef (globals): |
| 948 | def handleAtDef (configRies, configDiag): |
| 949 | """ |
| 950 | """ |
| 951 | global ATDEF |
| 952 | |
| 953 | #sys.stderr.write("#DBX %s: process @def/def\n" % (time.ctime())) |
| 954 | |
| 955 | try: |
| 956 | # remove old file, if any |
| 957 | os.remove(ATDEF) |
| 958 | except: |
| 959 | pass |
| 960 | if configRies: |
| 961 | tfd = open(ATDEF, 'w') |
| 962 | if configRies.data[ReadConfigRies.AT_DEF] != {}: |
| 963 | for func in configRies.data[ReadConfigRies.AT_DEF].keys(): |
| 964 | tfd.write('%s\n' % (''.join(configRies.data[ReadConfigRies.AT_DEF][func]))) |
| 965 | tfd.write('\n') |
| 966 | |
| 967 | tfd.close() |
| 968 | |
| 969 | if configDiag: |
| 970 | newline = '@conf.%s.%s = %s' % (RC_SYS_CONFIG_OBJ, RC_FUNC_DEF, ATDEF) |
| 971 | configDiag.setDataLine(newline) |
| 972 | |
| 973 | # run the function definition in ATDEF |
| 974 | if os.path.getsize(ATDEF) > 0: |
| 975 | execfile(ATDEF, globals()) |
| 976 | |
| 977 | |
| 978 | def handleAtConf (configRies, configDiag): |
| 979 | """ |
| 980 | """ |
| 981 | #sys.stderr.write("#DBX %s: process @conf.zzz\n" % (time.ctime())) |
| 982 | |
| 983 | if configDiag and configRies and configRies.data[ReadConfigRies.AT_CONF] != []: |
| 984 | for dline in configRies.data[ReadConfigRies.AT_CONF]: |
| 985 | j = dline.find('=+') |
| 986 | if j > -1: |
| 987 | # the value is to be appended to existing one(s) |
| 988 | lop = dline[:j].strip() |
| 989 | rop = dline[j+2:].strip() |
| 990 | if re.match(DIGITAL_RE, rop): |
| 991 | # if rhs are all [0-9], leave as is |
| 992 | newline = dline |
| 993 | else: |
| 994 | try: |
| 995 | # we need to eval things like get_addr() |
| 996 | newline = '%s =+ %#x' % (lop, eval(rop)) |
| 997 | except: |
| 998 | # if the right operand cannot be eval'ed, just use its |
| 999 | # original form. |
| 1000 | newline = dline |
| 1001 | else: |
| 1002 | # the value is to be used to overwrite existing one |
| 1003 | j = dline.find('=') |
| 1004 | lop = dline[:j].strip() |
| 1005 | rop = dline[j+1:].strip() |
| 1006 | if re.match(DIGITAL_RE, rop): |
| 1007 | # if rhs are all [0-9], leave as is |
| 1008 | newline = dline |
| 1009 | else: |
| 1010 | try: |
| 1011 | newline = '%s = %#x' % (lop, eval(rop)) |
| 1012 | except: |
| 1013 | newline = dline |
| 1014 | # add/update value in configDiag |
| 1015 | configDiag.setDataLine(newline) |
| 1016 | |
| 1017 | |
| 1018 | def createCommandParser (): |
| 1019 | """ |
| 1020 | """ |
| 1021 | global parser |
| 1022 | global riesReposit |
| 1023 | global nstrandObjs |
| 1024 | global configRC |
| 1025 | |
| 1026 | #sys.stderr.write("#DBX %s: createCommandParser()\n" % (time.ctime())) |
| 1027 | |
| 1028 | parser = CmdParserNi.CmdParserNi(riesReposit) |
| 1029 | # set the value in parser for later use |
| 1030 | parser.setNstrandObjs(nstrandObjs) |
| 1031 | |
| 1032 | # init zzz_cmd_RS() & RS_zzz() functions in CmdParserNiCmd |
| 1033 | #sys.stderr.write("#DBX %s: create CmdParserNiCmd\n" % (time.ctime())) |
| 1034 | initCmdParserNiCmd(riesReposit, nstrandObjs) |
| 1035 | |
| 1036 | # handle new_command() --- python command extension |
| 1037 | if configRC: |
| 1038 | if configRC.getObjData(ReadConfigDiag.TYPE_SYS_CONFIG, RC_SYS_CONFIG_OBJ, RC_COMMAND_EXT, silent=1): |
| 1039 | for cmd in configRC.getObjData(ReadConfigDiag.TYPE_SYS_CONFIG, RC_SYS_CONFIG_OBJ, RC_COMMAND_EXT): |
| 1040 | i = cmd.find('=') |
| 1041 | cmdkey = cmd[:i].strip() |
| 1042 | cmdVal = cmd[i+1].strip() |
| 1043 | parser.registerCommand(cmdkey, cmdVal) |
| 1044 | |
| 1045 | |
| 1046 | def registerAtDef (): |
| 1047 | """ |
| 1048 | """ |
| 1049 | global ATDEF |
| 1050 | global parser |
| 1051 | |
| 1052 | #sys.stderr.write("#DBX %s: registerAtDef()\n" % (time.ctime())) |
| 1053 | |
| 1054 | try: |
| 1055 | if os.path.getsize(ATDEF) > 0: |
| 1056 | fdtmp = open(ATDEF, 'r') |
| 1057 | for line in fdtmp.readlines(): |
| 1058 | if line.startswith('def '): |
| 1059 | # def func(...): |
| 1060 | lindex = line.find(' ') |
| 1061 | mindex = line.find('(', lindex) |
| 1062 | rindex = line.rfind(':') |
| 1063 | fname = line[lindex+1:mindex].strip() |
| 1064 | func = line[lindex+1:rindex].strip() |
| 1065 | parser.registerDoc(fname, func, '@DEF', '@def '+func, None) |
| 1066 | except: |
| 1067 | pass |
| 1068 | |
| 1069 | |
| 1070 | def debugMomConfig (config): |
| 1071 | """this function is N2 specific |
| 1072 | """ |
| 1073 | momConfig = ReadConfigDiag.ReadConfigDiag() |
| 1074 | momConfig.readConfig(config) |
| 1075 | momKeys = momConfig.getObjKeys('mom', 'mom0', silent=1) |
| 1076 | if momKeys != []: |
| 1077 | klist = momKeys |
| 1078 | klist.sort() |
| 1079 | for key in klist: |
| 1080 | data = momConfig.getData('mom0', key, silent=1) |
| 1081 | sys.stderr.write('MOM: %s : %s\n' % (key, data)) |
| 1082 | |
| 1083 | def blazercCmd (newBlazeCmd): |
| 1084 | """extract riesling commands (the ones with #@) from blazerc |
| 1085 | """ |
| 1086 | global riesReposit |
| 1087 | global optdir |
| 1088 | |
| 1089 | # handle blaze -c option, if one is specifed. |
| 1090 | if not optdir.has_key('--blazeopt'): |
| 1091 | return [] |
| 1092 | else: |
| 1093 | blazeopt = optdir['--blazeopt'] |
| 1094 | |
| 1095 | #sys.stderr.write('#DBX: SamFR::blazercCmd: blazeopt=%s\n' % (blazeopt)) #DBX |
| 1096 | |
| 1097 | ii = blazeopt.find('-c ') |
| 1098 | if ii < 0: |
| 1099 | # no -c option is specified |
| 1100 | return [] |
| 1101 | |
| 1102 | tmp = blazeopt[ii+3:].strip() |
| 1103 | jj = tmp.find(' ') |
| 1104 | if jj == -1: |
| 1105 | rcname = tmp |
| 1106 | else: |
| 1107 | rcname = tmp[:jj] |
| 1108 | try: |
| 1109 | fdrc = open(rcname, 'r') |
| 1110 | except: |
| 1111 | sys.stderr.write('ERROR: fail to open %s\n' % (rcname)) |
| 1112 | sys.exit() |
| 1113 | |
| 1114 | # sample sysconf statements in blazerc |
| 1115 | # sysconf cpu name=cpu0 cpu-type=SUNW,UltraSPARC-T1 clock-frequency=0x200000 system-frequency=0x100000 cpu-loopticks=2 cpu-stickincr=1 |
| 1116 | # sysconf dumbserial serial1 type=GUEST startpa=0x9f10000000 endpa=0x9f1000004f |
| 1117 | # sysconf dumbserial serial2 type=HYPERVISOR startpa=0xfff0c2c000 endpa=0xfff0c2c04f |
| 1118 | |
| 1119 | cmd = [ ] |
| 1120 | cpuCount = 0 |
| 1121 | riesReposit.blazeNumcpu = 0 |
| 1122 | for line in fdrc.readlines(): |
| 1123 | line = line.strip() |
| 1124 | if line and line.startswith('#@'): |
| 1125 | cmd.append(line[2:]) |
| 1126 | elif line and line.startswith('conf numcpu'): |
| 1127 | # record the numcpu value in blazerc and initialize the pmask value |
| 1128 | # base on that. |
| 1129 | tokens = line.split() |
| 1130 | riesReposit.blazeNumcpu = int(tokens[2]) |
| 1131 | riesReposit.pmask = 1L |
| 1132 | for i in range(1,riesReposit.blazeNumcpu): |
| 1133 | riesReposit.pmask = (riesReposit.pmask << 1) | 0x1 |
| 1134 | elif line.startswith('sysconf'): |
| 1135 | # sysconf -p ../../lib |
| 1136 | # sysconf cpu name=cpu0 cpu-type=... |
| 1137 | # sysconf dumbserial serial1 type=GUEST ... |
| 1138 | tokens = line.split() |
| 1139 | if (tokens[1].lower() != 'cpu') and (tokens[1] != '-p'): |
| 1140 | newBlazeCmd.append(tokens[1]) |
| 1141 | newBlazeCmd.append(tokens[2]) |
| 1142 | elif (tokens[1].lower() == 'cpu') and (tokens[2].lower().startswith('name=cpu')): |
| 1143 | cpuCount += 1 |
| 1144 | |
| 1145 | if (riesReposit.blazeNumcpu == 0) and (cpuCount > 0): |
| 1146 | riesReposit.blazeNumcpu = cpuCount |
| 1147 | riesReposit.pmask = 0x1L |
| 1148 | for i in range(1,riesReposit.blazeNumcpu): |
| 1149 | riesReposit.pmask = (riesReposit.pmask << 1) | 0x1L |
| 1150 | |
| 1151 | if optdir['--blaze'] in ['n2']: |
| 1152 | # convert blaze numcpu to coreAvailable |
| 1153 | if (riesReposit.blazeNumcpu % riesReposit.nstrands) == 0: |
| 1154 | cores = riesReposit.blazeNumcpu / riesReposit.nstrands |
| 1155 | else: |
| 1156 | cores = (riesReposit.blazeNumcpu / riesReposit.nstrands) + 1 |
| 1157 | |
| 1158 | for i in range(0, cores): |
| 1159 | if (i % riesReposit.ncores) == 0: |
| 1160 | setcmp = 0 |
| 1161 | cpuid = i / riesReposit.ncores |
| 1162 | coreAvail = 0xffL |
| 1163 | else: |
| 1164 | setcmp = 0 |
| 1165 | #coreAvail = (coreAvail << ((i%riesReposit.ncores)*8)) | 0xffL |
| 1166 | coreAvail = (coreAvail << 8) | 0xffL |
| 1167 | if ((i+1) % riesReposit.ncores) == 0: |
| 1168 | # re-adjust CMP registers |
| 1169 | setcmp = 1 |
| 1170 | strandid = cpuid * riesReposit.ncores * riesReposit.nstrands |
| 1171 | coreAvailable = strands[strandid].rdasi(0x41, 0x0L) & coreAvail |
| 1172 | strands[strandid].wrasi(0x41, 0x0L, coreAvailable) |
| 1173 | #???strands[strandid].wrasi(0x41, 0x10L, coreAvailable) |
| 1174 | strands[strandid].wrasi(0x41, 0x20L, coreAvailable) |
| 1175 | coreRunning = strands[strandid].rdasi(0x41, 0x50L) & coreAvail |
| 1176 | strands[strandid].wrasi(0x41, 0x50L, coreRunning) |
| 1177 | #???strands[strandid].wrasi(0x41, 0x58L, coreRunning) |
| 1178 | |
| 1179 | # final set |
| 1180 | if setcmp == 0: |
| 1181 | strandid = cpuid * riesReposit.ncores * riesReposit.nstrands |
| 1182 | coreAvailable = strands[strandid].rdasi(0x41, 0x0L) & coreAvail |
| 1183 | strands[strandid].wrasi(0x41, 0x0L, coreAvailable) |
| 1184 | #???strands[strandid].wrasi(0x41, 0x10L, coreAvailable) |
| 1185 | strands[strandid].wrasi(0x41, 0x20L, coreAvailable) |
| 1186 | coreRunning = strands[strandid].rdasi(0x41, 0x50L) & coreAvail |
| 1187 | strands[strandid].wrasi(0x41, 0x50L, coreRunning) |
| 1188 | #???strands[strandid].wrasi(0x41, 0x58L, coreRunning) |
| 1189 | |
| 1190 | if optdir.has_key('--pmask'): |
| 1191 | mask = long(optdir['--pmask'],16) |
| 1192 | coreRunning = mask & strands[strandid].rdasi(0x41, 0x0L) |
| 1193 | strands[strandid].wrasi(0x41, 0x50L, coreRunning) |
| 1194 | |
| 1195 | return cmd |
| 1196 | |
| 1197 | |
| 1198 | ######################## |
| 1199 | ##### MAIN ##### |
| 1200 | ######################## |
| 1201 | #if __name__ == '__main__': |
| 1202 | |
| 1203 | from CmdParserNiCmd import * |
| 1204 | import CmdParserNi |
| 1205 | import ReadConfigRies |
| 1206 | import ReadConfigDiag |
| 1207 | from SamUtility import * |
| 1208 | |
| 1209 | rsys = None |
| 1210 | # default arch configuration |
| 1211 | (ncpus, ncores, nucores, nstrands) = (0,0,0,0) |
| 1212 | (cpus, cores, ucores, strands) = ({},{},{},{}) |
| 1213 | configRC = None |
| 1214 | riesReposit = None |
| 1215 | optdir = None |
| 1216 | parser = None |
| 1217 | # folder to keep UI commands (the ones start with #@) extracted from blazerc |
| 1218 | rcCmd = [ ] |
| 1219 | nstrandObjs = 0 |
| 1220 | ATDEF = '.riesling.def' |
| 1221 | NEW_CONFIG = '.riesling.rc' |
| 1222 | |
| 1223 | |
| 1224 | def init (pfeSim, _optdir, uppers={}): |
| 1225 | """ |
| 1226 | frontend parser startup |
| 1227 | """ |
| 1228 | global rsys |
| 1229 | global ncpus |
| 1230 | global ncores |
| 1231 | global nstrands |
| 1232 | global cpus |
| 1233 | global cores |
| 1234 | global strands |
| 1235 | global configRC |
| 1236 | global riesReposit |
| 1237 | global optdir |
| 1238 | global parser |
| 1239 | global rcCmd |
| 1240 | |
| 1241 | # initialize SamUtility |
| 1242 | initSamUtility(pfeSim) |
| 1243 | |
| 1244 | optdir = _optdir |
| 1245 | |
| 1246 | import commands |
| 1247 | #sys.stderr.write("# %s\n" % (commands.getoutput('uname -a'))) |
| 1248 | #sys.stderr.write("# Python %s\n" % sys.version) |
| 1249 | #sys.stderr.write("# %s: start sam frontend\n" % (time.ctime())) |
| 1250 | |
| 1251 | # read -x diag.sam (and then diag.conf) |
| 1252 | if optdir.has_key('--rc'): |
| 1253 | # if --rc is used, then ignore -x |
| 1254 | # NOTE it will be tricky to use --rc in rtl cosim environment, |
| 1255 | # as we need socket-id to connect with rtl, and the id will |
| 1256 | # change from run to run, which is recorded in diag.conf by sims, |
| 1257 | # the socket-id in --rc won't work as it was from the previous |
| 1258 | # run, if at all. |
| 1259 | #sys.stderr.write('WARNING: cannot use --rc %s when cosim with RTL\n' % (optdir['--rc'])) |
| 1260 | NEW_CONFIG = optdir['--rc'] |
| 1261 | configRC = ReadConfigDiag.ReadConfigDiag() |
| 1262 | configRC.readConfig(optdir['--rc']) |
| 1263 | # run function definition specified by -x or --rc |
| 1264 | ATDEF = configRC.getData(RC_SYS_CONFIG_OBJ, RC_FUNC_DEF) |
| 1265 | #sys.stderr.write('#DBX: func-def %s\n' % (funcDef)) |
| 1266 | if ATDEF and os.path.getsize(ATDEF) > 0: |
| 1267 | execfile(ATDEF, globals()) |
| 1268 | else: |
| 1269 | readConfig(optdir) |
| 1270 | |
| 1271 | # check if blaze/mom will be used |
| 1272 | if configRC: |
| 1273 | momObjs = configRC.getObjIds('mom', silent=1) |
| 1274 | if (momObjs != []): |
| 1275 | # if user specifies a special version of mom, use that instead |
| 1276 | # of the default file. |
| 1277 | try: |
| 1278 | momSoPath = configRC.data['mom']['mom0']['so_path'] |
| 1279 | except: |
| 1280 | momSoPath = None |
| 1281 | if (momSoPath): |
| 1282 | if (os.path.exists(momSoPath)): |
| 1283 | cmd='ls -l *mom* ; /bin/cp -p %s . ; ls -l *mom*' % (momSoPath) |
| 1284 | os.system(cmd) |
| 1285 | else: |
| 1286 | sys.stderr.write('ERROR: mom module %s does not exist\n' % (momSoPath)) |
| 1287 | sys.exit() |
| 1288 | |
| 1289 | if (momObjs != []) and (not optdir.has_key('--blaze')): |
| 1290 | prompt = configRC.data[ReadConfigDiag.TYPE_SYS_CONFIG][RC_SYS_CONFIG_OBJ][RC_PROMPT] |
| 1291 | if prompt == 'nas': |
| 1292 | optdir['--blaze'] = 'n2' |
| 1293 | else: |
| 1294 | sys.stderr.write('ERROR: unknown system prompt %s\n' % (prompt)) |
| 1295 | sys.exit() |
| 1296 | |
| 1297 | |
| 1298 | # construct backend system |
| 1299 | SYSTEM = 'rsys' |
| 1300 | rsys = pfeSim |
| 1301 | sysAddr = 0L |
| 1302 | constructSystem(optdir) |
| 1303 | |
| 1304 | if configRC: |
| 1305 | MEM_IMAGE = configRC.getObjData(ReadConfigDiag.TYPE_SYS_CONFIG, RC_SYS_CONFIG_OBJ, RC_MEM_IMAGE) |
| 1306 | else: |
| 1307 | MEM_IMAGE = 'mem.image' |
| 1308 | |
| 1309 | # a Repository object for variables that should be availabe globally, |
| 1310 | # this is most useful in interactive mode, where we may need to eval() |
| 1311 | # commands at various locations. |
| 1312 | import Repository |
| 1313 | riesReposit = Repository.Repository() |
| 1314 | |
| 1315 | riesReposit.riesling = rsys |
| 1316 | riesReposit.topName = SYSTEM |
| 1317 | # record main program's globals so other functions deep in the code |
| 1318 | # structure can have access to top layer values. |
| 1319 | riesReposit.globals = globals() |
| 1320 | riesReposit.sysAddr = sysAddr |
| 1321 | riesReposit.ncpus = ncpus |
| 1322 | riesReposit.ncores = ncores |
| 1323 | riesReposit.nucores = nucores |
| 1324 | riesReposit.nstrands = nstrands |
| 1325 | riesReposit.optdir = optdir |
| 1326 | riesReposit.cpus = cpus |
| 1327 | riesReposit.cores = cores |
| 1328 | riesReposit.ucores = ucores |
| 1329 | riesReposit.strands = strands |
| 1330 | |
| 1331 | #declare variables for single, double and quad fp regs |
| 1332 | # is it ok to put n2 specific constants here? ---> fp is generic enough |
| 1333 | riesReposit.nSpregs = 64 |
| 1334 | riesReposit.nDpregs = 32 |
| 1335 | riesReposit.nQpregs = 16 |
| 1336 | riesReposit.arch = optdir['--ar'] |
| 1337 | |
| 1338 | # create a command parser |
| 1339 | #import CmdParserNi |
| 1340 | # we have to import CmdParserNiCmd* at this level so that all the |
| 1341 | # RS_zzz() can be globally available |
| 1342 | createCommandParser() |
| 1343 | |
| 1344 | parms = { 'confRC':configRC, 'reposit':riesReposit, 'parser':parser } |
| 1345 | |
| 1346 | # register @def/def functions' doc, if any |
| 1347 | registerAtDef() |
| 1348 | |
| 1349 | # load personal customization, if available |
| 1350 | filename = os.environ.get('PYTHONSTARTUP') |
| 1351 | if filename and os.path.isfile(filename): |
| 1352 | #sys.stderr.write('# Executing User Startup %s .. \n' % filename) |
| 1353 | execfile(filename) |
| 1354 | |
| 1355 | #sys.stderr.write("#DBX %s: ready for interactive mode\n" % (time.ctime())) |
| 1356 | |
| 1357 | if optdir.has_key('--blaze'): |
| 1358 | # parse blaze options, if available |
| 1359 | newBlazeCmd = [ ] |
| 1360 | rcCmd = blazercCmd(newBlazeCmd) |
| 1361 | #sys.stderr.write('#DBX: rcCmd=%s\n' % (rcCmd)) #DBX |
| 1362 | # register blaze cmooand map |
| 1363 | import SamCmdMap |
| 1364 | samCmdMap = SamCmdMap.SamCmdMap() |
| 1365 | parser.registerCmdMap(samCmdMap) |
| 1366 | # register new commands introduced by sysconf in blazerc |
| 1367 | for cmd in newBlazeCmd: |
| 1368 | samCmdMap.cmdMap.append(cmd) |
| 1369 | # switch to use 'sam' as prompt symbol, sam is blaze |
| 1370 | # infrastructure plus risling core |
| 1371 | if configRC: |
| 1372 | newline = '@conf.%s.%s = sam' % (RC_SYS_CONFIG_OBJ, RC_PROMPT) |
| 1373 | configRC.setDataLine(newline) |
| 1374 | |
| 1375 | # Historically a -p introduced pythoon script, so for now keep checking |
| 1376 | # for this -p option |
| 1377 | |
| 1378 | if optdir.has_key('-p'): |
| 1379 | files = optdir['-p'].split(',') |
| 1380 | for file in files: |
| 1381 | execfile(file) |
| 1382 | |
| 1383 | # The modern way is to treat all command line arguments that have no |
| 1384 | # dash something prefix as python scripts that are executed in the |
| 1385 | # order given |
| 1386 | |
| 1387 | if optdir.has_key('scripts'): |
| 1388 | for script in optdir['scripts']: |
| 1389 | execfile(script) |
| 1390 | |
| 1391 | # enter interactive mode |
| 1392 | #interact(banner="Sam Frontend Reader", local=vars(), **parms) |
| 1393 | |
| 1394 | # merge (optional) upper level globals() before go into the customized |
| 1395 | # interpreter |
| 1396 | uppers.update(globals()) |
| 1397 | uppers.update(locals()) |
| 1398 | interact(banner="Sam Frontend Reader", local=uppers, **parms) |