Do not change the valid bit; change the meaning of the valid bit. The
value in each cache entry does not have to change for it to no longer be
considered valid. It's similar to tightening a screw by keeping it fixed
with a screwdriver and rotating the whole world around it.
The way I would do something like this in software, would be to have a
global sequence number. Every time I wanted to invalidate the whole
cache, I would increment the sequence number. Every cache entry would
get a copy of this global sequence number, and would be considered valid
only if its copy of the sequence number still matches the global
sequence number.
Of course, there's the issue of wraparound, especially in hardware where
the size of the sequence number must be limited. The trick to avoid it
is to consider that there's no problem with wraparound as long as the
copy of the sequence number has been overwritten with a newer value by
the time the global sequence number wraps around. So as long as the
sequence number has more possible values than there are cache lines, the
following pseudocode should work:
invalidate_cache:
cache_line[invalidate_row].counter := global_counter
increment(invalidate_row)
increment(global_counter)
is_cache_valid:
cache_line[index].counter == global_counter
(And invalidate_row might just be the lower bits of global_counter, to
save space.)
This overwrites the sequence number of a single cache line on every
step, while guaranteeing that the sequence numbers on the whole cache
have already been incremented by the time it wraps around.
You could make variations on the theme, like this one with a separate
valid bit and global_counter the size of the cache index (normal
operations on the cache only have to set the valid bit, which should be
simpler to implement):
invalidate_cache:
cache_line[global_counter].valid := false
cache_line[global_counter].counter := global_counter
increment(global_counter)
is_cache_valid:
cache_line[index].valid &&
cache_line[index].counter == global_counter
set_cache_valid:
cache_line[index].valid := valid
Proving that this scheme works is left as an exercise for the reader.
--
Cesar Eduardo Barros
ces...@cesarb.eti.br