📄 counters.v
字号:
`timescale 1ns/10ps/*****************************************************************************$RCSfile: counters.v,v $$Revision: 1.8 $$Author: kohlere $$Date: 2000/04/16 19:32:27 $$State: Exp $$Source: /home/lefurgy/tmp/ISC-repository/isc/hardware/ARM10/behavioral/pipelined/counters.v,v $Description: This block keeps track of instruction count, when instructions are done, how many cycles have passed, etc...*****************************************************************************/module counters (nGCLK1, nGCLK2, nRESET, mispredicted, go, if_enbar, misp_rec, pc_touched, id_enbar, ex_enbar, me_enbar, hold_next_ex, ptaken_ex, pt, put, count, finished, cyc_count, eval, imiss, dmiss, InMREQ, DnMREQ, imiss_count, dmiss_count);/*------------------------------------------------------------------------ Ports------------------------------------------------------------------------*/input nGCLK1; //Core Clock Signalinput nGCLK2; //Core Clock Signalinput nRESET; //Reset Signalinput InMREQ; //Inst Access Requestinput DnMREQ; //Data Access Requestinput if_enbar; //Enable to IF Stageinput id_enbar; //Enable to ID Stageinput ex_enbar; //Enable to EX Stageinput me_enbar; //Enable to ME Stageinput imiss; //Instruction Cache Missinput dmiss; //Data Cache Missinput go; //Miss Being Servicedinput pt; //Predicting Takeninput put; //Predicting Untakeninput eval; //Evaluating a Predictioninput mispredicted; //Mispredicted a Branchinput misp_rec; //Mispredicted but have next Instinput pc_touched; //Taken Branch in EX stageinput hold_next_ex; //Mult in EX and workinginput ptaken_ex; //Prediction Stall for EXoutput [31:0] count; //Instruction Countoutput [31:0] cyc_count; //Core Cyclesoutput [31:0] imiss_count; //I$ Missesoutput [31:0] dmiss_count; //D$ Missesoutput finished; //Instruciton Finished/*------------------------------------------------------------------------ Variable/Signal Declarations------------------------------------------------------------------------*/reg [31:0] counter; //Count of current Instructionreg [31:0] cyc_count; //ECLK cyclesreg [31:0] pcorrect; //Branches Predicted Correctlyreg [31:0] predicted; //Predicted Branchesreg [31:0] imiss_count; //Number of I$ Missesreg [31:0] dmiss_count; //Number of D$ Missesreg [31:0] iaccesses; //Number of I$ Accessesreg [31:0] daccesses; //Number of D$ Accessesreg id_valid; //Instruction in ID Stagereg ex_valid; //Instruction in EX Stagereg me_valid; //Instruction in ME Stagereg wb_valid; //Instruction in WB Stagereg wb_waiting; //Inst in WB Stage, waiting to Completereg pre_clr; //Prediction Clearreg pre_me; //Predicted Br In ME Stagereg finished; //Instruction Completereg id_invalid; //Reset id_validreg me_invalid; //Reset me_validwire wb_reset; //Reset wb_waiting/*------------------------------------------------------------------------ Combinational Always Blocks------------------------------------------------------------------------*/assign count = counter;//This logic block watches for the completion of instructions //in the wb stage. Completion is detected when the following//instruction reaches the ME stage. always @(wb_waiting or me_valid or nGCLK1) begin if (wb_waiting & me_valid & nGCLK1) finished <= #2 1'b1; else finished <= #2 1'b0; end/*------------------------------------------------------------------------ Sequential Always Blocks ------------------------------------------------------------------------*///Count the total number of cycles, after memory stalls//synopsys async_set_reset "nRESET"always @(posedge nGCLK2 or negedge nRESET) begin if (~nRESET) cyc_count <= 32'h0; else cyc_count <= cyc_count + 1; end//Count the number of Misses to each Cache//May have to change this if ?miss isn't//stable until after the nGCLK1 clock edgealways @(negedge nGCLK1 or negedge nRESET) begin if (~nRESET) begin imiss_count <= 32'h00000000; dmiss_count <= 32'h00000000; end else begin imiss_count <= imiss_count + imiss; dmiss_count <= dmiss_count + dmiss; end end//Count the number of I$/D$ Accessesalways @(posedge nGCLK1 or negedge nRESET) begin if (~nRESET) begin iaccesses <= 32'h00000000; daccesses <= 32'h00000000; end else begin if (~InMREQ) iaccesses <= iaccesses + 1; if (~DnMREQ) daccesses <= daccesses + 1; end end//Count the number of correctly predicted brancheswire inc_correct = eval & ~mispredicted;//synopsys async_set_reset "nRESET"always @(posedge nGCLK2 or negedge nRESET) begin if (~nRESET) pcorrect <= 32'h0; else if (inc_correct) pcorrect <= pcorrect + 1; end //Count the number of incorrectly predicted branches//synopsys async_set_reset "nRESET"always @(posedge nGCLK2 or negedge nRESET) begin if (~nRESET) predicted <= 32'h0; else if (eval) predicted <= predicted + 1; end/* -- Follow Predictions -- Follow the results of branch prediction through the pipeline. If the prediction makes it past the ex stage, add an extra 1 to the instruction counter. Notes: 1) Need to use synchronous reset, other than nRESET 2) Predicted Branch makes it into ME stage when: a) there is a predicted branch in EX, ME is enabled and there's no active misprediction 3) Ensure that pre_ME does not get set on mispredicted branches by adding mispredicted to the enable.*/ wire en_pre_me = ~me_enbar | mispredicted;//synopsys async_set_reset "nRESET"always @(posedge nGCLK2 or negedge nRESET) begin if (~nRESET) pre_me <= 1'b0; else if (en_pre_me) pre_me <= eval & ~mispredicted; else pre_me <= 1'b0; end /* -- Follow Instruction in the Pipeline -- It is necessary to track the number of instructions that complete. This information is used by the verification environment to check the state of the machine versus a golden brick. To do so, there is a bit for each stage of the pipeline from ID - WB which indicates that a valid instruction is occupying the stage. When the bit for the WB stage is high, this indicates that an instruction is present, but not finished. Completion is indicated by an additional bit of logic. Notes: 1) The id_invalid signal resets the id_valid if some previous instruction has modified the PC, and there is no misprediction. It is important to insure that there is no misprediction because a mispredicted branch is detected at the same time the first incorrect instruction would signal a modification to the pc. Thus, mispredicted is higher priority. 2) Id_valid is set when Id is enabled, unless there is a multiplication holding up progress. If a prediction occured in the middle of a mult requiring 3+ registers, the id stage is allowed to load the next instruction, so the valid bit must be enabled in this case. 3) Ex_valid is set when Id_valid was high last cycle unless there is a multiplication in ex or a branch misprediction is detected. If there is a multiplication asserting hold_next_ex, then ex has already been set on entrance, so it must be cleared while the mult is occupying the stage or it will cause extra counts. On a misprediction, the ID stage was definitely invalid, so rather than asynchronously clearing ID, we insure ex_valid is cleared on the next cycle. This eliminates glitch worries on the misprediction logic. 4) Me_valid generally follows the ex_valid signal. Exceptions: a) On a misprediction, want to make it look like the branch was in the ex stage, so we set me_valid on the following cycle 5) The reset for me_valid is anded with GCLK to ensure glitches in the first half-cycle dont incorrectly cause a reset. Probably could fix this to be synchronous reset. 6) Wb_valid follows me_valid exactly.*///assign id_invalid = ((pc_touched & ~mispredicted) | ~nRESET) & ~nGCLK1;always @(nGCLK1 or pc_touched or mispredicted or nRESET) begin if (~nGCLK1) begin// if (nWAIT) id_invalid <= ((pc_touched & ~mispredicted) | ~nRESET); end endwire en_idvalid = ~hold_next_ex | (hold_next_ex & ptaken_ex);//synopsys async_set_reset "id_invalid"always @(posedge nGCLK1 or posedge id_invalid) begin if (id_invalid) id_valid <= 1'b0; else if (en_idvalid) id_valid <= ~id_enbar; end//Mux a 1 or 0 in depending on Mispredictedalways @(mispredicted) begin if (mispredicted) pre_clr = 1'b1; else pre_clr = 1'b0; end//synopsys async_set_reset "nRESET"always @(posedge nGCLK1 or negedge nRESET) begin if (~nRESET) ex_valid <= 1'b0; else ex_valid <= id_valid & ~hold_next_ex & ~pre_clr; end//assign me_invalid = (mispredicted & hold_next_ex & ~nGCLK1) | ~nRESET;always @(nGCLK1 or nRESET or mispredicted or hold_next_ex) begin if (~nGCLK1) begin// if (nWAIT) me_invalid <= (mispredicted & hold_next_ex) | ~nRESET; end end//synopsys async_set_reset "me_invalid"always @(posedge nGCLK1 or posedge me_invalid) begin if (me_invalid) me_valid <= 1'b0; else me_valid <= ex_valid | pre_clr; end //synopsys async_set_reset "nRESET"always @(posedge nGCLK2 or negedge nRESET) begin if (~nRESET) wb_valid <= 1'b0; else wb_valid <= me_valid; end//synopsys async_set_reset "nRESET"//if branch is there to be added in chthJ18.141116always @(posedge nGCLK2 or negedge nRESET) begin if (~nRESET) counter <= 32'h00000000; else if (me_valid | pre_me) counter <= counter + pre_me + me_valid; end//assign async_set_reset "wb_reset"assign wb_reset = finished | ~nRESET;always @(negedge nGCLK2 or posedge wb_reset) begin if (wb_reset) wb_waiting <= 1'b0; else wb_waiting <= me_valid | wb_waiting; endendmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -