1 |
48 |
alirezamon |
/*
|
2 |
|
|
* LatticeMico32
|
3 |
|
|
* Instruction 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 |
|
|
`define LM32_ITLB_CTRL_FLUSH 5'h1
|
36 |
|
|
`define LM32_ITLB_CTRL_UPDATE 5'h2
|
37 |
|
|
`define LM32_TLB_CTRL_INVALIDATE_ENTRY 5'h10
|
38 |
|
|
|
39 |
|
|
`define LM32_ITLB_STATE_RNG 1:0
|
40 |
|
|
`define LM32_ITLB_STATE_CHECK 2'b01
|
41 |
|
|
`define LM32_ITLB_STATE_FLUSH 2'b10
|
42 |
|
|
|
43 |
|
|
`define LM32_ITLB_OFFSET_RNG offset_msb:offset_lsb
|
44 |
|
|
`define LM32_ITLB_IDX_RNG index_msb:index_lsb
|
45 |
|
|
`define LM32_ITLB_VPFN_RNG vpfn_msb:vpfn_lsb
|
46 |
|
|
`define LM32_ITLB_TAG_RNG tag_msb:tag_lsb
|
47 |
|
|
`define LM32_ITLB_ADDR_RNG (index_width-1):0
|
48 |
|
|
`define LM32_ITLB_DATA_WIDTH (vpfn_width+tag_width+1)
|
49 |
|
|
`define LM32_ITLB_DATA_RNG (`LM32_ITLB_DATA_WIDTH-1):0
|
50 |
|
|
|
51 |
|
|
|
52 |
|
|
/////////////////////////////////////////////////////
|
53 |
|
|
// Module interface
|
54 |
|
|
/////////////////////////////////////////////////////
|
55 |
|
|
module lm32_itlb (
|
56 |
|
|
// ----- Inputs -------
|
57 |
|
|
clk_i,
|
58 |
|
|
rst_i,
|
59 |
|
|
enable,
|
60 |
|
|
stall_a,
|
61 |
|
|
stall_f,
|
62 |
|
|
stall_d,
|
63 |
|
|
stall_x,
|
64 |
|
|
pc_a,
|
65 |
|
|
pc_f,
|
66 |
|
|
pc_x,
|
67 |
|
|
read_enable_f,
|
68 |
|
|
tlbpaddr,
|
69 |
|
|
tlbvaddr,
|
70 |
|
|
update,
|
71 |
|
|
flush,
|
72 |
|
|
invalidate,
|
73 |
|
|
// ----- Outputs -------
|
74 |
|
|
physical_pc_f,
|
75 |
|
|
stall_request,
|
76 |
|
|
miss_vfn,
|
77 |
|
|
miss_f,
|
78 |
|
|
miss_x
|
79 |
|
|
);
|
80 |
|
|
|
81 |
|
|
/////////////////////////////////////////////////////
|
82 |
|
|
// Parameters
|
83 |
|
|
/////////////////////////////////////////////////////
|
84 |
|
|
|
85 |
|
|
parameter entries = 1024; // Number of entires in ITLB
|
86 |
|
|
parameter page_size = 4096; // ITLB page size
|
87 |
|
|
|
88 |
|
|
localparam offset_width = (`CLOG2(page_size)-2);
|
89 |
|
|
localparam index_width = `CLOG2(entries);
|
90 |
|
|
localparam offset_lsb = 2;
|
91 |
|
|
localparam offset_msb = (offset_lsb+offset_width-1);
|
92 |
|
|
localparam index_lsb = (offset_msb+1);
|
93 |
|
|
localparam index_msb = (index_lsb+index_width-1);
|
94 |
|
|
localparam tag_lsb = (index_msb+1);
|
95 |
|
|
localparam tag_msb = (`LM32_WORD_WIDTH-1);
|
96 |
|
|
localparam tag_width = (tag_msb-tag_lsb+1);
|
97 |
|
|
localparam vpfn_lsb = (offset_msb+1);
|
98 |
|
|
localparam vpfn_msb = (`LM32_WORD_WIDTH-1);
|
99 |
|
|
localparam vpfn_width = (vpfn_msb-vpfn_lsb+1);
|
100 |
|
|
|
101 |
|
|
/////////////////////////////////////////////////////
|
102 |
|
|
// Inputs
|
103 |
|
|
/////////////////////////////////////////////////////
|
104 |
|
|
|
105 |
|
|
input clk_i; // Clock
|
106 |
|
|
input rst_i; // Reset
|
107 |
|
|
|
108 |
|
|
input enable; // Instruction TLB enable
|
109 |
|
|
input stall_a; // Stall instruction in A stage
|
110 |
|
|
input stall_f; // Stall instruction in F stage
|
111 |
|
|
input stall_d; // Stall instruction in D stage
|
112 |
|
|
input stall_x; // Stall instruction in X stage
|
113 |
|
|
|
114 |
|
|
input [`LM32_PC_RNG] pc_a; // Address of instruction in A stage
|
115 |
|
|
input [`LM32_PC_RNG] pc_f; // Address of instruction in F stage
|
116 |
|
|
input [`LM32_PC_RNG] pc_x; // Address of instruction in X stage
|
117 |
|
|
|
118 |
|
|
input read_enable_f; // Indicates if cache access is valid
|
119 |
|
|
|
120 |
|
|
input [`LM32_WORD_RNG] tlbpaddr;
|
121 |
|
|
input [`LM32_WORD_RNG] tlbvaddr;
|
122 |
|
|
input update;
|
123 |
|
|
input flush;
|
124 |
|
|
input invalidate;
|
125 |
|
|
|
126 |
|
|
/////////////////////////////////////////////////////
|
127 |
|
|
// Outputs
|
128 |
|
|
/////////////////////////////////////////////////////
|
129 |
|
|
output [`LM32_PC_RNG] physical_pc_f;
|
130 |
|
|
reg [`LM32_PC_RNG] physical_pc_f;
|
131 |
|
|
output stall_request;
|
132 |
|
|
wire stall_request;
|
133 |
|
|
output [`LM32_WORD_RNG] miss_vfn;
|
134 |
|
|
wire [`LM32_WORD_RNG] miss_vfn;
|
135 |
|
|
output miss_f;
|
136 |
|
|
wire miss_f;
|
137 |
|
|
output miss_x;
|
138 |
|
|
reg miss_x;
|
139 |
|
|
|
140 |
|
|
/////////////////////////////////////////////////////
|
141 |
|
|
// Internal nets and registers
|
142 |
|
|
/////////////////////////////////////////////////////
|
143 |
|
|
|
144 |
|
|
wire [`LM32_ITLB_ADDR_RNG] read_address;
|
145 |
|
|
wire [`LM32_ITLB_ADDR_RNG] write_address;
|
146 |
|
|
wire read_port_enable;
|
147 |
|
|
wire write_port_enable;
|
148 |
|
|
wire [`LM32_ITLB_DATA_RNG] write_data;
|
149 |
|
|
reg [`LM32_ITLB_STATE_RNG] state;
|
150 |
|
|
reg [`LM32_ITLB_ADDR_RNG] flush_set;
|
151 |
|
|
|
152 |
|
|
wire [`LM32_ITLB_TAG_RNG] tlbe_tag_f;
|
153 |
|
|
wire [`LM32_ITLB_VPFN_RNG] tlbe_pfn_f;
|
154 |
|
|
wire tlbe_valid_f;
|
155 |
|
|
|
156 |
|
|
reg miss_d;
|
157 |
|
|
wire flushing;
|
158 |
|
|
|
159 |
|
|
/////////////////////////////////////////////////////
|
160 |
|
|
// Functions
|
161 |
|
|
/////////////////////////////////////////////////////
|
162 |
|
|
|
163 |
|
|
////////////////////////////////////////////////////
|
164 |
|
|
// Instantiations
|
165 |
|
|
/////////////////////////////////////////////////////
|
166 |
|
|
|
167 |
|
|
lm32_ram
|
168 |
|
|
#(
|
169 |
|
|
// ----- Parameters -------
|
170 |
|
|
.data_width (`LM32_ITLB_DATA_WIDTH),
|
171 |
|
|
.address_width (index_width)
|
172 |
|
|
// Modified for Milkymist: removed non-portable RAM parameters
|
173 |
|
|
) data_ram
|
174 |
|
|
(
|
175 |
|
|
// ----- Inputs -------
|
176 |
|
|
.read_clk (clk_i),
|
177 |
|
|
.write_clk (clk_i),
|
178 |
|
|
.reset (rst_i),
|
179 |
|
|
.read_address (read_address),
|
180 |
|
|
.enable_read (read_port_enable),
|
181 |
|
|
.write_address (write_address),
|
182 |
|
|
.enable_write (`TRUE),
|
183 |
|
|
.write_enable (write_port_enable),
|
184 |
|
|
.write_data (write_data),
|
185 |
|
|
// ----- Outputs -------
|
186 |
|
|
.read_data ({tlbe_pfn_f, tlbe_tag_f, tlbe_valid_f})
|
187 |
|
|
);
|
188 |
|
|
|
189 |
|
|
/////////////////////////////////////////////////////
|
190 |
|
|
// Combinational logic
|
191 |
|
|
/////////////////////////////////////////////////////
|
192 |
|
|
|
193 |
|
|
// Compute address to use to index into the ITLB memory
|
194 |
|
|
assign read_address = pc_a[`LM32_ITLB_IDX_RNG];
|
195 |
|
|
assign write_address = (flushing == `TRUE) ? flush_set : tlbvaddr[`LM32_ITLB_IDX_RNG];
|
196 |
|
|
|
197 |
|
|
assign read_port_enable = (stall_a == `FALSE);
|
198 |
|
|
assign write_port_enable = (update == `TRUE) || (invalidate == `TRUE) || (flushing == `TRUE);
|
199 |
|
|
|
200 |
|
|
assign write_data = ((invalidate == `TRUE) || (flushing == `TRUE))
|
201 |
|
|
? {{`LM32_ITLB_DATA_WIDTH-1{1'b0}}, `FALSE}
|
202 |
|
|
: {tlbpaddr[`LM32_ITLB_VPFN_RNG], tlbvaddr[`LM32_ITLB_TAG_RNG], `TRUE};
|
203 |
|
|
|
204 |
|
|
assign tlbe_match_f = ({tlbe_tag_f, tlbe_valid_f} == {pc_f[`LM32_ITLB_TAG_RNG], `TRUE});
|
205 |
|
|
|
206 |
|
|
assign miss_vfn = {pc_x[`LM32_ITLB_VPFN_RNG], {offset_width{1'b0}}, 2'b0};
|
207 |
|
|
assign miss_f = (enable == `TRUE) && (tlbe_match_f == `FALSE) && (stall_f == `FALSE);
|
208 |
|
|
|
209 |
|
|
assign flushing = state[1];
|
210 |
|
|
assign stall_request = (flushing == `TRUE);
|
211 |
|
|
|
212 |
|
|
always @(*)
|
213 |
|
|
begin
|
214 |
|
|
if (enable == `TRUE)
|
215 |
|
|
begin
|
216 |
|
|
if (tlbe_match_f == `TRUE)
|
217 |
|
|
physical_pc_f = {tlbe_pfn_f, pc_f[`LM32_ITLB_OFFSET_RNG]};
|
218 |
|
|
else
|
219 |
|
|
physical_pc_f = {`LM32_PC_WIDTH{1'b0}};
|
220 |
|
|
end
|
221 |
|
|
else
|
222 |
|
|
physical_pc_f = pc_f;
|
223 |
|
|
end
|
224 |
|
|
|
225 |
|
|
/////////////////////////////////////////////////////
|
226 |
|
|
// Sequential logic
|
227 |
|
|
/////////////////////////////////////////////////////
|
228 |
|
|
|
229 |
|
|
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
230 |
|
|
begin
|
231 |
|
|
if (rst_i == `TRUE)
|
232 |
|
|
begin
|
233 |
|
|
miss_d <= `FALSE;
|
234 |
|
|
miss_x <= `FALSE;
|
235 |
|
|
end
|
236 |
|
|
else
|
237 |
|
|
begin
|
238 |
|
|
if (stall_d == `FALSE)
|
239 |
|
|
miss_d <= miss_f;
|
240 |
|
|
if (stall_x == `FALSE)
|
241 |
|
|
miss_x <= miss_d;
|
242 |
|
|
end
|
243 |
|
|
end
|
244 |
|
|
|
245 |
|
|
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
246 |
|
|
begin
|
247 |
|
|
if (rst_i == `TRUE)
|
248 |
|
|
begin
|
249 |
|
|
flush_set <= {index_width{1'b1}};
|
250 |
|
|
state <= `LM32_ITLB_STATE_FLUSH;
|
251 |
|
|
end
|
252 |
|
|
else
|
253 |
|
|
begin
|
254 |
|
|
case (state)
|
255 |
|
|
|
256 |
|
|
`LM32_ITLB_STATE_CHECK:
|
257 |
|
|
begin
|
258 |
|
|
if (flush == `TRUE)
|
259 |
|
|
begin
|
260 |
|
|
flush_set <= {index_width{1'b1}};
|
261 |
|
|
state <= `LM32_ITLB_STATE_FLUSH;
|
262 |
|
|
end
|
263 |
|
|
end
|
264 |
|
|
|
265 |
|
|
`LM32_ITLB_STATE_FLUSH:
|
266 |
|
|
begin
|
267 |
|
|
if (flush_set == {index_width{1'b0}})
|
268 |
|
|
state <= `LM32_ITLB_STATE_CHECK;
|
269 |
|
|
flush_set <= flush_set - 1'b1;
|
270 |
|
|
end
|
271 |
|
|
|
272 |
|
|
endcase
|
273 |
|
|
end
|
274 |
|
|
end
|
275 |
|
|
|
276 |
|
|
endmodule
|
277 |
|
|
|
278 |
|
|
`endif
|
279 |
|
|
|