Class: Udb::ConfiguredArchitecture
- Inherits:
-
Architecture
- Object
- Architecture
- Udb::ConfiguredArchitecture
- Extended by:
- T::Sig
- Defined in:
- lib/udb/cfg_arch.rb,
lib/udb/condition.rb
Defined Under Namespace
Classes: MemoizedState, ValidationResult
Constant Summary collapse
- @@yaml_data_cache =
This classvariable is part of a private API. You should avoid using this classvariable if possible, as it may be removed or be changed in the future.
metaprogramming function to create accessor methods for top-level database objects
This is defined in ConfiguredArchitecture, rather than Architecture because the object models all expect to work with a ConfiguredArchitecture
For example, created the following functions:
extensions # array of all extensions extension_hash # hash of all extensions, indexed by name extension(name) # getter for extension 'name' instructions # array of all extensions instruction_hash # hash of all extensions, indexed by name instruction(name) # getter for extension 'name' ...Class-level cache of raw YAML file contents keyed by "#resolved_spec_path/#obj_type_dir". Maps each directory to an array of [content, original_path, realpath] triples so that a second ConfiguredArchitecture sharing the same spec path skips disk I/O and file locking. Benign race: two threads both missing the cache produce identical entries.
Concurrent::Hash.new
Instance Attribute Summary collapse
- #config ⇒ AbstractConfig readonly
-
#idl_compiler ⇒ Idl::Compiler
readonly
The IDL compiler.
-
#name ⇒ String
readonly
Name of this definition.
Class Method Summary collapse
Instance Method Summary collapse
-
#_hash ⇒ Array<>, ...
private
metaprogramming function to create accessor methods for top-level database objects.
-
#arch_condition ⇒ Condition
a condition representing the architecture, independent of the config.
- #config_type ⇒ ConfigType
-
#constructing_symtab? ⇒ Boolean
Used by implemented? callback to avoid triggering the Z3 solver on a partial symtab.
-
#convert_monospace_to_links(adoc) ⇒ String
Given an adoc string, find names of CSR/Instruction/Extension enclosed in
monospaceand replace them with links to the relevant object page. - #csrs_that_must_be_implemented(show_progress: false) ⇒ Array<Csr>
- #eql?(other) ⇒ Boolean
-
#expand_implemented_extension_list(ext_vers) ⇒ Array<ExtensionVersion>
given the current (invalid) config, try to come up with a list of extension versions that, if added, might make the config valid.
-
#explicitly_implemented_extension_versions ⇒ Object
deprecated
Deprecated.
in favor of implemented_extension_versions
-
#ext?(ext_name, ext_version_requirements = []) ⇒ Object
sig { params(ext_name: T.any(String, Symbol), ext_version_requirements: T::Array).returns(T::Boolean) }.
- #extension_requirement(name, requirements) ⇒ ExtensionRequirement
- #extension_version(name, version) ⇒ ExtensionVersion
-
#fetch ⇒ Idl::FetchAst
Fetch block.
- #fully_configured? ⇒ Boolean
- #function(name) ⇒ Idl::FunctionDefAst?
- #function_hash ⇒ Hash{String => Idl::FunctionDefAst}
-
#functions ⇒ Array<Idl::FunctionDefAst>
List of all functions defined by the architecture.
- #global_ast ⇒ Idl::IsaAst
-
#globals ⇒ Array<Idl::GlobalAst, Idl::GlobalWithInitializationAst>
List of globals.
-
#hash ⇒ Integer
private
hash for Hash lookup.
-
#implemented_csrs ⇒ Array<Csr>
List of all implemented CSRs.
-
#implemented_exception_codes ⇒ Array<ExceptionCode>
All exception codes known to be implemented.
- #implemented_extension_version(ext_name) ⇒ ExtensionVersion?
-
#implemented_extension_versions ⇒ Array<ExtensionVersion>
List of extension versions explicitly marked as implemented in the config.
-
#implemented_functions ⇒ Array<Idl::FunctionDefAst>
List of all reachable IDL functions for the config.
-
#implemented_instructions(show_progress: false) ⇒ Array<Instruction>
List of all implemented instructions, sorted by name.
-
#implemented_interrupt_codes ⇒ Array<InterruptCode>
All interrupt codes known to be implemented.
-
#implemented_non_isa_specs ⇒ Array<T.untyped>
List of all implemented non-ISA specs, filtered by configuration.
-
#in_scope_condition ⇒ Condition
a condition where both mandatory and non-mandatory extensions are required.
-
#in_scope_csrs(show_progress: false) ⇒ Array<Csr>
CSRs that are defined by mentioned extensions in the config.
-
#initialize(name, config)
constructor
Initialize a new configured architecture definition.
- #inspect ⇒ Object
- #instructions_that_must_be_implemented(show_progress: false) ⇒ Array<Csr>
-
#largest_encoding ⇒ Integer
The largest instruction encoding in the config.
-
#mandatory_extension_reqs ⇒ Array<ExtensionRequirement>
List of all mandatory extension requirements (not transitive).
-
#multi_xlen? ⇒ Boolean
Returns whether or not it may be possible to switch XLEN given this definition.
-
#multi_xlen_in_mode?(mode) ⇒ Boolean
Returns whether or not it may be possible to switch XLEN in
modegiven this definition. -
#mxlen ⇒ Integer?
MXLEN parameter value, or nil if it is not known.
-
#non_mandatory_extension_reqs ⇒ Array<ExtensionRequirement>
List of all mandatory extension requirements (not transitive).
-
#optional_extension_versions ⇒ Array<ExtensionRequirement>
list of all the extension versions that optional, i.e: lis of all the extension versions would not fufill a mandatory requirement and are not prhohibited.
-
#out_of_scope_params ⇒ Array<Parameter>
Returns list of parameters that out of scope for the config.
-
#param_term_satisfied_memo ⇒ Hash<ParameterTerm, SatisfiedResult>
Memoized Z3 satisfiability result for a ParameterTerm against this cfg_arch.
-
#param_values ⇒ Hash{String => T.untyped}
known parameter values as a hash of param_name => param_value.
-
#params_with_value ⇒ Array<ParameterWithValue>
List of all parameters with one known value in the config.
-
#params_without_value ⇒ Array<Parameter>
List of all available parameters without one known value in the config.
-
#partial_config_strictly_specified? ⇒ ValidationResult
returns whether or not the partial config transitively lists all requirements of mandatory extensions (as other mandatory extension and/or parameters).
- #partially_configured? ⇒ Boolean
-
#possible_csrs(show_progress: false) ⇒ Array<Csr>
(also: #not_prohibited_csrs)
List of all CSRs that it is possible to implement.
-
#possible_extension_versions ⇒ Object
the complete set of extension versions that could be implemented in this config.
-
#possible_extension_versions_by_name ⇒ Hash<String, Array<ExtensionVersion>>
Possible_extension_versions grouped by name.
-
#possible_extensions ⇒ Array<Extension>
(also: #not_prohibited_extensions)
List of extensions that are possibly supported.
-
#possible_instructions(show_progress: false) ⇒ Array<Instruction>
(also: #not_prohibited_instructions)
List of all instructions that are not prohibited by the config, sorted by name.
-
#possible_non_isa_specs ⇒ Array<T.untyped>
List of all non-ISA specs that could apply to this configuration.
- #possible_xlen?(xlen) ⇒ Boolean
-
#possible_xlens ⇒ Array<Integer>
List of possible XLENs in any mode for this config.
- #prohibited_ext?(ext) ⇒ Boolean
-
#prohibited_extension_versions ⇒ Array<ExtensionVersion>
List of all extension versions that are prohibited.
-
#prohibited_instructions ⇒ Array<Instruction>
List of all prohibited instructions, sorted by name.
-
#reachable_functions(show_progress: false) ⇒ Array<Idl::FunctionDefAst>
List of functions that can be reached by the configuration.
-
#render_erb(erb_template, what = "") ⇒ String
passes erb_template through ERB within the content of this config.
-
#s ⇒ Array<>, ...
private
metaprogramming function to create accessor methods for top-level database objects.
-
#symtab ⇒ Idl::SymbolTable
Symbol table with global scope included.
-
#to_condition ⇒ Condition
represent the config and architecture defintion as a Condition.
-
#transitive_implemented_csrs ⇒ Object
deprecated
Deprecated.
in favor of implemented_csrs
-
#transitive_implemented_extension_versions ⇒ Object
deprecated
Deprecated.
in favor of implemented_extension_versions
- #transitive_implemented_instructions ⇒ Object
-
#transitive_implemented_non_isa_specs ⇒ Object
deprecated
Deprecated.
in favor of #implemented_non_isa_specs
- #transitive_prohibited_instructions ⇒ Object
-
#type_check(show_progress: true, io: $stderr)
type check all IDL, including globals, instruction ops, and CSR functions.
- #unconfigured? ⇒ Boolean
-
#valid? ⇒ ValidationResult
whether or not the configuration is valid.
Constructor Details
#initialize(name, config)
Initialize a new configured architecture definition
675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 |
# File 'lib/udb/cfg_arch.rb', line 675 def initialize(name, config) Udb.logger.info "Constructing ConfiguredArchiture for #{name}" super(config.info.resolved_spec_path) @name = name.to_s.freeze @name_sym = @name.to_sym.freeze @memo = MemoizedState.new( multi_xlen_in_mode: {}, extension_requirements_hash: {}, extension_versions_hash: {} ) @config = config @config_type = T.let(@config.type, ConfigType) @mxlen = config.mxlen @mxlen.freeze @idl_compiler = Idl::Compiler.new end |
Instance Attribute Details
#config ⇒ AbstractConfig (readonly)
51 52 53 |
# File 'lib/udb/cfg_arch.rb', line 51 def config @config end |
#idl_compiler ⇒ Idl::Compiler (readonly)
Returns The IDL compiler.
41 42 43 |
# File 'lib/udb/cfg_arch.rb', line 41 def idl_compiler @idl_compiler end |
#name ⇒ String (readonly)
Returns Name of this definition. Special names are:
- '_' - The generic architecture, with no configuration settings.
- 'rv32' - A generic RV32 architecture, with only one parameter set (XLEN == 32)
- 'rv64' - A generic RV64 architecture, with only one parameter set (XLEN == 64).
48 49 50 |
# File 'lib/udb/cfg_arch.rb', line 48 def name @name end |
Class Method Details
.generate_obj_methods(fn_name, arch_dir, obj_class)
This method returns an undefined value.
733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 |
# File 'lib/udb/cfg_arch.rb', line 733 def self.generate_obj_methods(fn_name, arch_dir, obj_class) plural_fn = ActiveSupport::Inflector.pluralize(fn_name) define_method(plural_fn) do return @objects[arch_dir] unless @objects[arch_dir].nil? @objects[arch_dir] = Concurrent::Array.new @object_hashes[arch_dir] = Concurrent::Hash.new yaml_cache_key = "#{@arch_dir}/#{arch_dir}" cached_files = @@yaml_data_cache[yaml_cache_key] if cached_files.nil? entries = [] Dir.glob(@arch_dir / arch_dir / "**" / "*.yaml") do |obj_path| File.open(obj_path) do |f| f.flock(File::LOCK_EX) content = f.read f.flock(File::LOCK_UN) entries << [content, obj_path, Pathname.new(obj_path).realpath] end end cached_files = @@yaml_data_cache[yaml_cache_key] = entries end cached_files.each do |content, obj_path, realpath| obj_yaml = YAML.load(content, filename: obj_path, permitted_classes: [Date]) @objects[arch_dir] << obj_class.new(obj_yaml, realpath, T.cast(self, ConfiguredArchitecture)) @object_hashes[arch_dir][@objects[arch_dir].last.name] = @objects[arch_dir].last end @objects[arch_dir] end define_method("#{fn_name}_hash") do return @object_hashes[arch_dir] unless @object_hashes[arch_dir].nil? send(plural_fn) # create the hash @object_hashes[arch_dir] end define_method(fn_name) do |name| return @object_hashes[arch_dir][name] unless @object_hashes[arch_dir].nil? send(plural_fn) # create the hash @object_hashes[arch_dir][name] end end |
Instance Method Details
#_hash ⇒ Array<>, ...
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
metaprogramming function to create accessor methods for top-level database objects
This is defined in ConfiguredArchitecture, rather than Architecture because the object models all expect to work with a ConfiguredArchitecture
For example, created the following functions:
extensions # array of all extensions
extension_hash # hash of all extensions, indexed by name
extension(name) # getter for extension 'name'
instructions # array of all extensions
instruction_hash # hash of all extensions, indexed by name
instruction(name) # getter for extension 'name'
...
Class-level cache of raw YAML file contents keyed by "#resolved_spec_path/#obj_type_dir". Maps each directory to an array of [content, original_path, realpath] triples so that a second ConfiguredArchitecture sharing the same spec path skips disk I/O and file locking. Benign race: two threads both missing the cache produce identical entries.
730 |
# File 'lib/udb/cfg_arch.rb', line 730 @@yaml_data_cache = Concurrent::Hash.new |
#arch_condition ⇒ Condition
a condition representing the architecture, independent of the config
1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 |
# File 'lib/udb/cfg_arch.rb', line 1339 def arch_condition @arch_condition ||= begin extension_version_conditions = extension_versions.map do |ext_ver| unless ext_ver.requirements_condition.empty? ext_ver.to_condition.implies(ext_ver.requirements_condition) end end.compact c = Condition.conjunction(extension_version_conditions, self) params.each do |param| unless param.requirements_condition.empty? c = c & param.defined_by_condition.implies(param.requirements_condition) end end c end end |
#constructing_symtab? ⇒ Boolean
Used by implemented? callback to avoid triggering the Z3 solver on a partial symtab.
231 |
# File 'lib/udb/cfg_arch.rb', line 231 def constructing_symtab? = (@constructing_symtab_depth || 0) > 0 |
#convert_monospace_to_links(adoc) ⇒ String
Given an adoc string, find names of CSR/Instruction/Extension enclosed in monospace
and replace them with links to the relevant object page.
See backend_helpers.rb for a definition of the proprietary link format.
1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 |
# File 'lib/udb/cfg_arch.rb', line 1621 def convert_monospace_to_links(adoc) h = Class.new do include Udb::Helpers::TemplateHelpers end.new adoc.gsub(/`([\w.]+)`/) do |match| name = Regexp.last_match(1) csr_name, field_name = T.must(name).split(".") csr = not_prohibited_csrs.find { |c| c.name == csr_name } if !field_name.nil? && !csr.nil? && csr.field?(field_name) h.link_to_udb_doc_csr_field(csr_name, field_name) elsif !csr.nil? h.link_to_udb_doc_csr(csr_name) elsif not_prohibited_instructions.any? { |inst| inst.name == name } h.link_to_udb_doc_inst(name) elsif not_prohibited_extensions.any? { |ext| ext.name == name } h.link_to_udb_doc_ext(name) else match end end end |
#csrs_that_must_be_implemented(show_progress: false) ⇒ Array<Csr>
1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 |
# File 'lib/udb/cfg_arch.rb', line 1294 def csrs_that_must_be_implemented(show_progress: false) @csrs_that_must_be_implemented ||= if @config.fully_configured? implemented_csrs elsif @config.partially_configured? = if show_progress Udb.("determining CSRs that must be implemented [:bar]", total: csrs.size, output: $stdout) end csrs.select do |csr| .advance if show_progress (-csr.defined_by_condition).unsatisfiable_by_cfg_arch?(self) end else [] end end |
#eql?(other) ⇒ Boolean
194 195 196 197 198 |
# File 'lib/udb/cfg_arch.rb', line 194 def eql?(other) return false unless other.__send__(:is_a?, ConfiguredArchitecture) @name.eql?(other.__send__(:name)) end |
#expand_implemented_extension_list(ext_vers) ⇒ Array<ExtensionVersion>
given the current (invalid) config, try to come up with a list of extension versions that, if added, might make the config valid
For example, if C, F, and D are implemented but not Zca, Zcf, Zcd, return [Zca, Zcf, Zcd]
999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 |
# File 'lib/udb/cfg_arch.rb', line 999 def (ext_vers) # build up a condition requiring all ext_vers, have it expand, and then minimize it # what's left is the full list condition = Condition.conjunction(ext_vers.map(&:to_condition), self) res = condition.implied_extension_requirements (ext_vers + res.map do |cond_ext_req| if cond_ext_req.cond.empty? cond_ext_req.ext_req..fetch(0) else nil end end.compact).uniq end |
#explicitly_implemented_extension_versions ⇒ Object
in favor of implemented_extension_versions
943 |
# File 'lib/udb/cfg_arch.rb', line 943 def explicitly_implemented_extension_versions = implemented_extension_versions |
#ext?(ext_name) ⇒ Boolean #ext?(ext_name, ext_version_requirements) ⇒ Boolean
sig { params(ext_name: T.any(String, Symbol), ext_version_requirements: T::Array).returns(T::Boolean) }
1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 |
# File 'lib/udb/cfg_arch.rb', line 1176 def ext?(ext_name, ext_version_requirements = []) @ext_cache ||= {} cached_result = @ext_cache[[ext_name, ext_version_requirements]] return cached_result unless cached_result.nil? result = if @config.fully_configured? implemented_extension_versions.any? do |e| if ext_version_requirements.empty? e.name == ext_name.to_s else requirement = extension_requirement(ext_name.to_s, ext_version_requirements) requirement.satisfied_by?(e) end end elsif @config.partially_configured? mandatory_extension_reqs.any? do |e| if ext_version_requirements.empty? e.name == ext_name.to_s else requirement = extension_requirement(ext_name.to_s, ext_version_requirements) e..all? do |ext_ver| requirement.satisfied_by?(ext_ver) end end end else raise "unexpected type" unless unconfigured? false end @ext_cache[[ext_name, ext_version_requirements]] = result end |
#extension_requirement(name, requirements) ⇒ ExtensionRequirement
949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 |
# File 'lib/udb/cfg_arch.rb', line 949 def extension_requirement(name, requirements) requirement_specs = if requirements.is_a?(Array) if requirements.fetch(0).is_a?(RequirementSpec) requirements else requirements.map { |r| RequirementSpec.new(r) } end else if requirements.is_a?(RequirementSpec) requirements else RequirementSpec.new(requirements) end end key = if requirement_specs.is_a?(Array) [name, *requirement_specs].hash else [name, requirement_specs].hash end cached_ext_req = @memo.extension_requirements_hash[key] if cached_ext_req.nil? ext_req = ExtensionRequirement.send(:new, name, requirement_specs, arch: self) @memo.extension_requirements_hash[key] = ext_req else cached_ext_req end end |
#extension_version(name, version) ⇒ ExtensionVersion
981 982 983 984 985 986 987 988 989 990 991 992 |
# File 'lib/udb/cfg_arch.rb', line 981 def extension_version(name, version) version_spec = version.is_a?(VersionSpec) ? version : VersionSpec.new(version) key = [name, version_spec].hash cached_ext_ver = @memo.extension_versions_hash[key] if cached_ext_ver.nil? ext_req = ExtensionVersion.send(:new, name, version_spec, self, fail_if_version_does_not_exist: true) @memo.extension_versions_hash[key] = ext_req else cached_ext_ver end end |
#fetch ⇒ Idl::FetchAst
Returns Fetch block.
1242 1243 1244 |
# File 'lib/udb/cfg_arch.rb', line 1242 def fetch @fetch ||= global_ast.fetch end |
#fully_configured? ⇒ Boolean
54 |
# File 'lib/udb/cfg_arch.rb', line 54 def fully_configured? = @config.fully_configured? |
#function(name) ⇒ Idl::FunctionDefAst?
1236 1237 1238 |
# File 'lib/udb/cfg_arch.rb', line 1236 def function(name) function_hash[name] end |
#function_hash ⇒ Hash{String => Idl::FunctionDefAst}
1231 1232 1233 |
# File 'lib/udb/cfg_arch.rb', line 1231 def function_hash @function_hash ||= functions.map { |f| [f.name, f] }.to_h end |
#functions ⇒ Array<Idl::FunctionDefAst>
Returns List of all functions defined by the architecture.
1226 1227 1228 |
# File 'lib/udb/cfg_arch.rb', line 1226 def functions @functions ||= global_ast.functions end |
#global_ast ⇒ Idl::IsaAst
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/udb/cfg_arch.rb', line 234 def global_ast @global_ast ||= begin # now add globals to the phase1 symtab = @config.info. custom_globals_path = .nil? ? Pathname.new("/does/not/exist") : / "isa" / "globals.isa" idl_path = File.exist?(custom_globals_path) ? custom_globals_path : @config.info.spec_path / "isa" / "globals.isa" Udb.logger.info "Compiling global IDL" pb = Udb.( "Compiling IDL for #{name} [:bar]", clear: true ) @idl_compiler.pb = pb ast = @idl_compiler.compile_file( idl_path ) pb.finish @idl_compiler.unset_pb ast end end |
#globals ⇒ Array<Idl::GlobalAst, Idl::GlobalWithInitializationAst>
Returns List of globals.
1248 1249 1250 1251 1252 |
# File 'lib/udb/cfg_arch.rb', line 1248 def globals return @globals unless @globals.nil? @globals = global_ast.globals end |
#hash ⇒ Integer
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
hash for Hash lookup
191 |
# File 'lib/udb/cfg_arch.rb', line 191 def hash = @name_sym.hash |
#implemented_csrs ⇒ Array<Csr>
Returns List of all implemented CSRs.
1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 |
# File 'lib/udb/cfg_arch.rb', line 1256 def implemented_csrs @implemented_csrs ||= begin unless fully_configured? raise ArgumentError, "implemented_csrs is only defined for fully configured systems" end csrs.select do |csr| csr.defined_by_condition.satisfied_by_cfg_arch?(self) == SatisfiedResult::Yes end end end |
#implemented_exception_codes ⇒ Array<ExceptionCode>
Returns All exception codes known to be implemented.
1212 1213 1214 1215 |
# File 'lib/udb/cfg_arch.rb', line 1212 def implemented_exception_codes @implemented_exception_codes ||= exception_codes.select { |code| code.defined_by_condition.satisfiable_by_cfg_arch?(self) } end |
#implemented_extension_version(ext_name) ⇒ ExtensionVersion?
1019 1020 1021 1022 1023 1024 |
# File 'lib/udb/cfg_arch.rb', line 1019 def implemented_extension_version(ext_name) @memo.implemented_extension_version_hash ||= implemented_extension_versions.to_h { |ext_ver| [ext_ver.name, ext_ver] } @memo.implemented_extension_version_hash[ext_name] end |
#implemented_extension_versions ⇒ Array<ExtensionVersion>
Returns List of extension versions explicitly marked as implemented in the config.
929 930 931 932 933 934 935 936 937 938 939 940 |
# File 'lib/udb/cfg_arch.rb', line 929 def implemented_extension_versions @memo.implemented_extension_versions ||= begin unless fully_configured? raise ArgumentError, "implemented_extension_versions only valid for fully configured systems" end T.cast(@config, FullConfig).implemented_extensions.map do |e| extension_version(e.fetch("name"), e.fetch("version")) end end end |
#implemented_functions ⇒ Array<Idl::FunctionDefAst>
Returns List of all reachable IDL functions for the config.
1540 1541 1542 |
# File 'lib/udb/cfg_arch.rb', line 1540 def implemented_functions reachable_functions(show_progress: false) end |
#implemented_instructions(show_progress: false) ⇒ Array<Instruction>
Returns List of all implemented instructions, sorted by name.
1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 |
# File 'lib/udb/cfg_arch.rb', line 1442 def implemented_instructions(show_progress: false) unless fully_configured? raise ArgumentError, "implemented_instructions is only defined for fully configured systems" end @implemented_instructions ||= begin = if show_progress Udb.("determining implemented instructions [:bar] :current/:total", total: instructions.size) end instructions.select do |inst| .advance if show_progress inst.defined_by_condition.satisfiable_by_cfg_arch?(self) # inst.defined_by_condition.satisfied_by_cfg_arch?(self) == SatisfiedResult::Yes end end end |
#implemented_interrupt_codes ⇒ Array<InterruptCode>
Returns All interrupt codes known to be implemented.
1219 1220 1221 1222 |
# File 'lib/udb/cfg_arch.rb', line 1219 def implemented_interrupt_codes @implemented_interupt_codes ||= implemented_exception_codes.select { |code| code.defined_by_condition.satisfiable_by_cfg_arch?(self) } end |
#implemented_non_isa_specs ⇒ Array<T.untyped>
Returns List of all implemented non-ISA specs, filtered by configuration.
1762 1763 1764 1765 1766 1767 1768 1769 1770 |
# File 'lib/udb/cfg_arch.rb', line 1762 def implemented_non_isa_specs return @implemented_non_isa_specs if defined?(@implemented_non_isa_specs) @implemented_non_isa_specs = possible_non_isa_specs.select do |spec| spec.exists_in_cfg?(self) end @implemented_non_isa_specs end |
#in_scope_condition ⇒ Condition
a condition where both mandatory and non-mandatory extensions are required
1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 |
# File 'lib/udb/cfg_arch.rb', line 1406 def in_scope_condition @in_scope_condition ||= begin if fully_configured? ( Condition.conjunction(implemented_extension_versions.map(&:to_condition), self) \ & \ Condition.conjunction( params_with_value.map do |pv| Condition.new({ "param" => { "name" => pv.name, "equal" => pv.value } }, self) end, self ) ) elsif partially_configured? c = ( Condition.conjunction(mandatory_extension_reqs.map(&:to_condition) + non_mandatory_extension_reqs.map(&:to_condition), self) \ & \ Condition.conjunction( params_with_value.map do |pv| Condition.new({ "param" => { "name" => pv.name, "equal" => pv.value } }, self) end, self ) ) reqs = T.cast(@config, PartialConfig).requirements unless reqs.nil? c = (c & Condition.new(reqs, self)) end c end end end |
#in_scope_csrs(show_progress: false) ⇒ Array<Csr>
CSRs that are defined by mentioned extensions in the config
For a full config, this is CSRs defined by the implemented extensions
For a partial config, this is CSRs defined by the mandatory or non-mandatory extensions
1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 |
# File 'lib/udb/cfg_arch.rb', line 1319 def in_scope_csrs(show_progress: false) @mentioned_csrs ||= if @config.fully_configured? implemented_csrs elsif @config.partially_configured? = if show_progress Udb.("determining in scope CSRs [:bar]", total: csrs.size, output: $stdout) end csrs.select do |csr| .advance if show_progress (-csr.defined_by_condition & in_scope_condition).unsatisfiable? end else [] end end |
#inspect ⇒ Object
696 697 698 |
# File 'lib/udb/cfg_arch.rb', line 696 def inspect "CfgArch##{name}" end |
#instructions_that_must_be_implemented(show_progress: false) ⇒ Array<Csr>
1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 |
# File 'lib/udb/cfg_arch.rb', line 1514 def instructions_that_must_be_implemented(show_progress: false) @instructions_that_must_be_implemented ||= if @config.fully_configured? implemented_instructions elsif @config.partially_configured? = if show_progress Udb.("determining instructions that must be implemented [:bar]", total: instructions.size, clear: true) end instructions.select do |inst| .advance if show_progress (-inst.defined_by_condition).unsatisfiable_by_cfg_arch?(self) end else [] end end |
#largest_encoding ⇒ Integer
Returns The largest instruction encoding in the config.
1534 1535 1536 |
# File 'lib/udb/cfg_arch.rb', line 1534 def largest_encoding @largest_encoding ||= possible_instructions.map(&:max_encoding_width).max end |
#mandatory_extension_reqs ⇒ Array<ExtensionRequirement>
Returns List of all mandatory extension requirements (not transitive).
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 |
# File 'lib/udb/cfg_arch.rb', line 1028 def mandatory_extension_reqs @mandatory_extension_reqs ||= begin raise "Only partial configs have mandatory extension requirements" unless @config.is_a?(PartialConfig) @config.mandatory_extensions.map do |e| ename = T.cast(e["name"], String) if e["version"].nil? extension_requirement(ename, ">= 0") else extension_requirement(ename, e.fetch("version")) end end end end |
#multi_xlen? ⇒ Boolean
Returns whether or not it may be possible to switch XLEN given this definition.
There are three cases when this will return true:
1. A mode (e.g., U) is known to be implemented, and the CSR bit that controls XLEN in that mode is known to be writable.
2. A mode is known to be implemented, but the writability of the CSR bit that controls XLEN in that mode is not known.
3. It is not known if the mode is implemented.
81 82 83 84 85 86 87 88 |
# File 'lib/udb/cfg_arch.rb', line 81 def multi_xlen? @memo.multi_xlen ||= begin return true if @mxlen.nil? ["S", "U", "VS", "VU"].any? { |mode| multi_xlen_in_mode?(mode) } end end |
#multi_xlen_in_mode?(mode) ⇒ Boolean
Returns whether or not it may be possible to switch XLEN in mode given this definition.
There are three cases when this will return true:
1. +mode+ (e.g., U) is known to be implemented, and the CSR bit that controls XLEN in +mode+ is known to be writable.
2. +mode+ is known to be implemented, but the writability of the CSR bit that controls XLEN in +mode+ is not known.
3. It is not known if +mode+ is implemented.
Will return false if mode is not possible (e.g., because U is a prohibited extension)
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/udb/cfg_arch.rb', line 103 def multi_xlen_in_mode?(mode) @memo.multi_xlen_in_mode[mode] ||= begin return false if mxlen == 32 case mode when "M", "D" mxlen.nil? when "S" return true if unconfigured? if fully_configured? ext?(:S) && (param_values["SXLEN"].size > 1) elsif partially_configured? return false if prohibited_ext?(:S) return true unless ext?(:S) # if S is not known to be implemented, we can't say anything about it return true unless param_values.key?("SXLEN") param_values["SXLEN"].size > 1 else raise "Unexpected configuration state" end when "U" return false if prohibited_ext?(:U) return true if unconfigured? if fully_configured? ext?(:U) && (param_values["UXLEN"].size > 1) elsif partially_configured? return true unless ext?(:U) # if U is not known to be implemented, we can't say anything about it return true unless param_values.key?("UXLEN") param_values["UXLEN"].size > 1 else raise "Unexpected configuration state" end when "VS" return false if prohibited_ext?(:H) return true if unconfigured? if fully_configured? ext?(:H) && (param_values["VSXLEN"].size > 1) elsif partially_configured? return true unless ext?(:H) # if H is not known to be implemented, we can't say anything about it return true unless param_values.key?("VSXLEN") param_values["VSXLEN"].size > 1 else raise "Unexpected configuration state" end when "VU" return false if prohibited_ext?(:H) return true if unconfigured? if fully_configured? ext?(:H) && (param_values["VUXLEN"].size > 1) elsif partially_configured? return true unless ext?(:H) # if H is not known to be implemented, we can't say anything about it return true unless param_values.key?("VUXLEN") param_values["VUXLEN"].size > 1 else raise "Unexpected configuration state" end else raise ArgumentError, "Bad mode: #{mode}" end end end |
#mxlen ⇒ Integer?
MXLEN parameter value, or nil if it is not known
64 |
# File 'lib/udb/cfg_arch.rb', line 64 def mxlen = @config.mxlen |
#non_mandatory_extension_reqs ⇒ Array<ExtensionRequirement>
Returns List of all mandatory extension requirements (not transitive).
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 |
# File 'lib/udb/cfg_arch.rb', line 1047 def non_mandatory_extension_reqs @non_mandatory_extension_reqs ||= begin raise "Only partial configs have non-mandatory extension requirements" unless @config.is_a?(PartialConfig) @config.non_mandatory_extensions.map do |e| ename = T.cast(e["name"], String) if e["version"].nil? extension_requirement(ename, ">= 0") else extension_requirement(ename, e.fetch("version")) end end end end |
#optional_extension_versions ⇒ Array<ExtensionRequirement>
list of all the extension versions that optional, i.e: lis of all the extension versions would not fufill a mandatory requirement and are not prhohibited
1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 |
# File 'lib/udb/cfg_arch.rb', line 1067 def optional_extension_versions @optional_extension_versions ||= begin if fully_configured? [] elsif partially_configured? # optional is all extensions - mandatory - prohibited extension_versions.reject do |ext_ver| mandatory_extension_reqs.any? { |ext_req| ext_req.satisfied_by?(ext_ver) } || prohibited_extension_versions.any? { |prohibited_ext_ver| prohibited_ext_ver == ext_ver } end else # unconfig; all extension versions are optional extension_versions end end end |
#out_of_scope_params ⇒ Array<Parameter>
Returns list of parameters that out of scope for the config
913 914 915 916 917 918 919 920 921 922 923 924 925 |
# File 'lib/udb/cfg_arch.rb', line 913 def out_of_scope_params @memo.out_of_scope_params ||= begin out_of_scope_params = [] params.each do |param| next if params_with_value.any? { |p| p.name == param.name } next if params_without_value.any? { |p| p.name == param.name } out_of_scope_params << param end out_of_scope_params end end |
#param_term_satisfied_memo ⇒ Hash<ParameterTerm, SatisfiedResult>
Memoized Z3 satisfiability result for a ParameterTerm against this cfg_arch. Keyed by ParameterTerm (uses hash/eql? based on yaml_no_reason), so identical terms across different Condition objects share the same Z3 result.
1138 1139 1140 |
# File 'lib/udb/cfg_arch.rb', line 1138 def param_term_satisfied_memo @param_term_satisfied_memo ||= {} end |
#param_values ⇒ Hash{String => T.untyped}
known parameter values as a hash of param_name => param_value
68 |
# File 'lib/udb/cfg_arch.rb', line 68 def param_values = @config.param_values |
#params_with_value ⇒ Array<ParameterWithValue>
Returns List of all parameters with one known value in the config.
888 889 890 891 892 893 894 895 896 897 898 899 |
# File 'lib/udb/cfg_arch.rb', line 888 def params_with_value @memo.params_with_value ||= @config.param_values.map do |param_name, param_value| p = param(param_name) if p.nil? Udb.logger.warn "#{param_name} is not a parameter" nil else ParameterWithValue.new(p, param_value) end end.compact end |
#params_without_value ⇒ Array<Parameter>
List of all available parameters without one known value in the config
903 904 905 906 907 908 909 |
# File 'lib/udb/cfg_arch.rb', line 903 def params_without_value @memo.params_without_value ||= params.select do |p| !@config.param_values.key?(p.name) \ && p.defined_by_condition.could_be_satisfied_by_cfg_arch?(self) end end |
#partial_config_strictly_specified? ⇒ ValidationResult
returns whether or not the partial config transitively lists all requirements of mandatory extensions (as other mandatory extension and/or parameters)
For example:
mandatory_extensions: - name: A
is not strictly specified
but
mandatory_extensions: - name: A - name: Zaamo - name: Zalrsc
is
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 |
# File 'lib/udb/cfg_arch.rb', line 386 def partial_config_strictly_specified? raise "not a partial config" unless partially_configured? v = partial_config_valid? reasons = [] mandatory_extension_reqs.each do |ext_req| if ext_req.requirements_condition.satisfied_by_cfg_arch?(self) != SatisfiedResult::Yes failing = ext_req.requirements_condition.failing_conjuncts(self, expand: false) reasons << "Requirement of #{ext_req} are not met:\n" + if failing.empty? " Condition not yet determined: #{ext_req.requirements_condition.to_s_with_value(self, expand: false)}" else failing.map { |f| " - #{f}" }.join("\n") end end end ValidationResult.new(valid: v.valid & reasons.empty?, reasons: v.reasons + reasons) end |
#partially_configured? ⇒ Boolean
57 |
# File 'lib/udb/cfg_arch.rb', line 57 def partially_configured? = @config.partially_configured? |
#possible_csrs(show_progress: false) ⇒ Array<Csr> Also known as: not_prohibited_csrs
Returns List of all CSRs that it is possible to implement.
1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 |
# File 'lib/udb/cfg_arch.rb', line 1274 def possible_csrs(show_progress: false) @not_prohibited_csrs ||= if @config.fully_configured? implemented_csrs elsif @config.partially_configured? = if show_progress TTY::ProgressBar.new("determining possible CSRs [:bar]", total: csrs.size, output: $stdout) end csrs.select do |csr| .advance if show_progress csr.defined_by_condition.satisfiable_by_cfg_arch?(self) end else csrs end end |
#possible_extension_versions ⇒ Object
the complete set of extension versions that could be implemented in this config
1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 |
# File 'lib/udb/cfg_arch.rb', line 1112 def possible_extension_versions @possible_extension_versions ||= begin if @config.partially_configured? extension_versions.select { |ext_ver| ext_ver.to_condition.satisfiable_by_cfg_arch?(self) } elsif @config.fully_configured? # full config: only the implemented versions are possible implemented_extension_versions else # unconfig; everything is possible extensions.map(&:versions).flatten end end end |
#possible_extension_versions_by_name ⇒ Hash<String, Array<ExtensionVersion>>
Returns possible_extension_versions grouped by name.
1128 1129 1130 1131 |
# File 'lib/udb/cfg_arch.rb', line 1128 def possible_extension_versions_by_name @possible_extension_versions_by_name ||= possible_extension_versions.group_by(&:name) end |
#possible_extensions ⇒ Array<Extension> Also known as: not_prohibited_extensions
Returns List of extensions that are possibly supported.
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 |
# File 'lib/udb/cfg_arch.rb', line 1087 def possible_extensions return @not_prohibited_extensions if defined?(@not_prohibited_extensions) @not_prohibited_extensions ||= if @config.fully_configured? implemented_extension_versions.map { |ext_ver| ext_ver.ext }.uniq elsif @config.partially_configured? pb = Udb.("determining possible exts [:bar] :current/:total", total: extensions.size) extensions.select { |e| pb.advance; (e.to_condition).satisfiable_by_cfg_arch?(self) } else extensions end end |
#possible_instructions(show_progress: false) ⇒ Array<Instruction> Also known as: not_prohibited_instructions
Returns List of all instructions that are not prohibited by the config, sorted by name.
1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 |
# File 'lib/udb/cfg_arch.rb', line 1485 def possible_instructions(show_progress: false) return @not_prohibited_instructions if defined?(@not_prohibited_instructions) @not_prohibited_instructions ||= if @config.fully_configured? implemented_instructions(show_progress:) elsif @config.partially_configured? = if show_progress TTY::ProgressBar.new("determining possible instructions [:bar] :current/:total", total: instructions.size, clear: true) end instructions.select do |inst| .advance if show_progress inst.defined_by_condition.satisfiable_by_cfg_arch?(self) # possible_xlens.any? { |xlen| inst.defined_in_base?(xlen) } && \ # inst.defined_by_condition.satisfied_by_cfg_arch?(self) != SatisfiedResult::No end else instructions end @not_prohibited_instructions end |
#possible_non_isa_specs ⇒ Array<T.untyped>
Returns List of all non-ISA specs that could apply to this configuration.
1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 |
# File 'lib/udb/cfg_arch.rb', line 1731 def possible_non_isa_specs return @possible_non_isa_specs if defined?(@possible_non_isa_specs) @possible_non_isa_specs = [] # Discover local non-ISA specifications non_isa_path = Pathname.new(__dir__).parent.parent.parent.parent.parent / "spec/custom/non_isa" if non_isa_path.exist? non_isa_path.glob("*.yaml").each do |spec_file| next if spec_file.basename.to_s.start_with?("prm") # Skip PRM files begin spec_name = spec_file.basename(".yaml").to_s spec_data = YAML.load_file(spec_file) next unless spec_data["kind"] == "non-isa specification" spec_obj = Udb::NonIsaSpecification.new(spec_name, spec_data) @possible_non_isa_specs << spec_obj rescue => e Udb.logger.warn "Failed to load non-ISA spec #{spec_file}: #{e.}" end end end @possible_non_isa_specs.sort_by(&:name) end |
#possible_xlen?(xlen) ⇒ Boolean
186 |
# File 'lib/udb/cfg_arch.rb', line 186 def possible_xlen?(xlen) = possible_xlens.include?(xlen) |
#possible_xlens ⇒ Array<Integer>
Returns List of possible XLENs in any mode for this config.
183 |
# File 'lib/udb/cfg_arch.rb', line 183 def possible_xlens = multi_xlen? ? [32, 64] : [mxlen] |
#prohibited_ext?(ext) ⇒ Boolean #prohibited_ext?(ext) ⇒ Boolean
1152 1153 1154 1155 1156 1157 1158 1159 1160 |
# File 'lib/udb/cfg_arch.rb', line 1152 def prohibited_ext?(ext) if ext.is_a?(ExtensionVersion) prohibited_extension_versions.include?(ext) elsif ext.is_a?(String) || ext.is_a?(Symbol) prohibited_extension_versions.any? { |ext_ver| ext_ver.name == ext.to_s } else raise ArgumentError, "Argument to prohibited_ext? should be an ExtensionVersion or a String" end end |
#prohibited_extension_versions ⇒ Array<ExtensionVersion>
Returns List of all extension versions that are prohibited. This includes extensions explicitly prohibited by the config file and extensions that conflict with a mandatory extension.
1106 1107 1108 1109 |
# File 'lib/udb/cfg_arch.rb', line 1106 def prohibited_extension_versions @prohibited_extension_versions ||= extension_versions - possible_extension_versions end |
#prohibited_instructions ⇒ Array<Instruction>
Returns List of all prohibited instructions, sorted by name.
1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 |
# File 'lib/udb/cfg_arch.rb', line 1466 def prohibited_instructions @prohibited_instructions ||= if fully_configured? (instructions - implemented_instructions).sort elsif partially_configured? instructions.select do |inst| inst.defined_by_condition.unsatisfiable_by_cfg_arch?(self) # inst.defined_by_condition.satisfied_by_cfg_arch?(self) == SatisfiedResult::No end.sort else [] end end |
#reachable_functions(show_progress: false) ⇒ Array<Idl::FunctionDefAst>
Returns List of functions that can be reached by the configuration.
1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 |
# File 'lib/udb/cfg_arch.rb', line 1546 def reachable_functions(show_progress: false) return @reachable_functions unless @reachable_functions.nil? @reachable_functions = [] insts = possible_instructions(show_progress:) csrs = possible_csrs(show_progress:) = if show_progress TTY::ProgressBar.new("determining reachable IDL functions [:bar]", total: insts.size + csrs.size + 1 + global_ast.functions.size, output: $stdout) end # Shared cache across all instructions/CSRs so that common utility functions # are only traversed once rather than once per instruction. shared_cache = { 32 => T.let({}, Idl::AstNode::ReachableFunctionCacheType), 64 => T.let({}, Idl::AstNode::ReachableFunctionCacheType) } possible_instructions.each do |inst| .advance if show_progress fns = if inst.base.nil? if multi_xlen? (inst.reachable_functions(32, shared_cache.fetch(32)) + inst.reachable_functions(64, shared_cache.fetch(32))) else inst.reachable_functions(possible_xlens.fetch(0), shared_cache.fetch(possible_xlens.fetch(0))) end else inst.reachable_functions(T.must(inst.base), shared_cache.fetch(T.must(inst.base))) end @reachable_functions.concat(fns) end @reachable_functions += possible_csrs.flat_map do |csr| .advance if show_progress csr.reachable_functions(nil, shared_cache) end.uniq # now add everything from fetch st = @symtab.global_clone st.push(global_ast.fetch.body) possible_xlens.each do |xlen| @reachable_functions += global_ast.fetch.body.reachable_functions(st, shared_cache.fetch(xlen)) end .advance if show_progress st.release # now add everything from external functions st = @symtab.global_clone global_ast.functions.select { |fn| fn.external? }.each do |fn| st.push(fn) @reachable_functions << fn .advance if show_progress st.pop end st.release @reachable_functions.uniq! @reachable_functions end |
#render_erb(erb_template, what = "") ⇒ String
passes erb_template through ERB within the content of this config
1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 |
# File 'lib/udb/cfg_arch.rb', line 1713 def render_erb(erb_template, what = "") t = Tempfile.new("template") t.write erb_template t.flush begin Tilt["erb"].new(t.path, trim: "-").render(erb_env) rescue Udb.logger.error "While rendering ERB template: #{what}" raise ensure t.close t.unlink end end |
#s ⇒ Array<>, ...
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
metaprogramming function to create accessor methods for top-level database objects
This is defined in ConfiguredArchitecture, rather than Architecture because the object models all expect to work with a ConfiguredArchitecture
For example, created the following functions:
extensions # array of all extensions
extension_hash # hash of all extensions, indexed by name
extension(name) # getter for extension 'name'
instructions # array of all extensions
instruction_hash # hash of all extensions, indexed by name
instruction(name) # getter for extension 'name'
...
Class-level cache of raw YAML file contents keyed by "#resolved_spec_path/#obj_type_dir". Maps each directory to an array of [content, original_path, realpath] triples so that a second ConfiguredArchitecture sharing the same spec path skips disk I/O and file locking. Benign race: two threads both missing the cache produce identical entries.
730 |
# File 'lib/udb/cfg_arch.rb', line 730 @@yaml_data_cache = Concurrent::Hash.new |
#symtab ⇒ Idl::SymbolTable
Returns Symbol table with global scope included.
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/udb/cfg_arch.rb', line 202 def symtab @symtab ||= begin @symtab = create_symtab # Guard against re-entrant solver calls from within add_global_symbols. # Global initializers (e.g. FLEN) may call implemented?(), which triggers # prohibited_ext?() and the Z3 solver chain. If those calls see @symtab is # already set (partial), they'd use an incomplete symtab and fail. # A depth counter (rather than a boolean) is used so that if this block # ever nests (e.g. create_symtab is called recursively in the future), # the inner ensure does not prematurely clear the guard for the outer block. @constructing_symtab_depth = (@constructing_symtab_depth || 0) + 1 begin global_ast.add_global_symbols(@symtab) ensure @constructing_symtab_depth -= 1 end @symtab.deep_freeze raise if @symtab.name.nil? global_ast.freeze_tree(@symtab) @symtab end end |
#to_condition ⇒ Condition
represent the config and architecture defintion as a Condition
1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 |
# File 'lib/udb/cfg_arch.rb', line 1360 def to_condition @to_condition ||= begin if fully_configured? ( arch_condition \ & \ Condition.conjunction(implemented_extension_versions.map(&:to_condition), self) \ & \ Condition.conjunction( params_with_value.map do |pv| Condition.new({ "param" => { "name" => pv.name, "equal" => pv.value } }, self) end, self ) ) elsif partially_configured? c = arch_condition c = c & Condition.conjunction(mandatory_extension_reqs.map(&:to_condition), self) unless params_with_value.empty? c = c & Condition.conjunction( params_with_value.map do |pv| Condition.new({ "param" => { "name" => pv.name, "equal" => pv.value } }, self) end, self ) end unless T.cast(@config, PartialConfig).prohibited_extensions.empty? prohib = T.cast(@config, PartialConfig).prohibited_extensions.map do |e| extension_requirement(T.cast(e.fetch("name"), String), e.fetch("version")) end c = c & -Condition.disjunction(prohib.map(&:to_condition), self) end reqs = T.cast(@config, PartialConfig).requirements unless reqs.nil? c = (c & Condition.new(reqs, self)) end c else arch_condition end end end |
#transitive_implemented_csrs ⇒ Object
in favor of implemented_csrs
1270 |
# File 'lib/udb/cfg_arch.rb', line 1270 def transitive_implemented_csrs = implemented_csrs |
#transitive_implemented_extension_versions ⇒ Object
in favor of implemented_extension_versions
946 |
# File 'lib/udb/cfg_arch.rb', line 946 def transitive_implemented_extension_versions = implemented_extension_versions |
#transitive_implemented_instructions ⇒ Object
1462 |
# File 'lib/udb/cfg_arch.rb', line 1462 def transitive_implemented_instructions = implemented_instructions |
#transitive_implemented_non_isa_specs ⇒ Object
in favor of #implemented_non_isa_specs
1773 |
# File 'lib/udb/cfg_arch.rb', line 1773 def transitive_implemented_non_isa_specs = implemented_non_isa_specs |
#transitive_prohibited_instructions ⇒ Object
1481 |
# File 'lib/udb/cfg_arch.rb', line 1481 def transitive_prohibited_instructions = prohibited_instructions |
#type_check(show_progress: true, io: $stderr)
This method returns an undefined value.
type check all IDL, including globals, instruction ops, and CSR functions
794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 |
# File 'lib/udb/cfg_arch.rb', line 794 def type_check(show_progress: true, io: $stderr) io.puts "Type checking IDL code for #{@config.name}..." if show_progress insts = @config.unconfigured? ? instructions : possible_instructions(show_progress:) xlens = @config.unconfigured? ? [32, 64] : possible_xlens = if show_progress TTY::ProgressBar.new("type checking possible instructions [:bar] :current/:total", total: insts.size, output: io) end insts.each do |inst| .advance if show_progress if @mxlen == 32 if inst.rv32? inst.pruned_operation_ast(32) end else if inst.rv64? inst.pruned_operation_ast(64) end if xlens.include?(32) && inst.rv32? inst.pruned_operation_ast(32) end end end csr_list = @config.unconfigured? ? csrs : possible_csrs = if show_progress TTY::ProgressBar.new("type checking CSRs [:bar] :current/:total", total: csr_list.size, output: io) end csr_list.each do |csr| .advance if show_progress # Cache CSR base checks to avoid repeated method calls csr_in_base32 = csr.defined_in_base32? csr_in_base64 = csr.defined_in_base64? if csr.has_custom_sw_read? if (xlens.include?(32) && csr_in_base32) csr.type_checked_pruned_sw_read_ast(32) end if (xlens.include?(64) && csr_in_base64) csr.type_checked_pruned_sw_read_ast(64) end end csr.possible_fields.each do |field| if field.reset_value_ast if xlens.include?(32) && csr_in_base32 && field.defined_in_base32? field.pruned_reset_value_ast end if xlens.include?(64) && csr_in_base64 && field.defined_in_base64? field.pruned_reset_value_ast end end if field.has_custom_sw_write? if xlens.include?(32) && csr_in_base32 && field.defined_in_base32? field.pruned_sw_write_ast(32) end if xlens.include?(64) && csr_in_base64 && field.defined_in_base64? field.pruned_sw_write_ast(64) end end if field.type_ast if xlens.include?(32) && csr_in_base32 && field.defined_in_base32? field.pruned_type_ast(32) end if xlens.include?(64) && csr_in_base64 && field.defined_in_base64? field.pruned_type_ast(64) end end end end func_list = @config.unconfigured? ? functions : reachable_functions(show_progress:) = if show_progress TTY::ProgressBar.new("type checking functions [:bar] :current/:total", total: func_list.size, output: io) end func_list.each do |func| .advance if show_progress s = symtab.global_clone s.push(func) pruned = func.prune(s) s.pop pruned.type_check(s, strict: true) s.release end puts "done" if show_progress end |
#unconfigured? ⇒ Boolean
60 |
# File 'lib/udb/cfg_arch.rb', line 60 def unconfigured? = @config.unconfigured? |
#valid? ⇒ ValidationResult
whether or not the configuration is valid. if it's not, reasons are provided
268 269 270 271 272 273 274 275 276 |
# File 'lib/udb/cfg_arch.rb', line 268 def valid? if fully_configured? full_config_valid? elsif partially_configured? partial_config_valid? else ValidationResult.new(valid: true, reasons: []) end end |