Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: dmu_mmu_pab.v | |
4 | // Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved | |
5 | // 4150 Network Circle, Santa Clara, California 95054, U.S.A. | |
6 | // | |
7 | // * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
8 | // | |
9 | // This program is free software; you can redistribute it and/or modify | |
10 | // it under the terms of the GNU General Public License as published by | |
11 | // the Free Software Foundation; version 2 of the License. | |
12 | // | |
13 | // This program is distributed in the hope that it will be useful, | |
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | // GNU General Public License for more details. | |
17 | // | |
18 | // You should have received a copy of the GNU General Public License | |
19 | // along with this program; if not, write to the Free Software | |
20 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | // | |
22 | // For the avoidance of doubt, and except that if any non-GPL license | |
23 | // choice is available it will apply instead, Sun elects to use only | |
24 | // the General Public License version 2 (GPLv2) at this time for any | |
25 | // software where a choice of GPL license versions is made | |
26 | // available with the language indicating that GPLv2 or any later version | |
27 | // may be used, or where a choice of which version of the GPL is applied is | |
28 | // otherwise unspecified. | |
29 | // | |
30 | // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
31 | // CA 95054 USA or visit www.sun.com if you need additional information or | |
32 | // have any questions. | |
33 | // | |
34 | // ========== Copyright Header End ============================================ | |
35 | module dmu_mmu_pab | |
36 | ( | |
37 | clk, // clock | |
38 | rst_l, // reset | |
39 | csr2pab_ps, // csr page size | |
40 | tcb2pab_err, // tcb error | |
41 | tcb2pab_sel, // tcb select | |
42 | tdb2pab_par, // tdb parity | |
43 | tdb2pab_ppn, // tdb pyhsical page number | |
44 | tdb2pab_wrt, // tdb write | |
45 | tdb2pab_vld, // tdb valid | |
46 | tdb2pab_keyvld, // pab key valid | |
47 | tdb2pab_fnm, // pab function number | |
48 | tdb2pab_key, // pab key | |
49 | tlb2pab_addr, // tlb address | |
50 | tlb2pab_type, // tlb type | |
51 | tlb2pab_vld, // tlb valid | |
52 | tlb2pab_wrt, // tlb write | |
53 | pab2paq_rcd, // paq physical address record | |
54 | pab2tcb_err, // tcb error | |
55 | tlb2pab_sun4v_pgsz, // sun4v page size to concat pa offset | |
56 | sun4v_mode, // sun4v mode | |
57 | tlb2pab_byp_ps2 // 1 if sun4v mode and bypass detected | |
58 | ); | |
59 | ||
60 | // ---------------------------------------------------------------------------- | |
61 | // Parameters | |
62 | // ---------------------------------------------------------------------------- | |
63 | parameter PAM = `FIRE_PA_MSB; // physical address MSB = 42 | |
64 | parameter PAM_N2 = `N2_PA_MSB; // physical address MSB = 38 | |
65 | ||
66 | parameter MEM_RDT = 7'b0000000, // type encodings | |
67 | MEM_RDB = 7'b0100000, | |
68 | MEM_WRT = 7'b1000000, | |
69 | MEM_WRB = 7'b1100000, | |
70 | MSG_WRT = 7'b1010000, | |
71 | MSG_WRB = 7'b1110000, | |
72 | MSI_WRT = 7'b1011000, | |
73 | MSI_WRB = 7'b1111000; | |
74 | ||
75 | // ---------------------------------------------------------------------------- | |
76 | // Ports | |
77 | // ---------------------------------------------------------------------------- | |
78 | input clk; | |
79 | input rst_l; | |
80 | ||
81 | input csr2pab_ps; | |
82 | input tcb2pab_err; | |
83 | input tcb2pab_sel; | |
84 | input [`FIRE_DLC_MMU_TDD_PAR_BITS] tdb2pab_par; | |
85 | input [`FIRE_DLC_MMU_TDD_PPN_BITS] tdb2pab_ppn; | |
86 | input tdb2pab_wrt; | |
87 | input tdb2pab_vld; | |
88 | input [`FIRE_DLC_MMU_PA_ADDR_BITS] tlb2pab_addr; | |
89 | input [`FIRE_DLC_MMU_PA_TYPE_BITS] tlb2pab_type; | |
90 | input tlb2pab_vld; | |
91 | input tlb2pab_wrt; | |
92 | input [`FIRE_DLC_MMU_TDD_KEY_BITS] tdb2pab_key; | |
93 | input [`FIRE_DLC_MMU_TDD_FNM_BITS] tdb2pab_fnm; | |
94 | input tdb2pab_keyvld; | |
95 | output [`FIRE_DLC_MMU_PAR_BITS] pab2paq_rcd; | |
96 | output [`FIRE_DLC_MMU_PAB_ERR_BITS] pab2tcb_err; | |
97 | input [2:0] tlb2pab_sun4v_pgsz; | |
98 | input sun4v_mode; | |
99 | input tlb2pab_byp_ps2; | |
100 | ||
101 | // ---------------------------------------------------------------------------- | |
102 | // Variables | |
103 | // ---------------------------------------------------------------------------- | |
104 | wire [`FIRE_DLC_MMU_PAR_BITS] pab2paq_rcd; | |
105 | reg [`FIRE_DLC_MMU_PA_ADDR_BITS] addr_ps2; | |
106 | wire [3:0] dpe, par; | |
107 | wire [1:0] sel; | |
108 | reg [25:0] sun4v_pab_addr; | |
109 | ||
110 | reg [`FIRE_DLC_MMU_PAB_ERR_BITS] pab2tcb_err; | |
111 | reg [`FIRE_DLC_MMU_PA_ADDR_BITS] addr_ps3; | |
112 | reg [`FIRE_DLC_MMU_PA_TYPE_BITS] type_ps3; | |
113 | reg aerr_ps3; | |
114 | reg dok, vok, wok; | |
115 | ||
116 | // ---------------------------------------------------------------------------- | |
117 | // Zero In Checkers | |
118 | // ---------------------------------------------------------------------------- | |
119 | //BP N2 comment out until new tdb ram parity is finalized | |
120 | // // 0in odd_parity -var {tdb2pab_ppn[PAM:PAM-7], tdb2pab_par[`FIRE_DLC_MMU_TDD_PAR_LSB+3]} -active ~tcb2pab_sel | |
121 | // // 0in odd_parity -var {tdb2pab_ppn[PAM-8:PAM-15], tdb2pab_par[`FIRE_DLC_MMU_TDD_PAR_LSB+2]} -active ~tcb2pab_sel | |
122 | // // 0in odd_parity -var {tdb2pab_ppn[PAM-16:PAM-23], tdb2pab_par[`FIRE_DLC_MMU_TDD_PAR_LSB+1]} -active ~tcb2pab_sel | |
123 | // // 0in odd_parity -var {tdb2pab_ppn[PAM-24:13], tdb2pab_vld, tdb2pab_wrt, tdb2pab_par[`FIRE_DLC_MMU_TDD_PAR_LSB]} -active ~tcb2pab_sel | |
124 | ||
125 | // 0in odd_parity -var {tdb2pab_key[`FIRE_DLC_MMU_TDD_KEY_MSB:`FIRE_DLC_MMU_TDD_KEY_LSB+4], tdb2pab_par[`FIRE_DLC_MMU_TDD_PAR_LSB+3]} -active ~tcb2pab_sel | |
126 | // 0in odd_parity -var {tdb2pab_key[`FIRE_DLC_MMU_TDD_KEY_LSB+3:`FIRE_DLC_MMU_TDD_KEY_LSB],tdb2pab_ppn[`FIRE_DLC_MMU_TDD_PPN_MSB:`FIRE_DLC_MMU_TDD_PPN_MSB-7], tdb2pab_par[`FIRE_DLC_MMU_TDD_PAR_LSB+2]} -active ~tcb2pab_sel | |
127 | // 0in odd_parity -var {tdb2pab_ppn[`FIRE_DLC_MMU_TDD_PPN_MSB-8:`FIRE_DLC_MMU_TDD_PPN_LSB+6], tdb2pab_par[`FIRE_DLC_MMU_TDD_PAR_LSB+1]} -active ~tcb2pab_sel | |
128 | // 0in odd_parity -var {tdb2pab_ppn[`FIRE_DLC_MMU_TDD_PPN_LSB+5:`FIRE_DLC_MMU_TDD_PPN_LSB],tdb2pab_fnm,tdb2pab_keyvld,tdb2pab_wrt,tdb2pab_vld, tdb2pab_par[`FIRE_DLC_MMU_TDD_PAR_LSB] } -active ~tcb2pab_sel | |
129 | ||
130 | // ---------------------------------------------------------------------------- | |
131 | // Combinational | |
132 | // ---------------------------------------------------------------------------- | |
133 | ||
134 | // physical address record creation | |
135 | assign pab2paq_rcd[`FIRE_DLC_MMU_PAR_ADDR_BITS] = addr_ps3; | |
136 | assign pab2paq_rcd[`FIRE_DLC_MMU_PAR_AERR_BITS] = aerr_ps3; | |
137 | assign pab2paq_rcd[`FIRE_DLC_MMU_PAR_TYPE_BITS] = type_ps3; | |
138 | ||
139 | // errors | |
140 | always @ (dok or wok or vok) begin | |
141 | case ({dok, wok, vok}) // synopsys parallel_case | |
142 | 3'b000 : pab2tcb_err = 3'b100; | |
143 | 3'b001 : pab2tcb_err = 3'b100; | |
144 | 3'b010 : pab2tcb_err = 3'b100; | |
145 | 3'b011 : pab2tcb_err = 3'b100; | |
146 | 3'b100 : pab2tcb_err = 3'b001; | |
147 | 3'b101 : pab2tcb_err = 3'b010; | |
148 | 3'b110 : pab2tcb_err = 3'b001; | |
149 | 3'b111 : pab2tcb_err = 3'b000; | |
150 | endcase | |
151 | end | |
152 | ||
153 | // parity | |
154 | // assign par[3] = ^tdb2pab_ppn[PAM:PAM-7]; | |
155 | // assign par[2] = ^tdb2pab_ppn[PAM-8:PAM-15]; | |
156 | // assign par[1] = ^tdb2pab_ppn[PAM-16:PAM-23]; | |
157 | // assign par[0] = ^tdb2pab_ppn[PAM-24:13] ^ tdb2pab_vld ^ tdb2pab_wrt; | |
158 | ||
159 | assign par[3] = ^{tdb2pab_key[`FIRE_DLC_MMU_TDD_KEY_MSB:`FIRE_DLC_MMU_TDD_KEY_LSB+4]}; | |
160 | assign par[2] = ^{tdb2pab_key[`FIRE_DLC_MMU_TDD_KEY_LSB+3:`FIRE_DLC_MMU_TDD_KEY_LSB],tdb2pab_ppn[`FIRE_DLC_MMU_TDD_PPN_MSB:`FIRE_DLC_MMU_TDD_PPN_MSB-7]}; | |
161 | assign par[1] = ^tdb2pab_ppn[`FIRE_DLC_MMU_TDD_PPN_MSB-8:`FIRE_DLC_MMU_TDD_PPN_LSB+6]; | |
162 | assign par[0] = ^{tdb2pab_ppn[`FIRE_DLC_MMU_TDD_PPN_LSB+5:`FIRE_DLC_MMU_TDD_PPN_LSB],tdb2pab_fnm,tdb2pab_keyvld,tdb2pab_wrt,tdb2pab_vld}; | |
163 | ||
164 | // data parity errors | |
165 | assign dpe[3] = ~par[3] ^ tdb2pab_par[`FIRE_DLC_MMU_TDD_PAR_LSB+3]; | |
166 | assign dpe[2] = ~par[2] ^ tdb2pab_par[`FIRE_DLC_MMU_TDD_PAR_LSB+2]; | |
167 | assign dpe[1] = ~par[1] ^ tdb2pab_par[`FIRE_DLC_MMU_TDD_PAR_LSB+1]; | |
168 | assign dpe[0] = ~par[0] ^ tdb2pab_par[`FIRE_DLC_MMU_TDD_PAR_LSB]; | |
169 | ||
170 | // select data, write, and valid | |
171 | //BP N2 fix after parity is done in tdb ram 8-26-04 | |
172 | wire dat = tcb2pab_sel | ~(|dpe); | |
173 | // wire dat = tcb2pab_sel ; | |
174 | wire wrt = tcb2pab_sel ? tlb2pab_wrt : tdb2pab_wrt; | |
175 | wire vld = tcb2pab_sel ? tlb2pab_vld : tdb2pab_vld; | |
176 | ||
177 | // select based upon page size | |
178 | assign sel[1] = tcb2pab_sel; | |
179 | assign sel[0] = tcb2pab_sel | csr2pab_ps; | |
180 | ||
181 | // physical address | |
182 | //BP 9-29-05 assign addr_ps2[PAM:16] = sel[1] ? tlb2pab_addr[PAM:16] : {{4{1'b0}},tdb2pab_ppn[PAM_N2:16]}; | |
183 | //BP 9-29-05 assign addr_ps2[15:13] = sel[0] ? tlb2pab_addr[15:13] : tdb2pab_ppn[15:13]; | |
184 | //BP 9-29-05 assign addr_ps2[12:2] = tlb2pab_addr[12:2]; | |
185 | //BP 9-29-05 sun4v requires 4 page sizes | |
186 | always @(sun4v_mode or tlb2pab_addr or sel or tdb2pab_ppn or sun4v_pab_addr ) begin | |
187 | ||
188 | if (!sun4v_mode) begin | |
189 | addr_ps2[PAM:16] = sel[1] ? tlb2pab_addr[PAM:16] : | |
190 | {{4{1'b0}},tdb2pab_ppn[PAM_N2:16]}; | |
191 | addr_ps2[15:13] = (sel[0] ) ? tlb2pab_addr[15:13] : tdb2pab_ppn[15:13]; | |
192 | addr_ps2[12:2] = tlb2pab_addr[12:2]; | |
193 | end | |
194 | else begin | |
195 | addr_ps2[PAM:2] = {{4{1'b0}},sun4v_pab_addr[25:0],tlb2pab_addr[12:2]}; | |
196 | end | |
197 | end | |
198 | //BP 9-29-05 this logic switches between the tlb data(pipeline or tablewalk) | |
199 | // and the tdb pa value | |
200 | always @(tlb2pab_sun4v_pgsz or tlb2pab_addr or tdb2pab_ppn or sel ) begin | |
201 | ||
202 | sun4v_pab_addr[25:0] = {26{1'b0}}; // PAM=42,`N2_PA_MSB=38 | |
203 | ||
204 | case(tlb2pab_sun4v_pgsz) | |
205 | 3'b000: if (sel[1]) sun4v_pab_addr = tlb2pab_addr[`N2_PA_MSB:13]; // 8k pages | |
206 | else sun4v_pab_addr = tdb2pab_ppn[`N2_PA_MSB:13]; | |
207 | 3'b001: if (sel[1]) sun4v_pab_addr = tlb2pab_addr[`N2_PA_MSB:13]; // 64k pages | |
208 | else sun4v_pab_addr = {tdb2pab_ppn[`N2_PA_MSB:16],tlb2pab_addr[15:13]}; | |
209 | 3'b010: sun4v_pab_addr = {26{1'b0}}; // invalid | |
210 | 3'b011: if (sel[1]) sun4v_pab_addr = tlb2pab_addr[`N2_PA_MSB:13]; // 4M pages | |
211 | else sun4v_pab_addr = {tdb2pab_ppn[`N2_PA_MSB:22],tlb2pab_addr[21:13]}; | |
212 | 3'b100: sun4v_pab_addr = {26{1'b0}}; // invalid | |
213 | 3'b101: if (sel[1]) sun4v_pab_addr = tlb2pab_addr[`N2_PA_MSB:13]; // 256M pages | |
214 | else sun4v_pab_addr = {tdb2pab_ppn[`N2_PA_MSB:28],tlb2pab_addr[27:13]}; | |
215 | 3'b110: sun4v_pab_addr = {26{1'b0}}; // invalid | |
216 | 3'b111: sun4v_pab_addr = {26{1'b0}}; // invalid | |
217 | default: sun4v_pab_addr = {26{1'b0}}; | |
218 | endcase | |
219 | end | |
220 | ||
221 | ||
222 | ||
223 | ||
224 | ||
225 | ||
226 | // address error | |
227 | wire aerr_ps2 = tcb2pab_err; | |
228 | ||
229 | //BP n2 12-14-05 fire assumed all 64 bit address were bypass , n2 needs | |
230 | // to add 64 bit translation also | |
231 | // data ok | |
232 | always @ (tlb2pab_type or dat or sun4v_mode or tlb2pab_byp_ps2) begin | |
233 | case ({tlb2pab_byp_ps2,sun4v_mode,tlb2pab_type}) // synopsys parallel_case | |
234 | {1'b0,1'b0,MEM_RDT} : dok = dat; // sun4u | |
235 | {1'b0,1'b0,MEM_WRT} : dok = dat; // sun4u | |
236 | {1'b0,1'b0,MSG_WRT} : dok = dat; // sun4u | |
237 | {1'b0,1'b0,MSI_WRT} : dok = dat; // sun4u | |
238 | ||
239 | {1'b0,1'b1,MEM_RDT} : dok = dat; // sun4v | |
240 | {1'b0,1'b1,MEM_WRT} : dok = dat; // sun4v | |
241 | {1'b0,1'b1,MSG_WRT} : dok = dat; // sun4v | |
242 | {1'b0,1'b1,MSI_WRT} : dok = dat; // sun4v | |
243 | {1'b0,1'b1,MEM_RDB} : dok = dat; // sun4v | |
244 | {1'b0,1'b1,MEM_WRB} : dok = dat; // sun4v | |
245 | {1'b0,1'b1,MSG_WRB} : dok = dat; // sun4v | |
246 | {1'b0,1'b1,MSI_WRB} : dok = dat; // sun4v | |
247 | default : dok = 1'b1; | |
248 | endcase | |
249 | end | |
250 | ||
251 | // write ok | |
252 | always @ (tlb2pab_type or wrt) begin | |
253 | case (tlb2pab_type) // synopsys parallel_case | |
254 | MEM_WRT : wok = wrt; | |
255 | MEM_WRB : wok = wrt; | |
256 | MSG_WRT : wok = wrt; | |
257 | MSG_WRB : wok = wrt; | |
258 | MSI_WRT : wok = wrt; | |
259 | MSI_WRB : wok = wrt; | |
260 | default : wok = 1'b1; | |
261 | endcase | |
262 | end | |
263 | ||
264 | // valid ok | |
265 | always @ (tlb2pab_type or vld) begin | |
266 | case (tlb2pab_type) // synopsys parallel_case | |
267 | MEM_RDT : vok = vld; | |
268 | MEM_RDB : vok = vld; | |
269 | MEM_WRT : vok = vld; | |
270 | MEM_WRB : vok = vld; | |
271 | MSG_WRT : vok = vld; | |
272 | MSG_WRB : vok = vld; | |
273 | MSI_WRT : vok = vld; | |
274 | MSI_WRB : vok = vld; | |
275 | default : vok = 1'b1; | |
276 | endcase | |
277 | end | |
278 | ||
279 | // ---------------------------------------------------------------------------- | |
280 | // Sequential | |
281 | // ---------------------------------------------------------------------------- | |
282 | always @ (posedge clk) begin | |
283 | if (!rst_l) begin | |
284 | addr_ps3 <= 0; | |
285 | aerr_ps3 <= 0; | |
286 | type_ps3 <= 0; | |
287 | end | |
288 | else begin | |
289 | addr_ps3 <= addr_ps2; | |
290 | aerr_ps3 <= aerr_ps2; | |
291 | type_ps3 <= tlb2pab_type; | |
292 | end | |
293 | end | |
294 | ||
295 | endmodule // dmu_mmu_pab |