📄 counters.v
字号:
`timescale 1ns/10ps/*****************************************************************************$RCSfile: counters.v,v $$Revision: 1.8 $$Author: kohlere $$Date: 2000/05/11 01:07:57 $$State: Exp $$Source: /home/lefurgy/tmp/ISC-repository/isc/hardware/ARM10/behavioral/pipelined/fpga2/counters.v,v $Description: This block keeps track of instruction count, when instructions are done, how many cycles have passed, etc...*****************************************************************************/module counters (nGCLK, nRESET, nWAIT, mispredicted, 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, go, imiss_count, dmiss_count, IABORT, DABORT, iaccesses, daccesses, predicted, pcorrect, spec_iabort, spec_dabort, time_count);/*------------------------------------------------------------------------ Ports------------------------------------------------------------------------*/input nGCLK; //Core Clock Signalinput nRESET; //Reset Signalinput nWAIT; //Clock Enable Signalinput InMREQ; //Inst Access Requestinput DnMREQ; //Data Access Requestinput IABORT; //Compressed Instruction Missinput DABORT; //Compressed Data Missinput 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; //Cache 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] time_count; //All Clock Cyclesoutput [31:0] imiss_count; //Number of I$ Missesoutput [31:0] dmiss_count; //Number of D$ Missesoutput [31:0] iaccesses; //Instruction Cache Accessesoutput [31:0] daccesses; //Data Cache Accessesoutput [31:0] predicted; //Number of Predicted Branchesoutput [31:0] pcorrect; //Number of Correctly Predicted Branchesoutput [31:0] spec_iabort; //Number of Speculative IABORTSoutput [31:0] spec_dabort; //Number of Speculative DABORTSoutput finished; //Instruciton Finished/*------------------------------------------------------------------------ Variable/Signal Declarations------------------------------------------------------------------------*/reg [31:0] counter; //Count of current Instructionreg [31:0] cyc_count; //ECLK cyclesreg [31:0] time_count; //Timer (Counts all Clock Cycles)reg [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 [31:0] spec_dabort; //Number of Spec. DABORTSreg [31:0] spec_iabort; //Number of Spec. IABORTSreg 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 nGCLK or nWAIT) begin if (nGCLK) begin if (nWAIT) begin if (wb_waiting & me_valid) finished <= #2 1'b1; end end else finished <= #2 1'b0; end/*------------------------------------------------------------------------ Sequential Always Blocks ------------------------------------------------------------------------*///Create a Program Timer//synopsys async_set_reset "nRESET"always @(posedge nGCLK or negedge nRESET) begin if (~nRESET) time_count <= 32'h0; else time_count <= time_count + 1; end//Count the total number of cycles, after memory stalls//synopsys async_set_reset "nRESET"always @(posedge nGCLK or negedge nRESET) begin if (~nRESET) cyc_count <= 32'h0; else if (nWAIT) 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 nGCLK clock edgealways @(negedge nGCLK or negedge nRESET) begin if (~nRESET) begin imiss_count <= 32'h00000000; dmiss_count <= 32'h00000000; end else if (~go) begin imiss_count <= imiss_count + imiss; dmiss_count <= dmiss_count + dmiss; end end//Count Number of Speculate IABORTSalways @(posedge nGCLK or negedge nRESET) begin if (~nRESET) spec_iabort <= {32{1'b0}}; else if (nWAIT) begin if (~id_enbar) spec_iabort <= spec_iabort + IABORT; end end//Count the Number of Speculative DABORTSalways @(posedge nGCLK or negedge nRESET) begin if (~nRESET) spec_dabort <= {32{1'b0}}; else if (nWAIT) spec_dabort <= spec_dabort + DABORT; end//Count the number of I$/D$ Accessesalways @(posedge nGCLK or negedge nRESET) begin if (~nRESET) begin iaccesses <= 32'h00000000; daccesses <= 32'h00000000; end else if (nWAIT) 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 nGCLK or negedge nRESET) begin if (~nRESET) pcorrect <= 32'h0; else if (nWAIT) begin if (inc_correct) pcorrect <= pcorrect + 1; end end//Count the number of incorrectly predicted branches//synopsys async_set_reset "nRESET"always @(posedge nGCLK or negedge nRESET) begin if (~nRESET) predicted <= 32'h0; else if (nWAIT) begin if (eval) predicted <= predicted + 1; end 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 nGCLK or negedge nRESET) begin if (~nRESET) pre_me <= 1'b0; else if (nWAIT) begin if (en_pre_me) pre_me <= eval & ~mispredicted; else pre_me <= 1'b0; end 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.*/always @(nGCLK or nWAIT or pc_touched or mispredicted or nRESET) begin if (~nGCLK) begin if (nWAIT) id_invalid <= ((pc_touched & ~mispredicted) | ~nRESET); end end//assign id_invalid = ((pc_touched & ~mispredicted) | ~nRESET) & (nGCLK & nWAIT);wire en_idvalid = ~hold_next_ex | (hold_next_ex & ptaken_ex);//synopsys async_set_reset "id_invalid"always @(posedge nGCLK or posedge id_invalid) begin if (id_invalid) id_valid <= 1'b0; else if (nWAIT) begin if (en_idvalid) id_valid <= ~id_enbar; end 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 nGCLK or negedge nRESET) begin if (~nRESET) ex_valid <= 1'b0; else if (nWAIT) ex_valid <= id_valid & ~hold_next_ex & ~pre_clr; endalways @(nGCLK or nWAIT or nRESET or mispredicted or hold_next_ex) begin if (~nGCLK) begin if (nWAIT) me_invalid <= (mispredicted & hold_next_ex) | ~nRESET; end end//assign me_invalid = (mispredicted & hold_next_ex & (nGCLK & nWAIT)) | ~nRESET;//synopsys async_set_reset "me_invalid"always @(posedge nGCLK or posedge me_invalid) begin if (me_invalid) me_valid <= 1'b0; else if (nWAIT) me_valid <= ex_valid | pre_clr; end //synopsys async_set_reset "nRESET"always @(posedge nGCLK or negedge nRESET) begin if (~nRESET) wb_valid <= 1'b0; else if (nWAIT) wb_valid <= me_valid; end//synopsys async_set_reset "nRESET"//if branch is there to be added in chthJ18.141116always @(posedge nGCLK or negedge nRESET) begin if (~nRESET) counter <= 32'h00000000; else if (nWAIT) begin if (me_valid | pre_me) counter <= counter + pre_me + me_valid; end end//assign async_set_reset "wb_reset"assign wb_reset = finished | ~nRESET;always @(negedge nGCLK or posedge wb_reset) begin if (wb_reset) wb_waiting <= 1'b0; else if (nWAIT) wb_waiting <= me_valid | wb_waiting; endendmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -