diff --git a/Makefile b/Makefile index 3e84e6891d42afdd1025cdaaa8ed40f77b0e528a..48269dde4fae4c4a58aafa552b66b647f038296b 100644 --- a/Makefile +++ b/Makefile @@ -81,7 +81,6 @@ ariane_pkg := include/riscv_pkg.sv \ include/axi_intf.sv \ tb/ariane_soc_pkg.sv \ include/ariane_axi_pkg.sv \ - src/pmp/include/pmp_pkg.sv \ src/fpu/src/fpnew_pkg.sv \ src/fpu/src/fpu_div_sqrt_mvp/hdl/defs_div_sqrt_mvp.sv ariane_pkg := $(addprefix $(root-dir), $(ariane_pkg)) diff --git a/include/riscv_pkg.sv b/include/riscv_pkg.sv index 3799734e8e879a5c0b1659ce1123a02b9c19682e..db864f4a567baf8966dbf8711d23be6ee608a30b 100644 --- a/include/riscv_pkg.sv +++ b/include/riscv_pkg.sv @@ -528,20 +528,33 @@ package riscv; } fcsr_t; // PMP - typedef enum logic [1:0] { - OFF = 2'b00, - TOR = 2'b01, - NA4 = 2'b10, - NAPOT = 2'b11 + typedef enum logic [1:0] { + OFF = 2'b00, + TOR = 2'b01, + NA4 = 2'b10, + NAPOT = 2'b11 } pmp_addr_mode_t; + + // PMP Access Type + typedef enum logic [2:0] { + ACCESS_NONE = 3'b000, + ACCESS_READ = 3'b001, + ACCESS_WRITE = 3'b010, + ACCESS_EXEC = 3'b100 + } pmp_access_t; + + typedef struct packed { + logic x; + logic w; + logic r; + } pmpcfg_access_t; + // packed struct of a PMP configuration register (8bit) typedef struct packed { bit locked; // lock this configuration logic [1:0] reserved; pmp_addr_mode_t addr_mode; // Off, TOR, NA4, NAPOT - logic x; // execute - logic w; // write - logic r; // read + pmpcfg_access_t access_type; } pmpcfg_t; // ----- diff --git a/src/pmp b/src/pmp deleted file mode 120000 index 2ae9b9f6906d3cdf387a0364d9aaadcaacafada4..0000000000000000000000000000000000000000 --- a/src/pmp +++ /dev/null @@ -1 +0,0 @@ -/home/mo/Documents/mixedcriticality/code/iopmp \ No newline at end of file diff --git a/src/pmp/.gitignore b/src/pmp/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b255355662125d4c03559b37376f367c0a3d524e --- /dev/null +++ b/src/pmp/.gitignore @@ -0,0 +1,85 @@ +cockpit + +# Created by https://www.gitignore.io/api/modelsim,visualstudiocode +# Edit at https://www.gitignore.io/?templates=modelsim,visualstudiocode + +### ModelSim ### +# ignore ModelSim generated files and directories (temp files and so on) +[_@]* + +# ignore compilation output of ModelSim +*.mti +*.dat +*.dbs +*.psm +*.bak +*.cmp +*.jpg +*.html +*.bsf + +# ignore simulation output of ModelSim +wlf* +*.wlf +*.vstf +*.ucdb +cov*/ +transcript* +sc_dpiheader.h +vsim.dbg +modelsim.ini + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +# Created by https://www.gitignore.io/api/synopsysvcs +# Edit at https://www.gitignore.io/?templates=synopsysvcs + +### SynopsysVCS ### +# Waveform formats +*.vcd +*.vpd +*.evcd +*.fsdb + +# Default name of the simulation executable. A different name can be +# specified with this switch (the associated daidir database name is +# also taken from here): -o <path>/<filename> +simv + +# Generated for Verilog and VHDL top configs +simv.daidir/ +simv.db.dir/ + +# Infrastructure necessary to co-simulate SystemC models with +# Verilog/VHDL models. An alternate directory may be specified with this +# switch: -Mdir=<directory_path> +csrc/ + +# Log file - the following switch allows to specify the file that will be +# used to write all messages from simulation: -l <filename> +*.log + +# Coverage results (generated with urg) and database location. The +# following switch can also be used: urg -dir <coverage_directory>.vdb +simv.vdb/ +urgReport/ + +# DVE and UCLI related files. +DVEfiles/ +ucli.key + +# When the design is elaborated for DirectC, the following file is created +# with declarations for C/C++ functions. +vc_hdrs.h + +# End of https://www.gitignore.io/api/modelsim,visualstudiocode + diff --git a/src/pmp/Bender.yml b/src/pmp/Bender.yml new file mode 100644 index 0000000000000000000000000000000000000000..7fede43330d72ab876f47265112df6e329ec8e93 --- /dev/null +++ b/src/pmp/Bender.yml @@ -0,0 +1,24 @@ +package: + name: pmp + authors: + - "Moritz Schneider <moritz.schneider@inf.ethz.ch>" + +export_include_dirs: + - include + +sources: + # packages + - include/pmp_pkg.sv + # sources + - src/napot_extract.sv + - src/pmp_napot_entry.sv + - src/pmp_tor_entry.sv + - src/pmp_na4_entry.sv + - src/pmp_entry.sv + - src/pmp.sv + + - target: simulation + files: + - tb/pmp_napot_entry_tb.sv + - tb/pmp_tor_entry_tb.sv + - tb/pmp_tb.sv \ No newline at end of file diff --git a/src/pmp/Makefile b/src/pmp/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3e6d38f5639912e3293c97e7e96c16a413d048aa --- /dev/null +++ b/src/pmp/Makefile @@ -0,0 +1,31 @@ +# questa library +library ?= work +# Top level module to compile +top_level ?= pmp_tb +# QuestaSim Version +questa_version ?= 10.7b + +compile_flags = +cover -incr -64 -permissive +sim_flags = -t 1ps -debugdb -voptargs="+acc" -do "run -all; quit" + +src = $(wildcard src/*.sv) +inc = $(wildcard include/*.sv) +tb = $(wildcard tb/*.sv) + +compile-sim: + rm -rf ${library} + vlog-${questa_version} -work ${library} ${compile_flags} ${inc} + vlog-${questa_version} -work ${library} ${compile_flags} ${src} + vlog-${questa_version} -work ${library} ${compile_flags} ${tb} + +sim: compile-sim + vsim-${questa_version} -c -work ${library} ${sim_flags} ${top_level} + +sim-gui: + rm -rf ${library} + vlog-${questa_version} -work ${library} ${compile_flags} ${src} + vlog-${questa_version} -work ${library} ${compile_flags} ${tb} + vsim-${questa_version} -work ${library} ${sim_flags} ${top_level} + +clean: + @rm -rf ${library} transcript vsim.dbg vsim.wlf \ No newline at end of file diff --git a/src/pmp/README.md b/src/pmp/README.md new file mode 100644 index 0000000000000000000000000000000000000000..e48445b5c9c12f7527de8d390fe2f8705acf693e --- /dev/null +++ b/src/pmp/README.md @@ -0,0 +1,3 @@ +# PMP + +This repository houses a purely combinatorial and parametrizable physical memory protection (PMP) unit. \ No newline at end of file diff --git a/src/pmp/formal.sby b/src/pmp/formal.sby new file mode 100644 index 0000000000000000000000000000000000000000..28c822eb9a558a1d8b5b525994af94807c04930b --- /dev/null +++ b/src/pmp/formal.sby @@ -0,0 +1,31 @@ +[options] +mode prove +depth 20 + +[engines] +smtbmc boolector +smtbmc z3 +smtbmc yices + +[script] +verific -vlog-incdir ./include +verific -sv -DFORMAL \ + pmp_pkg.sv \ + napot_extract.sv \ + pmp_napot_entry.sv \ + pmp_tor_entry.sv \ + pmp_na4_entry.sv \ + pmp_entry.sv \ + pmp.sv + +verific -import -all pmp +prep -flatten -nordff -top pmp + +[files] +include/pmp_pkg.sv +src/napot_extract.sv +src/pmp_napot_entry.sv +src/pmp_tor_entry.sv +src/pmp_na4_entry.sv +src/pmp_entry.sv +src/pmp.sv diff --git a/src/pmp/scripts/dc_compile.tcl b/src/pmp/scripts/dc_compile.tcl new file mode 100644 index 0000000000000000000000000000000000000000..6ac2d039a69b8b906d59f40f93f559ca401aca41 --- /dev/null +++ b/src/pmp/scripts/dc_compile.tcl @@ -0,0 +1,41 @@ +# remove previous library +sh rm -rf WORK/* +remove_design -design + +# set multithreading +set disable_multicore_resource_checks true +set NumberThreads [exec cat /proc/cpuinfo | grep -c processor] +set_host_options -max_cores $NumberThreads + +# This script was generated automatically by bender. +set search_path_initial $search_path +set ROOT "/home/scmoritz/Documents/platformsec/iopmp" + +set search_path $search_path_initial +lappend search_path "$ROOT/include" + +analyze -format sv \ + [list \ + "$ROOT/include/pmp_pkg.sv" \ + "$ROOT/src/napot_extract.sv" \ + "$ROOT/src/pmp_napot_entry.sv" \ + "$ROOT/src/pmp_tor_entry.sv" \ + "$ROOT/src/pmp_na4_entry.sv" \ + "$ROOT/src/pmp_entry.sv" \ + "$ROOT/src/pmp.sv" \ + ] + +set search_path $search_path_initial + +elaborate pmp + +# Constraints +set_max_delay -to [all_outputs] 200 +set_max_area 0 +set_load 0.1 [all_outputs] +set_max_fanout 1 [all_inputs] +set_fanout_load 8 [all_outputs] + +compile_ultra + +report_timing \ No newline at end of file diff --git a/src/pmp/src/napot_extract.sv b/src/pmp/src/napot_extract.sv new file mode 100644 index 0000000000000000000000000000000000000000..ad175751330f3e21a572b32d870642b47b408169 --- /dev/null +++ b/src/pmp/src/napot_extract.sv @@ -0,0 +1,43 @@ +// Copyright 2019 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this 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. +// +// Author: Moritz Schneider, ETH Zurich +// Date: 2.10.2019 +// Description: NAPOT extract + +module napot_extract #( + parameter int unsigned PMP_LEN = 54 +) ( + input logic [PMP_LEN-1:0] conf_addr_i, + output int unsigned size_o +); + always_comb begin + int unsigned i; + for (i = 0; i < PMP_LEN; i++) begin + if (conf_addr_i[i] != 1'b1) begin + break; + end + end + size_o = i+3; + + `ifdef FORMAL + assert(size_o > 2); + if (size_o < PMP_LEN) begin + assert(conf_addr_i[size_o - 3] == 0); // check 0 bit that seperates the ones in the end + end + + for (i = 0; i < PMP_LEN; i++) begin + if (size_o > 3 && i <= size_o - 4) begin + assert(conf_addr_i[i] == 1); // check that all the rest are ones + end + end + `endif + end +endmodule \ No newline at end of file diff --git a/src/pmp/src/pmp.sv b/src/pmp/src/pmp.sv new file mode 100644 index 0000000000000000000000000000000000000000..af2e550ce418840577f4955dd7306784cf1177f9 --- /dev/null +++ b/src/pmp/src/pmp.sv @@ -0,0 +1,57 @@ +// Copyright 2019 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this 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. +// +// Author: Moritz Schneider, ETH Zurich +// Date: 2.10.2019 +// Description: purely combinatorial PMP unit (with extraction for more complex configs such as NAPOT) + +module pmp #( + parameter int unsigned XLEN = 32, // rv64: 64 + parameter int unsigned PMP_LEN = 32, // rv64: 54 + parameter int unsigned NR_ENTRIES = 4 +) ( + // Input + input logic [XLEN-1:0] addr_i, + input riscv::pmp_access_t access_type_i, + // Configuration + input logic [NR_ENTRIES-1:0][PMP_LEN-1:0] conf_addr_i, + input riscv::pmpcfg_t [NR_ENTRIES-1:0] conf_i, + // Output + output logic allow_o +); + logic [NR_ENTRIES-1:0] match; + + for (genvar i = 0; i < NR_ENTRIES; i++) begin + pmp_entry #( + .XLEN(XLEN), + .PMP_LEN(PMP_LEN) + ) i_pmp_entry( + .addr_i ( addr_i ), + .conf_addr_i ( conf_addr_i[i] ), + .conf_addr_prev_i ( i == 0 ? '0 : conf_addr_i[i-1] ), + .conf_addr_mode_i ( conf_i[i].addr_mode ), + .match_o ( match[i] ) + ); + end + + always_comb begin + allow_o = 1'b1; + if (access_type_i == 3'b000) begin + allow_o = 1'b0; + end else begin + for (int j = 0; j < NR_ENTRIES; j++) begin + if (match[j]) begin + if ((access_type_i & conf_i[j].access_type) != access_type_i) allow_o &= 1'b0; + else allow_o &= 1'b1; + end + end + end + end +endmodule diff --git a/src/pmp/src/pmp_entry.sv b/src/pmp/src/pmp_entry.sv new file mode 100644 index 0000000000000000000000000000000000000000..6ab15e91dcba536d768c2c8c02d1e44ed89e6f94 --- /dev/null +++ b/src/pmp/src/pmp_entry.sv @@ -0,0 +1,80 @@ +// Copyright 2019 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this 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. +// +// Author: Moritz Schneider, ETH Zurich +// Date: 2.10.2019 +// Description: single PMP entry + +module pmp_entry #( + parameter int unsigned XLEN = 64, + parameter int unsigned PMP_LEN = 54 +) ( + // Input + input logic [XLEN-1:0] addr_i, + + // Configuration + input logic [PMP_LEN-1:0] conf_addr_i, + input logic [PMP_LEN-1:0] conf_addr_prev_i, + input riscv::pmp_addr_mode_t conf_addr_mode_i, + + // Output + output logic match_o +); + logic [3:0] match; + + pmp_tor_entry #( + .XLEN(XLEN), + .PMP_LEN(PMP_LEN) + ) i_pmp_tor_entry( + .addr_i, + .conf_addr_lo_i (conf_addr_prev_i), + .conf_addr_hi_i (conf_addr_i ), + .match_o (match[riscv::TOR]) + ); + + pmp_na4_entry #( + .XLEN(XLEN), + .PMP_LEN(PMP_LEN) + ) i_pmp_na4_entry( + .addr_i, + .conf_addr_i, + .match_o (match[riscv::NA4]) + ); + + pmp_napot_entry #( + .XLEN(XLEN), + .PMP_LEN(PMP_LEN) + ) i_pmp_napot_entry( + .addr_i, + .conf_addr_i, + .match_o (match[riscv::NAPOT]) + ); + + assign match[riscv::OFF] = 0; + + always_comb begin + unique case (conf_addr_mode_i) + riscv::TOR: match_o = match[riscv::TOR]; + riscv::NA4: match_o = match[riscv::NA4]; + riscv::NAPOT: match_o = match[riscv::NAPOT]; + riscv::OFF: match_o = match[riscv::OFF]; + default: match_o = 0; + endcase + end + + `ifdef FORMAL + always @(*) begin + if(conf_addr_mode_i == riscv::OFF) begin + assert(match_o == '0); + end + end + `endif + +endmodule \ No newline at end of file diff --git a/src/pmp/src/pmp_na4_entry.sv b/src/pmp/src/pmp_na4_entry.sv new file mode 100644 index 0000000000000000000000000000000000000000..d0fd3f58574d26db2cbf9fe63bfa98de62e025c9 --- /dev/null +++ b/src/pmp/src/pmp_na4_entry.sv @@ -0,0 +1,57 @@ +// Copyright 2019 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this 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. +// +// Author: Moritz Schneider, ETH Zurich +// Date: 2.10.2019 +// Description: NA4 PMP entry + +module pmp_na4_entry #( + parameter int unsigned XLEN = 64, + parameter int unsigned PMP_LEN = 54 +) ( + input logic [XLEN-1:0] addr_i, + input logic [PMP_LEN-1:0] conf_addr_i, + + output logic match_o +); + always_comb begin + logic [XLEN-1:0] base; + logic [XLEN-1:0] padded_addr; + logic [XLEN-1:0] mask; + + mask = '1 << 2; + // pad the addr such that size_i lower bits are zero + padded_addr = addr_i & mask; + + base = (conf_addr_i << 2) & mask; + + if (padded_addr == base) begin + match_o = '1; + end else begin + match_o = '0; + end + + `ifdef FORMAL + if (base + 2**2 > base) begin // check for overflow + if (match_o == 0) begin + assert(addr_i >= base + 2**2 || addr_i < base); + end else begin + assert(addr_i < base + 2**2 && addr_i >= base); + end + end else begin + if (match_o == 0) begin + assert(addr_i - 2**2 >= base || addr_i < base); + end else begin + assert(addr_i - 2**2 < base && addr_i >= base); + end + end + `endif + end +endmodule \ No newline at end of file diff --git a/src/pmp/src/pmp_napot_entry.sv b/src/pmp/src/pmp_napot_entry.sv new file mode 100644 index 0000000000000000000000000000000000000000..f8145fb3beb5888c2b90cf161469c276f044f117 --- /dev/null +++ b/src/pmp/src/pmp_napot_entry.sv @@ -0,0 +1,71 @@ +// Copyright 2019 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this 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. +// +// Author: Moritz Schneider, ETH Zurich +// Date: 2.10.2019 +// Description: NAPOT PMP entry + +module pmp_napot_entry #( + parameter int unsigned XLEN = 64, + parameter int unsigned PMP_LEN = 54 +) ( + input logic [XLEN-1:0] addr_i, + input logic [PMP_LEN-1:0] conf_addr_i, + + output logic match_o +); + int unsigned size; + + napot_extract #(.PMP_LEN(PMP_LEN)) i_napot_extract ( + .conf_addr_i, + .size_o(size) + ); + + always_comb begin + logic [XLEN-1:0] padded_addr; + logic [XLEN-1:0] mask; + logic [XLEN-1:0] base; + + mask = '1 << size; + // pad the addr such that size_i lower bits are zero + padded_addr = addr_i & mask; + + base = (conf_addr_i << 2) & mask; + + if (padded_addr == base) begin + match_o = '1; + end else begin + match_o = '0; + end + + end + + `ifdef FORMAL + always @(*) begin + logic[XLEN-1:0] base_lo; + logic[XLEN:0] base_hi; + base_lo = (conf_addr_i << 2) & ('1 << size); + base_hi = base_lo + 2**size; + if (base_hi < base_lo) begin + base_hi = '1; + end + if (size < XLEN) begin + if (match_o == 0) begin + assert(addr_i >= base_hi || addr_i < base_lo); + end else begin + assert(addr_i < base_hi && addr_i >= base_lo); + end + end else begin + assert(match_o == 1); + end + end + `endif + +endmodule \ No newline at end of file diff --git a/src/pmp/src/pmp_tor_entry.sv b/src/pmp/src/pmp_tor_entry.sv new file mode 100644 index 0000000000000000000000000000000000000000..7e5b74499e04adf181a747fea7f0139a4573e34e --- /dev/null +++ b/src/pmp/src/pmp_tor_entry.sv @@ -0,0 +1,45 @@ +// Copyright 2019 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this 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. +// +// Author: Moritz Schneider, ETH Zurich +// Date: 2.10.2019 +// Description: TOR PMP entry + +module pmp_tor_entry #( + parameter int unsigned XLEN = 64, + parameter int unsigned PMP_LEN = 54 +) ( + input logic [XLEN-1:0] addr_i, + input logic [PMP_LEN-1:0] conf_addr_lo_i, + input logic [PMP_LEN-1:0] conf_addr_hi_i, + + output logic match_o +); + logic [XLEN-1:0] addr_lo, addr_hi; + assign addr_lo = conf_addr_lo_i << 2; + assign addr_hi = conf_addr_hi_i << 2; + always_comb begin + if (addr_i >= addr_lo && addr_i < addr_hi ) begin + match_o = '1; + end else begin + match_o = '0; + end + end + + `ifdef FORMAL + always @(*) begin + if (match_o == 0) begin + assert(addr_i >= addr_hi || addr_i < addr_lo); + end else begin + assert(addr_i < addr_hi || addr_i >= addr_lo); + end + end + `endif +endmodule \ No newline at end of file diff --git a/src/pmp/tb/pmp_napot_entry_tb.sv b/src/pmp/tb/pmp_napot_entry_tb.sv new file mode 100644 index 0000000000000000000000000000000000000000..c14f064e116f16cde08135fa1a51cb01eb6a98c7 --- /dev/null +++ b/src/pmp/tb/pmp_napot_entry_tb.sv @@ -0,0 +1,66 @@ +// Copyright 2019 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this 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. +// +// Author: Moritz Schneider, ETH Zurich +// Date: 2.10.2019 +// Description: + +import tb_pkg::*; + +module pmp_napot_entry_tb; + timeunit 1ns; + timeprecision 1ps; + + localparam int unsigned WIDTH = 16; + localparam int unsigned PMP_LEN = 13; + + logic[WIDTH-1:0] addr; + logic[WIDTH-1:0] base; + int unsigned size; + + logic[PMP_LEN-1:0] conf_addr; + + logic out; + + pmp_napot_entry #(.XLEN(WIDTH), .PMP_LEN(PMP_LEN)) + i_iopmp( + .addr_i(addr), + .conf_addr_i(conf_addr), + .match_o(out) + ); + + initial begin + addr = 16'b00011001_10111010; + base = 16'b00011001_10110000; + size = 4; + conf_addr = P#(.WIDTH(WIDTH), .PMP_LEN(PMP_LEN))::base_to_conf(base, size); + assert(conf_addr == 16'b00000110_01101101); + #5ns; + assert(out == 1); + addr = 16'b00011001_10110000; + base = 16'b00011001_10100000; + size = 4; + conf_addr = P#(.WIDTH(WIDTH), .PMP_LEN(PMP_LEN))::base_to_conf(base, size); + #5ns; + assert(out == 0); + addr = 16'b00011001_10111000; + base = 16'b00011001_10100000; + size = 5; + conf_addr = P#(.WIDTH(WIDTH), .PMP_LEN(PMP_LEN))::base_to_conf(base, size); + #5ns; + assert(out == 1); + addr = 16'b00011001_10111000; + base = 16'b00011001_10100000; + size = 6; + conf_addr = P#(.WIDTH(WIDTH), .PMP_LEN(PMP_LEN))::base_to_conf(base, size); + #5ns; + assert(out == 1); + end +endmodule \ No newline at end of file diff --git a/src/pmp/tb/pmp_tb.sv b/src/pmp/tb/pmp_tb.sv new file mode 100644 index 0000000000000000000000000000000000000000..2d1e508d2e8b9fb0dd52fab0d2af78def04d3121 --- /dev/null +++ b/src/pmp/tb/pmp_tb.sv @@ -0,0 +1,99 @@ +// Copyright 2019 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this 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. +// +// Author: Moritz Schneider, ETH Zurich +// Date: 2.10.2019 +// Description: + +import pmp_pkg::*; +import tb_pkg::*; + +module pmp_tb; + timeunit 1ns; + timeprecision 1ps; + + localparam int unsigned WIDTH = 16; + localparam int unsigned PMP_LEN = 13; + localparam int unsigned NR_ENTRIES = 4; + + logic [WIDTH-1:0] addr; + access_t access_type; + + // Configuration + logic [NR_ENTRIES-1:0][PMP_LEN-1:0] conf_addr; + pmp_conf_t [NR_ENTRIES-1:0] conf; + + // Output + logic allow; + + // helper signals + logic[WIDTH-1:0] base; + int unsigned size; + + pmp #( + .XLEN(WIDTH), + .PMP_LEN(PMP_LEN), + .NR_ENTRIES(NR_ENTRIES) + ) i_pmp( + .addr_i ( addr ), + .access_type_i ( access_type ), + .conf_addr_i ( conf_addr ), + .conf_i ( conf ), + .allow_o ( allow ) + ); + + + initial begin + // set all pmps to disabled initially + for (int i = 0; i < NR_ENTRIES; i++) begin + conf[i].addr_mode = OFF; + end + + // test napot 1 + addr = 16'b00011001_10111010; + access_type = READ; + + // pmp 0 + base = 16'b00011001_00000000; + size = 8; + conf_addr[0] = P#(.WIDTH(WIDTH), .PMP_LEN(PMP_LEN))::base_to_conf(base, size); + conf[0].addr_mode = NAPOT; + conf[0].access_type = READ | WRITE | EXECUTE; + + #5ns; + assert(allow == 1); + + // add second PMP entry that disallows + + // pmp 1 + base = 16'b00011001_10110000; + size = 4; + conf_addr[1] = P#(.WIDTH(WIDTH), .PMP_LEN(PMP_LEN))::base_to_conf(base, size); + conf[1].addr_mode = NAPOT; + conf[1].access_type = '0; + + #5ns; + assert(allow == 0); + + // add third PMP entry that allows again + // should fail since pmp1 disallows + + // pmp 2 + base = 16'b00011001_10111000; + size = 3; + conf_addr[2] = P#(.WIDTH(WIDTH), .PMP_LEN(PMP_LEN))::base_to_conf(base, size); + conf[2].addr_mode = NAPOT; + conf[2].access_type = READ; + + #5ns; + assert(allow == 0); + + end +endmodule \ No newline at end of file diff --git a/src/pmp/tb/pmp_tor_entry_tb.sv b/src/pmp/tb/pmp_tor_entry_tb.sv new file mode 100644 index 0000000000000000000000000000000000000000..381cf864f8192cb0c19e92c7e4b74dfc686a0f54 --- /dev/null +++ b/src/pmp/tb/pmp_tor_entry_tb.sv @@ -0,0 +1,58 @@ +// Copyright 2019 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this 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. +// +// Author: Moritz Schneider, ETH Zurich +// Date: 2.10.2019 +// Description: + +module pmp_tor_entry_tb; + timeunit 1ns; + timeprecision 1ps; + + localparam int unsigned WIDTH = 16; + localparam int unsigned PMP_LEN = 13; + + logic[WIDTH-1:0] addr; + logic[PMP_LEN-1:0] addr_lo; + logic[PMP_LEN-1:0] addr_hi; + + logic out; + + pmp_tor_entry #(.XLEN(WIDTH), .PMP_LEN(PMP_LEN)) + i_iopmp( + .addr_i(addr), + .conf_addr_lo_i(addr_lo), + .conf_addr_hi_i(addr_hi), + .match_o(out) + ); + + initial begin + addr = 16'h1a54; + addr_lo = 16'h1a53 >> 2; + addr_hi = 16'h1a5F >> 2; + #5ns; + assert(out == 1); + addr = 16'h1a54; + addr_lo = 16'h1a54 >> 2; + addr_hi = 16'h1a5F >> 2; + #5ns; + assert(out == 1); + addr = 16'h1a54; + addr_lo = 16'h1a50 >> 2; + addr_hi = 16'h1a54 >> 2; + #5ns; + assert(out == 0); + addr = 16'h1a50; + addr_lo = 16'h1a54 >> 2; + addr_hi = 16'h1a5F >> 2; + #5ns; + assert(out == 0); + end +endmodule \ No newline at end of file diff --git a/src/pmp/tb/tb_pkg.sv b/src/pmp/tb/tb_pkg.sv new file mode 100644 index 0000000000000000000000000000000000000000..ffd39587a699e587f51c8b159fef4af5131e147b --- /dev/null +++ b/src/pmp/tb/tb_pkg.sv @@ -0,0 +1,36 @@ +// Copyright 2019 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this 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. +// +// Author: Moritz Schneider, ETH Zurich +// Date: 2.10.2019 +// Description: + +package tb_pkg; + + class P #(parameter WIDTH=32, parameter PMP_LEN=32); + static function logic[PMP_LEN-1:0] base_to_conf(logic[WIDTH-1:0] base, int unsigned size_i); + logic[PMP_LEN-1:0] pmp_reg; + + pmp_reg = '0; + for (int i = 0; i < WIDTH-2 && i < PMP_LEN; i++) begin + if (i+3 > size_i) begin + pmp_reg[i] = base[i+2]; + end else if (i+3 == size_i) begin + pmp_reg[i] = 1'b0; + end else begin + pmp_reg[i] = 1'b1; + end + end + + return pmp_reg; + endfunction + endclass + +endpackage \ No newline at end of file