Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RACL] Implement config parsing, racl_ctrl, and reggen checks #25664

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions hw/top_darjeeling/rtl/autogen/top_racl_pkg.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// ------------------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! -------------------//
// PLEASE DO NOT HAND-EDIT THIS FILE. IT HAS BEEN AUTO-GENERATED WITH THE FOLLOWING COMMAND:
//
// util/topgen.py -t hw/top_darjeeling/data/top_darjeeling.hjson \
// -o hw/top_darjeeling/ \
// --rnd_cnst_seed \
// 1017106219537032642877583828875051302543807092889754935647094601236425074047


package top_racl_pkg;
// Number of RACL policies used
parameter int unsigned NrRaclPolicies = 1;

// Number of RACL bits transferred
parameter int unsigned NrRaclBits = 4;

// Number of CTN UID bits transferred
parameter int unsigned NrCtnUidBits = 8;

// RACL role type binary encoded
typedef logic [NrRaclBits-1:0] racl_role_t;

// CTN UID assigned the bus originator
typedef logic [NrCtnUidBits-1:0] ctn_uid_t;

// RACL permission: A one-hot encoded role vector
typedef logic [(2**NrRaclBits)-1:0] racl_role_vec_t;

// RACL policy containing a read and write permission
typedef struct packed {
racl_role_vec_t read_perm;
racl_role_vec_t write_perm;
} racl_policy_t;

// RACL policy vector for distributing RACL policies from the RACL widget to the subscribing IP
typedef racl_policy_t [NrRaclPolicies-1:0] racl_policy_vec_t;

// RACL information logged in case of a denial
typedef struct packed {
racl_role_t racl_role;
ctn_uid_t ctn_uid;
// 0: Write access, 1: Read access
logic read_not_write;
} racl_error_log_t;

// Extract RACL role bits from the TLUL reserved user bits
function automatic racl_role_t tlul_extract_racl_role_bits(logic [tlul_pkg::RsvdWidth-1:0] rsvd);
// Waive unused bits
logic unused_rsvd_bits;
unused_rsvd_bits = ^{rsvd};

return racl_role_t'(rsvd[11:8]);
endfunction

// Extract CTN UID bits from the TLUL reserved user bits
function automatic ctn_uid_t tlul_extract_ctn_uid_bits(logic [tlul_pkg::RsvdWidth-1:0] rsvd);
// Waive unused bits
logic unused_rsvd_bits;
unused_rsvd_bits = ^{rsvd};

return ctn_uid_t'(rsvd[7:0]);
endfunction


endpackage
1 change: 1 addition & 0 deletions hw/top_darjeeling/top_darjeeling.core
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ filesets:
files_rtl_generic:
depend:
# Place the autogen packages first to avoid conflicts
- lowrisc:systems:top_darjeeling_racl_pkg
- lowrisc:opentitan:top_darjeeling_alert_handler_reg
- lowrisc:opentitan:top_darjeeling_pwrmgr_pkg
- lowrisc:ip:uart:0.1
Expand Down
21 changes: 21 additions & 0 deletions hw/top_darjeeling/top_darjeeling_racl_pkg.core
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
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:systems:top_darjeeling_racl_pkg:0.1"
description: "Autogenerated top_darjeeling_racl_pkg used in RTL and DV."
virtual:
- lowrisc:systems:top_racl_pkg

filesets:
files_rtl:
depend:
- lowrisc:tlul:headers
files:
- rtl/autogen/top_racl_pkg.sv
file_type: systemVerilogSource

targets:
default: &default_target
filesets:
- files_rtl
69 changes: 69 additions & 0 deletions hw/top_earlgrey/rtl/autogen/top_racl_pkg.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// ------------------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! -------------------//
// PLEASE DO NOT HAND-EDIT THIS FILE. IT HAS BEEN AUTO-GENERATED WITH THE FOLLOWING COMMAND:
//
// util/topgen.py -t hw/top_earlgrey/data/top_earlgrey.hjson \
// -o hw/top_earlgrey/ \
// --rnd_cnst_seed \
// 1017106219537032642877583828875051302543807092889754935647094601236425074047


package top_racl_pkg;
// Number of RACL policies used
parameter int unsigned NrRaclPolicies = 1;

// Number of RACL bits transferred
parameter int unsigned NrRaclBits = 4;

// Number of CTN UID bits transferred
parameter int unsigned NrCtnUidBits = 8;

// RACL role type binary encoded
typedef logic [NrRaclBits-1:0] racl_role_t;

// CTN UID assigned the bus originator
typedef logic [NrCtnUidBits-1:0] ctn_uid_t;

// RACL permission: A one-hot encoded role vector
typedef logic [(2**NrRaclBits)-1:0] racl_role_vec_t;

// RACL policy containing a read and write permission
typedef struct packed {
racl_role_vec_t read_perm;
racl_role_vec_t write_perm;
} racl_policy_t;

// RACL policy vector for distributing RACL policies from the RACL widget to the subscribing IP
typedef racl_policy_t [NrRaclPolicies-1:0] racl_policy_vec_t;

// RACL information logged in case of a denial
typedef struct packed {
racl_role_t racl_role;
ctn_uid_t ctn_uid;
// 0: Write access, 1: Read access
logic read_not_write;
} racl_error_log_t;

// Extract RACL role bits from the TLUL reserved user bits
function automatic racl_role_t tlul_extract_racl_role_bits(logic [tlul_pkg::RsvdWidth-1:0] rsvd);
// Waive unused bits
logic unused_rsvd_bits;
unused_rsvd_bits = ^{rsvd};

return racl_role_t'(rsvd[11:8]);
endfunction

// Extract CTN UID bits from the TLUL reserved user bits
function automatic ctn_uid_t tlul_extract_ctn_uid_bits(logic [tlul_pkg::RsvdWidth-1:0] rsvd);
// Waive unused bits
logic unused_rsvd_bits;
unused_rsvd_bits = ^{rsvd};

return ctn_uid_t'(rsvd[7:0]);
endfunction


endpackage
1 change: 1 addition & 0 deletions hw/top_earlgrey/top_earlgrey.core
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ filesets:
files_rtl_generic:
depend:
# Place the autogen packages first to avoid conflicts
- lowrisc:systems:top_earlgrey_racl_pkg
- lowrisc:opentitan:top_earlgrey_alert_handler_reg
- lowrisc:opentitan:top_earlgrey_pwrmgr_pkg
- lowrisc:ip:uart:0.1
Expand Down
21 changes: 21 additions & 0 deletions hw/top_earlgrey/top_earlgrey_racl_pkg.core
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
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:systems:top_earlgrey_racl_pkg:0.1"
description: "Autogenerated top_earlgrey_racl_pkg used in RTL and DV."
virtual:
- lowrisc:systems:top_racl_pkg

filesets:
files_rtl:
depend:
- lowrisc:tlul:headers
files:
- rtl/autogen/top_racl_pkg.sv
file_type: systemVerilogSource

targets:
default: &default_target
filesets:
- files_rtl
3 changes: 3 additions & 0 deletions util/raclgen/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Copyright lowRISC contributors (OpenTitan project).
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
51 changes: 51 additions & 0 deletions util/raclgen/lib.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Copyright lowRISC contributors (OpenTitan project).
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

import hjson
import sys
from reggen.validate import check_keys

# Required fields for the RACL hjson
racl_required = {
'roles': ['l', 'List, specifying all RACL roles'],
'policies': ['g', 'Dict, specifying the policies of all RACL groups']
}


# Default configuration to render the RACL package for systems that don't use RACL but need the
# type definitions
DEFAULT_RACL_CONFIG = {
'nr_policies': 1,
'policies': {},
}


def parse_racl_config(config_path: str):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coud you add a return type, probably ...str) -> Dict[str, object]: or some more specific type for the value in the Dict?

try:
with open(config_path, 'r') as f_racl_config:
racl_config = hjson.load(f_racl_config)
except OSError:
raise SystemExit(sys.exc_info()[1])

# TODO further error handling
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some hint about the missing checks?

error = check_keys(racl_config, racl_required, [], [], 'RACL Config')
if error:
raise SystemExit(f"Error occurred while validating {config_path}")

# Determine the maximum number of policies over all RACL groups for RTL
# RTL needs to create the vectors based on the largest group
racl_config['nr_policies'] = max(len(policies) for policies in racl_config['policies'].values())

for racl_group, policies in racl_config['policies'].items():
for policy in policies:
def compute_policy_value(permission: str):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the return value type delaration could be ... str) -> int:

permission_value = 0
for role in policy[permission]:
role_id = racl_config['roles'][role]['role_id']
permission_value += 2**role_id
return permission_value

policy['rd_default'] = compute_policy_value('allowed_rd')
policy['wr_default'] = compute_policy_value('allowed_wr')
return racl_config
19 changes: 19 additions & 0 deletions util/topgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
IpTemplate, TemplateRenderError)
from mako import exceptions
from mako.template import Template
from raclgen.lib import DEFAULT_RACL_CONFIG, parse_racl_config
from reggen import access, gen_rtl, gen_sec_cm_testplan, window
from reggen.countermeasure import CounterMeasure
from reggen.inter_signal import InterSignal
Expand Down Expand Up @@ -526,6 +527,15 @@ def generate_ac_range_check(topcfg: Dict[str, object], out_path: Path) -> None:
ipgen_render("ac_range_check", topname, params, out_path)


# Generate RACL collateral
def generate_racl(topcfg: Dict[str, object], out_path: Path) -> None:
# Not all tops use RACL
if 'racl_config' not in topcfg:
return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it make sense to set topcfg['racl'] to None in this situation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason this was not added is to make it easier to detect if no RACL is used, i.e., down below: completecfg.get('racl', DEFAULT_RACL_CONFIG)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Detection of no RACL could be as simple as racl not in completecfg, and we could have no trace of racl if it is not used. Perhaps the package could be avoided in those cases to keep it simple.


topcfg['racl'] = parse_racl_config(topcfg['racl_config'])


def generate_top_only(top_only_dict: Dict[str, bool], out_path: Path,
top_name: str, alt_hjson_path: str) -> None:
log.info("Generating top only modules")
Expand Down Expand Up @@ -866,6 +876,9 @@ def _process_top(
# Generate ac_range_check
generate_ac_range_check(completecfg, out_path)

# Generate RACL collateral
generate_racl(completecfg, out_path)

# Generate top only modules
# These modules are not ipgen, but are not in hw/ip
generate_top_only(top_only_dict, cfg_path, top_name, args.hjson_path)
Expand Down Expand Up @@ -1249,6 +1262,12 @@ def render_template(template_path: str, rendered_path: Path,
out_path / f"rtl/autogen/{top_name}_rnd_cnst_pkg.sv",
gencmd=gencmd)

racl_config = completecfg.get('racl', DEFAULT_RACL_CONFIG)
render_template(TOPGEN_TEMPLATE_PATH / 'toplevel_racl_pkg.sv.tpl',
out_path / 'rtl' / 'autogen' / 'top_racl_pkg.sv',
gencmd=gencmd,
racl_config=racl_config)

# Since SW does not use FuseSoC and instead expects those files always
# to be in hw/top_{topname}/sw/autogen, we currently create these files
# twice:
Expand Down
82 changes: 82 additions & 0 deletions util/topgen/templates/toplevel_racl_pkg.sv.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
${gencmd}

package top_racl_pkg;
// Number of RACL policies used
parameter int unsigned NrRaclPolicies = ${racl_config['nr_policies']};

// Number of RACL bits transferred
parameter int unsigned NrRaclBits = 4;

// Number of CTN UID bits transferred
parameter int unsigned NrCtnUidBits = 8;

// RACL role type binary encoded
typedef logic [NrRaclBits-1:0] racl_role_t;

// CTN UID assigned the bus originator
typedef logic [NrCtnUidBits-1:0] ctn_uid_t;

// RACL permission: A one-hot encoded role vector
typedef logic [(2**NrRaclBits)-1:0] racl_role_vec_t;

// RACL policy containing a read and write permission
typedef struct packed {
racl_role_vec_t read_perm;
racl_role_vec_t write_perm;
} racl_policy_t;

// RACL policy vector for distributing RACL policies from the RACL widget to the subscribing IP
typedef racl_policy_t [NrRaclPolicies-1:0] racl_policy_vec_t;

// RACL information logged in case of a denial
typedef struct packed {
racl_role_t racl_role;
ctn_uid_t ctn_uid;
// 0: Write access, 1: Read access
logic read_not_write;
} racl_error_log_t;

// Extract RACL role bits from the TLUL reserved user bits
function automatic racl_role_t tlul_extract_racl_role_bits(logic [tlul_pkg::RsvdWidth-1:0] rsvd);
// Waive unused bits
logic unused_rsvd_bits;
unused_rsvd_bits = ^{rsvd};

return racl_role_t'(rsvd[11:8]);
endfunction

// Extract CTN UID bits from the TLUL reserved user bits
function automatic ctn_uid_t tlul_extract_ctn_uid_bits(logic [tlul_pkg::RsvdWidth-1:0] rsvd);
// Waive unused bits
logic unused_rsvd_bits;
unused_rsvd_bits = ^{rsvd};

return ctn_uid_t'(rsvd[7:0]);
endfunction

% for racl_group, policies in racl_config['policies'].items():
<% prefix = "" if len(racl_config['policies'].keys()) == 1 else f"{racl_group.upper()}_" %>\
/**
* Policies for group ${racl_group}
*/

% for policy in policies:
/*
* Policy ${policy['name']} allowed READ roles:
* ${', '.join(policy['allowed_wr'])}
*/
parameter racl_policy_t RACL_POLICY_${prefix}${policy['name'].upper()}_RD_DEFAULT = 16'h${f"{policy['rd_default']:x}"};

/**
* Policy ${policy['name']} allowed WRITE roles:
* ${', '.join(policy['allowed_wr'])}
*/
parameter racl_policy_t RACL_POLICY_${prefix}${policy['name'].upper()}_WR_DEFAULT = 16'h${f"{policy['wr_default']:x}"};

% endfor
% endfor

endpackage
1 change: 1 addition & 0 deletions util/topgen/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
'num_cores': ['pn', "number of computing units"],
'power': ['g', 'power domains supported by the design'],
'port': ['g', 'assign special attributes to specific ports'],
'racl_config': ['s', 'Path to a RACL configuration HJSON file'],
'rnd_cnst_seed': ['int', "Seed for random netlist constant computation"],
'unmanaged_resets': ['l', 'List of unmanaged external resets']
}
Expand Down