Skip to content

Commit

Permalink
Add detection of optional CSR fields, and color them differently with…
Browse files Browse the repository at this point in the history
… wavedrom
  • Loading branch information
dhower-qc committed Oct 18, 2024
1 parent e41c3bd commit 53d42b6
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 64 deletions.
27 changes: 19 additions & 8 deletions backends/arch_gen/lib/arch_gen.rb
Original file line number Diff line number Diff line change
Expand Up @@ -716,11 +716,18 @@ def maybe_add_csr(csr_name, extra_env = {})
end

csr_obj = Csr.new(csr_data[csr_name])
arch_def_mock = Object.new
arch_def_mock.define_singleton_method(:fully_configured?) { true }
pos_xlen_local = possible_xlens
arch_def_mock.define_singleton_method(:possible_xlens) do
pos_xlen_local
end
impl_ext = @cfg_impl_ext.map { |e| ExtensionVersion.new(e[0], e[1]) }
arch_def_mock.define_singleton_method(:implemented_extensions) do
impl_ext
end
belongs =
csr_obj.exists_in_cfg?(
possible_xlens,
@cfg_impl_ext.map { |e| ExtensionVersion.new(e[0], e[1]) }
)
csr_obj.exists_in_cfg?(arch_def_mock)

@implemented_csrs ||= []
@implemented_csrs << csr_name if belongs
Expand Down Expand Up @@ -967,11 +974,15 @@ def maybe_add_inst(inst_name, extra_env = {})
possible_xlens << 64 if [64, 3264].include?(params["VSXLEN"])
possible_xlens << 64 if [64, 3264].include?(params["VUXLEN"])
end
arch_def_mock = Object.new
arch_def_mock.define_singleton_method(:fully_configured?) { true }
arch_def_mock.define_singleton_method(:possible_xlens) { possible_xlens }
impl_ext = @cfg_impl_ext.map { |e| ExtensionVersion.new(e[0], e[1]) }
arch_def_mock.define_singleton_method(:implemented_extensions) do
impl_ext
end
belongs =
inst_obj.exists_in_cfg?(
possible_xlens.uniq,
@cfg_impl_ext.map { |e| ExtensionVersion.new(e[0], e[1]) }
)
inst_obj.exists_in_cfg?(arch_def_mock)

@implemented_instructions ||= []
@implemented_instructions << inst_name if belongs
Expand Down
6 changes: 3 additions & 3 deletions backends/crd_doc/templates/crd.adoc.erb
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ h| Privilege Mode | <%= csr.priv_mode %>
.<%= csr.name %> format
[wavedrom, ,svg,subs='attributes',width="100%"]
....
<%= JSON.dump csr.wavedrom_desc(crd.arch_def, csr.base.nil? ? 32 : csr.base) %>
<%= JSON.dump csr.wavedrom_desc(crd.arch_def, csr.base.nil? ? 32 : csr.base, optional_type: 3) %>
....
<% else -%>
<%# CSR has a dynamic length, or a field has a dynamic location,
Expand All @@ -527,13 +527,13 @@ This CSR format changes dynamically with XLEN.
.<%= csr.name %> Format when <%= csr.length_cond32 %>
[wavedrom, ,svg,subs='attributes',width="100%"]
....
<%= JSON.dump csr.wavedrom_desc(crd.arch_def, 32) %>
<%= JSON.dump csr.wavedrom_desc(crd.arch_def, 32, optional_type: 3) %>
....

.<%= csr.name %> Format when <%= csr.length_cond64 %>
[wavedrom, ,svg,subs='attributes',width="100%"]
....
<%= JSON.dump csr.wavedrom_desc(crd.arch_def, 64) %>
<%= JSON.dump csr.wavedrom_desc(crd.arch_def, 64, optional_type: 3) %>
....


Expand Down
2 changes: 1 addition & 1 deletion lib/arch_def.rb
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ def mandatory_extensions
return @mandatory_extensions unless @mandatory_extensions.nil?

@mandatory_extensions = []
if @arch_def.key?("mandtory_extensions")
if @arch_def.key?("mandatory_extensions")
@arch_def["mandatory_extensions"].each do |e|
@mandatory_extensions << ExtensionRequirement.new(e["name"], e["version"])
end
Expand Down
2 changes: 1 addition & 1 deletion lib/arch_obj_models/crd.rb
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ def in_scope_ext_params(ext_req)
ext_param_db.defined_in_extension_version?(ver["version"])
end

ext_params <<
ext_params <<
InScopeExtensionParameter.new(ext_param_db, param_data["schema"], param_data["note"])
end

Expand Down
39 changes: 30 additions & 9 deletions lib/arch_obj_models/csr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ def implemented_fields(arch_def)
end

@implemented_fields = fields.select do |f|
f.exists_in_cfg?(implemented_bases, arch_def.implemented_extensions)
f.exists_in_cfg?(arch_def)
end
end

Expand Down Expand Up @@ -509,8 +509,10 @@ def pruned_sw_read_ast(arch_def)
#
# @param arch_def [ArchDef] A configuration
# @param effective_xlen [Integer,nil] Effective XLEN to use when CSR length is dynamic
# @param exclude_unimplemented [Boolean] If true, do not create include unimplemented fields in the figure
# @param optional_type [Integer] Wavedrom type (Fill color) for fields that are optional (not mandatory) in a partially-specified arch_def
# @return [Hash] A representation of the WaveDrom drawing for the CSR (should be turned into JSON for wavedrom)
def wavedrom_desc(arch_def, effective_xlen, exclude_unimplemented: false)
def wavedrom_desc(arch_def, effective_xlen, exclude_unimplemented: false, optional_type: 2)
desc = {
"reg" => []
}
Expand All @@ -533,7 +535,11 @@ def wavedrom_desc(arch_def, effective_xlen, exclude_unimplemented: false)

desc["reg"] << { "bits" => n, type: 1 }
end
desc["reg"] << { "bits" => field.location(arch_def, effective_xlen).size, "name" => field.name, type: 2 }
if field.optional_in_cfg?(arch_def)
desc["reg"] << { "bits" => field.location(arch_def, effective_xlen).size, "name" => field.name, type: optional_type }
else
desc["reg"] << { "bits" => field.location(arch_def, effective_xlen).size, "name" => field.name, type: 2 }
end
last_idx = field.location(arch_def, effective_xlen).max
end
if !field_list.empty? && (field_list.last.location(arch_def, effective_xlen).max != (length(arch_def, effective_xlen) - 1))
Expand All @@ -546,11 +552,26 @@ def wavedrom_desc(arch_def, effective_xlen, exclude_unimplemented: false)
desc
end

# @param possible_xlens [Array<Integer>] List of xlens that be used in any implemented mode
# @param extensions [Array<ExtensionVersion>] List of extensions implemented
# @return [Boolean] whether or not the instruction is implemented given the supplies config options
def exists_in_cfg?(possible_xlens, extensions)
(@data["base"].nil? || (possible_xlens.include? @data["base"])) &&
extensions.any? { |e| defined_by?(e) }
# @param arch_def [ArchDef] Architecture def
# @return [Boolean] whether or not the CSR is possibly implemented given the supplies config options
def exists_in_cfg?(arch_def)
if arch_def.fully_configured?
(@data["base"].nil? || (arch_def.possible_xlens.include? @data["base"])) &&
arch_def.implemented_extensions.any? { |e| defined_by?(e) }
else
(@data["base"].nil? || (arch_def.possible_xlens.include? @data["base"])) &&
arch_def.prohibited_extensions.none? { |e| defined_by?(e) }
end
end

# @param arch_def [ArchDef] Architecture def
# @return [Boolean] whether or not the CSR is optional in the config
def optional_in_cfg?(arch_def)
raise "optional_in_cfg? should only be used by a partially-specified arch def" unless arch_def.partially_configured?

exists_in_cfg?(arch_def) &&
arch_def.mandatory_extensions.none? do |ext_req|
ext_req.satisfying_versions(arch_def).none? { |ext_ver| defined_by?(ext_ver) }
end
end
end
29 changes: 25 additions & 4 deletions lib/arch_obj_models/csr_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,31 @@ def initialize(parent_csr, field_data)
# @param possible_xlens [Array<Integer>] List of xlens that be used in any implemented mode
# @param extensions [Array<ExtensionVersion>] List of extensions implemented
# @return [Boolean] whether or not the instruction is implemented given the supplies config options
def exists_in_cfg?(possible_xlens, extensions)
parent.exists_in_cfg?(possible_xlens, extensions) &&
(@data["base"].nil? || possible_xlens.include?(@data["base"])) &&
(@data["definedBy"].nil? || extensions.any? { |e| defined_by?(e) } )
def exists_in_cfg?(arch_def)
if arch_def.fully_configured?
parent.exists_in_cfg?(arch_def) &&
(@data["base"].nil? || arch_def.possible_xlens.include?(@data["base"])) &&
(@data["definedBy"].nil? || arch_def.implemented_extensions.any? { |ext_ver| defined_by?(ext_ver) })
else
raise "unexpected type" unless arch_def.partially_configured?

parent.exists_in_cfg?(arch_def) &&
(@data["base"].nil? || arch_def.possible_xlens.include?(@data["base"])) &&
(@data["definedBy"].nil? || arch_def.prohibited_extensions.none? { |ext_ver| defined_by?(ext_ver) })
end
end

# @return [Boolean] For a partially configured arch_def, whether or not the field is optional (not mandatory or prohibited)
def optional_in_cfg?(arch_def)
raise "optional_in_cfg? should only be called on a partially configured arch_def" unless arch_def.partially_configured?

exists_in_cfg?(arch_def) &&
(
parent.optional_in_cfg?(arch_def) ||
(data["definedBy"].nil? || arch_def.mandatory_extensions.none? do |ext_req|
ext_req.satisfying_versions(arch_def).none? { |ext_ver| defined_by?(ext_ver) }
end)
)
end

# @return [Idl::FunctionBodyAst] Abstract syntax tree of the type() function
Expand Down
19 changes: 13 additions & 6 deletions lib/arch_obj_models/instruction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -713,12 +713,19 @@ def excluded_by?(*args)
end
end

# @param possible_xlens [Array<Integer>] List of xlens that be used in any implemented mode
# @param extensions [Array<ExtensionVersion>] List of extensions implemented
# @param arch_def [ArchDef] The architecture definition
# @return [Boolean] whether or not the instruction is implemented given the supplies config options
def exists_in_cfg?(possible_xlens, extensions)
(@data["base"].nil? || (possible_xlens.include? @data["base"])) &&
extensions.any? { |e| defined_by?(e) } &&
extensions.none? { |e| excluded_by?(e) }
def exists_in_cfg?(arch_def)
if arch_def.fully_configured?
(@data["base"].nil? || (arch_def.possible_xlens.include? @data["base"])) &&
arch_def.implemented_extensions.any? { |e| defined_by?(e) } &&
arch_def.implemented_extensions.none? { |e| excluded_by?(e) }
else
raise "unexpected arch_def type" unless arch_def.partially_configured?

(@data["base"].nil? || (arch_def.possible_xlens.include? @data["base"])) &&
arch_def.prohibited_extensions.none? { |e| defined_by?(e) } &&
arch_def.mandatory_extensions.none? { |e| excluded_by?(e) }
end
end
end
66 changes: 34 additions & 32 deletions lib/arch_obj_models/obj.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,38 +116,38 @@ def defined_by?(*args)
end
end

def to_extension_requirement(obj)
if obj.is_a?(String)
ExtensionRequirement.new(obj, ">= 0")
else
ExtensionRequirement.new(*obj)
end
end
private :to_extension_requirement

def to_extension_requirement_list(obj)
list = []
if obj.is_a?(Array)
# could be either a single extension with exclusion, or a list of exclusions
if extension_exclusion?(obj[0])
list << to_extension_requirement(obj[0])
else
# this is a list
obj.each do |r|
list << to_extension_exclusion(r)
end
end
else
list << to_extension_requirement(obj)
end
list
end
# def to_extension_requirement(obj)
# if obj.is_a?(String)
# ExtensionRequirement.new(obj, ">= 0")
# else
# ExtensionRequirement.new(*obj)
# end
# end
# private :to_extension_requirement

# def to_extension_requirement_list(obj)
# list = []
# if obj.is_a?(Array)
# # could be either a single extension with exclusion, or a list of exclusions
# if extension_exclusion?(obj[0])
# list << to_extension_requirement(obj[0])
# else
# # this is a list
# obj.each do |r|
# list << to_extension_exclusion(r)
# end
# end
# else
# list << to_extension_requirement(obj)
# end
# list
# end

def extension_requirement?(obj)
obj.is_a?(String) && obj =~ /^([A-WY])|([SXZ][a-z]+)$/ ||
obj.is_a?(Array) && obj[0] =~ /^([A-WY])|([SXZ][a-z]+)$/
end
private :extension_requirement?
# def extension_requirement?(obj)
# obj.is_a?(String) && obj =~ /^([A-WY])|([SXZ][a-z]+)$/ ||
# obj.is_a?(Array) && obj[0] =~ /^([A-WY])|([SXZ][a-z]+)$/
# end
# private :extension_requirement?

# @return [SchemaCondition] Extension(s) that define the instruction. If *any* requirement is met, the instruction is defined.
def defined_by
Expand Down Expand Up @@ -258,6 +258,8 @@ def company = @data["company"]
class SchemaCondition
# @param composition_hash [Hash] A possibly recursive hash of "allOf", "anyOf", "oneOf"
def initialize(composition_hash)
raise ArgumentError, "composition_hash is nil" if composition_hash.nil?

unless is_a_condition?(composition_hash)
raise ArgumentError, "Expecting a JSON schema comdition (got #{composition_hash})"
end
Expand Down Expand Up @@ -322,7 +324,7 @@ def is_a_condition?(hsh)
end
end
else
raise "unexpected #{hsh.class.name} #{hsh}"
raise "unexpected #{hsh.class.name} #{hsh} #{@hsh}"
end

true
Expand Down

0 comments on commit 53d42b6

Please sign in to comment.