Quoting nathan binkert <[email protected]>:
The problem Gabe is seeing is related to x86 micro-ops. He is having a race
condition between commit redirecting fetch before fetch has finished issuing
a macro-op that is doing operations that cannot be interrupted because they
can't be replayed safely. For instance updating the stack pointer mid
instruction. He is trying not to wait for the pipe to drain as much as he
is trying to allow fetch to issue what it needs to before redirecting as
soon as possible.
I guess the thing I don't understand is, why is commit redirecting
fetch? Why isn't an interrupt simply directly redirecting the fetch
stage as if there were some sort of "interrupt macroop" in the middle
of the fetch stream?
I'll admit that I don't know how it works on x86, but I'm pretty sure
that on alpha an interrupt is a fetch stage thing.
Steve/Ali, any ideas?
Nate
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev
There seems to be some confusion over how this works, and that's
understandable since it is a bit confusing. I'm not sure I have it
totally right. This is how I think it works.
1. Commit decides the time is right for an interrupt. It uses ISA
defined functions/whatnot to do that, but basically, imagine an
interrupt is queued up and an instruction just turned on interrupts.
It signals this back to fetch, keeps processing instructions, and
waits for a condition described below.
2. Fetch gets the signal from commit. It waits until it finds a break
in the instruction stream where interrupts are allowed, at which point
it stops creating new instructions.
3. Commit waits until everything that's coming has made it's way
through and the pipe is empty and up to a commit point. It checks if
interrupts are still enabled (an intermediate instruction may have
turned interrupts back off), and if they're still on it services the
interrupt.
4. Fetch starts back up at the start of the interrupt.
What my patch is addressing is how commit decides everything fetch is
going to send has made its way through the pipe. Before, it would just
make sure the ROB and store queue were empty. That would miss cases
where instructions hadn't made it to the ROB (they were stuck by
serialization in decode, for instance). If those instructions which
get left behind were necessary to get all the way up to a commit
point, you'll effectively take an interrupt in the middle of an
instruction (bad news). My change replaces that check with one that
makes sure the instList (I think?) is empty. When an instruction is
created in fetch, as part of that function call it's put into the
list. I believe the only time an instruction is ever removed is when
it's in commit and it is recognized as squashed or is committed.
Basically it holds all the "live" instructions in the CPU, and a
comment near its declaration I think even says as much. Maybe this
misses committed stores that haven't written back? Not sure.
I think maybe this scheme is flawed in any case. What if there's a
branch mispredict in microcode? Will the squashed microops just be
dropped? Will fetch remain stopped at it's "boundary" even though it
didn't get all of it, or will it start up again and find a new
boundary? This may work, but I suspect it's an overlooked corner case.
Another possibility other than communicating back to fetch, having
fetch find a boundary, making commit infer everything has bubbled
through, and then checking if interrupts are still allowed (which has
a flaw I detailed earlier). To me it makes sense to just make commit
decide "INTERRUPT NOW. Everyone out of the pool!" at some commit
point, have it nuke everything else in the pipe, and make fetch start
again from that point. It would basically be the same as the fault
handling mechanism. As I explained before, it seems like it would be a
wash performance wise.
Is that any clearer now? Did I mangle any of the facts?
Gabe
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev