something handled by data-forward must be handled by stall if no data-forward anymore. so when
d_srcA in { e_dstE, M_dstM, M_dstE, W_dstM, W_dstE } ||
d_srcB in { e_dstE, M_dstM, M_dstE, W_dstM, W_dstE }
data hazard happens, we have to insert bubble in phase E and stall phase F&D
load/use hazard
load/use hazard only happens when we use data-forward. no load/use hazard if no data-forward.
pay attention
d_srcA == E_dstM || d_srcB == E_dstM
now toggles data hazard.d_srcA == RNONE == e_dstE == E_dstM == ...etc
, that’s not
data hazardso we get:
situation: data_hazard
bool s_data_hazard =
(
(
d_srcA != RNONE &&
d_srcA in { e_dstE, E_dstM, M_dstM, M_dstE, W_dstM, W_dstE }
) ||
(
d_srcB != RNONE &&
d_srcB in { e_dstE, E_dstM, M_dstM, M_dstE, W_dstM, W_dstE }
)
)
keep same
situation: ret
bool s_ret = IRET in { D_icode, E_icode, M_icode };
keep same
situation: jxx error
bool s_jxx_error = (E_icode == IJXX && !e_Cnd);
X means nothing to do; stall means stall; bubble means inserting bubble
num | data | ret | jxx | F | D | E | M | W |
---|---|---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | X | X | X | X | X |
2 | 0 | 0 | 1 | X | bubble | bubble | X | X |
3 | 0 | 1 | 0 | stall | bubble | X | X | X |
4 | 1 | 0 | 0 | stall | stall | bubble | X | X |
situation 1: nothing happens, every thing is fine
situation 2: just jxx error, keep same with book
situation 3: just ret, keep same with book
situation 4: just data hazard, stall phase F and D, insert bubble in phase E, M and W keep same
what if two/three of them happen same time?
ret:
+-----------+ +-----------+ +-----------+
M | | M | | M | ret |
+-----------+ +-----------+ +-----------+
E | | E | ret | E | nop |
+-----------+ +-----------+ +-----------+
D | ret | D | nop | D | nop |
+-----------+ +-----------+ +-----------+
1 2 3
one of them
jxx error:
+-----------+
M | |
+-----------+
E | jxx |
+-----------+
D | |
+-----------+
when jxx error happens, E_icode must be jxx
data hazard:
<--+
+-----------+ |
M | |<--+
+-----------+ |
E | |<--+
+-----------+ |
D | xxx +---+
+-----------+
when data hazard happens, D_icode is not sure, xxx means any instruction
composition 1: ret and jxx
keep same on book
composition 2: ret and data hazard
they two happens same time, so xxx must be ret
<--+
+-----------+ |
M | |<--+
+-----------+ |
E | |<--+
+-----------+ |
D | ret +---+
+-----------+
when they happen same time, data hazard is prior to ret because if ret doesn’t stall to avoid data hazard, we get wrong answer with ISA
composition 3: jxx error and data hazard
<--+
+-----------+ |
M | |<--+
+-----------+ |
E | jxx |<--+
+-----------+ |
D | xxx +---+
+-----------+
when they two happens same time, jxx error is prior to data hazard because next 2 instructions is canceled when jxx error, xxx is canceled anymore.
composition 4: ret & jxx error & data hazard
<--+
+-----------+ |
M | |<--+
+-----------+ |
E | jxx |<--+
+-----------+ |
D | ret +---+
+-----------+
same like composition 3.
finally:
num | data | ret | jxx | F | D | E | M | W |
---|---|---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | X | X | X | X | X |
2 | 0 | 0 | 1 | X | bubble | bubble | X | X |
3 | 0 | 1 | 0 | stall | bubble | X | X | X |
4 | 1 | 0 | 0 | stall | stall | bubble | X | X |
5 | 0 | 1 | 1 | X | bubble | bubble | X | X |
6 | 1 | 0 | 1 | X | bubble | bubble | X | X |
7 | 1 | 1 | 0 | stall | stall | bubble | X | X |
8 | 1 | 1 | 1 | X | bubble | bubble | X | X |
F:
D:
E:
M:
keep same
W:
keep same
finally:
check file ./site/content/chapter4/code/sim/pipe/pipe-stall.hcl
watch changes with origin pipe-stall.hcl file
(cd ./site/content/chapter4/code/sim/pipe; diff -u origin-pipe-stall.hcl pipe-stall.hcl)
--- origin-pipe-stall.hcl 2021-02-25 07:26:33.309259378 +0000
+++ pipe-stall.hcl 2021-02-25 07:26:33.309259378 +0000
@@ -303,40 +303,95 @@
];
################ Pipeline Register Control #########################
+# situation: ret
+# bool s_ret = IRET in { D_icode, E_icode, M_icode };
+#
+# situation: jxx error
+# bool s_jxx_error = (E_icode == IJXX && !e_Cnd);
+#
+# situation: data_hazard
+# bool s_data_hazard =
+# (
+# (
+# d_srcA != RNONE &&
+# d_srcA in { e_dstE, E_dstM, M_dstM, M_dstE, W_dstM, W_dstE }
+# ) ||
+# (
+# d_srcB != RNONE &&
+# d_srcB in { e_dstE, E_dstM, M_dstM, M_dstE, W_dstM, W_dstE }
+# )
+# )
# Should I stall or inject a bubble into Pipeline Register F?
# At most one of these can be true.
-bool F_stall =
- # Modify the following to stall the update of pipeline register F
- 0 ||
- # Stalling at fetch while ret passes through pipeline
- IRET in { D_icode, E_icode, M_icode };
+# bool F_stall = (s_ret || s_data_hazard) && !s_jxx_error;
+bool F_stall = (
+ (IRET in { D_icode, E_icode, M_icode }) ||
+ (
+ (
+ d_srcA != RNONE &&
+ d_srcA in { e_dstE, E_dstM, M_dstM, M_dstE, W_dstM, W_dstE }
+ ) ||
+ (
+ d_srcB != RNONE &&
+ d_srcB in { e_dstE, E_dstM, M_dstM, M_dstE, W_dstM, W_dstE }
+ )
+ )
+ ) &&
+ !(E_icode == IJXX && !e_Cnd);
bool F_bubble = 0;
# Should I stall or inject a bubble into Pipeline Register D?
# At most one of these can be true.
-bool D_stall =
- # Modify the following to stall the instruction in decode
- 0;
+# bool D_stall = s_data_hazard && !s_jxx_error;
+# bool D_bubble = s_jxx_error || (!s_data_hazard && s_ret)
+bool D_stall = (
+ (
+ d_srcA != RNONE &&
+ d_srcA in { e_dstE, E_dstM, M_dstM, M_dstE, W_dstM, W_dstE }
+ ) ||
+ (
+ d_srcB != RNONE &&
+ d_srcB in { e_dstE, E_dstM, M_dstM, M_dstE, W_dstM, W_dstE }
+ )
+ ) &&
+ !(E_icode == IJXX && !e_Cnd);
bool D_bubble =
- # Mispredicted branch
- (E_icode == IJXX && !e_Cnd) ||
- # Stalling at fetch while ret passes through pipeline
- !(E_icode in { IMRMOVQ, IPOPQ } && E_dstM in { d_srcA, d_srcB }) &&
- # but not condition for a generate/use hazard
- !0 &&
- IRET in { D_icode, E_icode, M_icode };
+ (E_icode == IJXX && !e_Cnd) ||
+ (
+ !(
+ (
+ d_srcA != RNONE &&
+ d_srcA in { e_dstE, E_dstM, M_dstM, M_dstE, W_dstM, W_dstE }
+ ) ||
+ (
+ d_srcB != RNONE &&
+ d_srcB in { e_dstE, E_dstM, M_dstM, M_dstE, W_dstM, W_dstE }
+ )
+ ) &&
+ (IRET in { D_icode, E_icode, M_icode })
+ );
# Should I stall or inject a bubble into Pipeline Register E?
# At most one of these can be true.
+# bool E_stall = 0;
+# bool E_bubble = s_jxx_error || s_data_hazard
bool E_stall = 0;
bool E_bubble =
- # Mispredicted branch
- (E_icode == IJXX && !e_Cnd) ||
- # Modify the following to inject bubble into the execute stage
- 0;
+ (E_icode == IJXX && !e_Cnd) ||
+ (
+ (
+ d_srcA != RNONE &&
+ d_srcA in { e_dstE, E_dstM, M_dstM, M_dstE, W_dstM, W_dstE }
+ ) ||
+ (
+ d_srcB != RNONE &&
+ d_srcB in { e_dstE, E_dstM, M_dstM, M_dstE, W_dstM, W_dstE }
+ )
+ );
+
# Should I stall or inject a bubble into Pipeline Register M?
# At most one of these can be true.