Skip to content

Commit

Permalink
Fix: Wasn't looking in optional extensions to find all in scope param…
Browse files Browse the repository at this point in the history
…eters.
  • Loading branch information
james-ball-qualcomm committed Sep 27, 2024
1 parent 60ade32 commit e5f0e46
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 83 deletions.
4 changes: 4 additions & 0 deletions arch/csc_crd/MC-1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ MC-1:
optional:
- name: B
note: "This is just for testing. B isn't really optional for MC-1."
param_constraints:
MUTABLE_MISA_B:
schema:
const: true

requirement_groups:
- name: MC-Unpriv
Expand Down
40 changes: 18 additions & 22 deletions backends/csc_crd_doc/templates/crd.adoc.erb
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ a| <%- rev.changes.each do |change| %>
|===
| M | S | U | VS | VU

| <%- if crd.family.mandatory_priv_modes.include?('M') -%> MANDATORY <%- else -%> OUT_OF_SCOPE <%- end -%>
| <%- if crd.family.mandatory_priv_modes.include?('S') -%> MANDATORY <%- else -%> OUT_OF_SCOPE <%- end -%>
| <%- if crd.family.mandatory_priv_modes.include?('U') -%> MANDATORY <%- else -%> OUT_OF_SCOPE <%- end -%>
| <%- if crd.family.mandatory_priv_modes.include?('VS') -%> MANDATORY <%- else -%> OUT_OF_SCOPE <%- end -%>
| <%- if crd.family.mandatory_priv_modes.include?('VU') -%> MANDATORY <%- else -%> OUT_OF_SCOPE <%- end -%>
| <%- if crd.family.mandatory_priv_modes.include?('M') -%> MANDATORY <%- else -%> OUT OF SCOPE <%- end -%>
| <%- if crd.family.mandatory_priv_modes.include?('S') -%> MANDATORY <%- else -%> OUT OF SCOPE <%- end -%>
| <%- if crd.family.mandatory_priv_modes.include?('U') -%> MANDATORY <%- else -%> OUT OF SCOPE <%- end -%>
| <%- if crd.family.mandatory_priv_modes.include?('VS') -%> MANDATORY <%- else -%> OUT OF SCOPE <%- end -%>
| <%- if crd.family.mandatory_priv_modes.include?('VU') -%> MANDATORY <%- else -%> OUT OF SCOPE <%- end -%>

|===

Expand Down Expand Up @@ -107,20 +107,20 @@ These parameters are covered by an <%= crd.name %> certificate.
|===
| Parameter | Constraint | Note
<%- crd.param_constraints(ext_req).each do |constraint| -%>
| <<anchor-ext-<%= ext_req.name %>-param-<%= constraint.param.name %>,<%= constraint.param.name %>>>
| <%= constraint.schema_constraint_pretty == "" ? "Unconstrained" : constraint.schema_constraint_pretty %>
| <<anchor-ext-<%= ext_req.name %>-param-<%= constraint.param_db.name %>,<%= constraint.param_db.name %>>>
| <%= constraint.schema_constraint_pretty %>
a| <%= constraint.note %>
<%- end # do constraint -%>
|===
<%- end # unless table -%>
<%- unless crd.extension_out_of_scope_param_constraints(ext_req).empty? -%>
<%- unless crd.extension_out_of_scope_params(ext_req.name).empty? -%>
==== OUT OF SCOPE Parameters
These parameters are *NOT* covered by an <%= crd.name %> certificate.
<%- crd.extension_out_of_scope_param_constraints(ext_req).each do |param| -%>
* <<anchor-ext-<%= ext_req.name %>-param-<%= param.name %>,<%= param.name %>>>
<%- crd.extension_out_of_scope_params(ext_req.name).each do |param_db| -%>
* <<anchor-ext-<%= ext_req.name %>-param-<%= param_db.name %>,<%= param_db.name %>>>
<%- end # do constraint -%>
<%- end # unless table -%>
<%- end # do extension-%>
Expand Down Expand Up @@ -194,29 +194,25 @@ None
<%- unless crd.param_constraints(ext_req).empty? -%>
==== IN SCOPE Parameters
These parameters are covered by an <%= crd.name %> certificate.
<%- crd.param_constraints(ext_req).each do |constraint| -%>
[[anchor-ext-<%= ext_req.name %>-param-<%= constraint.param.name %>]]
<%= constraint.param.name %>::
[[anchor-ext-<%= ext_req.name %>-param-<%= constraint.param_db.name %>]]
<%= constraint.param_db.name %>::
+
--
<%= constraint.param.desc %>
<%= constraint.param_db.desc %>
--
<%- end # do constraint -%>
<%- end # unless table -%>
<%- unless crd.extension_out_of_scope_param_constraints(ext_req).empty? -%>
<%- unless crd.extension_out_of_scope_params(ext_req.name).empty? -%>
==== OUT OF SCOPE Parameters
These parameters are *NOT* covered by an <%= crd.name %> certificate.
<%- crd.extension_out_of_scope_param_constraints(ext_req).each do |param| -%>
[[anchor-ext-<%= ext_req.name %>-param-<%= param.name %>]]
<%= param.name %>::
<%- crd.extension_out_of_scope_params(ext_req.name).each do |param_db| -%>
[[anchor-ext-<%= ext_req.name %>-param-<%= param_db.name %>]]
<%= param_db.name %>::
+
--
<%= param.desc %>
<%= param_db.desc %>
--
<%- end # do constraint -%>
<%- end # unless table -%>
Expand Down
128 changes: 70 additions & 58 deletions lib/arch_obj_models/csc_crd.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# Classes for CRD (Certification Requirements Documents).
# Each CRD is a member of a CRD family (e.g., Microcontroller).
#
# Some classes inherit from the ArchDefObject class. This provides facilities for accessing
# the contents of a CRD family or CRD YAML definition via the "data" member (hash holding YAML file contents).
# A variable name with a "_crd" suffix indicates it is from the CRD family/member YAML file.
#
# The "archdef" member is an ArchDef class containing the "database" of RISC-V standards
# including extensions, instructions, CSRs, Profiles, and CRDs.
# A variable name with a "_db" suffix indicates it is from the archdef.

class CscCrdFamily < ArchDefObject
class Revision < ArchDefObject
Expand Down Expand Up @@ -95,29 +105,31 @@ def debug_manual_revision = @data["debug_manual_revision"]

def description = @data["description"]

# @return [Array<ExtensionRequirements>] - # An extension with its CRD information.
def extension_reqs
return @extension_reqs unless @extension_reqs.nil?
return @extension_reqs_crd unless @extension_reqs_crd.nil?

@extension_reqs = []
@extension_reqs_crd = []
[ "mandatory", "optional"].each do |status|
@data["extensions"][status]&.each do |ext|
@extension_reqs <<
ExtensionRequirement.new(ext["name"], ext["version"], note: ext["note"], req_id: "REQ-EXT-" + ext["name"],
status: status)
@data["extensions"][status]&.each do |ext_crd|
@extension_reqs_crd <<
ExtensionRequirement.new(ext_crd["name"], ext_crd["version"],
note: ext_crd["note"], req_id: "REQ-EXT-" + ext_crd["name"], status: status)
end
end
@extension_reqs
@extension_reqs_crd
end

class ParameterConstraint
attr_reader :param # ExtensionParameter object
# Holds an extension's parameter schema constraint from the CRD YAML.
class CrdParameterConstraint
attr_reader :param_db # ExtensionParameter object (from the architecture database)
attr_reader :note

def initialize(param, constraint, note)
raise ArgumentError, "Expecting ExtensionParameter" unless param.is_a?(ExtensionParameter)
def initialize(param_db, schema_constraint, note)
raise ArgumentError, "Expecting ExtensionParameter" unless param_db.is_a?(ExtensionParameter)

@param = param
@schema_constraint = constraint
@param_db = param_db
@schema_constraint = schema_constraint
@note = note
end

Expand All @@ -126,15 +138,15 @@ def single_value?
end

def value
raise "Parameter constraint for #{@param.name} is not a single value" unless single_value?
raise "Parameter schema_constraint for #{@param_db.name} is not a single value" unless single_value?

@schema_constraint["const"]
end

def schema_constraint_pretty
return "" if @schema_constraint.nil?
return "Unconstrained" if (@schema_constraint.nil? or @schema_constraint == "")
if @schema_constraint.key?("const")
"== #{@schema_constraint["const"]}"
"#{@schema_constraint["const"]}"
elsif @schema_constraint.key?("enum")
"One of: [#{@schema_constraint["enum"].join(', ')}]"
else
Expand All @@ -143,70 +155,71 @@ def schema_constraint_pretty
end
end

# @return [Array<ParameterConstraint>] List of parameters constraints specified by an extension requirement.
def param_constraints(ext_req)
# @return [Array<CrdParameterConstraint>] List of parameters constraints from CRD extension information.
def param_constraints(ext_req_crd)
param_constraints = [] # Local variable, no caching

ext_data = @data["extensions"][ext_req.status].find {|ext| ext["name"] == ext_req.name}
raise "Cannot find extension named #{ext_req.name}" if ext_data.nil?
# Get extension information from CRD YAML for passed in extension requirement.
ext_crd = @data["extensions"][ext_req_crd.status].find {|ext| ext["name"] == ext_req_crd.name}
raise "Cannot find extension named #{ext_req_crd.name}" if ext_crd.nil?

# Find Extension object from database
ext_db = @arch_def.extension(ext_data["name"])
raise "Cannot find extension named #{ext_data["name"]}" if ext_db.nil?
ext_db = @arch_def.extension(ext_crd["name"])
raise "Cannot find extension named #{ext_crd["name"]}" if ext_db.nil?

# & is the safe navigation operator
ext_data["param_constraints"]&.each do |param_name, param_data|
# Loop through an extension's parameter constraints (hash) from the CRD.
# Note that "&" is the Ruby safe navigation operator (i.e., skip do loop if nil).
ext_crd["param_constraints"]&.each do |param_name, param_data|
# Find ExtensionParameter object from database
ext_param_db = ext_db.params.find { |p| p.name == param_name }
raise "There is no param '#{param_name}' in extension '#{ext_data["name"]}" if ext_param_db.nil?
raise "There is no param '#{param_name}' in extension '#{ext_crd["name"]}" if ext_param_db.nil?

param_constraints << ParameterConstraint.new(ext_param_db, param_data["schema"], param_data["note"])
param_constraints << CrdParameterConstraint.new(ext_param_db, param_data["schema"], param_data["note"])
end

param_constraints
end

# @return [Array<ParameterConstraint>] List of parameters constraints specified by any extension.
def in_scope_param_constraints
return @in_scope_param_constraints unless @in_scope_param_constraints.nil?
# @return [Array<CrdParameterConstraint>] List of parameters constraints specified by any extension in CRD.
def all_in_scope_parmeter_contraints
return @all_in_scope_parmeter_contraints unless @all_in_scope_parmeter_contraints.nil?

@in_scope_param_constraints = []
@all_in_scope_parmeter_contraints = []

# XXX - Only looks at mandatory
@data["extensions"]["mandatory"].each do |ext_data|
# Find Extension object from database
ext_db = @arch_def.extension(ext_data["name"])
raise "Cannot find extension named #{ext_data["name"]}" if ext_db.nil?

next if ext_data["param_constraints"].nil?

ext_data["param_constraints"].each do |param_name, param_data|
param = ext_db.params.find { |p| p.name == param_name }
raise "There is no param '#{param_name}' in extension '#{ext_data["name"]}" if param.nil?

@in_scope_param_constraints << ParameterConstraint.new(param, param_data["schema"], param_data["note"])
[ "mandatory", "optional"].each do |status|
@data["extensions"][status].each do |ext_crd|
# Find Extension object from database
ext_db = @arch_def.extension(ext_crd["name"])
raise "Cannot find extension named #{ext_crd["name"]}" if ext_db.nil?

ext_crd["param_constraints"]&.each do |param_name, param_data|
param_db = ext_db.params.find { |p| p.name == param_name }
raise "There is no param '#{param_name}' in extension '#{ext_crd["name"]}" if param_db.nil?

@all_in_scope_parmeter_contraints << CrdParameterConstraint.new(param_db, param_data["schema"], param_data["note"])
end
end
end
@in_scope_param_constraints
@all_in_scope_parmeter_contraints
end

# @return [Array<ParameterConstraint>] List of parameters that are out of scope across all extensions.
def out_of_scope_param_constraints
return @out_of_scope_param_constraints unless @out_of_scope_param_constraints.nil?
# @return [Array<ExtensionParameter>] List of parameters that are out of scope across all extensions.
def all_out_of_scope_params
return @all_out_of_scope_params unless @all_out_of_scope_params.nil?

@out_of_scope_param_constraints = []
extension_reqs.each do |ext_req|
@arch_def.extension(ext_req.name).params.each do |param|
next if in_scope_param_constraints.any? { |c| c.param.name == param.name }
@out_of_scope_param_constraints << param
@all_out_of_scope_params = []
extension_reqs.each do |ext_req_crd|
@arch_def.extension(ext_req_crd.name).params.each do |param_db|
next if all_in_scope_parmeter_contraints.any? { |c| c.param_db.name == param_db.name }
@all_out_of_scope_params << param_db
end
end
@out_of_scope_param_constraints
@all_out_of_scope_params
end

# @return [Array<ExtensionParameter>] List of parameters that are out of scope
def extension_out_of_scope_param_constraints(ext_req)
out_of_scope_param_constraints.select{|param| param.exts.any? {|ext| ext.name == ext_req.name} }
# @return [Array<ExtensionParameter>] List of parameters that are out of scope for named extension.
def extension_out_of_scope_params(ext_name)
all_out_of_scope_params.select{|param_db| param_db.exts.any? {|ext| ext.name == ext_name} }
end

class Requirement < ArchDefObject
Expand Down Expand Up @@ -280,5 +293,4 @@ def requirement_groups
end
@requirement_groups
end

end
end
5 changes: 2 additions & 3 deletions lib/arch_obj_models/extension.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

require_relative "obj"


# an implmentation parameter/option for an extension
# A parameter (AKA option, AKA implementation-defined value) supported by an extension
class ExtensionParameter
# @return [String] Parameter name
attr_reader :name
Expand Down Expand Up @@ -296,7 +295,7 @@ def <=>(other)
end
end

# represents an extension requirement, that is an extension name paired with version requirement(s)
# Represents an extension requirement, that is an extension name paired with version requirement(s)
class ExtensionRequirement
# @return [String] Extension name
attr_reader :name
Expand Down

0 comments on commit e5f0e46

Please sign in to comment.