diff options
Diffstat (limited to 'util')
-rw-r--r-- | util/statetrace/arch/tracechild_sparc.cc | 172 | ||||
-rw-r--r-- | util/statetrace/arch/tracechild_sparc.hh | 8 | ||||
-rw-r--r-- | util/term/term.c | 283 | ||||
-rwxr-xr-x | util/tracediff | 62 |
4 files changed, 316 insertions, 209 deletions
diff --git a/util/statetrace/arch/tracechild_sparc.cc b/util/statetrace/arch/tracechild_sparc.cc index 378de0865..bad81b647 100644 --- a/util/statetrace/arch/tracechild_sparc.cc +++ b/util/statetrace/arch/tracechild_sparc.cc @@ -47,10 +47,10 @@ string SparcTraceChild::regNames[numregs] = { //Input registers "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7", //Floating point - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", - "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", - "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", - "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", + "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14", + "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30", + "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46", + "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62", //Miscelaneous "fsr", "fprs", "pc", "npc", "y", "cwp", "pstate", "asi", "ccr"}; @@ -98,37 +98,37 @@ int64_t getRegs(regs & myregs, fpu & myfpu, case SparcTraceChild::I7: return inputs[7]; //Floating point case SparcTraceChild::F0: return myfpu.f_fpstatus.fpu_fr[0]; - case SparcTraceChild::F1: return myfpu.f_fpstatus.fpu_fr[1]; - case SparcTraceChild::F2: return myfpu.f_fpstatus.fpu_fr[2]; - case SparcTraceChild::F3: return myfpu.f_fpstatus.fpu_fr[3]; - case SparcTraceChild::F4: return myfpu.f_fpstatus.fpu_fr[4]; - case SparcTraceChild::F5: return myfpu.f_fpstatus.fpu_fr[5]; - case SparcTraceChild::F6: return myfpu.f_fpstatus.fpu_fr[6]; - case SparcTraceChild::F7: return myfpu.f_fpstatus.fpu_fr[7]; - case SparcTraceChild::F8: return myfpu.f_fpstatus.fpu_fr[8]; - case SparcTraceChild::F9: return myfpu.f_fpstatus.fpu_fr[9]; - case SparcTraceChild::F10: return myfpu.f_fpstatus.fpu_fr[10]; - case SparcTraceChild::F11: return myfpu.f_fpstatus.fpu_fr[11]; - case SparcTraceChild::F12: return myfpu.f_fpstatus.fpu_fr[12]; - case SparcTraceChild::F13: return myfpu.f_fpstatus.fpu_fr[13]; - case SparcTraceChild::F14: return myfpu.f_fpstatus.fpu_fr[14]; - case SparcTraceChild::F15: return myfpu.f_fpstatus.fpu_fr[15]; - case SparcTraceChild::F16: return myfpu.f_fpstatus.fpu_fr[16]; - case SparcTraceChild::F17: return myfpu.f_fpstatus.fpu_fr[17]; - case SparcTraceChild::F18: return myfpu.f_fpstatus.fpu_fr[18]; - case SparcTraceChild::F19: return myfpu.f_fpstatus.fpu_fr[19]; - case SparcTraceChild::F20: return myfpu.f_fpstatus.fpu_fr[20]; - case SparcTraceChild::F21: return myfpu.f_fpstatus.fpu_fr[21]; - case SparcTraceChild::F22: return myfpu.f_fpstatus.fpu_fr[22]; - case SparcTraceChild::F23: return myfpu.f_fpstatus.fpu_fr[23]; - case SparcTraceChild::F24: return myfpu.f_fpstatus.fpu_fr[24]; - case SparcTraceChild::F25: return myfpu.f_fpstatus.fpu_fr[25]; - case SparcTraceChild::F26: return myfpu.f_fpstatus.fpu_fr[26]; - case SparcTraceChild::F27: return myfpu.f_fpstatus.fpu_fr[27]; - case SparcTraceChild::F28: return myfpu.f_fpstatus.fpu_fr[28]; - case SparcTraceChild::F29: return myfpu.f_fpstatus.fpu_fr[29]; - case SparcTraceChild::F30: return myfpu.f_fpstatus.fpu_fr[30]; - case SparcTraceChild::F31: return myfpu.f_fpstatus.fpu_fr[31]; + case SparcTraceChild::F2: return myfpu.f_fpstatus.fpu_fr[1]; + case SparcTraceChild::F4: return myfpu.f_fpstatus.fpu_fr[2]; + case SparcTraceChild::F6: return myfpu.f_fpstatus.fpu_fr[3]; + case SparcTraceChild::F8: return myfpu.f_fpstatus.fpu_fr[4]; + case SparcTraceChild::F10: return myfpu.f_fpstatus.fpu_fr[5]; + case SparcTraceChild::F12: return myfpu.f_fpstatus.fpu_fr[6]; + case SparcTraceChild::F14: return myfpu.f_fpstatus.fpu_fr[7]; + case SparcTraceChild::F16: return myfpu.f_fpstatus.fpu_fr[8]; + case SparcTraceChild::F18: return myfpu.f_fpstatus.fpu_fr[9]; + case SparcTraceChild::F20: return myfpu.f_fpstatus.fpu_fr[10]; + case SparcTraceChild::F22: return myfpu.f_fpstatus.fpu_fr[11]; + case SparcTraceChild::F24: return myfpu.f_fpstatus.fpu_fr[12]; + case SparcTraceChild::F26: return myfpu.f_fpstatus.fpu_fr[13]; + case SparcTraceChild::F28: return myfpu.f_fpstatus.fpu_fr[14]; + case SparcTraceChild::F30: return myfpu.f_fpstatus.fpu_fr[15]; + case SparcTraceChild::F32: return myfpu.f_fpstatus.fpu_fr[16]; + case SparcTraceChild::F34: return myfpu.f_fpstatus.fpu_fr[17]; + case SparcTraceChild::F36: return myfpu.f_fpstatus.fpu_fr[18]; + case SparcTraceChild::F38: return myfpu.f_fpstatus.fpu_fr[19]; + case SparcTraceChild::F40: return myfpu.f_fpstatus.fpu_fr[20]; + case SparcTraceChild::F42: return myfpu.f_fpstatus.fpu_fr[21]; + case SparcTraceChild::F44: return myfpu.f_fpstatus.fpu_fr[22]; + case SparcTraceChild::F46: return myfpu.f_fpstatus.fpu_fr[23]; + case SparcTraceChild::F48: return myfpu.f_fpstatus.fpu_fr[24]; + case SparcTraceChild::F50: return myfpu.f_fpstatus.fpu_fr[25]; + case SparcTraceChild::F52: return myfpu.f_fpstatus.fpu_fr[26]; + case SparcTraceChild::F54: return myfpu.f_fpstatus.fpu_fr[27]; + case SparcTraceChild::F56: return myfpu.f_fpstatus.fpu_fr[28]; + case SparcTraceChild::F58: return myfpu.f_fpstatus.fpu_fr[29]; + case SparcTraceChild::F60: return myfpu.f_fpstatus.fpu_fr[30]; + case SparcTraceChild::F62: return myfpu.f_fpstatus.fpu_fr[31]; //Miscelaneous case SparcTraceChild::FSR: return myfpu.f_fpstatus.Fpu_fsr; case SparcTraceChild::FPRS: return myregs.r_fprs; @@ -188,46 +188,110 @@ bool SparcTraceChild::step() //being breakpointed should be word (64bit) aligned, and that both the //next instruction and the instruction after that need to be breakpointed //so that annulled branches will still stop as well. + + /* + * Useful constants + */ const static uint64_t breakInst = 0x91d02001; const static uint64_t breakWord = breakInst | (breakInst << 32); - const static uint64_t lowMask = (uint64_t)(0xFFFFFFFF); + const static uint64_t lowMask = 0xFFFFFFFFULL; const static uint64_t highMask = lowMask << 32; + + /* + * storage for the original contents of the child process's memory + */ uint64_t originalInst, originalAnnulInst; + + /* + * Get information about where the process is and is headed next. + */ + uint64_t currentPC = getRegVal(PC); + bool unalignedPC = currentPC & 7; + uint64_t alignedPC = currentPC & (~7); uint64_t nextPC = getRegVal(NPC); - bool unaligned = nextPC & 7; - uint64_t alignedPC = nextPC & (~7); - originalInst = ptrace(PTRACE_PEEKTEXT, pid, alignedPC, 0); - if(unaligned) + bool unalignedNPC = nextPC & 7; + uint64_t alignedNPC = nextPC & (~7); + + /* + * Store the original contents of the child process's memory + */ + originalInst = ptrace(PTRACE_PEEKTEXT, pid, alignedNPC, 0); + //Save a ptrace call if we can + if(unalignedNPC) { - originalAnnulInst = ptrace(PTRACE_PEEKTEXT, pid, alignedPC+8, 0); + originalAnnulInst = ptrace(PTRACE_PEEKTEXT, pid, alignedNPC+8, 0); } - uint64_t newInst; - if(unaligned) + + /* + * Prepare breakpointed copies of child processes memory + */ + uint64_t newInst, newAnnulInst; + //If the current instruction is in the same word as the npc + if(alignedPC == alignedNPC) { - newInst = (originalInst & highMask) | (breakInst << 0); - if(ptrace(PTRACE_POKETEXT, pid, alignedPC, newInst) != 0) - cerr << "Poke failed" << endl; - newInst = (originalAnnulInst & lowMask) | (breakInst << 32); - if(ptrace(PTRACE_POKETEXT, pid, alignedPC+8, newInst) != 0) - cerr << "Poke failed" << endl; + //Make sure we only replace the other part + if(unalignedPC) + newInst = (originalInst & lowMask) | (breakWord & highMask); + else + newInst = (originalInst & highMask) | (breakWord & lowMask); + } + else + { + //otherwise replace the whole thing + newInst = breakWord; + } + //If the current instruction is in the same word as the word after + //the npc + if(alignedPC == alignedNPC+8) + { + //Make sure we only replace the other part + if(unalignedPC) + newAnnulInst = (originalAnnulInst & lowMask) | (breakWord & highMask); + else + newAnnulInst = (originalAnnulInst & highMask) | (breakWord & lowMask); } else { - if(ptrace(PTRACE_POKETEXT, pid, alignedPC, breakWord) != 0) + //otherwise replace the whole thing + newAnnulInst = breakWord; + } + + /* + * Stuff the breakpoint instructions into the child's address space. + */ + //Replace the word at npc + if(ptrace(PTRACE_POKETEXT, pid, alignedNPC, newInst) != 0) + cerr << "Poke failed" << endl; + //Replace the next word, if necessary + if(unalignedNPC) + { + if(ptrace(PTRACE_POKETEXT, pid, alignedNPC+8, newAnnulInst) != 0) cerr << "Poke failed" << endl; } + + /* + * Restart the child process + */ //Note that the "addr" parameter is supposed to be ignored, but in at //least one version of the kernel, it must be 1 or it will set what //pc to continue from - if(ptrace(PTRACE_CONT, pid, /*nextPC - 4*/ 1, 0) != 0) + if(ptrace(PTRACE_CONT, pid, 1, 0) != 0) cerr << "Cont failed" << endl; doWait(); + + /* + * Update our record of the child's state + */ update(pid); - if(ptrace(PTRACE_POKETEXT, pid, alignedPC, originalInst) != 0) + + /* + * Put back the original contents of the childs address space + */ + if(ptrace(PTRACE_POKETEXT, pid, alignedNPC, originalInst) != 0) cerr << "Repoke failed" << endl; - if(unaligned) + if(unalignedNPC) { - if(ptrace(PTRACE_POKETEXT, pid, alignedPC+8, originalAnnulInst) != 0) + if(ptrace(PTRACE_POKETEXT, pid, alignedNPC+8, originalAnnulInst) != 0) cerr << "Repoke failed" << endl; } return true; diff --git a/util/statetrace/arch/tracechild_sparc.hh b/util/statetrace/arch/tracechild_sparc.hh index d177d5941..80770211a 100644 --- a/util/statetrace/arch/tracechild_sparc.hh +++ b/util/statetrace/arch/tracechild_sparc.hh @@ -57,10 +57,10 @@ public: //Input registers I0, I1, I2, I3, I4, I5, I6, I7, //Floating point - F0, F1, F2, F3, F4, F5, F6, F7, - F8, F9, F10, F11, F12, F13, F14, F15, - F16, F17, F18, F19, F20, F21, F22, F23, - F24, F25, F26, F27, F28, F29, F30, F31, + F0, F2, F4, F6, F8, F10, F12, F14, + F16, F18, F20, F22, F24, F26, F28, F30, + F32, F34, F36, F38, F40, F42, F44, F46, + F48, F50, F52, F54, F56, F58, F60, F62, //Miscelaneous FSR, FPRS, PC, NPC, Y, CWP, PSTATE, ASI, CCR, numregs diff --git a/util/term/term.c b/util/term/term.c index 8a95480b1..597966159 100644 --- a/util/term/term.c +++ b/util/term/term.c @@ -60,46 +60,49 @@ void usage(int); int main(int argc, char *argv[]) { - int ch, s, ret; - char *host, *port, *endp; - struct addrinfo hints; - socklen_t len; - - ret = 1; - s = 0; - host = NULL; - port = NULL; - endp = NULL; - - strncpy(progname, argv[0], sizeof progname); - - /* Cruft to make sure options are clean, and used properly. */ - if (argc != 3 || !argv[1] || !argv[2]) - usage(1); - + int ch, s, ret; + char *host, *port, *endp; + struct addrinfo hints; + socklen_t len; + + ret = 1; + s = 0; + host = NULL; + port = NULL; + endp = NULL; + + strncpy(progname, argv[0], sizeof progname); + + /* Cruft to make sure options are clean, and used properly. */ + if (argc == 2) { + host = "localhost"; + port = argv[1]; + } else if (argc == 3) { host = argv[1]; port = argv[2]; + } else { + usage(1); + } + if (!isatty(STDIN_FILENO)) + errx(1, "not attached to a terminal"); - if (!isatty(STDIN_FILENO)) - errx(1, "not attached to a terminal"); + raw_term(); - raw_term(); + /* Initialize addrinfo structure */ + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; - /* Initialize addrinfo structure */ - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; + s = remote_connect(host, port, hints); + ret = 0; + readwrite(s); - s = remote_connect(host, port, hints); - ret = 0; - readwrite(s); + if (s) + close(s); - if (s) - close(s); - - exit(ret); + exit(ret); } /* @@ -110,28 +113,28 @@ main(int argc, char *argv[]) int remote_connect(char *host, char *port, struct addrinfo hints) { - struct addrinfo *res, *res0; - int s, error; + struct addrinfo *res, *res0; + int s, error; - if ((error = getaddrinfo(host, port, &hints, &res))) - errx(1, "getaddrinfo: %s", gai_strerror(error)); + if ((error = getaddrinfo(host, port, &hints, &res))) + errx(1, "getaddrinfo: %s", gai_strerror(error)); - res0 = res; - do { - if ((s = socket(res0->ai_family, res0->ai_socktype, - res0->ai_protocol)) < 0) - continue; + res0 = res; + do { + if ((s = socket(res0->ai_family, res0->ai_socktype, + res0->ai_protocol)) < 0) + continue; - if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0) - break; + if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0) + break; - close(s); - s = -1; - } while ((res0 = res0->ai_next) != NULL); + close(s); + s = -1; + } while ((res0 = res0->ai_next) != NULL); - freeaddrinfo(res); + freeaddrinfo(res); - return (s); + return (s); } /* @@ -141,79 +144,79 @@ remote_connect(char *host, char *port, struct addrinfo hints) void readwrite(int nfd) { - struct pollfd pfd[2]; - char buf[BUFSIZ]; - int wfd = fileno(stdin), n, ret; - int lfd = fileno(stdout); - int escape = 0; - - /* Setup Network FD */ - pfd[0].fd = nfd; - pfd[0].events = POLLIN; - - /* Setup STDIN FD */ - pfd[1].fd = wfd; - pfd[1].events = POLLIN; - - while (pfd[0].fd != -1) { - if ((n = poll(pfd, 2, -1)) < 0) { - close(nfd); - err(1, "Polling Error"); - } + struct pollfd pfd[2]; + char buf[BUFSIZ]; + int wfd = fileno(stdin), n, ret; + int lfd = fileno(stdout); + int escape = 0; + + /* Setup Network FD */ + pfd[0].fd = nfd; + pfd[0].events = POLLIN; + + /* Setup STDIN FD */ + pfd[1].fd = wfd; + pfd[1].events = POLLIN; + + while (pfd[0].fd != -1) { + if ((n = poll(pfd, 2, -1)) < 0) { + close(nfd); + err(1, "Polling Error"); + } - if (n == 0) - return; + if (n == 0) + return; + + if (pfd[0].revents & POLLIN) { + if ((n = read(nfd, buf, sizeof(buf))) < 0) + return; + else if (n == 0) { + shutdown(nfd, SHUT_RD); + pfd[0].fd = -1; + pfd[0].events = 0; + } else { + if ((ret = atomicio(write, lfd, buf, n)) != n) + return; + } + } - if (pfd[0].revents & POLLIN) { - if ((n = read(nfd, buf, sizeof(buf))) < 0) - return; - else if (n == 0) { - shutdown(nfd, SHUT_RD); - pfd[0].fd = -1; - pfd[0].events = 0; - } else { - if ((ret = atomicio(write, lfd, buf, n)) != n) - return; - } + if (pfd[1].revents & POLLIN) { + if ((n = read(wfd, buf, sizeof(buf))) < 0) + return; + else if (n == 0) { + shutdown(nfd, SHUT_WR); + pfd[1].fd = -1; + pfd[1].events = 0; + } else { + if (escape) { + char buf2[] = "~"; + if (*buf == '.') { + printf("quit!\n"); + return; + } + escape = 0; + if (*buf != '~' && + (ret = atomicio(write, nfd, buf2, 1)) != n) + return; + } else { + escape = (*buf == '~'); + if (escape) + continue; } - if (pfd[1].revents & POLLIN) { - if ((n = read(wfd, buf, sizeof(buf))) < 0) - return; - else if (n == 0) { - shutdown(nfd, SHUT_WR); - pfd[1].fd = -1; - pfd[1].events = 0; - } else { - if (escape) { - char buf2[] = "~"; - if (*buf == '.') { - printf("quit!\n"); - return; - } - escape = 0; - if (*buf != '~' && - (ret = atomicio(write, nfd, buf2, 1)) != n) - return; - } else { - escape = (*buf == '~'); - if (escape) - continue; - } - - if ((ret = atomicio(write, nfd, buf, n)) != n) - return; - } - } + if ((ret = atomicio(write, nfd, buf, n)) != n) + return; + } } + } } void usage(int ret) { - fprintf(stderr, "usage: %s hostname port\n", progname); - if (ret) - exit(1); + fprintf(stderr, "usage: %s hostname port\n", progname); + if (ret) + exit(1); } /* @@ -247,22 +250,22 @@ usage(int ret) ssize_t atomicio(ssize_t (*f) (), int fd, void *_s, size_t n) { - char *s = _s; - ssize_t res, pos = 0; - - while (n > pos) { - res = (f) (fd, s + pos, n - pos); - switch (res) { - case -1: - if (errno == EINTR || errno == EAGAIN) - continue; - case 0: - return (res); - default: - pos += res; - } + char *s = _s; + ssize_t res, pos = 0; + + while (n > pos) { + res = (f) (fd, s + pos, n - pos); + switch (res) { + case -1: + if (errno == EINTR || errno == EAGAIN) + continue; + case 0: + return (res); + default: + pos += res; } - return (pos); + } + return (pos); } /* @@ -284,28 +287,28 @@ atomicio(ssize_t (*f) (), int fd, void *_s, size_t n) void raw_term() { - struct termios ios; + struct termios ios; - if (tcgetattr(STDIN_FILENO, &ios) < 0) - errx(1, "tcgetagttr\n"); + if (tcgetattr(STDIN_FILENO, &ios) < 0) + errx(1, "tcgetagttr\n"); - memcpy(&saved_ios, &ios, sizeof(struct termios)); + memcpy(&saved_ios, &ios, sizeof(struct termios)); - ios.c_iflag &= ~(ISTRIP|ICRNL|IGNCR|ICRNL|IXOFF|IXON); - ios.c_oflag &= ~(OPOST); - ios.c_oflag &= (ONLCR); - ios.c_lflag &= ~(ISIG|ICANON|ECHO); - ios.c_cc[VMIN] = 1; - ios.c_cc[VTIME] = 0; + ios.c_iflag &= ~(ISTRIP|ICRNL|IGNCR|ICRNL|IXOFF|IXON); + ios.c_oflag &= ~(OPOST); + ios.c_oflag &= (ONLCR); + ios.c_lflag &= ~(ISIG|ICANON|ECHO); + ios.c_cc[VMIN] = 1; + ios.c_cc[VTIME] = 0; - if (tcsetattr(STDIN_FILENO, TCSANOW, &ios) < 0) - errx(1, "tcsetattr\n"); + if (tcsetattr(STDIN_FILENO, TCSANOW, &ios) < 0) + errx(1, "tcsetattr\n"); - atexit(restore_term); + atexit(restore_term); } void restore_term() { - tcsetattr(STDIN_FILENO, TCSANOW, &saved_ios); + tcsetattr(STDIN_FILENO, TCSANOW, &saved_ios); } diff --git a/util/tracediff b/util/tracediff index f2377a999..b25efe9b2 100755 --- a/util/tracediff +++ b/util/tracediff @@ -33,23 +33,63 @@ # ******Note that you need to enable some trace flags in the args in order # to do anything useful!****** # -# If you want to pass different arguments to the two instances of m5, -# you can embed them in the simulator arguments like this: +# Script arguments are handled uniformly as follows: +# - If the argument does not contain a '|' character, it is appended +# to both command lines. +# - If the argument has a '|' character in it, the text on either side +# of the '|' is appended to the respective command lines. Note that +# you'll have to quote the arg or escape the '|' with a backslash +# so that the shell doesn't think you're doing a pipe. # -# % tracediff "m5.opt --option1" "m5.opt --option2" [common args] +# In other words, the arguments should look like the command line you +# want to run, with "|" used to list the alternatives for the parts +# that you want to differ between the two runs. +# +# For example: +# +# % tracediff m5.opt --opt1 "--opt2|--opt3" --opt4 +# would compare these two runs: +# m5.opt --opt1 --opt2 --opt4 +# m5.opt --opt1 --opt3 --opt4 +# +# If you want to compare two different simulator binaries, put a '|' +# in the first script argument ("path1/m5.opt|path2/m5.opt"). If you +# want to add arguments to one run only, just put a '|' in with text +# only on one side ("--onlyOn1|"). You can do this with multiple +# arguments together too ("|-a -b -c" adds three args to the second +# run only). # if (@ARGV < 2) { - die "Usage: tracediff sim1 sim2 [--root.trace.flags=X args...]\n"; + die "Usage: tracediff \"sim1|sim2\" [common-arg \"arg1|arg2\" ...]\n"; +} + +foreach $arg (@ARGV) { + @pair = split('\|', $arg, -1); # -1 enables null trailing fields + if ($#pair > 0) { + push @cmd1, $pair[0]; + push @cmd2, $pair[1]; + } else { + push @cmd1, $arg; + push @cmd2, $arg; + } } # First two args are the two simulator binaries to compare -$sim1 = shift; -$sim2 = shift; +$sim1 = shift @cmd1; +$sim2 = shift @cmd2; + +# Everything else is a simulator arg. +$args1 = join(' ', @cmd1); +$args2 = join(' ', @cmd2); -# Everything else on the command line is taken to be an m5 argument to -# be given to both invocations -$simargs = '"' . join('" "', @ARGV) . '"'; +# Common mistake: if you don't set any traceflags this often isn't +# doing what you want. +if ($args1 !~ /--trace-flags/) { + print "****\n"; + print "**** WARNING: no trace flags set... you may not be diffing much!\n"; + print "****\n"; +} # Run individual invocations in separate dirs so output and intermediate # files (particularly config.py and config.ini) don't conflict. @@ -58,8 +98,8 @@ $dir2 = "tracediff-$$-2"; mkdir($dir1) or die "Can't create dir $dir1\n"; mkdir($dir2) or die "Can't create dir $dir2\n"; -$cmd1 = "$sim1 -d $dir1 $simargs 2>&1 |"; -$cmd2 = "$sim2 -d $dir2 $simargs 2>&1 |"; +$cmd1 = "$sim1 -d $dir1 $args1 2>&1 |"; +$cmd2 = "$sim2 -d $dir2 $args2 2>&1 |"; # This only works if you have rundiff in your path. I just edit it # with an explicit path if necessary. |