-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patholdland_tlb.v
More file actions
128 lines (113 loc) · 3.2 KB
/
oldland_tlb.v
File metadata and controls
128 lines (113 loc) · 3.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
module oldland_tlb(input wire clk,
input wire rst,
input wire enabled,
input wire starting_miss,
input wire user_mode,
/* Maintenance signals. */
input wire inval,
input wire [31:0] load_data,
input wire load_virt,
input wire load_phys,
/* Lookup signals. */
input wire translate,
input wire [31:12] virt,
output reg [31:12] phys,
output reg [1:0] access,
output reg valid,
output wire miss,
output reg complete);
parameter nr_entries = 8;
localparam entry_bits = myclog2(nr_entries);
// verilator lint_off UNUSED
reg [31:0] next_virt = 32'b0;
// verilator lint_on UNUSED
reg [entry_bits - 1:0] victim_sel = {entry_bits{1'b0}};
reg [nr_entries - 1:0] load_entry = {nr_entries{1'b0}};
wire [nr_entries - 1:0] entry_valid;
wire [31:12] entry_virt[nr_entries - 1:0];
wire [31:12] entry_phys[nr_entries - 1:0];
wire [1:0] entry_access[nr_entries - 1:0];
reg [entry_bits:0] entry_idx = {entry_bits + 1{1'b0}};
reg [entry_bits - 1:0] entry = {entry_bits{1'b0}};
reg tlb_miss = 1'b0;
assign miss = tlb_miss && enabled;
genvar i;
initial begin
phys = 20'b0;
valid = 1'b0;
complete = 1'b0;
tlb_miss = 1'b0;
end
generate
for (i = 0; i < nr_entries; i = i + 1) begin: entries
oldland_tlb_entry entry(.clk(clk),
.rst(rst),
.user_mode(user_mode),
.inval(inval),
.virt_in(next_virt[31:12]),
.phys_in(load_data[31:12]),
.access_in(next_virt[3:0]),
.load(load_entry[i]),
.virt_out(entry_virt[i]),
.phys_out(entry_phys[i]),
.access_out(entry_access[i]),
.valid_out(entry_valid[i]));
end
endgenerate
always @(posedge clk) begin
if (load_virt)
next_virt <= load_data;
if (rst)
victim_sel <= {entry_bits{1'b0}};
if (load_phys)
victim_sel <= victim_sel + 1'b1;
end
always @(*) begin
/*
* Generate the load signal for an entry. If there is already
* a mapping for a virtual address we need to overwrite that one so we
* don't have duplicate entries, otherwise take the next victim in
* a round-robin fashion.
*/
for (entry_idx = 0; entry_idx < nr_entries; entry_idx = entry_idx + 1'b1) begin
entry = entry_idx[entry_bits - 1:0];
if (entry_valid[entry] && entry_virt[entry] == next_virt[31:12] && load_phys)
load_entry[entry] = 1'b1;
else
load_entry[entry] = 1'b0;
end
if (~|load_entry && load_phys)
load_entry[victim_sel] = 1'b1;
end
always @(posedge clk) begin
if (translate) begin
valid <= 1'b0;
tlb_miss <= 1'b0;
phys <= virt;
access <= 2'b11;
end
complete <= translate;
if (enabled)
tlb_miss <= translate;
for (entry_idx = 0; entry_idx < nr_entries; entry_idx = entry_idx + 1'b1) begin
if (entry_valid[entry_idx[entry_bits - 1:0]] &&
entry_virt[entry_idx[entry_bits - 1:0]] == virt[31:12] &&
translate && enabled) begin
phys <= entry_phys[entry_idx[entry_bits - 1:0]];
access <= entry_access[entry_idx[entry_bits - 1:0]];
valid <= 1'b1;
tlb_miss <= 1'b0;
end
end
/*
* If we are starting a new miss then the TLB will be disabled on the
* next cycle so we need to make sure that we have a valid output.
*/
if ((!enabled || starting_miss)) begin
phys <= virt;
valid <= 1'b1;
tlb_miss <= 1'b0;
access <= 2'b11;
end
end
endmodule