Fix priority inversion for two back-to-back divides (#948)
If the first one is killed for some unrelated reason (e.g. write port hazard), the second one will still issue to the div-sqrt unit. While it will itself later be killed, the fact that the later instruction acquires a resource needed by the former instruction leads to deadlock.
This commit is contained in:
		| @@ -581,12 +581,17 @@ class FPU(cfg: FPUParams)(implicit p: Parameters) extends FPUModule()(p) { | ||||
|   val req_valid = ex_reg_valid || io.cp_req.valid | ||||
|   val ex_reg_inst = RegEnable(io.inst, io.valid) | ||||
|   val ex_cp_valid = io.cp_req.fire() | ||||
|   val mem_reg_valid = Reg(next=ex_reg_valid && !io.killx || ex_cp_valid, init=Bool(false)) | ||||
|   val mem_reg_inst = RegEnable(ex_reg_inst, ex_reg_valid) | ||||
|   val mem_cp_valid = Reg(next=ex_cp_valid, init=Bool(false)) | ||||
|   val killm = (io.killm || io.nack_mem) && !mem_cp_valid | ||||
|   val wb_reg_valid = Reg(next=mem_reg_valid && (!killm || mem_cp_valid), init=Bool(false)) | ||||
|   val wb_cp_valid = Reg(next=mem_cp_valid, init=Bool(false)) | ||||
|   val mem_reg_valid = RegInit(false.B) | ||||
|   val killm = (io.killm || io.nack_mem) && !mem_cp_valid | ||||
|   // Kill X-stage instruction if M-stage is killed.  This prevents it from | ||||
|   // speculatively being sent to the div-sqrt unit, which can cause priority | ||||
|   // inversion for two back-to-back divides, the first of which is killed. | ||||
|   val killx = io.killx || mem_reg_valid && killm | ||||
|   mem_reg_valid := ex_reg_valid && !killx || ex_cp_valid | ||||
|   val mem_reg_inst = RegEnable(ex_reg_inst, ex_reg_valid) | ||||
|   val wb_reg_valid = Reg(next=mem_reg_valid && (!killm || mem_cp_valid), init=Bool(false)) | ||||
|  | ||||
|   val fp_decoder = Module(new FPUDecoder) | ||||
|   fp_decoder.io.inst := io.inst | ||||
|   | ||||
		Reference in New Issue
	
	Block a user