Whenever a pipeline does not have execution stall, but instead is stalled due to data dependences and control dependences, you increment the corresponding counters in the ID stage
The same instruction can increment both data hazard counter and control hazard counter.
If one instruction has two data dependences (i.e., both source operands are dependent on other instructions), data hazard counter is only incremented by one.
If the same instruction needs to wait for several cycles in the ID stage , you still
increment the data hazard counter multiple cycles. (i.e., while an instruction is waiting in the ID stage,
the data hazard counter is continuously incremented. ) .You will increment the control hazard counter multiple times, if there is no execution stall and a branch instruction is waiting in the ID stage for multiple cycles.
Yes, you must implement sim_end_condition.
The success variable at "success = (gzread(stream, &trace_op, sizeof(Trace_op)) > 0 );"
tells the end of trace. If the success value is false, it means the end of trace.
When the trace reaches the end, you must send an op that indicates the end of trace by using some conditions such as (op->last_op = TRUE). If that op reaches WB_stage, the simulator sets sim_end_condition as TRUE.
Note that last_op field is not provided in the simulator frame. You must add such kind of field.
Please focus on sim.cpp sim.h file. trace.cpp is to generate traces and *knob* files are just to support knob features.
To avoid of calling malloc all the time, op structures are already created.
max_insts: a simulation ends after executing max_insts number of instructions.
max_cycles: a simulation ends after executing max_cycles number of cycles.