[stats] Store stats backends in a vector for termination

Conflicts:

	src/init.cpp
	src/zsim.cpp

Conflicts:

	src/init.cpp
[tracing] Uncompressed tracing

Slightly cleaned-up code from tracing branch. Seems that this is
generally useful, so should be in master. Needs compression though.
[tracing] Compressed tracing based on HDF5 packet tables

~6x-12x compression, but unfortunately can't use SHUF which gives
another 5x. Will fix in future commit.
[tracing] Cleanup
[tracing] Add access_tracing.cpp, add shuffle filter

With both shuffle and gzip, we compress the dealII access trace by about
20x (1.15 bytes / 24-byte record). I guess this depends on the entropy
of the address stream, b/c the cycle, latency, access type and childId
have very little entropy to begin with.
[tracing] Bugfixes

- Correct operation of nextChunk()
- Initialize glob mem in both dumptrace and sorttrace

With these, an L3 + mem simulation running from a 10B-instruction dealII
simulation (32M references, 40MB)  finishes in 12s (~900Mcycles/s) and
gets 99% CPU utilization. Trace-driven sims are probably not I/O-bound
anymore, though this is a 4MB/sec thput, which the zgzs are probably
still too weak to handle well.
[tracing] Remove magic number

Now that traces are HDF5 files, we don't need this (bonus: they can be
read from python trivially, just like the stats).
[all] NULL -> nullptr

Shouldn't be using NULL anymore.

Conflicts:

	src/coherence_ctrls.h
	src/init.cpp
	src/partitioner.h
[log] Assertions so nice you'll want some to fail

I've noticed I often get:

[S 0] Failed assertion on build/opt/zsim.cpp:119

Then go turn the assertion into an assert_msg to get the values, and
leave it there.

Instead, a failing assertion now prints:

[S 0] Failed assertion on build/opt/zsim.cpp:119 'cid >= zinfo->numCores' (with '0 >= 1')

Note this shows the expression AND the captured values. This renders
most assert_msgs unnecessary, and saves you a trip to the code. It
also does not decrease performance.

Capturing expression values works for most typical expressions,
including comparisons, arithmetic and logical expressions. It relies on
truly evil operator overloading. A side-effect of this is that if
components of an expression don't go through a stringsteam (basically
comparisons between iterators, e.g., assert(it != vec.end())), the
expression needs to be parenthesized, i.e., assert((it != vec.end())).
These will be fixed in the next commit.
[log] Fix assertion expressions whose values can't be captured

Basically, iterator comparisons, since iterators can't be printed.
[stats] Make Counter, ProxyStats, ProxyFuncStat inherit from ScalarStat

Simplifies stats backends.
[proc_stats] General per-process stats

This is slated to substitute ProcessStats, hence the similar name.

ProcStats gets a filtered set of stats and records them per-process. For
example, with:

sim.procStatsFilter = "(core.*|l1i.*)|(l1d.*|l2.*)"

the stats file will have a procStats entry, with one entry per process,
and each per-process entry has all the stats that math the regex (in the
example above, all the core, l1d, l1i, and l2 stats).

ProcStats gets notified about deschedulings and updates its stats from the
original stats tree, so it works for arbitrary stats. May not get exact
results for overcommitted systems (i.e. with mid-phase deschedulings).
[proc_stats] Cleanup
[virt/fs] Revamp patchRoot to patch arbitrary system paths

- Much more robust implementation that catches symlinks and implements
  the path resolution process exactly. Instead of calling realpath, which
  resolves all symlinks at once, the code now tries to match against
  faked paths on every intermediate symlink.
- fakedPaths is resolved at runtime instead of being hardcoded. This
  means that patchRoot can now have any part of the filesystem, and
  we'll patch all the base folders that match (e.g., lib, usr, ...).
- patchRoot can now have symlinks instead of the actual files.

With these, patchRoot can be now used to fake the whole fs, and not only
/proc and /sys. In particular, patching /usr and /lib lets us intercept
and patch all dynamically loaded libraries and all binaries executed as
subprocesses to a stable directory, even if the host machine has
different ones or the host libs change over time.
[misc/patchRoot] Fix minor bug in genPatchRoot script

The cpuXX/online files were being written to cpuXX/topology/online
[harness] More robust SIGCHLD handler

The old version seems to have a race. Not clear if this fixes it, but in
a couple of runs it seems to do the trick.
[str] g-vector stringifier
[zcache] Simple ILP optimization

Often, ZArray::preinsert consumes ~30% of exec time. Preinsert was
dominated (95% of exec time according to perf top) by an unpredictable,
long-latency, data-dependent branch inside a loop. Rewrote the code to
remove the branch without changing the semantics.

Haven't reprofiled, but objdump shows the branch is gone and gcc starts
unrolling/software-pipelining the loop.
[tests/pgo] Change PGO flow to profile zcache

We were not hitting this code with the pgo.cfg file.
[locks] Tune futex_lock spin interval

Much lower interval than before. Overall, puts more pressure on the
kernel (__ticket_spinlock overheads are frequent), but this works out
well because (a) we typically overcommit systems, so blocking sooner
leaves space for another useful contexts, and (b) this is much more
fair, because heavily queued-up locks don't contend with user-space
waiters as frequently when they're woken up from the kernel.

~10% faster on Jigsaw.