From 45ce906dafffa9e4bc4855c1f5a088a96c528202 Mon Sep 17 00:00:00 2001 From: Robert Schilling Date: Fri, 22 Nov 2024 20:29:10 +0100 Subject: [PATCH] [hw,ac_range_check,rtl] Implement range check logic Signed-off-by: Robert Schilling --- .../ac_range_check/rtl/ac_range_check.sv.tpl | 81 ++++++++++++++++++- .../ac_range_check/ac_range_check.core | 70 ++++++++++++++++ 2 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 hw/top_darjeeling/ip_autogen/ac_range_check/ac_range_check.core diff --git a/hw/ip_templates/ac_range_check/rtl/ac_range_check.sv.tpl b/hw/ip_templates/ac_range_check/rtl/ac_range_check.sv.tpl index 5b8fe3f172f8a..74d58d43c3823 100644 --- a/hw/ip_templates/ac_range_check/rtl/ac_range_check.sv.tpl +++ b/hw/ip_templates/ac_range_check/rtl/ac_range_check.sv.tpl @@ -2,10 +2,11 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 -module ${module_instance_name} +module ${module_instance_name} import tlul_pkg::*; - import ${module_instance_name}_reg_pkg::*; + import ${module_instance_name}_reg_pkg::*; #( + parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}} ) ( input logic clk_i, input logic rst_ni, @@ -60,6 +61,7 @@ module ${module_instance_name} reg2hw.alert_test.recov_ctrl_update_err.qe }; + localparam logic [NumAlerts-1:0] IsFatal = {1'b1, 1'b0}; for (genvar i = 0; i < NumAlerts; i++) begin : gen_alert_tx prim_alert_sender #( .AsyncOn(AlertAsyncOn[i]), @@ -76,6 +78,81 @@ module ${module_instance_name} ); end + ////////////////////////////////////////////////////////////////////////////// + // Range Check Logic + ////////////////////////////////////////////////////////////////////////////// + + logic [NumRanges-1:0] deny_mask, read_mask, write_mask, execute_mask, log_enable_mask; + + for (genvar i = 0; i < NumRanges; i++) begin : gen_range_checks + // Extend base, limit, and mask to 32-bit + logic [31:0] base_ext, limit_ext; + logic addr_hit, tor_hit; + + assign base_ext = {reg2hw.range_base[i].q, 2'b0}; + assign limit_ext = {reg2hw.range_limit[i].q, 2'b00}; + + assign tor_hit = (ctn_tl_h2d_i.a_address >= base_ext) & + (ctn_tl_h2d_i.a_address < limit_ext); + + // Request hits an enabled range and comparison logic + assign addr_hit = prim_mubi_pkg::mubi4_test_true_strict(reg2hw.range_perm[i].enable.q) & + tor_hit; + + // Decode the multi-bit access fields for convinient access + logic read_access, write_access, execute_access; + assign read_access = prim_mubi_pkg::mubi4_test_true_strict(reg2hw.range_perm[i].read_access.q); + assign write_access = + prim_mubi_pkg::mubi4_test_true_strict(reg2hw.range_perm[i].write_access.q); + assign execute_access = + prim_mubi_pkg::mubi4_test_true_strict(reg2hw.range_perm[i].execute_access.q); + + // Access is denied if no read_, write_, or execute access is set in the permission mask + assign deny_mask[i] = addr_hit & ~(read_access | write_access | execute_access); + + // Determine the read, write, and execute mask. Store a hit in their index + assign read_mask[i] = addr_hit & read_access; + assign write_mask[i] = addr_hit & write_access; + assign execute_mask[i] = addr_hit & execute_access; + end + + + // Fiddle out bits to determine if its an execute request or not + assign no_exec_access, exec_access; + assign no_exec_access = prim_mubi_pkg::mubi4_test_false_strict(ctn_tl_h2d_i.a_user.instr_type); + assign exec_access = prim_mubi_pkg::mubi4_test_true_strict(ctn_tl_h2d_i.a_user.instr_type); + + // Priority comparison. If the deny mask is larger than the read, write, or execute mask, there + // was an address match with a higher priority for the range to be denied + logic read_allowed, write_allowed, execute_allowed; + assign read_allowed = (ctn_tl_h2d_i.a_opcode == Get) & no_exec_access & (read_mask > deny_mask); + assign write_allowed = ((ctn_tl_h2d_i.a_opcode == PutFullData) | + (ctn_tl_h2d_i.a_opcode == PutPartialData)) & (write_mask > deny_mask); + assign execute_allowed = (ctn_tl_h2d_i.a_opcode == Get) & exec_access & + (execute_mask > deny_mask); + + // The access fails if nothing is allowed and no overwrite is present + logic range_check_fail; + assign range_check_fail = + ctn_tl_h2d_i.a_valid & ~(|{read_allowed, write_allowed, execute_allowed, + prim_mubi_pkg::mubi4_test_true_strict(range_check_overwrite_i)}); + + ////////////////////////////////////////////////////////////////////////////// + // TLUL Loopback for failing accesses + ////////////////////////////////////////////////////////////////////////////// + + tlul_request_loopback u_req_loopback ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .squash_req_i ( range_check_fail ), + // Incoming request + .tl_h2d_i ( ctn_tl_h2d_i ), + .tl_d2h_o ( ctn_tl_d2h_o ), + // Outgoing request/rsp if not squashed + .tl_h2d_o ( ctn_filtered_tl_h2d_o ), + .tl_d2h_i ( ctn_filtered_tl_d2h_i ) + ); + ////////////////////////////////////////////////////////////////////////////// // Assertions ////////////////////////////////////////////////////////////////////////////// diff --git a/hw/top_darjeeling/ip_autogen/ac_range_check/ac_range_check.core b/hw/top_darjeeling/ip_autogen/ac_range_check/ac_range_check.core new file mode 100644 index 0000000000000..088495efbf1dc --- /dev/null +++ b/hw/top_darjeeling/ip_autogen/ac_range_check/ac_range_check.core @@ -0,0 +1,70 @@ +CAPI=2: +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: lowrisc:opentitan:top_darjeeling_ac_range_check:0.1 +description: "AC Range Check RTL" +virtual: + - lowrisc:ip_interfaces:ac_range_check + +filesets: + files_rtl: + depend: + - lowrisc:ip:tlul + - lowrisc:prim:mubi + - lowrisc:prim:all + files: + - rtl/ac_range_check_reg_pkg.sv + - rtl/ac_range_check_reg_top.sv + - rtl/ac_range_check.sv + file_type: systemVerilogSource + + files_verilator_waiver: + depend: + # common waivers + - lowrisc:lint:common + - lowrisc:lint:comportable + files: + - lint/ac_range_check.vlt + file_type: vlt + + files_ascentlint_waiver: + depend: + # common waivers + - lowrisc:lint:common + - lowrisc:lint:comportable + files: + - lint/ac_range_check.waiver + file_type: waiver + + files_veriblelint_waiver: + depend: + # common waivers + - lowrisc:lint:common + - lowrisc:lint:comportable + +parameters: + SYNTHESIS: + datatype: bool + paramtype: vlogdefine + + +targets: + default: &default_target + filesets: + - tool_verilator ? (files_verilator_waiver) + - tool_ascentlint ? (files_ascentlint_waiver) + - tool_veriblelint ? (files_veriblelint_waiver) + - files_rtl + toplevel: ac_range_check + + lint: + <<: *default_target + default_tool: verilator + parameters: + - SYNTHESIS=true + tools: + verilator: + mode: lint-only + verilator_options: + - "-Wall"