1 |
48 |
alirezamon |
/*
|
2 |
|
|
* LatticeMico32
|
3 |
|
|
* Data Translation Lookaside Buffer
|
4 |
|
|
*
|
5 |
|
|
* Copyright (c) 2011-2012 Yann Sionneau <yann.sionneau@gmail.com>
|
6 |
|
|
* Copyright (c) 2012 Michael Walle <michael@walle.cc>
|
7 |
|
|
* All rights reserved.
|
8 |
|
|
*
|
9 |
|
|
* Redistribution and use in source and binary forms, with or without
|
10 |
|
|
* modification, are permitted provided that the following conditions
|
11 |
|
|
* are met:
|
12 |
|
|
* 1. Redistributions of source code must retain the above copyright
|
13 |
|
|
* notice, this list of conditions and the following disclaimer.
|
14 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
15 |
|
|
* notice, this list of conditions and the following disclaimer in the
|
16 |
|
|
* documentation and/or other materials provided with the distribution.
|
17 |
|
|
* 3. The name of the author may not be used to endorse or promote products
|
18 |
|
|
* derived from this software without specific prior written permission.
|
19 |
|
|
*
|
20 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
21 |
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
22 |
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
23 |
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
24 |
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
25 |
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
26 |
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
27 |
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
28 |
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
29 |
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30 |
|
|
*/
|
31 |
|
|
|
32 |
|
|
`include "lm32_include.v"
|
33 |
|
|
|
34 |
|
|
`ifdef CFG_MMU_ENABLED
|
35 |
|
|
|
36 |
|
|
`define LM32_DTLB_STATE_RNG 1:0
|
37 |
|
|
`define LM32_DTLB_STATE_CHECK 2'b01
|
38 |
|
|
`define LM32_DTLB_STATE_FLUSH 2'b10
|
39 |
|
|
|
40 |
|
|
`define LM32_DTLB_OFFSET_RNG offset_msb:offset_lsb
|
41 |
|
|
`define LM32_DTLB_IDX_RNG index_msb:index_lsb
|
42 |
|
|
`define LM32_DTLB_VPFN_RNG vpfn_msb:vpfn_lsb
|
43 |
|
|
`define LM32_DTLB_TAG_RNG tag_msb:tag_lsb
|
44 |
|
|
`define LM32_DTLB_ADDR_RNG (index_width-1):0
|
45 |
|
|
`define LM32_DTLB_DATA_WIDTH (vpfn_width+tag_width+3) // +3 for valid, ci, ro
|
46 |
|
|
`define LM32_DTLB_DATA_RNG (`LM32_DTLB_DATA_WIDTH-1):0
|
47 |
|
|
|
48 |
|
|
|
49 |
|
|
/////////////////////////////////////////////////////
|
50 |
|
|
// Module interface
|
51 |
|
|
/////////////////////////////////////////////////////
|
52 |
|
|
|
53 |
|
|
module lm32_dtlb (
|
54 |
|
|
// ----- Inputs -------
|
55 |
|
|
clk_i,
|
56 |
|
|
rst_i,
|
57 |
|
|
enable,
|
58 |
|
|
stall_x,
|
59 |
|
|
stall_m,
|
60 |
|
|
address_x,
|
61 |
|
|
address_m,
|
62 |
|
|
load_d,
|
63 |
|
|
store_d,
|
64 |
|
|
load_q_x,
|
65 |
|
|
store_q_x,
|
66 |
|
|
load_q_m,
|
67 |
|
|
store_q_m,
|
68 |
|
|
tlbpaddr,
|
69 |
|
|
tlbvaddr,
|
70 |
|
|
update,
|
71 |
|
|
flush,
|
72 |
|
|
invalidate,
|
73 |
|
|
// ----- Outputs -----
|
74 |
|
|
physical_load_store_address_m,
|
75 |
|
|
stall_request,
|
76 |
|
|
miss_vfn,
|
77 |
|
|
miss_x,
|
78 |
|
|
fault_x,
|
79 |
|
|
cache_inhibit_x
|
80 |
|
|
);
|
81 |
|
|
|
82 |
|
|
/////////////////////////////////////////////////////
|
83 |
|
|
// Parameters
|
84 |
|
|
/////////////////////////////////////////////////////
|
85 |
|
|
|
86 |
|
|
parameter entries = 1024; // Number of entries in DTLB
|
87 |
|
|
parameter page_size = 4096; // DTLB page size
|
88 |
|
|
|
89 |
|
|
localparam offset_width = `CLOG2(page_size);
|
90 |
|
|
localparam index_width = `CLOG2(entries);
|
91 |
|
|
localparam offset_lsb = 0;
|
92 |
|
|
localparam offset_msb = (offset_lsb+offset_width-1);
|
93 |
|
|
localparam index_lsb = (offset_msb+1);
|
94 |
|
|
localparam index_msb = (index_lsb+index_width-1);
|
95 |
|
|
localparam tag_lsb = (index_msb+1);
|
96 |
|
|
localparam tag_msb = (`LM32_WORD_WIDTH-1);
|
97 |
|
|
localparam tag_width = (tag_msb-tag_lsb+1);
|
98 |
|
|
localparam vpfn_lsb = (offset_msb+1);
|
99 |
|
|
localparam vpfn_msb = (`LM32_WORD_WIDTH-1);
|
100 |
|
|
localparam vpfn_width = (vpfn_msb-vpfn_lsb+1);
|
101 |
|
|
|
102 |
|
|
/////////////////////////////////////////////////////
|
103 |
|
|
// Inputs
|
104 |
|
|
/////////////////////////////////////////////////////
|
105 |
|
|
|
106 |
|
|
input clk_i; // Clock
|
107 |
|
|
input rst_i; // Reset
|
108 |
|
|
|
109 |
|
|
input enable; // Data TLB enable
|
110 |
|
|
|
111 |
|
|
input stall_x; // Stall X stage
|
112 |
|
|
input stall_m; // Stall M stage
|
113 |
|
|
|
114 |
|
|
input [`LM32_WORD_RNG] address_x; // X stage load/store address
|
115 |
|
|
input [`LM32_WORD_RNG] address_m; // M stage load/store address
|
116 |
|
|
input load_d; // Load instruction in D stage
|
117 |
|
|
input store_d; // Store instruction in D stage
|
118 |
|
|
input load_q_x; // Load instruction in X stage
|
119 |
|
|
input store_q_x; // Store instruction in X stage
|
120 |
|
|
input load_q_m; // Load instruction in M stage
|
121 |
|
|
input store_q_m; // Store instruction in M stage
|
122 |
|
|
|
123 |
|
|
input [`LM32_WORD_RNG] tlbpaddr;
|
124 |
|
|
input [`LM32_WORD_RNG] tlbvaddr;
|
125 |
|
|
input update;
|
126 |
|
|
input flush;
|
127 |
|
|
input invalidate;
|
128 |
|
|
|
129 |
|
|
/////////////////////////////////////////////////////
|
130 |
|
|
// Outputs
|
131 |
|
|
/////////////////////////////////////////////////////
|
132 |
|
|
|
133 |
|
|
output [`LM32_WORD_RNG] physical_load_store_address_m;
|
134 |
|
|
wire [`LM32_WORD_RNG] physical_load_store_address_m;
|
135 |
|
|
output stall_request;
|
136 |
|
|
wire stall_request;
|
137 |
|
|
output [`LM32_WORD_RNG] miss_vfn;
|
138 |
|
|
wire [`LM32_WORD_RNG] miss_vfn;
|
139 |
|
|
output miss_x;
|
140 |
|
|
wire miss_x;
|
141 |
|
|
output fault_x;
|
142 |
|
|
wire fault_x;
|
143 |
|
|
output cache_inhibit_x;
|
144 |
|
|
wire cache_inhibit_x;
|
145 |
|
|
|
146 |
|
|
/////////////////////////////////////////////////////
|
147 |
|
|
// Internal nets and registers
|
148 |
|
|
/////////////////////////////////////////////////////
|
149 |
|
|
|
150 |
|
|
wire [`LM32_DTLB_ADDR_RNG] read_address;
|
151 |
|
|
wire [`LM32_DTLB_ADDR_RNG] write_address;
|
152 |
|
|
wire [`LM32_DTLB_DATA_RNG] write_data;
|
153 |
|
|
wire [`LM32_DTLB_DATA_RNG] tlbe;
|
154 |
|
|
wire [`LM32_DTLB_DATA_RNG] tlbe_inval;
|
155 |
|
|
wire [`LM32_DTLB_TAG_RNG] tlbe_tag_x;
|
156 |
|
|
wire [`LM32_DTLB_VPFN_RNG] tlbe_pfn_x;
|
157 |
|
|
wire tlbe_valid_x;
|
158 |
|
|
wire tlbe_ro_x;
|
159 |
|
|
wire tlbe_ci_x;
|
160 |
|
|
wire checking;
|
161 |
|
|
wire flushing;
|
162 |
|
|
wire write_port_enable;
|
163 |
|
|
|
164 |
|
|
reg [`LM32_DTLB_STATE_RNG] state; // Current state of FSM
|
165 |
|
|
reg [`LM32_DTLB_ADDR_RNG] flush_set;
|
166 |
|
|
reg [`LM32_DTLB_VPFN_RNG] tlbe_pfn_m;
|
167 |
|
|
reg lookup;
|
168 |
|
|
|
169 |
|
|
|
170 |
|
|
/////////////////////////////////////////////////////
|
171 |
|
|
// Functions
|
172 |
|
|
/////////////////////////////////////////////////////
|
173 |
|
|
|
174 |
|
|
////////////////////////////////////////////////////
|
175 |
|
|
// Instantiations
|
176 |
|
|
/////////////////////////////////////////////////////
|
177 |
|
|
|
178 |
|
|
lm32_ram
|
179 |
|
|
#(
|
180 |
|
|
// ----- Parameters -------
|
181 |
|
|
.data_width (`LM32_DTLB_DATA_WIDTH),
|
182 |
|
|
.address_width (index_width)
|
183 |
|
|
// Modified for Milkymist: removed non-portable RAM parameters
|
184 |
|
|
) data_ram
|
185 |
|
|
(
|
186 |
|
|
// ----- Inputs -------
|
187 |
|
|
.read_clk (clk_i),
|
188 |
|
|
.write_clk (clk_i),
|
189 |
|
|
.reset (rst_i),
|
190 |
|
|
.read_address (read_address),
|
191 |
|
|
.enable_read (lookup),
|
192 |
|
|
.write_address (write_address),
|
193 |
|
|
.enable_write (`TRUE),
|
194 |
|
|
.write_enable (write_port_enable),
|
195 |
|
|
.write_data (write_data),
|
196 |
|
|
// ----- Outputs -------
|
197 |
|
|
.read_data ({tlbe_pfn_x, tlbe_tag_x, tlbe_ci_x, tlbe_ro_x, tlbe_valid_x})
|
198 |
|
|
);
|
199 |
|
|
|
200 |
|
|
/////////////////////////////////////////////////////
|
201 |
|
|
// Combinational logic
|
202 |
|
|
/////////////////////////////////////////////////////
|
203 |
|
|
|
204 |
|
|
// Compute address to use to index into the DTLB data memory
|
205 |
|
|
assign read_address = address_x[`LM32_DTLB_IDX_RNG];
|
206 |
|
|
|
207 |
|
|
// tlb_update_address will receive data from a CSR register
|
208 |
|
|
assign write_address = (flushing == `TRUE)
|
209 |
|
|
? flush_set
|
210 |
|
|
: tlbvaddr[`LM32_DTLB_IDX_RNG];
|
211 |
|
|
|
212 |
|
|
assign write_port_enable = (update == `TRUE) || (invalidate == `TRUE) || (flushing == `TRUE);
|
213 |
|
|
|
214 |
|
|
assign physical_load_store_address_m = (enable == `FALSE)
|
215 |
|
|
? address_m
|
216 |
|
|
: {tlbe_pfn_m, address_m[`LM32_DTLB_OFFSET_RNG]};
|
217 |
|
|
|
218 |
|
|
assign tlbe = {
|
219 |
|
|
tlbpaddr[`LM32_DTLB_VPFN_RNG], // pfn
|
220 |
|
|
tlbvaddr[`LM32_DTLB_TAG_RNG], // tag
|
221 |
|
|
tlbpaddr[2], // cache inhibit
|
222 |
|
|
tlbpaddr[1], // read only
|
223 |
|
|
`TRUE}; // valid
|
224 |
|
|
assign tlbe_inval = {{`LM32_DTLB_DATA_WIDTH-1{1'b0}}, `FALSE};
|
225 |
|
|
assign write_data = ((invalidate == `TRUE) || (flushing)) ? tlbe_inval : tlbe;
|
226 |
|
|
|
227 |
|
|
|
228 |
|
|
assign tlbe_match = ({tlbe_tag_x, tlbe_valid_x} == {address_x[`LM32_DTLB_TAG_RNG], `TRUE});
|
229 |
|
|
|
230 |
|
|
assign miss_vfn = {address_x[`LM32_DTLB_VPFN_RNG], {offset_width{1'b0}}};
|
231 |
|
|
assign miss_x = ((enable == `TRUE) && ((load_q_x == `TRUE) || (store_q_x == `TRUE)) && (tlbe_match == `FALSE) && (lookup == `FALSE));
|
232 |
|
|
assign cache_inhibit_x = ((enable == `TRUE) && (tlbe_ci_x == `TRUE));
|
233 |
|
|
assign fault_x = ((enable == `TRUE) && (store_q_x == `TRUE) && (tlbe_match == `TRUE) && (tlbe_ro_x == `TRUE));
|
234 |
|
|
|
235 |
|
|
assign checking = state[0];
|
236 |
|
|
assign flushing = state[1];
|
237 |
|
|
assign stall_request = (flushing == `TRUE) || (lookup == `TRUE);
|
238 |
|
|
|
239 |
|
|
/////////////////////////////////////////////////////
|
240 |
|
|
// Sequential logic
|
241 |
|
|
/////////////////////////////////////////////////////
|
242 |
|
|
|
243 |
|
|
// Lookup logic
|
244 |
|
|
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
245 |
|
|
begin
|
246 |
|
|
if (rst_i == `TRUE)
|
247 |
|
|
lookup <= `FALSE;
|
248 |
|
|
else
|
249 |
|
|
begin
|
250 |
|
|
if ((enable == `TRUE) && (stall_x == `FALSE) && ((load_d == `TRUE) || (store_d == `TRUE)))
|
251 |
|
|
lookup <= `TRUE;
|
252 |
|
|
else
|
253 |
|
|
lookup <= `FALSE;
|
254 |
|
|
end
|
255 |
|
|
end
|
256 |
|
|
|
257 |
|
|
// X/M stage registers
|
258 |
|
|
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
259 |
|
|
begin
|
260 |
|
|
if (rst_i == `TRUE)
|
261 |
|
|
tlbe_pfn_m <= {vpfn_width{1'bx}};
|
262 |
|
|
else if (stall_m == `FALSE)
|
263 |
|
|
tlbe_pfn_m <= tlbe_pfn_x;
|
264 |
|
|
end
|
265 |
|
|
|
266 |
|
|
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
267 |
|
|
begin
|
268 |
|
|
if (rst_i == `TRUE)
|
269 |
|
|
begin
|
270 |
|
|
flush_set <= {index_width{1'b1}};
|
271 |
|
|
state <= `LM32_DTLB_STATE_FLUSH;
|
272 |
|
|
end
|
273 |
|
|
else
|
274 |
|
|
begin
|
275 |
|
|
case (state)
|
276 |
|
|
|
277 |
|
|
`LM32_DTLB_STATE_CHECK:
|
278 |
|
|
begin
|
279 |
|
|
if (flush == `TRUE) begin
|
280 |
|
|
flush_set <= {index_width{1'b1}};
|
281 |
|
|
state <= `LM32_DTLB_STATE_FLUSH;
|
282 |
|
|
end
|
283 |
|
|
end
|
284 |
|
|
|
285 |
|
|
`LM32_DTLB_STATE_FLUSH:
|
286 |
|
|
begin
|
287 |
|
|
if (flush_set == {index_width{1'b0}})
|
288 |
|
|
state <= `LM32_DTLB_STATE_CHECK;
|
289 |
|
|
flush_set <= flush_set - 1'b1;
|
290 |
|
|
end
|
291 |
|
|
|
292 |
|
|
endcase
|
293 |
|
|
end
|
294 |
|
|
end
|
295 |
|
|
|
296 |
|
|
endmodule
|
297 |
|
|
|
298 |
|
|
`endif
|
299 |
|
|
|