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 69840565 : input logic clk,
33 69840565 : input logic free_l2clk,
34 69840565 : input logic csr_wr_clk,
35 338 : input logic rst_l,
36 42288 : 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 1000 : 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 120 : 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 : // Excluding scan_mode from coverage as its usage is determined by the integrator of the VeeR core.
62 : /*verilator coverage_off*/
63 : input logic scan_mode
64 : /*verilator coverage_on*/
65 : );
66 :
67 500 : logic wr_pmpcfg_r;
68 100 : logic [3:0] wr_pmpcfg_group;
69 :
70 544 : logic wr_pmpaddr0_sel;
71 0 : logic wr_pmpaddr16_sel;
72 0 : logic wr_pmpaddr32_sel;
73 0 : logic wr_pmpaddr48_sel;
74 544 : logic wr_pmpaddr_r;
75 0 : logic [1:0] wr_pmpaddr_quarter;
76 0 : logic [5:0] wr_pmpaddr_address;
77 :
78 334 : logic [3:0] pmp_quarter_rdaddr;
79 354 : logic [31:0] pmp_pmpcfg_rddata;
80 :
81 : // ----------------------------------------------------------------------
82 :
83 0 : logic [pt.PMP_ENTRIES-1:0] entry_lock_eff; // Effective entry lock
84 : for (genvar r = 0; r < pt.PMP_ENTRIES; r++) begin : g_pmpcfg_lock
85 : `ifdef RV_SMEPMP
86 : // Smepmp allow modifying locked entries when mseccfg.RLB is set
87 : assign entry_lock_eff[r] = pmp_pmpcfg[r].lock & ~mseccfg.RLB;
88 : `else
89 : assign entry_lock_eff[r] = pmp_pmpcfg[r].lock;
90 : `endif
91 : end
92 :
93 : // ----------------------------------------------------------------------
94 : // PMPCFGx (RW)
95 : // [31:24] : PMP entry (x*4 + 3) configuration
96 : // [23:16] : PMP entry (x*4 + 2) configuration
97 : // [15:8] : PMP entry (x*4 + 1) configuration
98 : // [7:0] : PMP entry (x*4 + 0) configuration
99 :
100 : localparam PMPCFG = 12'h3a0;
101 :
102 : assign wr_pmpcfg_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:4] == PMPCFG[11:4]);
103 : 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)
104 :
105 : for (genvar entry_idx = 0; entry_idx < pt.PMP_ENTRIES; entry_idx++) begin : gen_pmpcfg_ff
106 : logic [7:0] raw_wdata;
107 : logic [7:0] csr_wdata;
108 :
109 : // PMPCFG fields are WARL. Mask out bits 6:5 during write.
110 : // When Smepmp is disabled R=0 and W=1 combination is illegal mask out W
111 : // when R is cleared.
112 : assign raw_wdata = dec_csr_wrdata_r[(entry_idx[1:0]*8)+7:(entry_idx[1:0]*8)+0];
113 : `ifdef RV_SMEPMP
114 : assign csr_wdata = raw_wdata & 8'b10011111;
115 : `else
116 : assign csr_wdata = raw_wdata[0] ? (raw_wdata & 8'b10011111) : (raw_wdata & 8'b10011101);
117 : `endif
118 :
119 : rvdffe #(8) pmpcfg_ff (.*, .clk(free_l2clk),
120 : .en(wr_pmpcfg_r & (wr_pmpcfg_group == entry_idx[5:2]) & (~entry_lock_eff[entry_idx])),
121 : .din(csr_wdata),
122 : .dout(pmp_pmpcfg[entry_idx]));
123 : end
124 :
125 : // ----------------------------------------------------------------------
126 : // PMPADDRx (RW)
127 : // [31:0] : PMP entry (x) address selector (word addressing)
128 : //
129 : // NOTE: VeeR-EL2 uses 32-bit physical addressing, register bits 31:30 mapping
130 : // to bits 33:32 of the physical address are always set to 0. (WARL)
131 :
132 : localparam PMPADDR0 = 12'h3b0;
133 : localparam PMPADDR16 = 12'h3c0;
134 : localparam PMPADDR32 = 12'h3d0;
135 : localparam PMPADDR48 = 12'h3e0;
136 :
137 : assign wr_pmpaddr0_sel = dec_csr_wraddr_r[11:4] == PMPADDR0[11:4];
138 : assign wr_pmpaddr16_sel = dec_csr_wraddr_r[11:4] == PMPADDR16[11:4];
139 : assign wr_pmpaddr32_sel = dec_csr_wraddr_r[11:4] == PMPADDR32[11:4];
140 : assign wr_pmpaddr48_sel = dec_csr_wraddr_r[11:4] == PMPADDR48[11:4];
141 : assign wr_pmpaddr_r = dec_csr_wen_r_mod & (wr_pmpaddr0_sel | wr_pmpaddr16_sel | wr_pmpaddr32_sel | wr_pmpaddr48_sel);
142 :
143 : assign wr_pmpaddr_quarter[0] = wr_pmpaddr16_sel | wr_pmpaddr48_sel;
144 : assign wr_pmpaddr_quarter[1] = wr_pmpaddr32_sel | wr_pmpaddr48_sel;
145 : assign wr_pmpaddr_address = {wr_pmpaddr_quarter, dec_csr_wraddr_r[3:0]}; // entry address
146 :
147 : for (genvar entry_idx = 0; entry_idx < pt.PMP_ENTRIES; entry_idx++) begin : gen_pmpaddr_ff
148 : logic pmpaddr_lock;
149 : logic pmpaddr_lock_next;
150 : if (entry_idx+1 < pt.PMP_ENTRIES)
151 : assign pmpaddr_lock_next = entry_lock_eff[entry_idx+1] & pmp_pmpcfg[entry_idx+1].mode == TOR;
152 : else
153 : assign pmpaddr_lock_next = 1'b0;
154 : assign pmpaddr_lock = entry_lock_eff[entry_idx] | pmpaddr_lock_next;
155 : assign pmp_pmpaddr[entry_idx][31:30] = 2'b00;
156 : rvdffe #(30) pmpaddr_ff (.*, .clk(free_l2clk),
157 : .en(wr_pmpaddr_r & (wr_pmpaddr_address == entry_idx)
158 : & (~pmpaddr_lock)),
159 : .din(dec_csr_wrdata_r[29:0]),
160 : .dout(pmp_pmpaddr[entry_idx][29:0]));
161 : end
162 :
163 : // CSR read mux
164 :
165 : assign pmp_quarter_rdaddr = dec_csr_rdaddr_d[3:0];
166 : assign pmp_pmpcfg_rddata = { pmp_pmpcfg[{pmp_quarter_rdaddr, 2'h3}],
167 : pmp_pmpcfg[{pmp_quarter_rdaddr, 2'h2}],
168 : pmp_pmpcfg[{pmp_quarter_rdaddr, 2'h1}],
169 : pmp_pmpcfg[{pmp_quarter_rdaddr, 2'h0}]
170 : };
171 : assign dec_pmp_read_d = csr_pmpcfg | csr_pmpaddr0 | csr_pmpaddr16 | csr_pmpaddr32 | csr_pmpaddr48;
172 : assign dec_pmp_rddata_d[31:0] = ( ({32{csr_pmpcfg}} & pmp_pmpcfg_rddata) |
173 : ({32{csr_pmpaddr0}} & pmp_pmpaddr[{2'h0, pmp_quarter_rdaddr}]) |
174 : ({32{csr_pmpaddr16}} & pmp_pmpaddr[{2'h1, pmp_quarter_rdaddr}]) |
175 : ({32{csr_pmpaddr32}} & pmp_pmpaddr[{2'h2, pmp_quarter_rdaddr}]) |
176 : ({32{csr_pmpaddr48}} & pmp_pmpaddr[{2'h3, pmp_quarter_rdaddr}])
177 : );
178 :
179 : endmodule // dec_pmp_ctl
|