2 Copyright (c) 2013, IIT Madras
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 * Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
15 /*========= package imports========== */
17 import SpecialFIFOs::*;
18 import Connectable::*;
21 /*==================================== */
22 /* ======== project imports ========= */
24 import defined_types::*;
25 `include "core_parameters.bsv"
27 /* ================================== */
30 /*============================ Miscellaneous interface =========================== */
31 method Action flush (Bit#(`VADDR) new_pc, Flush_type fl);
32 method Action stall_fetch(Bool stall);
33 interface Get#(Tuple5#(Bit#(2),Bit#(`VADDR),Bit#(`VADDR),Bool, Bit#(3))) request_to_imem;
34 method Action instruction_response_from_imem(Maybe#(Tuple7#(Bit#(`VADDR),Bit#(2),Bit#(`VADDR),Bit#(32), Trap_type, Bit#(`PERFMONITORS),Bit#(3))) x);
35 interface Put#(Tuple4#(Bit#(3),Bit#(`VADDR),Bit#(`VADDR),Bit#(2))) prediction_response;
36 interface Get#(Tuple2#(Bit#(3),Bit#(`VADDR))) send_prediction_request;
37 interface TXe#(IF_ID_type) tx_out; // pipe interface to the external FIFO;
38 method Action push_ras(Maybe#(Bit#(`VADDR)) addr);
39 method Action update_eEpoch;
40 method Action update_wEpoch;
41 /*============================================================================== */
42 endinterface:Ifc_fetch
45 (*preempts="flush,enque_new_pc"*)
46 (*conflict_free="enque_new_pc,prediction_response_put"*)
47 module mkfetch#(Bit#(`VADDR) reset_vector)(Ifc_fetch);
48 FIFOF#(Tuple3#(Bit#(2),Bit#(`VADDR), Bit#(`VADDR))) generate_pc<-mkLFIFOF();
49 Reg#(Bit#(`VADDR)) rg_programcounter[3]<-mkCReg(3,'h1000);
50 Reg#(Bit#(1)) eEpoch <-mkReg(0);
51 Reg#(Bit#(1)) wEpoch <-mkReg(0);
52 Reg#(Bit#(1)) iEpoch[2] <-mkCReg(2,0);
53 Wire#(Maybe#(Bit#(`VADDR))) wr_flush_prediction <-mkDWire(tagged Invalid);
55 Wire#(Bool) wr_stall_fetch <- mkDWire(False);
56 Reg#(Bool) rg_fence[2]<-mkCReg(2,False);
57 FIFOF#(Tuple7#(Bit#(`VADDR),Bit#(2),Bit#(`VADDR),Bit#(32),Trap_type, Bit#(`PERFMONITORS),Bit#(3))) ff_response_to_cpu <-mkSizedBypassFIFOF(1);
58 TX#(IF_ID_type) tx <-mkTX;
59 Ifc_Stack ras <-mkStack;
61 rule get_instruction_from_cache;
62 let {pc,prediction,npc,instruction,trap,perfmonitors,epoch}=ff_response_to_cpu.first;
63 ff_response_to_cpu.deq;
64 Bool rs1_link=case (instruction[19:15]) matches 'b00?01:True; default :False; endcase;
65 Bool rd_link=case (instruction[11:7]) matches 'b00?01:True; default :False; endcase;
66 `ifdef verbose $display($time,"\t************* FETCH STAGE FIRING ************ PC: %h Instr-EPOCHS: %b Current_Epochs: %b",pc, epoch,{iEpoch[0],eEpoch,wEpoch}); `endif
67 if(epoch!={iEpoch[0],eEpoch,wEpoch})begin
68 `ifdef verbose $display($time,"\tFETCH: Dropping Instruction Since Epochs do not match"); `endif
71 if(instruction[6:2] matches 'b110?1 &&& !rd_link &&& rs1_link)begin
74 if(x!=npc || prediction[1]==0)begin
76 iEpoch[0]<=~iEpoch[0];
77 wr_flush_prediction<=tagged Valid npc;
80 `ifdef verbose $display($time,"TAKING RAS as the NEXT PC: %h",x); `endif
83 else if((prediction[1]==1 && instruction[6:4]!='b110))begin
84 iEpoch[0]<=~iEpoch[0];
85 wr_flush_prediction<=tagged Valid (pc+4);
88 tx.u.enq(IF_ID_type{program_counter:pc,
89 instruction:instruction[31:0],
91 prediction:prediction,
92 perfmonitors:perfmonitors,
94 epochs:{eEpoch,wEpoch}
96 `ifdef verbose $display($time,"\tInstruction Fetched: %h \t PC: %h PERF: %h Prediction: ",instruction,pc,perfmonitors,fshow(prediction)," next pc: %h",npc); `endif
100 rule enque_new_pc(wr_flush_prediction matches tagged Valid .newpc);
101 `ifdef verbose $display($time,"\tFETCH: Enquiing new PC to ICACHE: %h",newpc); `endif
102 generate_pc.enq(tuple3('b00,newpc,newpc+4));
105 // /* ================================== Methods and interface definitions =======================*/
106 interface request_to_imem = interface Get
107 method ActionValue#(Tuple5#(Bit#(2),Bit#(`VADDR),Bit#(`VADDR),Bool, Bit#(3))) get if(tx.u.notFull && !wr_stall_fetch);
108 let {prediction,pc,npc}=generate_pc.first;
109 `ifdef verbose $display($time,"\tFETCH: Address sent to IMEM: %h epochs: %b",pc,{iEpoch[0],eEpoch,wEpoch}); `endif
113 return tuple5(prediction,npc,pc,rg_fence[0],{iEpoch[0],eEpoch,wEpoch});
116 method Action instruction_response_from_imem(Maybe#(Tuple7#(Bit#(`VADDR),Bit#(2),Bit#(`VADDR),Bit#(32), Trap_type, Bit#(`PERFMONITORS),Bit#(3))) x);
117 if(x matches tagged Valid .instr1)begin
118 let {pc,prediction,npc,instruction,trap,perfmonitors,epoch}=instr1;
119 `ifdef verbose $display($time,"\tFETCH: GOT Instructions: ",fshow(instr1)); `endif
120 ff_response_to_cpu.enq(instr1);
123 method Action flush (Bit#(`VADDR) new_pc, Flush_type fl);
124 `ifdef verbose $display($time,"\tFETCH: Flushing New PC: %h",new_pc); `endif
125 rg_programcounter[1]<=new_pc;
130 method Action stall_fetch(Bool stall);
131 wr_stall_fetch <= stall;
133 interface tx_out = tx.e;
134 method Action push_ras(Maybe#(Bit#(`VADDR)) addr);
135 if(addr matches tagged Valid .x)begin
136 `ifdef verbose $display($time,"RAS: Pushing Addr: %h",x); `endif
140 interface prediction_response=interface Put
141 method Action put (Tuple4#(Bit#(3),Bit#(`VADDR),Bit#(`VADDR),Bit#(2)) x);
142 let {epoch,pc,npc,prediction}=x;
143 if(epoch=={iEpoch[1],eEpoch,wEpoch} &&& wr_flush_prediction matches tagged Invalid)begin
146 rg_programcounter[0]<=npc;
147 `ifdef verbose $display($time,"\tFETCH: Got prediction from BPU: %b for PC: %h New PC: %h",prediction,pc,npc); `endif
148 generate_pc.enq(tuple3(prediction,pc,npc));
152 $display($time,"\tFETCH: Dropping response from BPU for PC: %h",pc); `endif
155 interface send_prediction_request=interface Get
156 method ActionValue#(Tuple2#(Bit#(3),Bit#(`VADDR))) get;
157 if(wr_flush_prediction matches tagged Valid .newpc)begin
158 `ifdef verbose $display($time,"\tFETCH: Sending Program Counter to BPU: %h",newpc+4); `endif
159 return tuple2({iEpoch[1],eEpoch,wEpoch},newpc+4);
162 `ifdef verbose $display($time,"\tFETCH: Sending Program Counter to BPU: %h",rg_programcounter[2]); `endif
163 return tuple2({iEpoch[1],eEpoch,wEpoch},rg_programcounter[2]);
167 method Action update_eEpoch;
170 method Action update_wEpoch;
173 /*================================================================================================= */
175 endpackage:fetch_stage