If we are doing cache simulation, refuse to start at all if the minimum
cache line size is smaller than the maximum guest register size.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12606 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/callgrind/global.h b/callgrind/global.h
index 63f6e10..b10165d 100644
--- a/callgrind/global.h
+++ b/callgrind/global.h
@@ -827,6 +827,8 @@
/* Function active counter array, indexed by function number */
extern UInt* CLG_(fn_active_array);
extern Bool CLG_(instrument_state);
+ /* min of L1 and LL cache line sizes */
+extern Int CLG_(min_line_size);
extern call_stack CLG_(current_call_stack);
extern fn_stack CLG_(current_fn_stack);
diff --git a/callgrind/main.c b/callgrind/main.c
index 62ca8c9..66af64b 100644
--- a/callgrind/main.c
+++ b/callgrind/main.c
@@ -52,6 +52,10 @@
/* thread and signal handler specific */
exec_state CLG_(current_state);
+/* min of L1 and LL cache line sizes. This only gets set to a
+ non-zero value if we are doing cache simulation. */
+Int CLG_(min_line_size) = 0;
+
/*------------------------------------------------------------*/
/*--- Statistics ---*/
@@ -613,8 +617,9 @@
{
Event* evt;
tl_assert(isIRAtom(ea));
- tl_assert(datasize >= 1 && datasize <= MIN_LINE_SIZE);
+ tl_assert(datasize >= 1);
if (!CLG_(clo).simulate_cache) return;
+ tl_assert(datasize <= CLG_(min_line_size));
if (clgs->events_used == N_EVENTS)
flushEvents(clgs);
@@ -634,8 +639,9 @@
Event* lastEvt;
Event* evt;
tl_assert(isIRAtom(ea));
- tl_assert(datasize >= 1 && datasize <= MIN_LINE_SIZE);
+ tl_assert(datasize >= 1);
if (!CLG_(clo).simulate_cache) return;
+ tl_assert(datasize <= CLG_(min_line_size));
/* Is it possible to merge this write with the preceding read? */
lastEvt = &clgs->events[clgs->events_used-1];
@@ -1027,8 +1033,8 @@
// instructions will be done inaccurately, but they're
// very rare and this avoids errors from hitting more
// than two cache lines in the simulation.
- if (dataSize > MIN_LINE_SIZE)
- dataSize = MIN_LINE_SIZE;
+ if (CLG_(clo).simulate_cache && dataSize > CLG_(min_line_size))
+ dataSize = CLG_(min_line_size);
if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify)
addEvent_Dr( &clgs, curr_inode, dataSize, d->mAddr );
if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify)
diff --git a/callgrind/sim.c b/callgrind/sim.c
index c1deff7..8703c60 100644
--- a/callgrind/sim.c
+++ b/callgrind/sim.c
@@ -1307,6 +1307,28 @@
D1.name = "D1";
LL.name = "LL";
+ // min_line_size is used to make sure that we never feed
+ // accesses to the simulator straddling more than two
+ // cache lines at any cache level
+ CLG_(min_line_size) = (I1c.line_size < D1c.line_size)
+ ? I1c.line_size : D1c.line_size;
+ CLG_(min_line_size) = (LLc.line_size < CLG_(min_line_size))
+ ? LLc.line_size : CLG_(min_line_size);
+
+ Int largest_load_or_store_size
+ = VG_(machine_get_size_of_largest_guest_register)();
+ if (CLG_(min_line_size) < largest_load_or_store_size) {
+ /* We can't continue, because the cache simulation might
+ straddle more than 2 lines, and it will assert. So let's
+ just stop before we start. */
+ VG_(umsg)("Callgrind: cannot continue: the minimum line size (%d)\n",
+ (Int)CLG_(min_line_size));
+ VG_(umsg)(" must be equal to or larger than the maximum register size (%d)\n",
+ largest_load_or_store_size );
+ VG_(umsg)(" but it is not. Exiting now.\n");
+ VG_(exit)(1);
+ }
+
cachesim_initcache(I1c, &I1);
cachesim_initcache(D1c, &D1);
cachesim_initcache(LLc, &LL);