
def stall(instruction, IRID):
if (rs(IRID) == instruction.destEX) and use_rs(IRID) and instruction.RegWriteEX:
return True
elif (rs(IRID) == instruction.destMEM) and use_rs(IRID) and instruction.RegWriteMEM:
return True
elif (rs(IRID) == instruction.destWB) and use_rs(IRID) and instruction.RegWriteWB:
return True
elif (instruction.rt == IRID.destEX) and use_rt(IRID) and instruction.RegWriteEX:
return True
elif (instruction.rt == IRID.destMEM) and use_rt(IRID) and instruction.RegWriteMEM:
return True
elif (instruction.rt == IRID.destWB) and use_rt(IRID) and instruction.RegWriteWB:
return True
return False
def detect_data_hazard(rs, rt, shred):
# Check EX stage
if shred.ex_mem_latch.instruction is not None:
ex_decoded_instruction = shred.ex_mem_latch.decoded_instruction
if ex_decoded_instruction['control_signals']['RegWrite']:
ex_rd = ex_decoded_instruction['rd']
if rs == ex_rd or rt == ex_rd:
return True
# Check MEM stage
if shred.mem_wb_latch.instruction is not None:
mem_decoded_instruction = shred.mem_wb_latch.decoded_instruction
if mem_decoded_instruction['control_signals']['RegWrite']:
mem_rd = mem_decoded_instruction['rd']
if rs == mem_rd or rt == mem_rd:
return True
return False
The detect_data_hazard function checks for data hazards in a pipelined processor by examining the ex_mem_latch and mem_wb_latch stages. It first verifies if the current instruction's source registers (rs or rt) match the destination register (rd) of instructions in these pipeline stages that are performing register writes (RegWrite).
If either the ex_mem_latch or mem_wb_latch contains an instruction performing a register write to a register that the current instruction depends on (rs or rt), the function returns True, indicating a data hazard. Otherwise, it returns False, indicating no hazard is detected.
def isBranch(opcode):
return opcode in [2, 3, 4, 5] # j, jal, beq, bne
# Check for control hazards
if self.ex_mem_latch.isBranch and self.ex_mem_latch.isTaken:
log.write(f"Pipeline stalled due to control hazard at clock cycle {self.clock}\n")
shred.pc = self.ex_mem_latch.result # Update PC to the branch target
shred.stall = True
# Clear the pipeline stages
self.pipeline[0] = None
self.pipeline[1] = None
self.pipeline[2] = None
else:
shred.stall = False
The control hazard detection logic in the pipeline ensures the proper handling of branch instructions and their potential to alter the program flow. This is achieved by checking the isBranch and isTaken flags in the EX/MEM latch. If a branch instruction is detected (isBranch is true) and the branch is taken (isTaken is true), the pipeline is stalled, the program counter (PC) is updated to the branch target address (shred.pc = self.ex_mem_latch.result), and the initial stages of the pipeline (IF, ID, EX) are cleared to prevent any incorrect instructions from being fetched or executed.