diff --git a/lib/arch_obj_models/csr.rb b/lib/arch_obj_models/csr.rb index 9bd386be1..0cc4b88fc 100644 --- a/lib/arch_obj_models/csr.rb +++ b/lib/arch_obj_models/csr.rb @@ -46,7 +46,7 @@ def defined_in_base64? = @data["base"].nil? || @data["base"] == 64 # @return [Boolean] true if this CSR is defined regardless of the effective XLEN def defined_in_all_bases? = @data["base"].nil? - # @param design [Design] A configuration + # @param design [Design] The design # @return [Boolean] Whether or not the format of this CSR changes when the effective XLEN changes in some mode def format_changes_with_xlen?(design) dynamic_length?(design) || @@ -55,7 +55,7 @@ def format_changes_with_xlen?(design) end end - # @param design [Design] A configuration + # @param design [Design] The design # @return [Array] List of functions reachable from this CSR's sw_read or a field's sw_write function def reachable_functions(design) return @reachable_functions unless @reachable_functions.nil? @@ -104,7 +104,7 @@ def reachable_functions_unevaluated(design) @reachable_functions_unevaluated = fns.uniq end - # @param design [Design] A configuration + # @param design [Design] The design # @return [Boolean] Whether or not the length of the CSR depends on a runtime value # (e.g., mstatus.SXL) def dynamic_length?(design) @@ -142,7 +142,7 @@ def min_length(design) end end - # @param design [Design] A configuration (can be nil if the lenth is not dependent on a config parameter) + # @param design [Design] The design (can be nil if the length is not dependent on a config parameter) # @param effective_xlen [Integer] The effective xlen, needed since some fields change location with XLEN. If the field location is not determined by XLEN, then this parameter can be nil # @return [Integer] Length, in bits, of the CSR, given effective_xlen # @return [nil] if the length cannot be determined from the design (e.g., because SXLEN is unknown and +effective_xlen+ was not provided) @@ -254,7 +254,7 @@ def length_cond64 end end - # @param design [Design] A configuration + # @param design [Design] The design # @return [String] Pretty-printed length string def length_pretty(design, effective_xlen=nil) if dynamic_length?(design) @@ -306,7 +306,7 @@ def description_html Asciidoctor.convert description end - # @param design [Design] A configuration + # @param design [Design] The design # @return [Array] All implemented fields for this CSR at the given effective XLEN, sorted by location (smallest location first) # Excluded any fields that are defined by unimplemented extensions or a base that is not effective_xlen def implemented_fields_for(design, effective_xlen) @@ -321,7 +321,7 @@ def implemented_fields_for(design, effective_xlen) end end - # @param design [Design] A configuration + # @param design [Design] The design # @return [Array] All implemented fields for this CSR # Excluded any fields that are defined by unimplemented extensions def implemented_fields(design) @@ -377,7 +377,7 @@ def field(field_name) field_hash[field_name.to_s] end - # @param design [Design] A configuration + # @param design [Design] The design # @param effective_xlen [Integer] The effective XLEN to apply, needed when field locations change with XLEN in some mode # @return [Idl::BitfieldType] A bitfield type that can represent all fields of the CSR def bitfield_type(design, effective_xlen = nil) @@ -425,7 +425,7 @@ def type_checked_sw_read_ast(symtab) end # @return [FunctionBodyAst] The abstract syntax tree of the sw_read() function - # @param design [Design] A configuration + # @param design [Design] The design def sw_read_ast(symtab) raise ArgumentError, "Argument should be a symtab" unless symtab.is_a?(Idl::SymbolTable) @@ -493,7 +493,7 @@ def pruned_sw_read_ast(design) # {bits: 12, name: 'imm12', attr: [''], type: 6} # ]} # - # @param design [Design] A configuration + # @param design [Design] The design # @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 design @@ -543,10 +543,10 @@ def wavedrom_desc(design, effective_xlen, exclude_unimplemented: false, optional def exists_in_design?(design) if design.fully_configured? (@data["base"].nil? || (design.possible_xlens.include? @data["base"])) && - design.transitive_implemented_ext_vers.any? { |e| defined_by?(e) } + design.transitive_implemented_ext_vers.any? { |ext_ver| defined_by?(ext_ver) } else (@data["base"].nil? || (design.possible_xlens.include? @data["base"])) && - design.prohibited_ext_reqs.none? { |ext_req| ext_req.satisfying_versions.any? { |e| defined_by?(e) } } + design.prohibited_ext_reqs.none? { |ext_req| ext_req.satisfying_versions.any? { |ext_ver| defined_by?(ext_ver) } } end end @@ -556,10 +556,6 @@ def optional_in_design?(design) raise "optional_in_design? should only be used by a partially-specified arch def" unless design.partially_configured? exists_in_design?(design) && - design.mandatory_ext_reqs.all? do |ext_req| - ext_req.satisfying_versions.none? do |ext_ver| - defined_by?(ext_ver) - end - end + design.mandatory_ext_reqs.all? { |ext_req| ext_req.satisfying_versions.none? { |ext_ver| defined_by?(ext_ver) } } end end diff --git a/lib/arch_obj_models/csr_field.rb b/lib/arch_obj_models/csr_field.rb index 3fc1c83ad..36f13b1b8 100644 --- a/lib/arch_obj_models/csr_field.rb +++ b/lib/arch_obj_models/csr_field.rb @@ -28,9 +28,8 @@ def initialize(parent_csr, field_name, field_data) @type_cache = {} end - # @param possible_xlens [Array] List of xlens that be used in any implemented mode - # @param extensions [Array] List of extensions implemented - # @return [Boolean] whether or not the instruction is implemented given the supplies config options + # @param design [Design] The design + # @return [Boolean] whether or not the instruction is implemented given the supplied design def exists_in_design?(design) if design.fully_configured? parent.exists_in_design?(design) && @@ -54,11 +53,7 @@ def optional_in_design?(design) if data["definedBy"].nil? parent.optional_in_design?(design) else - design.mandatory_ext_reqs.all? do |ext_req| - ext_req.satisfying_versions.none? do |ext_ver| - defined_by?(ext_ver) - end - end + design.mandatory_ext_reqs.all? { |ext_req| ext_req.satisfying_versions.none? { |ext_ver| defined_by?(ext_ver) } } end ) end @@ -146,7 +141,7 @@ def pruned_type_ast(symtab) @pruned_type_asts[symtab_hash] = ast end - # returns the definitive type for a design + # Returns the definitive type for the design part of the symbol table. # # @param symtab [SymbolTable] Symbol table # @return [String] @@ -250,9 +245,9 @@ def alias @alias end - # @return [Array] List of functions called thorugh this field # @param design [Design] The design # @Param effective_xlen [Integer] 32 or 64; needed because fields can change in different XLENs + # @return [Array] List of functions called thorough this field def reachable_functions(design, effective_xlen) return @reachable_functions unless @reachable_functions.nil? diff --git a/lib/arch_obj_models/database_obj.rb b/lib/arch_obj_models/database_obj.rb index eaea68634..f82f7d734 100644 --- a/lib/arch_obj_models/database_obj.rb +++ b/lib/arch_obj_models/database_obj.rb @@ -206,13 +206,23 @@ def keys = @data.keys # @return (see Hash#key?) def key?(k) = @data.key?(k) + # @param ext_ver [ExtensionVersion] Version of the extension + # @param design [Design] The backend design + # @return [Boolean] Whether or not the object is defined-by the given ExtensionVersion in the given Design. + def in_scope?(ext_ver, design) + raise ArgumentError, "Require an ExtensionVersion object but got a #{ext_ver.class} object" unless ext_ver.is_a?(ExtensionVersion) + raise ArgumentError, "Require a Design object but got a #{design.class} object" unless design.is_a?(Design) + + defined_by?(ext_ver) + end + # @overload defined_by?(ext_name, ext_version) # @param ext_name [#to_s] An extension name # @param ext_version [#to_s] A specific extension version - # @return [Boolean] Whether or not the instruction is defined by extension `ext`, version `version` + # @return [Boolean] Whether or not the object is defined by extension `ext`, version `version` # @overload defined_by?(ext_version) # @param ext_version [ExtensionVersion] An extension version - # @return [Boolean] Whether or not the instruction is defined by ext_version + # @return [Boolean] Whether or not the object is defined by ext_version def defined_by?(*args) ext_ver = if args.size == 1 @@ -228,7 +238,7 @@ def defined_by?(*args) raise ArgumentError, "Unsupported number of arguments (#{args.size})" end - defined_by_condition.satisfied_by? { |req| req.satisfied_by?(ext_ver) } + defined_by_condition.satisfied_by? { |ext_req| ext_req.satisfied_by?(ext_ver) } end # because of multiple ("allOf") conditions, we generally can't return a list of extension versions here.... @@ -564,7 +574,6 @@ def to_rb_helper(hsh) # return a string that can be eval'd to determine if the objects in +ary_name+ # meet the Condition # - # @param ary_name [String] Name of a ruby string in the eval binding # @return [Boolean] If the condition is met def to_rb to_rb_helper(@hsh) @@ -592,7 +601,10 @@ def satisfied_by?(&block) raise ArgumentError, "Expecting one argument to block" unless block.arity == 1 - eval to_rb + # Written to allow debug breakpoints on individual lines. + to_rb_expr = to_rb + ret = eval to_rb_expr + ret end def satisfying_ext_versions diff --git a/lib/arch_obj_models/extension.rb b/lib/arch_obj_models/extension.rb index 1c24adf6c..ae17dd2b7 100644 --- a/lib/arch_obj_models/extension.rb +++ b/lib/arch_obj_models/extension.rb @@ -517,6 +517,34 @@ def implemented_instructions inst.defined_by?(self) end end + + # @param design [Design] The design + # @return [Array] List of CSRs in-scope for this design for this extension version (may be empty) + # Factors in effect of design's xlen in the appropriate mode for the CSR. + def in_scope_csrs(design) + raise ArgumentError, "Require a Design object but got a #{design.class} object" unless design.is_a?(Design) + + return @in_scope_csrs unless @in_scope_csrs.nil? + + @in_scope_csrs = @arch.csrs.select do |csr| + csr.defined_by?(self) && + (csr.base.nil? || (design.possible_xlens.include?(csr.base))) + end + end + + # @param design [Design] The design + # @return [Array] List of instructions in-scope for this design for this extension version (may be empty) + # Factors in effect of design's xlen in the appropriate mode for the instruction. + def in_scope_instructions(design) + raise ArgumentError, "Require a Design object but got a #{design.class} object" unless design.is_a?(Design) + + return @in_scope_instructions unless @in_scope_instructions.nil? + + @in_scope_instructions = @arch.instructions.select do |inst| + inst.defined_by?(self) && + (inst.base.nil? || (design.possible_xlens.include?(inst.base))) + end + end end # Is the extension mandatory, optional, various kinds of optional, etc. diff --git a/lib/arch_obj_models/instruction.rb b/lib/arch_obj_models/instruction.rb index 029858b28..73ecb293b 100644 --- a/lib/arch_obj_models/instruction.rb +++ b/lib/arch_obj_models/instruction.rb @@ -743,8 +743,7 @@ def excluded_by?(*args) # # TODO: Does this function actually work for a partially configured design? # It is calling DatabaseObject.defined_by? with ExtensionRequirement objects - # returned from Design.prohibited_ext_reqs() and Design.mandatory_ext_reqs() - # but only accepts an ExtensionVersion object. + # returned from Design.mandatory_ext_reqs() but only accepts an ExtensionVersion object. def exists_in_design?(design) if design.fully_configured? (@data["base"].nil? || (design.possible_xlens.include?(@data["base"]))) && @@ -754,7 +753,7 @@ def exists_in_design?(design) raise "unexpected design type" unless design.partially_configured? (@data["base"].nil? || (design.possible_xlens.include?(@data["base"]))) && - design.prohibited_ext_reqs.none? { |ext_req| defined_by?(ext_req) } && + design.prohibited_ext_reqs.none? { |ext_req| ext_req.satisfying_versions.any? { |ext_ver| defined_by?(ext_ver) } } design.mandatory_ext_reqs.none? { |ext_req| excluded_by?(ext_req) } end end diff --git a/lib/arch_obj_models/portfolio.rb b/lib/arch_obj_models/portfolio.rb index 5c17218df..312ec89f9 100644 --- a/lib/arch_obj_models/portfolio.rb +++ b/lib/arch_obj_models/portfolio.rb @@ -127,30 +127,36 @@ def in_scope_extensions end + # @param design [Design] The design # @return [Array] Sorted list of all instructions associated with extensions listed as # mandatory or optional in portfolio. Uses instructions provided by the # minimum version of the extension that meets the extension requirement. - def in_scope_instructions + def in_scope_instructions(design) + raise ArgumentError, "Require a Design object but got a #{design.class} object" unless design.is_a?(Design) + return @in_scope_instructions unless @in_scope_instructions.nil? @in_scope_instructions = [] portfolios.each do |portfolio| - @in_scope_instructions += portfolio.in_scope_instructions + @in_scope_instructions += portfolio.in_scope_instructions(design) end @in_scope_instructions = @in_scope_instructions.uniq(&:name).sort_by(&:name) end + # @param design [Design] The design # @return [Array] Unsorted list of all CSRs associated with extensions listed as # mandatory or optional in portfolio. Uses CSRs provided by the # minimum version of the extension that meets the extension requirement. - def in_scope_csrs + def in_scope_csrs(design) + raise ArgumentError, "Require a Design object but got a #{design.class} object" unless design.is_a?(Design) + return @in_scope_csrs unless @in_scope_csrs.nil? @in_scope_csrs = [] portfolios.each do |portfolio| - @in_scope_csrs += portfolio.in_scope_csrs + @in_scope_csrs += portfolio.in_scope_csrs(design) end @in_scope_csrs.uniq(&:name) @@ -349,24 +355,30 @@ def in_scope_min_satisfying_extension_versions @in_scope_min_satisfying_extension_versions end + # @param design [Design] The design # @return [Array] Sorted list of all instructions associated with extensions listed as # mandatory or optional in portfolio. Uses instructions provided by the # minimum version of the extension that meets the extension requirement. - def in_scope_instructions + def in_scope_instructions(design) + raise ArgumentError, "Require a Design object but got a #{design.class} object" unless design.is_a?(Design) + return @in_scope_instructions unless @in_scope_instructions.nil? @in_scope_instructions = - in_scope_min_satisfying_extension_versions.map {|ext_ver| ext_ver.implemented_instructions }.flatten.uniq.sort + in_scope_min_satisfying_extension_versions.map {|ext_ver| ext_ver.in_scope_instructions(design) }.flatten.uniq.sort end + # @param design [Design] The design # @return [Array] Unsorted list of all CSRs associated with extensions listed as # mandatory or optional in portfolio. Uses CSRs provided by the # minimum version of the extension that meets the extension requirement. - def in_scope_csrs + def in_scope_csrs(design) + raise ArgumentError, "Require a Design object but got a #{design.class} object" unless design.is_a?(Design) + return @in_scope_csrs unless @in_scope_csrs.nil? @in_scope_csrs = - in_scope_min_satisfying_extension_versions.map {|ext_ver| ext_ver.implemented_csrs }.flatten.uniq + in_scope_min_satisfying_extension_versions.map {|ext_ver| ext_ver.in_scope_csrs(design) }.flatten.uniq end # @return [Boolean] Does the profile differentiate between different types of optional. diff --git a/lib/config.rb b/lib/config.rb index 344686551..e52b84e54 100644 --- a/lib/config.rb +++ b/lib/config.rb @@ -178,7 +178,4 @@ def implemented_extensions def mandatory_extensions = raise "mandatory_extensions is only available for a PartialConfig" def prohibited_extensions = raise "prohibited_extensions is only available for a PartialConfig" - - # def prohibited_ext?(ext_name, cfg_arch) = !ext?(ext_name, cfg_arch) - # def ext?(ext_name, cfg_arch) = implemented_extensions(cfg_arch).any? { |e| e.name == ext_name.to_s } end diff --git a/lib/portfolio_design.rb b/lib/portfolio_design.rb index ad3a24ec6..cc67502ff 100644 --- a/lib/portfolio_design.rb +++ b/lib/portfolio_design.rb @@ -179,12 +179,14 @@ def in_scope_ext_reqs = @portfolio_grp.in_scope_ext_reqs # @return [Array] Sorted list of all instructions associated with extensions listed as # mandatory or optional in portfolio. Uses instructions provided by the # minimum version of the extension that meets the extension requirement. - def in_scope_instructions = @portfolio_grp.in_scope_instructions + # Factors in things like XLEN in design. + def in_scope_instructions = @portfolio_grp.in_scope_instructions(self) # @return [Array] Unsorted list of all CSRs associated with extensions listed as # mandatory or optional in portfolio. Uses CSRs provided by the # minimum version of the extension that meets the extension requirement. - def in_scope_csrs = @portfolio_grp.in_scope_csrs + # Factors in things like XLEN in design. + def in_scope_csrs = @portfolio_grp.in_scope_csrs(self) # @return [String] Given an extension +ext_name+, return the presence as a string. # Returns the greatest presence string across all portfolios in this design.