Skip to content

Commit

Permalink
Merge pull request #119 from antmicro/pmp
Browse files Browse the repository at this point in the history
Physical Memory Protection unit
  • Loading branch information
tmichalak authored Oct 10, 2023
2 parents 3cd9d9d + afbf4d0 commit d0e9a66
Show file tree
Hide file tree
Showing 42 changed files with 2,628 additions and 468 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test-regression.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
test: ["hello_world", "hello_world_dccm", "hello_world_iccm", "cmark", "cmark_dccm", "cmark_iccm", "dhry"]
test: ["hello_world", "hello_world_dccm", "hello_world_iccm", "cmark", "cmark_dccm", "cmark_iccm", "dhry", "pmp"]
coverage: ["branch", "toggle"] #TODO: add functional coverage
env:
DEBIAN_FRONTEND: "noninteractive"
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/test-uarch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ jobs:
- "block/iccm"
- "block/dccm"
- "block/lib_axi4_to_ahb"
- "block/pmp"
env:
CCACHE_DIR: "/opt/verification/.cache/"
VERILATOR_VERSION: v5.010
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ obj_dir
*.log
*.exe
*.swp
*.sym
verilator-build
program.hex
snapshots
__pycache__
sim_build
sim-build*
venv
results.xml
verification/sim
verilator-cocotb-build
*.dat
*.xml
*.json
20 changes: 14 additions & 6 deletions configs/veer.config
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ Parameters that can be set by the end user:
if 1, minimize clock-gating to facilitate FPGA builds
-text_in_iccm = {0, 1}
Don't add ICCM preload code in generated link.ld
-set=pmp_entries = {0, 1, ..., 64 }
number of PMP entries
Additionally the following may be set for bus masters and slaves using the -set=var=value option:
Expand Down Expand Up @@ -266,6 +268,7 @@ my $text_in_iccm = 0;

my $lsu2dma = 0;

my $pmp_entries=16;

$ret_stack_size=8;
$btb_enable=1;
Expand Down Expand Up @@ -815,13 +818,15 @@ my @perf_events = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
45, 46, 47, 48, 49, 50, 54, 55, 56,
512, 513, 514, 515, 516);

foreach my $i (0 .. 3) {
$csr{"pmpcfg$i"} = { "exists" => "false" };
}
# FIXME: PMP CSR handling

foreach my $i (0 .. 15) {
$csr{"pmpaddr$i"} = { "exists" => "false" };
}
#foreach my $i (0 .. 3) {
# $csr{"pmpcfg$i"} = { "exists" => "false" };
#}

#foreach my $i (0 .. 15) {
# $csr{"pmpaddr$i"} = { "exists" => "false" };
#}

# }}}
# Main config hash, with default values
Expand Down Expand Up @@ -1035,6 +1040,7 @@ our %config = (#{{{
"SDVT_AHB" => "$ahb",
},
"protection" => { # Design parms, Overridable - static MPU
"pmp_entries" => "$pmp_entries",
"inst_access_enable0" => "0x0",
"inst_access_addr0" => "0x00000000",
"inst_access_mask0" => "0xffffffff",
Expand Down Expand Up @@ -1134,6 +1140,7 @@ our %verilog_parms = (
"bitmanip_zbr" => '1',
"fast_interrupt_redirect" => '1',

"pmp_entries" => '7',
"inst_access_enable0" => '1',
"inst_access_addr0" => '32',
"inst_access_mask0" => '32',
Expand Down Expand Up @@ -1357,6 +1364,7 @@ if ($config{core}{div_new}==0 && $config{core}{div_bit}!=1) {
die("$helpusage\n\nFAIL: div_new=0 requires div_bit=1 ILLEGAL !!!\n\n");
}

$c=$config{protection}{pmp_entries}; if (!($c==64 || $c==16 || $c==0)) { die("$helpusage\n\nFAIL: pmp_entries must be either 0, 16 or 64 !!!\n\n"); }
$c=$config{protection}{inst_access_addr0}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: inst_access_addr0 lower 6b must be 0s $c !!!\n\n"); }
$c=$config{protection}{inst_access_addr1}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: inst_access_addr1 lower 6b must be 0s !!!\n\n"); }
$c=$config{protection}{inst_access_addr2}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: inst_access_addr2 lower 6b must be 0s !!!\n\n"); }
Expand Down
16 changes: 16 additions & 0 deletions design/dec/csrdecode
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ csr_perfvi = [00110011....]
csr_mcountinhibit = [001100100000]
csr_mfdht = [011111001110]
csr_mfdhs = [011111001111]
csr_pmpcfg = [00111010....]
csr_pmpaddr0 = [00111011....]
csr_pmpaddr16 = [00111100....]
csr_pmpaddr32 = [00111101....]
csr_pmpaddr48 = [00111110....]

.input

Expand Down Expand Up @@ -171,6 +176,11 @@ csr_dicad0h
csr_dicad0
csr_dicad1
csr_dicago
csr_pmpcfg
csr_pmpaddr0
csr_pmpaddr16
csr_pmpaddr32
csr_pmpaddr48
valid_only
presync
postsync
Expand Down Expand Up @@ -256,4 +266,10 @@ csr[ csr_perfvg ] = { valid_only }
csr[ csr_perfvh ] = { valid_only }
csr[ csr_perfvi ] = { valid_only }

csr[ csr_pmpcfg ] = { csr_pmpcfg }
csr[ csr_pmpaddr0 ] = { csr_pmpaddr0 }
csr[ csr_pmpaddr16 ] = { csr_pmpaddr16 }
csr[ csr_pmpaddr32 ] = { csr_pmpaddr32 }
csr[ csr_pmpaddr48 ] = { csr_pmpaddr48 }

.end
603 changes: 308 additions & 295 deletions design/dec/el2_dec.sv

Large diffs are not rendered by default.

148 changes: 148 additions & 0 deletions design/dec/el2_dec_pmp_ctl.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2023 Antmicro <www.antmicro.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


//********************************************************************************
// el2_dec_pmp_ctl.sv
//
//
// Function: Physical Memory Protection CSRs
// Comments:
//
//********************************************************************************


module el2_dec_pmp_ctl
import el2_pkg::*;
#(
`include "el2_param.vh"
)
(
input logic clk,
input logic free_l2clk,
input logic csr_wr_clk,
input logic rst_l,
input logic dec_csr_wen_r_mod, // csr write enable at wb
input logic [11:0] dec_csr_wraddr_r, // write address for csr
input logic [31:0] dec_csr_wrdata_r, // csr write data at wb
input logic [11:0] dec_csr_rdaddr_d, // read address for csr

input logic csr_pmpcfg,
input logic csr_pmpaddr0,
input logic csr_pmpaddr16,
input logic csr_pmpaddr32,
input logic csr_pmpaddr48,

input logic dec_pause_state, // Paused
input logic dec_tlu_pmu_fw_halted, // pmu/fw halted
input logic internal_dbg_halt_timers, // debug halted

output logic [31:0] dec_pmp_rddata_d, // pmp CSR read data
output logic dec_pmp_read_d, // pmp CSR address match

output el2_pmp_cfg_pkt_t pmp_pmpcfg [pt.PMP_ENTRIES],
output logic [31:0] pmp_pmpaddr [pt.PMP_ENTRIES],

input logic scan_mode
);

logic wr_pmpcfg_r;
logic [3:0] wr_pmpcfg_group;

logic wr_pmpaddr0_sel;
logic wr_pmpaddr16_sel;
logic wr_pmpaddr32_sel;
logic wr_pmpaddr48_sel;
logic wr_pmpaddr_r;
logic [1:0] wr_pmpaddr_quarter;
logic [5:0] wr_pmpaddr_address;

logic [3:0] pmp_quarter_rdaddr;
logic [31:0] pmp_pmpcfg_rddata;

// ----------------------------------------------------------------------
// PMPCFGx (RW)
// [31:24] : PMP entry (x*4 + 3) configuration
// [23:16] : PMP entry (x*4 + 2) configuration
// [15:8] : PMP entry (x*4 + 1) configuration
// [7:0] : PMP entry (x*4 + 0) configuration

localparam PMPCFG = 12'h3a0;

assign wr_pmpcfg_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:4] == PMPCFG[11:4]);
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)

for (genvar entry_idx = 0; entry_idx < pt.PMP_ENTRIES; entry_idx++) begin : gen_pmpcfg_ff
rvdffe #(8) pmpcfg_ff (.*, .clk(free_l2clk),
.en(wr_pmpcfg_r & (wr_pmpcfg_group == entry_idx[5:2]) & (~pmp_pmpcfg[entry_idx].lock)),
.din(dec_csr_wrdata_r[(entry_idx[1:0]*8)+7:(entry_idx[1:0]*8)+0] & 8'b10011111),
.dout(pmp_pmpcfg[entry_idx]));
end

// ----------------------------------------------------------------------
// PMPADDRx (RW)
// [31:0] : PMP entry (x) address selector (word addressing)
//
// NOTE: VeeR-EL2 uses 32-bit physical addressing, register bits 31:30 mapping
// to bits 33:32 of the physical address are always set to 0. (WARL)

localparam PMPADDR0 = 12'h3b0;
localparam PMPADDR16 = 12'h3c0;
localparam PMPADDR32 = 12'h3d0;
localparam PMPADDR48 = 12'h3e0;

assign wr_pmpaddr0_sel = dec_csr_wraddr_r[11:4] == PMPADDR0[11:4];
assign wr_pmpaddr16_sel = dec_csr_wraddr_r[11:4] == PMPADDR16[11:4];
assign wr_pmpaddr32_sel = dec_csr_wraddr_r[11:4] == PMPADDR32[11:4];
assign wr_pmpaddr48_sel = dec_csr_wraddr_r[11:4] == PMPADDR48[11:4];
assign wr_pmpaddr_r = dec_csr_wen_r_mod & (wr_pmpaddr0_sel | wr_pmpaddr16_sel | wr_pmpaddr32_sel | wr_pmpaddr48_sel);

assign wr_pmpaddr_quarter[0] = wr_pmpaddr16_sel | wr_pmpaddr48_sel;
assign wr_pmpaddr_quarter[1] = wr_pmpaddr32_sel | wr_pmpaddr48_sel;
assign wr_pmpaddr_address = {wr_pmpaddr_quarter, dec_csr_wraddr_r[3:0]}; // entry address

for (genvar entry_idx = 0; entry_idx < pt.PMP_ENTRIES; entry_idx++) begin : gen_pmpaddr_ff
logic pmpaddr_lock;
logic pmpaddr_lock_next;
assign pmpaddr_lock_next = ((entry_idx+1 < pt.PMP_ENTRIES)
? (pmp_pmpcfg[entry_idx+1].lock
& pmp_pmpcfg[entry_idx+1].mode == TOR)
: 1'b0);
assign pmpaddr_lock = pmp_pmpcfg[entry_idx].lock | pmpaddr_lock_next;
assign pmp_pmpaddr[entry_idx][31:30] = 2'b00;
rvdffe #(30) pmpaddr_ff (.*, .clk(free_l2clk),
.en(wr_pmpaddr_r & (wr_pmpaddr_address == entry_idx)
& (~pmpaddr_lock)),
.din(dec_csr_wrdata_r[29:0]),
.dout(pmp_pmpaddr[entry_idx][29:0]));
end

// CSR read mux

assign pmp_quarter_rdaddr = dec_csr_rdaddr_d[3:0];
assign pmp_pmpcfg_rddata = { pmp_pmpcfg[{pmp_quarter_rdaddr, 2'h3}],
pmp_pmpcfg[{pmp_quarter_rdaddr, 2'h2}],
pmp_pmpcfg[{pmp_quarter_rdaddr, 2'h1}],
pmp_pmpcfg[{pmp_quarter_rdaddr, 2'h0}]
};
assign dec_pmp_read_d = csr_pmpcfg | csr_pmpaddr0 | csr_pmpaddr16 | csr_pmpaddr32 | csr_pmpaddr48;
assign dec_pmp_rddata_d[31:0] = ( ({32{csr_pmpcfg}} & pmp_pmpcfg_rddata) |
({32{csr_pmpaddr0}} & pmp_pmpaddr[{2'h0, pmp_quarter_rdaddr}]) |
({32{csr_pmpaddr16}} & pmp_pmpaddr[{2'h1, pmp_quarter_rdaddr}]) |
({32{csr_pmpaddr32}} & pmp_pmpaddr[{2'h2, pmp_quarter_rdaddr}]) |
({32{csr_pmpaddr48}} & pmp_pmpaddr[{2'h3, pmp_quarter_rdaddr}])
);

endmodule // dec_pmp_ctl
Loading

0 comments on commit d0e9a66

Please sign in to comment.