add core
[shakti-core.git] / src / core / fetch_stage.bsv
1 /*
2 Copyright (c) 2013, IIT Madras
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
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.
10
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 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
13 */
14 package fetch_stage;
15 /*========= package imports========== */
16 import FIFOF::*;
17 import SpecialFIFOs::*;
18 import Connectable::*;
19 import GetPut::*;
20 import DReg::*;
21 /*==================================== */
22 /* ======== project imports ========= */
23 import TxRx ::*;
24 import defined_types::*;
25 `include "defined_parameters.bsv"
26 import Stack::*;
27 /* ================================== */
28
29 interface Ifc_fetch;
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
43
44 (*synthesize*)
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);
54
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;
60
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
69 end
70 else begin
71 if(instruction[6:2] matches 'b110?1 &&& !rd_link &&& rs1_link)begin
72 if(!ras.empty)begin
73 let x<-ras.top;
74 if(x!=npc || prediction[1]==0)begin
75 npc=x;
76 iEpoch[0]<=~iEpoch[0];
77 wr_flush_prediction<=tagged Valid npc;
78 prediction='b10;
79 end
80 `ifdef verbose $display($time,"TAKING RAS as the NEXT PC: %h",x); `endif
81 end
82 end
83 else if((prediction[1]==1 && instruction[6:4]!='b110))begin
84 iEpoch[0]<=~iEpoch[0];
85 wr_flush_prediction<=tagged Valid (pc+4);
86 prediction[1]=0;
87 end
88 tx.u.enq(IF_ID_type{program_counter:pc,
89 instruction:instruction[31:0],
90 nextpc:npc,
91 prediction:prediction,
92 perfmonitors:perfmonitors,
93 exception:trap,
94 epochs:{eEpoch,wEpoch}
95 });
96 `ifdef verbose $display($time,"\tInstruction Fetched: %h \t PC: %h PERF: %h Prediction: ",instruction,pc,perfmonitors,fshow(prediction)," next pc: %h",npc); `endif
97 end
98 endrule
99
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));
103 endrule
104
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
110 rg_fence[0]<=False;
111 if(!rg_fence[0])
112 generate_pc.deq;
113 return tuple5(prediction,npc,pc,rg_fence[0],{iEpoch[0],eEpoch,wEpoch});
114 endmethod
115 endinterface;
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);
121 end
122 endmethod
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;
126 generate_pc.clear;
127 if(fl==Fence)
128 rg_fence[1]<=True;
129 endmethod
130 method Action stall_fetch(Bool stall);
131 wr_stall_fetch <= stall;
132 endmethod
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
137 ras.push(x);
138 end
139 endmethod
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
144 if(prediction[1]==0)
145 npc=pc+4;
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));
149 end
150 `ifdef verbose
151 else
152 $display($time,"\tFETCH: Dropping response from BPU for PC: %h",pc); `endif
153 endmethod
154 endinterface;
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);
160 end
161 else begin
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]);
164 end
165 endmethod
166 endinterface;
167 method Action update_eEpoch;
168 eEpoch<=~eEpoch;
169 endmethod
170 method Action update_wEpoch;
171 wEpoch<=~wEpoch;
172 endmethod
173 /*================================================================================================= */
174 endmodule:mkfetch
175 endpackage:fetch_stage