Skip to content

feat(schema): convert param 'when' to full extension req cond #751

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions arch/ext/Sm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ params:
minimum: 0
maximum: 0xFFFFFFFFFFFFFFFF
when:
name: Sm
version: ">= 1.12.0"
PMA_GRANULARITY:
description: |
Expand Down
6 changes: 1 addition & 5 deletions backends/portfolio/tasks.rake
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ require_relative "#{$lib}/idl/passes/gen_adoc"

# @return [Architecture]
def pf_create_arch
# Ensure that unconfigured resolved architecture called "_" exists.
Rake::Task["#{$root}/.stamps/resolve-_.stamp"].invoke

# Create architecture object using the unconfigured resolved architecture called "_".
Architecture.new($root / "gen" / "resolved_arch" / "_")
cfg_arch_for("_")
end

# @param portfolio_grp_with_arch [PortfolioGroup] Contains one or more Portfolio objects that have an arch (not a cfg_arch).
Expand Down
23 changes: 12 additions & 11 deletions lib/arch_obj_models/certificate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,12 @@ def all_in_scope_params
param = ext.params.find { |p| p.name == param_name }
raise "There is no param '#{param_name}' in extension '#{ext_name}" if param.nil?

next unless ext.versions.any? do |ext_ver|
ver_req = ext_data["version"] || ">= #{ext.min_version.version_spec}"
ExtensionRequirement.new(ext_name, ver_req, arch: @arch).satisfied_by?(ext_ver) &&
param.defined_in_extension_version?(ext_ver)
next unless param.when.satisfied_by? do |when_ext_req|
in_scope_ext_reqs.any? do |in_scope_ext_req|
in_scope_ext_req.satisfying_versions.any? do |in_scope_ext_ver|
when_ext_req.satisfied_by?(in_scope_ext_ver)
end
end
end

@all_in_scope_params << InScopeParameter.new(param, param_data["schema"], param_data["note"])
Expand Down Expand Up @@ -208,8 +210,12 @@ def in_scope_params(ext_req)
param = ext.params.find { |p| p.name == param_name }
raise "There is no param '#{param_name}' in extension '#{ext_req.name}" if param.nil?

next unless ext.versions.any? do |ext_ver|
ext_req.satisfied_by?(ext_ver) && param.defined_in_extension_version?(ext_ver)
next unless param.when.satisfied_by? do |when_ext_req|
in_scope_ext_reqs.any? do |in_scope_ext_req|
in_scope_ext_req.satisfying_versions.any? do |in_scope_ext_ver|
when_ext_req.satisfied_by?(in_scope_ext_ver)
end
end
Comment on lines +213 to +218
Copy link
Collaborator

Choose a reason for hiding this comment

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

given this code is exactly the same in the function above, there could be some refactoring here

end

params << InScopeParameter.new(param, param_data["schema"], param_data["note"])
Expand All @@ -229,11 +235,6 @@ def all_out_of_scope_params
ext.params.each do |param|
next if all_in_scope_params.any? { |c| c.param.name == param.name }

next unless ext.versions.any? do |ext_ver|
ext_req.satisfied_by?(ext_ver) &&
param.defined_in_extension_version?(ext_ver)
end

@all_out_of_scope_params << param
end
end
Expand Down
14 changes: 13 additions & 1 deletion lib/arch_obj_models/extension.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ def ratified_versions
def ratified = ratified_versions.any?

# @return [ExtensionVersion] Mimumum defined version of this extension
sig { returns(ExtensionVersion) }
def min_version
versions.min { |a, b| a.version_spec <=> b.version_spec }
end
Expand Down Expand Up @@ -160,6 +161,8 @@ def <=>(other_ext)

# A specific version of an extension
class ExtensionVersion
extend T::Sig

# @return [String] Name of the extension
attr_reader :name

Expand Down Expand Up @@ -258,8 +261,17 @@ def contributors
end

# @return [Array<Parameter>] The list of parameters for this extension version
sig { returns(T::Array[Parameter]) }
def params
@ext.params.select { |p| p.defined_in_extension_version?(self) }
@ext.params.select do |p|
p.when.satisfied_by? do |ext_req|
if ext_req.name == name
ext_req.satisfied_by?(self)
else
@arch.possible_extension_versions.any? { |poss_ext_ver| ext_req.satisfied_by?(poss_ext_ver) }
end
end
end
end

# @return [String] formatted like the RVI manual
Expand Down
44 changes: 35 additions & 9 deletions lib/arch_obj_models/parameter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@

# A parameter (AKA option, AKA implementation-defined value) supported by an extension
class Parameter
# @return [Architecture] The defining architecture
attr_reader :arch
extend T::Sig

# @return [String] Parameter name
attr_reader :name
Expand Down Expand Up @@ -46,12 +45,13 @@ def default
# @param ext [Extension]
# @param name [String]
# @param data [Hash<String, Object]
sig { params(ext: Extension, name: String, data: T::Hash[String, Object]).void }
def initialize(ext, name, data)
raise ArgumentError, "Expecting Extension but got #{ext.class}" unless ext.is_a?(Extension)
raise ArgumentError, "Expecting String but got #{name.class}" unless name.is_a?(String)
raise ArgumentError, "Expecting Hash but got #{data.class}" unless data.is_a?(Hash)

@arch = ext.arch
@cfg_arch = ext.cfg_arch
@data = data
@name = name
@desc = data["description"]
Expand All @@ -62,7 +62,7 @@ def initialize(ext, name, data)
unless also_defined_in_data.nil?
if also_defined_in_data.is_a?(String)
other_ext_name = also_defined_in_data
other_ext = @arch.extension(other_ext_name)
other_ext = @cfg_arch.extension(other_ext_name)
raise "Definition error in #{ext.name}.#{name}: #{other_ext_name} is not a known extension" if other_ext.nil?

also_defined_in_array << other_ext
Expand All @@ -72,7 +72,7 @@ def initialize(ext, name, data)
end

also_defined_in_data.each do |other_ext_name|
other_ext = @arch.extension(other_ext_name)
other_ext = @cfg_arch.extension(other_ext_name)
raise "Definition error in #{ext.name}.#{name}: #{also_defined_in_data} is not a known extension" if other_ext.nil?

also_defined_in_array << other_ext
Expand All @@ -83,10 +83,36 @@ def initialize(ext, name, data)
@idl_type = @schema.to_idl_type.make_const.freeze
end

# @param version [ExtensionVersion]
# @return [Boolean] if this parameter is defined in +version+
def defined_in_extension_version?(version)
return false if @exts.none? { |ext| ext.name == version.ext.name }
# @return [ExtensionRequirementExpression] Condition when the parameter exists
sig { returns(ExtensionRequirementExpression) }
def when
@when ||=
if @data["when"].nil?
# the parent extension is implictly required
cond =
if @exts.size > 1
{ "anyOf" => @exts.map { |ext| { "name" => ext.name, "version" => ">= #{ext.min_version.version_str}" } }}
else
{ "name" => @exts[0].name, "version" => ">= #{@exts[0].min_version.version_str}"}
end
ExtensionRequirementExpression.new(cond, @cfg_arch)
else
# the parent extension is implictly required
cond =
if @exts.size > 1
{ "allOf" => [{"anyOf" => @exts.map { |ext| { "name" => ext.name, "version" => ">= #{ext.min_version.version_str}" } } }, @data["when"]] }
else
{ "allOf" => [ { "name" => @exts[0].name, "version" => ">= #{@exts[0].min_version.version_str}"}, @data["when"]] }
end
cond =
ExtensionRequirementExpression.new(cond, @cfg_arch)
end
end

# @param cfg_arch [ConfiguredArchitecture]
# @return [Boolean] if this parameter is defined in +cfg_arch+
def defined_in_cfg?(cfg_arch)
return false if @exts.none? { |ext| cfg_arch.ext.name == version.ext.name }
return true if @data.dig("when", "version").nil?

@exts.any? do |ext|
Expand Down
1 change: 1 addition & 0 deletions lib/arch_obj_models/portfolio.rb
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ class Portfolio < DatabaseObject
# @param obj_yaml [Hash<String, Object>] Contains contents of Portfolio yaml file (put in @data)
# @param data_path [String] Path to yaml file
# @param arch [Architecture] Entire database of RISC-V architecture standards
sig { params(obj_yaml: T::Hash[String, Object], yaml_path: T.any(String, Pathname), arch: ConfiguredArchitecture).void }
def initialize(obj_yaml, yaml_path, arch)
super # Calls parent class with same args I got
end
Expand Down
4 changes: 0 additions & 4 deletions lib/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -319,10 +319,6 @@ def initialize(portfolio_grp)

@portfolio_grp = portfolio_grp

portfolio_grp.portfolios.each do |portfolio|
raise "Portfolio #{portfolio.name} shouldn't have a non-nil cfg_arch member" if portfolio.cfg_arch?
raise "Portfolio #{portfolio.name} shouldn't have a an arch member of type ConfiguredArchitecture" if portfolio.arch.is_a?(ConfiguredArchitecture)
end
end

###############################
Expand Down
3 changes: 2 additions & 1 deletion schemas/ext_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
"$ref": "json-schema-draft-07.json#"
},
"when": {
"$ref": "schema_defs.json#/$defs/when_condition"
"description": "Extension requirement condition that must be met for parameter to exist. The condition that the defining extension is implemented is implicit, and does not need to be explicitly listed",
"$ref": "schema_defs.json#/$defs/requires_entry"
},
"extra_validation": {
"description": "Ruby code to perform extra validation, when it is not easily expressed with JSON Schema (_e.g._, because it depends on the value of another parameter)",
Expand Down
Loading