Line data Source code
1 : // SPDX-License-Identifier: Apache-2.0
2 : // Copyright 2023 Antmicro <www.antmicro.com>
3 : //
4 : // Licensed under the Apache License, Version 2.0 (the "License");
5 : // you may not use this file except in compliance with the License.
6 : // You may obtain a copy of the License at
7 : //
8 : // http://www.apache.org/licenses/LICENSE-2.0
9 : //
10 : // Unless required by applicable law or agreed to in writing, software
11 : // distributed under the License is distributed on an "AS IS" BASIS,
12 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : // See the License for the specific language governing permissions and
14 : // limitations under the License.
15 :
16 :
17 : //********************************************************************************
18 : // el2_dec_pmp_ctl.sv
19 : //
20 : //
21 : // Function: Physical Memory Protection CSRs
22 : // Comments:
23 : //
24 : //********************************************************************************
25 :
26 : module el2_dec_pmp_ctl
27 : import el2_pkg::*;
28 : #(
29 : `include "el2_param.vh"
30 : )
31 : (
32 69890155 : input logic clk,
33 69890155 : input logic free_l2clk,
34 69890155 : input logic csr_wr_clk,
35 338 : input logic rst_l,
36 42194 : input logic dec_csr_wen_r_mod, // csr write enable at wb
37 542 : input logic [11:0] dec_csr_wraddr_r, // write address for csr
38 1686 : input logic [31:0] dec_csr_wrdata_r, // csr write data at wb
39 986 : input logic [11:0] dec_csr_rdaddr_d, // read address for csr
40 :
41 896 : input logic csr_pmpcfg,
42 802 : input logic csr_pmpaddr0,
43 16 : input logic csr_pmpaddr16,
44 10 : input logic csr_pmpaddr32,
45 14 : input logic csr_pmpaddr48,
46 :
47 2 : input logic dec_pause_state, // Paused
48 108 : input logic dec_tlu_pmu_fw_halted, // pmu/fw halted
49 118 : input logic internal_dbg_halt_timers, // debug halted
50 :
51 : `ifdef RV_SMEPMP
52 2 : input el2_mseccfg_pkt_t mseccfg,
53 : `endif
54 :
55 262 : output logic [31:0] dec_pmp_rddata_d, // pmp CSR read data
56 1738 : output logic dec_pmp_read_d, // pmp CSR address match
57 :
58 0 : output el2_pmp_cfg_pkt_t pmp_pmpcfg [pt.PMP_ENTRIES],
59 : output logic [31:0] pmp_pmpaddr [pt.PMP_ENTRIES],
60 :
61 0 : input logic scan_mode
62 : );
63 :
64 500 : logic wr_pmpcfg_r;
65 94 : logic [3:0] wr_pmpcfg_group;
66 :
67 544 : logic wr_pmpaddr0_sel;
68 0 : logic wr_pmpaddr16_sel;
69 0 : logic wr_pmpaddr32_sel;
70 0 : logic wr_pmpaddr48_sel;
71 544 : logic wr_pmpaddr_r;
72 0 : logic [1:0] wr_pmpaddr_quarter;
73 0 : logic [5:0] wr_pmpaddr_address;
74 :
75 322 : logic [3:0] pmp_quarter_rdaddr;
76 354 : logic [31:0] pmp_pmpcfg_rddata;
77 :
78 : // ----------------------------------------------------------------------
79 :
80 0 : logic [pt.PMP_ENTRIES-1:0] entry_lock_eff; // Effective entry lock
81 : for (genvar r = 0; r < pt.PMP_ENTRIES; r++) begin : g_pmpcfg_lock
82 : `ifdef RV_SMEPMP
83 : // Smepmp allow modifying locked entries when mseccfg.RLB is set
84 : assign entry_lock_eff[r] = pmp_pmpcfg[r].lock & ~mseccfg.RLB;
85 : `else
86 : assign entry_lock_eff[r] = pmp_pmpcfg[r].lock;
87 : `endif
88 : end
89 :
90 : // ----------------------------------------------------------------------
91 : // PMPCFGx (RW)
92 : // [31:24] : PMP entry (x*4 + 3) configuration
93 : // [23:16] : PMP entry (x*4 + 2) configuration
94 : // [15:8] : PMP entry (x*4 + 1) configuration
95 : // [7:0] : PMP entry (x*4 + 0) configuration
96 :
97 : localparam PMPCFG = 12'h3a0;
98 :
99 : assign wr_pmpcfg_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:4] == PMPCFG[11:4]);
100 : assign wr_pmpcfg_group = dec_csr_wraddr_r[3:0]; // selects group of 4 pmpcfg entries (group 1 -> entries 4-7; up to 16 groups)
101 :
102 : for (genvar entry_idx = 0; entry_idx < pt.PMP_ENTRIES; entry_idx++) begin : gen_pmpcfg_ff
103 : logic [7:0] raw_wdata;
104 : logic [7:0] csr_wdata;
105 :
106 : // PMPCFG fields are WARL. Mask out bits 6:5 during write.
107 : // When Smepmp is disabled R=0 and W=1 combination is illegal mask out W
108 : // when R is cleared.
109 : assign raw_wdata = dec_csr_wrdata_r[(entry_idx[1:0]*8)+7:(entry_idx[1:0]*8)+0];
110 : `ifdef RV_SMEPMP
111 : assign csr_wdata = raw_wdata & 8'b10011111;
112 : `else
113 : assign csr_wdata = (raw_wdata & 8'b00000001) ? (raw_wdata & 8'b10011111) : (raw_wdata & 8'b10011101);
114 : `endif
115 :
116 : rvdffe #(8) pmpcfg_ff (.*, .clk(free_l2clk),
117 : .en(wr_pmpcfg_r & (wr_pmpcfg_group == entry_idx[5:2]) & (~entry_lock_eff[entry_idx])),
118 : .din(csr_wdata),
119 : .dout(pmp_pmpcfg[entry_idx]));
120 : end
121 :
122 : // ----------------------------------------------------------------------
123 : // PMPADDRx (RW)
124 : // [31:0] : PMP entry (x) address selector (word addressing)
125 : //
126 : // NOTE: VeeR-EL2 uses 32-bit physical addressing, register bits 31:30 mapping
127 : // to bits 33:32 of the physical address are always set to 0. (WARL)
128 :
129 : localparam PMPADDR0 = 12'h3b0;
130 : localparam PMPADDR16 = 12'h3c0;
131 : localparam PMPADDR32 = 12'h3d0;
132 : localparam PMPADDR48 = 12'h3e0;
133 :
134 : assign wr_pmpaddr0_sel = dec_csr_wraddr_r[11:4] == PMPADDR0[11:4];
135 : assign wr_pmpaddr16_sel = dec_csr_wraddr_r[11:4] == PMPADDR16[11:4];
136 : assign wr_pmpaddr32_sel = dec_csr_wraddr_r[11:4] == PMPADDR32[11:4];
137 : assign wr_pmpaddr48_sel = dec_csr_wraddr_r[11:4] == PMPADDR48[11:4];
138 : assign wr_pmpaddr_r = dec_csr_wen_r_mod & (wr_pmpaddr0_sel | wr_pmpaddr16_sel | wr_pmpaddr32_sel | wr_pmpaddr48_sel);
139 :
140 : assign wr_pmpaddr_quarter[0] = wr_pmpaddr16_sel | wr_pmpaddr48_sel;
141 : assign wr_pmpaddr_quarter[1] = wr_pmpaddr32_sel | wr_pmpaddr48_sel;
142 : assign wr_pmpaddr_address = {wr_pmpaddr_quarter, dec_csr_wraddr_r[3:0]}; // entry address
143 :
144 : for (genvar entry_idx = 0; entry_idx < pt.PMP_ENTRIES; entry_idx++) begin : gen_pmpaddr_ff
145 : logic pmpaddr_lock;
146 : logic pmpaddr_lock_next;
147 : if (entry_idx+1 < pt.PMP_ENTRIES)
148 : assign pmpaddr_lock_next = entry_lock_eff[entry_idx+1] & pmp_pmpcfg[entry_idx+1].mode == TOR;
149 : else
150 : assign pmpaddr_lock_next = 1'b0;
151 : assign pmpaddr_lock = entry_lock_eff[entry_idx] | pmpaddr_lock_next;
152 : assign pmp_pmpaddr[entry_idx][31:30] = 2'b00;
153 : rvdffe #(30) pmpaddr_ff (.*, .clk(free_l2clk),
154 : .en(wr_pmpaddr_r & (wr_pmpaddr_address == entry_idx)
155 : & (~pmpaddr_lock)),
156 : .din(dec_csr_wrdata_r[29:0]),
157 : .dout(pmp_pmpaddr[entry_idx][29:0]));
158 : end
159 :
160 : // CSR read mux
161 :
162 : assign pmp_quarter_rdaddr = dec_csr_rdaddr_d[3:0];
163 : assign pmp_pmpcfg_rddata = { pmp_pmpcfg[{pmp_quarter_rdaddr, 2'h3}],
164 : pmp_pmpcfg[{pmp_quarter_rdaddr, 2'h2}],
165 : pmp_pmpcfg[{pmp_quarter_rdaddr, 2'h1}],
166 : pmp_pmpcfg[{pmp_quarter_rdaddr, 2'h0}]
167 : };
168 : assign dec_pmp_read_d = csr_pmpcfg | csr_pmpaddr0 | csr_pmpaddr16 | csr_pmpaddr32 | csr_pmpaddr48;
169 : assign dec_pmp_rddata_d[31:0] = ( ({32{csr_pmpcfg}} & pmp_pmpcfg_rddata) |
170 : ({32{csr_pmpaddr0}} & pmp_pmpaddr[{2'h0, pmp_quarter_rdaddr}]) |
171 : ({32{csr_pmpaddr16}} & pmp_pmpaddr[{2'h1, pmp_quarter_rdaddr}]) |
172 : ({32{csr_pmpaddr32}} & pmp_pmpaddr[{2'h2, pmp_quarter_rdaddr}]) |
173 : ({32{csr_pmpaddr48}} & pmp_pmpaddr[{2'h3, pmp_quarter_rdaddr}])
174 : );
175 :
176 : endmodule // dec_pmp_ctl
|