add ClintBase
[shakti-core.git] / src / core / memory_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 memory_stage;
15 /*===== Package Imports ==== */
16 import TxRx::*;
17 import FIFOF::*;
18 import DReg::*;
19 import Vector::*;
20 import GetPut::*;
21 /*========================== */
22 /*===== Project Imports ======*/
23 `include "core_parameters.bsv"
24 import defined_types::*;
25 //import dcache::*;
26 /*============================ */
27
28 interface Ifc_memory_stage;
29 /* ====================== pipe connections ========= */
30 interface RXe#(IE_IMEM_type) rx_in;
31 interface TXe#(IMEM_IWB_type) tx_out;
32 /*================================================== */
33 method Action update_wEpoch;
34 interface Put#(Maybe#(Tuple4#(Bit#(`Reg_width), Trap_type, Bit#(`PERFMONITORS),Bit#(1)))) response_from_dmem;
35 method Action loadtrigger_info(TriggerData tdata);
36 method Action storetrigger_info(TriggerData tdata);
37 method Maybe#(Tuple3#(Bit#(`Reg_width), Bit#(TLog#(`PRFDEPTH)), Bit#(4))) forwarding_data;
38 endinterface
39
40 (*synthesize*)
41 module mkmemory_stage(Ifc_memory_stage);
42 RX#(IE_IMEM_type) rx <-mkRX; // receive from the execution stage
43 TX#(IMEM_IWB_type) tx <-mkTX; // send to the writeback stage;
44 Wire#(Memout) wr_info_to_dmem <-mkWire;// holds the information to be given to dmem
45 Wire#(TriggerData) wr_loadtrigger<-mkDWire(TriggerData{ttype:tagged None,matchscheme:0});
46 Wire#(TriggerData) wr_storetrigger<-mkDWire(TriggerData{ttype:tagged None,matchscheme:0});
47 Wire#(Maybe#(Tuple4#(Bit#(`Reg_width), Trap_type,Bit#(`PERFMONITORS),Bit#(1)))) wr_response_to_cpu <- mkDWire(tagged Invalid);
48 //Wire#(Maybe#(Operand_forwading_type)) wr_forward_from_MEM <-mkDWire(tagged Invalid);// holds the forwarded data from the memory stage
49 //Reg#(Maybe#(Tuple3#(Bit#(`Reg_width), Bit#(TLog#(`PRFDEPTH)), Bit#(4)))) wr_forward_from_MEM <-mkDReg(tagged Invalid);// holds the forwarded data from the memory stage
50 Wire#(Maybe#(Tuple3#(Bit#(`Reg_width), Bit#(TLog#(`PRFDEPTH)), Bit#(4)))) wr_forward_from_MEM <-mkDWire(tagged Invalid);// holds the forwarded data from the memory stage
51 //Ifc_dcache dcache<-mkdcache;
52 Reg#(Bit#(1)) wEpoch <-mkReg(0);
53
54 function Bool checktrigger(TriggerData tdata, Bit#(`Reg_width) address, Bit#(`Reg_width) lsdata);
55 if(tdata.ttype matches tagged Address .addr)
56 if(tdata.matchscheme==0 && addr==truncate(address))
57 return True;
58 else if(tdata.matchscheme==2 && addr>=truncate(address))
59 return True;
60 else if(tdata.matchscheme==3 && addr<=truncate(address))
61 return True;
62 else if(tdata.matchscheme==4 && addr[31:0]==(addr[31:0]&address[31:0]))
63 return True;
64 else if(tdata.matchscheme==5 && addr[31:0]==(addr[`VADDR-1:32]&address[`VADDR-1:32]))
65 return True;
66 else
67 return False;
68 else if(tdata.ttype matches tagged Data .data)
69 if(tdata.matchscheme==0 && data==lsdata)
70 return True;
71 else if(tdata.matchscheme==2 && data>=lsdata)
72 return True;
73 else if(tdata.matchscheme==3 && data<=lsdata)
74 return True;
75 else if(tdata.matchscheme==4 && data[31:0]==(data[63:32]&lsdata[31:0]))
76 return True;
77 else if(tdata.matchscheme==5 && data[31:0]==(data[63:32]&lsdata[63:32]))
78 return True;
79 else
80 return False;
81 else
82 return False;
83 endfunction
84
85 //(*conflict_free="receive_info_from_execution_stage,response_to_core"*)
86 rule receive_info_from_execution_stage(rx.u.notEmpty && tx.u.notFull);
87 Bit#(`PERFMONITORS) pm=rx.u.first.perfmonitors;
88 let info=rx.u.first();
89 let pc=rx.u.first.program_counter;
90 let dest=rx.u.first.destination;
91 let rdtype=rx.u.first.rd_type;
92 `ifdef simulate let instr=rx.u.first.instruction; `endif
93 let sysinstr=False;
94 Bit#(`ADDR) baddr = 0;
95 WriteBackType result1=?;
96 `ifdef verbose $display($time,"\t*****************MEMORY STAGE*************************\t PC: %h PRFINDEX: %d PID: %d EPOCHS: %b wEpoch: %b",pc,rx.u.first.index,rx.u.first.pid, rx.u.first.epochs, wEpoch); `endif
97
98 /* If the instruction is a memory operation (Load/Store/Atomic/Fence) then generate
99 the request to the cache in this rule and expect the response in the consecutive rule*/
100 if(info.execresult matches tagged MEMORY .meminfo)begin
101 Bool lstrigger=False;
102 `ifdef verbose $display($time,"\tMEMORY: load_trigger: ", fshow(wr_loadtrigger)); `endif
103 let exception=rx.u.first.exception;
104 if(wr_response_to_cpu matches tagged Valid .d)begin
105 let {data,e,perfmonitors,epochs}=d;
106 exception=exception matches tagged None?e:exception;
107 Bit#(`Reg_width) fwd_data=0;
108 if(exception matches tagged Exception .exc)begin
109 result1 = tagged RESULT Arithout{aluresult:meminfo.address,fflags:0};
110 end
111 `ifdef spfpu
112 else if(meminfo.transfer_size==2 && rx.u.first.rd_type==FloatingRF)begin
113 result1 = tagged RESULT Arithout{aluresult:{'1,data[31:0]},fflags:0};
114 fwd_data={'1,data[31:0]};
115 end
116 `endif
117 else begin
118 result1 = tagged RESULT Arithout{aluresult:data,fflags:0};
119 fwd_data=data;
120 end
121 pm=pm|perfmonitors;
122 rx.u.deq;
123 if(epochs==wEpoch)begin
124 `ifdef verbose $display($time,"\tMEMORY: Response from DCACHE: Data: %h Address: %h transfersize: %d epochs: %b wEpochs: %b",data,meminfo.address,meminfo.transfer_size,epochs,wEpoch); `endif
125 tx.u.enq(IMEM_IWB_type{commit_data:result1, index:rx.u.first.index, pid:rx.u.first.pid, debugcause:rx.u.first.debugcause,
126 program_counter:pc, destination:dest, epochs:{rx.u.first.epochs[1],epochs},
127 rd_type:rdtype, exception:exception, perfmonitors:rx.u.first.perfmonitors
128 `ifdef simulate , instruction:instr `endif });
129 if(meminfo.mem_type!=Store &&& ((rdtype==IntegerRF && dest!=0) `ifdef spfpu || rdtype==FloatingRF `endif ) &&& exception matches tagged None)
130 wr_forward_from_MEM <= tagged Valid tuple3(fwd_data, rx.u.first.index, rx.u.first.pid);
131 end
132 else begin
133 `ifdef verbose $display($time,"\tMEMORY: Dropping the received response from DCACHE"); `endif
134 end
135 end
136 end
137 /* If the instruction is not a memory operation then bypass this stage
138 and enque into the write-back stage. If this is a CSR operation changing
139 the FCSR register then generate the necessary flag. Also generate the forwarding
140 signal to the decode stage*/
141 else begin
142 rx.u.deq;
143 if(rx.u.first.epochs[0]!=wEpoch)begin
144 `ifdef verbose $display($time,"\tMEMORY: PC: %h Dropping instructions",rx.u.first.program_counter); `endif
145 end
146 else begin
147 `ifdef verbose $display($time,"\tMEMORY: Bypassing Memory Stage"); `endif
148 if(info.execresult matches tagged SYSTEM .res1)begin
149 result1=tagged SYSTEM res1 ;
150 end
151 else if(info.execresult matches tagged RESULT .res1)begin
152 result1=tagged RESULT res1;
153 end
154 tx.u.enq(IMEM_IWB_type{commit_data:result1, index:rx.u.first.index, pid:rx.u.first.pid, debugcause:rx.u.first.debugcause,
155 program_counter:pc, destination:dest, epochs:rx.u.first.epochs,
156 rd_type:rdtype, exception:info.exception, perfmonitors:rx.u.first.perfmonitors
157 `ifdef simulate , instruction:instr `endif });
158 end
159 end
160 endrule
161 method tx_out=tx.e;
162 method rx_in=rx.e;
163 interface response_from_dmem = interface Put
164 method Action put(Maybe#(Tuple4#(Bit#(`Reg_width), Trap_type, Bit#(`PERFMONITORS),Bit#(1))) resp);
165 wr_response_to_cpu <= resp;
166 endmethod
167 endinterface;
168 method Action loadtrigger_info(TriggerData tdata);
169 wr_loadtrigger<=tdata;
170 endmethod
171 method Action storetrigger_info(TriggerData tdata);
172 wr_storetrigger<=tdata;
173 endmethod
174 method Maybe#(Tuple3#(Bit#(`Reg_width), Bit#(TLog#(`PRFDEPTH)), Bit#(4))) forwarding_data=wr_forward_from_MEM;
175 method Action update_wEpoch;
176 wEpoch<=~wEpoch;
177 endmethod
178 endmodule
179 endpackage:memory_stage