Class: Udb::ExtensionVersion
- Inherits:
-
Object
- Object
- Udb::ExtensionVersion
- Extended by:
- T::Sig
- Includes:
- Comparable
- Defined in:
- lib/udb/obj/extension.rb,
lib/udb/condition.rb
Overview
A specific version of an extension
Defined Under Namespace
Classes: MemomizedState
Instance Attribute Summary collapse
- #arch ⇒ ConfiguredArchitecture readonly
-
#ext ⇒ Extension
readonly
Extension.
-
#name ⇒ String
readonly
Name of the extension.
- #version_spec ⇒ VersionSpec readonly
- #version_str ⇒ String readonly
Class Method Summary collapse
-
.create(yaml, cfg_arch) ⇒ ExtensionVersion
create an ExtensionVersion from YAML.
-
.to_ext_req(ext_vers) ⇒ ExtensionRequirement
given a set of extension versions from the same extension, return the minimal set of extension requirements that would cover then all.
Instance Method Summary collapse
-
#<=>(other) ⇒ Integer?
sorts extension by name, then by version.
- #all_csrs_that_must_be_implemented ⇒ Array<Csr>
-
#all_instructions_that_must_be_implemented ⇒ Array<Instruction>
list of all instructions that must be defined if this extension version is implemented includes both those instructions directly defined by the extension plus any instruction that must exist because of a dependence.
-
#breaking? ⇒ Boolean
Whether or not this is a breaking version (i.e., incompatible with all prior versions).
-
#canonical_version ⇒ String
Canonical version string.
- #changes ⇒ Array<String>?
-
#compatible?(other) ⇒ Boolean
Whether or not
otheris compatible with self. -
#compatible_versions ⇒ Array<ExtensionVersion>
the list is inclsive (this version is present).
- #condition_hash ⇒ Hash{String => T.untyped}, false
- #conditional_extension_requirements(expand:) ⇒ Array<ConditionalExtensionRequirement>
-
#contributors ⇒ Array<Person>
List of contributors to this extension version.
- #csrs ⇒ Array<Csr>
- #defining_extension_requirements ⇒ Array<ConditionalExtensionRequirement>
-
#directly_defined_instructions ⇒ Array<Instruction>
excluding instructions required by a dependence.
- #directly_defined_instructions_set ⇒ Set<Instruction> private
- #eql?(other) ⇒ Boolean
-
#exception_codes ⇒ Array<ExceptionCode>
the list of exception codes that require this extension version (or a compatible version) in order to be defined.
- #ext_conflicts(expand:) ⇒ Array<ConditionalExtensionRequirement>
-
#ext_requirements(expand:) ⇒ Array<ConditionalExtensionRequirement>
list of requirements that must be met to implement this ExtensionVersion If conditional, the requirement only applies when the condition is true.
- #hash ⇒ Integer
- #implied_csrs ⇒ Array<Csr>
- #implied_instructions ⇒ Array<Instruction>
- #implied_instructions_set ⇒ Set<Instruction>
-
#in_scope_csrs(design) ⇒ Array<Csr>
List of CSRs in-scope for this design for this extension version (may be empty).
-
#in_scope_instructions(design) ⇒ Array<Instruction>
List of instructions in-scope for this design for this extension version (may be empty).
- #initialize(name, version_spec, arch, fail_if_version_does_not_exist: false) constructor
- #inspect ⇒ Object private
-
#interrupt_codes ⇒ Array<InterruptCode>
the list of interrupt codes that require this extension version (or a compatible version) in order to be defined.
-
#params ⇒ Array<Parameter, ParameterWithValue>
The list of parameters for this extension version.
- #ratification_date ⇒ String?
-
#requirements_condition ⇒ AbstractCondition
the combination of this extension version requirement along with the overall extension requirements.
-
#state ⇒ String
The state of the extension version (‘ratified’, ‘developemnt’, etc).
- #to_condition ⇒ AbstractCondition
- #to_ext_req ⇒ ExtensionRequirement
- #to_h ⇒ Hash{String => T.untyped}
-
#to_rvi_s ⇒ String
Formatted like the RVI manual.
-
#to_s ⇒ String
Ext@Version.
- #to_term ⇒ ExtensionTerm private
-
#unconditional_extension_conflicts(expand:) ⇒ Array<ExtensionRequirement>
return all ExtensionRequirements that this ExtensionVersion unconditionally conflicts with When expand is false, just return the list of ExtensionRequirements directly mentioned by the extension When expand is true, also include ExtensionRequirements that are required by those directly mentioned by the extension (i.e., collect the list from the transitive closure of requirements).
-
#unconditional_extension_requirements(expand:) ⇒ Array<ExtensionRequirement>
return all ExtensionRequirements that this ExtensionVersion unconditionally depends on When expand is false, just return the list of ExtensionRequirements directly mentioned by the extension When expand is true, also include ExtensionRequirements that are required by those directly mentioned by the extension (i.e., collect the list from the transitive closure of requirements).
-
#unconditional_extension_version_conflicts ⇒ Array<ExtensionVersion>
return the exhaustive, transitive list of all known extension versions that unconditionally conflict with self.
- #url ⇒ String?
-
#valid? ⇒ Boolean
true if the extension version is defined in the database, regardless of config false otherwise.
-
#version_specific_requirements_condition ⇒ AbstractCondition
Condition that must be met for this version to be allowed.
Constructor Details
#initialize(name, version_spec, arch, fail_if_version_does_not_exist: false)
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 |
# File 'lib/udb/obj/extension.rb', line 498 def initialize(name, version_spec, arch, fail_if_version_does_not_exist: false) @name = name.freeze @version_spec = version_spec.freeze @version_str = @version_spec.canonical.freeze @arch = arch @ext = @arch.extension(@name) if fail_if_version_does_not_exist && @ext.nil? raise "Extension #{name} not found in architecture" elsif @ext.nil? Udb.logger.warn "Extension #{name} not found in architecture" return # can't go futher end @data = @ext.data["versions"].find { |v| VersionSpec.new(v["version"]) == @version_spec } if fail_if_version_does_not_exist && @data.nil? raise ArgumentError, "Version #{version_str} of #{@name} extension is not defined" elsif @data.nil? Udb.logger.warn "Version #{version_str} of #{@name} extension is not defined" end @memo = MemomizedState.new end |
Instance Attribute Details
#arch ⇒ ConfiguredArchitecture (readonly)
447 448 449 |
# File 'lib/udb/obj/extension.rb', line 447 def arch @arch end |
#ext ⇒ Extension (readonly)
Returns Extension.
436 437 438 |
# File 'lib/udb/obj/extension.rb', line 436 def ext @ext end |
#name ⇒ String (readonly)
Returns Name of the extension.
432 433 434 |
# File 'lib/udb/obj/extension.rb', line 432 def name @name end |
#version_spec ⇒ VersionSpec (readonly)
440 441 442 |
# File 'lib/udb/obj/extension.rb', line 440 def version_spec @version_spec end |
#version_str ⇒ String (readonly)
444 445 446 |
# File 'lib/udb/obj/extension.rb', line 444 def version_str @version_str end |
Class Method Details
.create(yaml, cfg_arch) ⇒ ExtensionVersion
create an ExtensionVersion from YAML
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 |
# File 'lib/udb/obj/extension.rb', line 456 def self.create(yaml, cfg_arch) requirements = if yaml.key?("version") yaml.fetch("version") else raise "not an extension version" end if requirements.is_a?(Array) if requirements.size != 1 raise "not an extension version: #{requirements} (#{requirements.size})" end requirements = requirements.fetch(0) end begin cfg_arch.extension_version(yaml.fetch("name"), RequirementSpec.new(requirements).version_spec) rescue raise "not an extension version" end end |
.to_ext_req(ext_vers) ⇒ ExtensionRequirement
given a set of extension versions from the same extension, return the minimal set of extension requirements that would cover then all
542 543 544 545 546 547 548 549 550 551 552 |
# File 'lib/udb/obj/extension.rb', line 542 def self.to_ext_req(ext_vers) raise "ext_vers cannot be empty" if ext_vers.empty? raise "All ext_vers must be of the same extension" unless ext_vers.all? { |ev| ev.name == ext_vers.fetch(0).name } sorted = ext_vers.sort unless T.must(sorted.min).compatible?(T.must(sorted.max)) raise "Impossible to combine because the set contains incompatible versions" end ext_vers.fetch(0).arch.extension_requirement(ext_vers.fetch(0).name, "~> #{T.must(sorted.min).version_str}") end |
Instance Method Details
#<=>(other) ⇒ Integer?
sorts extension by name, then by version
1166 1167 1168 1169 1170 1171 1172 1173 1174 |
# File 'lib/udb/obj/extension.rb', line 1166 def <=>(other) return nil unless other.is_a?(ExtensionVersion) if other.name != @name @name <=> other.name else @version_spec <=> other.version_spec end end |
#all_csrs_that_must_be_implemented ⇒ Array<Csr>
771 772 773 |
# File 'lib/udb/obj/extension.rb', line 771 def all_csrs_that_must_be_implemented @all_csrs_that_must_be_implemented ||= csrs + implied_csrs end |
#all_instructions_that_must_be_implemented ⇒ Array<Instruction>
list of all instructions that must be defined if this extension version is implemented includes both those instructions directly defined by the extension plus any instruction that must exist because of a dependence
721 722 723 724 |
# File 'lib/udb/obj/extension.rb', line 721 def all_instructions_that_must_be_implemented @all_instructions_that_must_be_implemented ||= directly_defined_instructions + implied_instructions end |
#breaking? ⇒ Boolean
Returns Whether or not this is a breaking version (i.e., incompatible with all prior versions).
599 600 601 |
# File 'lib/udb/obj/extension.rb', line 599 def breaking? !@data["breaking"].nil? end |
#canonical_version ⇒ String
Returns Canonical version string.
605 |
# File 'lib/udb/obj/extension.rb', line 605 def canonical_version = @version_spec.canonical |
#changes ⇒ Array<String>?
629 |
# File 'lib/udb/obj/extension.rb', line 629 def changes = @data["changes"].nil? ? [] : T.cast(@data.fetch("changes"), T::Array[String]) |
#compatible?(other) ⇒ Boolean
Returns Whether or not other is compatible with self.
595 |
# File 'lib/udb/obj/extension.rb', line 595 def compatible?(other) = compatible_versions.include?(other) |
#compatible_versions ⇒ Array<ExtensionVersion>
the list is inclsive (this version is present)
579 580 581 582 583 584 585 586 587 588 589 590 |
# File 'lib/udb/obj/extension.rb', line 579 def compatible_versions return @memo.compatible_versions unless @memo.compatible_versions.nil? @memo.compatible_versions = [] @ext.versions.each do |v| @memo.compatible_versions << v if v.version_spec >= @version_spec break if @memo.compatible_versions.size.positive? && v.breaking? end raise "Didn't even find self?" if compatible_versions.empty? @memo.compatible_versions end |
#condition_hash ⇒ Hash{String => T.untyped}, false
567 568 569 570 571 572 573 574 |
# File 'lib/udb/obj/extension.rb', line 567 def condition_hash { "extension" => { "name" => name, "version" => "= #{version_str}" } } end |
#conditional_extension_requirements(expand:) ⇒ Array<ConditionalExtensionRequirement>
965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 |
# File 'lib/udb/obj/extension.rb', line 965 def conditional_extension_requirements(expand:) if && !@memo..nil? @memo. elsif ! && !@memo..nil? @memo. else req = requirements_condition.to_logic_tree(expand:) cb = LogicNode.make_replace_cb do |node| next node unless node.type == LogicNodeType::Term rterm = node.children.fetch(0) next node unless rterm.is_a?(ExtensionTerm) # remove self next LogicNode::True if rterm.to_ext_req(@arch).satisfied_by?(self) # remove terms unconditionally true or false next LogicNode::True if unconditional_extension_requirements(expand: true).any? { |ext_req| ext_req.satisfied_by?(rterm.to_ext_req(@arch)) } next LogicNode::False if unconditional_extension_conflicts(expand: true).any? { |ext_req| ext_req.satisfied_by?(rterm.to_ext_req(@arch)) } node end remaining = req.replace_terms(cb).minimize(LogicNode::CanonicalizationType::ProductOfSums) list = T.let([], T::Array[ConditionalExtensionRequirement]) # for the remaining terms, find out which ones remaining.terms.each do |term| next unless term.is_a?(ExtensionTerm) # find unconditional reqs of self && term c = Condition.conjunction([term.to_condition(@arch), to_condition], @arch) ctree = c.to_logic_tree(expand: true) unconditional_terms = remaining.terms.select do |cterm| next if cterm.is_a?(ParameterTerm) || cterm.is_a?(XlenTerm) raise "?" if cterm.is_a?(FreeTerm) next if cterm.name == name next if cterm.name == term.name cb = LogicNode.make_replace_cb do |node| if node.type == LogicNodeType::Term && node.node_children.fetch(0).is_a?(ExtensionTerm) node_term = T.cast(node.node_children.fetch(0), ExtensionTerm) if node_term.name == name LogicNode::True elsif node_term.name == cterm.name LogicNode::False else node end else node end end !ctree.replace_terms(cb).satisfiable? end next if unconditional_terms.empty? if unconditional_terms.size == 1 cond = T.cast(unconditional_terms.fetch(0), ExtensionTerm).to_ext_req(@arch).to_condition contradiction = Condition.conjunction( [ cond, Condition.not(term.to_condition(@arch), @arch), to_condition ], @arch ) is_needed = !contradiction.satisfiable? if is_needed if Condition.conjunction([cond, Condition.not(term.to_condition(@arch), @arch)], @arch).satisfiable? # skip reqs that are implied list << ConditionalExtensionRequirement.new( ext_req: term.to_ext_req(@arch), cond: ) end end else conj = Condition.conjunction(unconditional_terms.map { |t| T.cast(t, ExtensionTerm).to_condition(@arch) }, @arch) conj_tree = conj.to_logic_tree(expand: false) formula = LogicNode.new( LogicNodeType::And, conj_tree.node_children.map do |node| covered = conj_tree.node_children.any? do |other_node| next false if node.equal?(other_node) if Condition.conjunction([to_condition, Condition.new(other_node.to_h, @arch)], @arch).always_implies?(Condition.new(node.to_h, @arch)) true else false end end if covered LogicNode::True else node end end ) # is this needed? if self can still be satisfied when condition is false but term is true, # this term isn't actually a requirement (it's most likely related to a conflict) contradiction = Condition.conjunction( [ conj, Condition.not(term.to_condition(@arch), @arch), to_condition ], @arch ) is_needed = !contradiction.satisfiable? cond = Condition.new(formula.reduce.to_h, @arch) if is_needed # && Condition.conjunction([cond, term.to_condition(@arch), to_condition], @arch).satisfiable? # make sure it's a requirement if Condition.conjunction([cond, Condition.not(term.to_condition(@arch), @arch)], @arch).satisfiable? list << ConditionalExtensionRequirement.new( ext_req: term.to_ext_req(@arch), cond: ) end end end end if list.each do |cond_ext_req| ext_ver = T.must(cond_ext_req.ext_req..max) ext_ver.ext_requirements(expand:).each do |nested_cond_ext_req| already_in_cond_list = list.any? { |c| c.ext_req.satisfied_by?(nested_cond_ext_req.ext_req) } \ || list.any? { |c| c.cond.to_logic_tree(expand: false).terms.any? { |t| T.cast(t, ExtensionTerm).to_ext_req(@arch).satisfied_by?(nested_cond_ext_req.ext_req) } } already_in_uncond_list = unconditional_extension_requirements(expand:).any? { |ext_req| nested_cond_ext_req.ext_req.satisfied_by?(ext_req) } next if already_in_uncond_list if already_in_cond_list # keep the one with the more expansive condition else if nested_cond_ext_req.cond.empty? list << ConditionalExtensionRequirement.new( ext_req: nested_cond_ext_req.ext_req, cond: cond_ext_req.cond ) else list << ConditionalExtensionRequirement.new( ext_req: nested_cond_ext_req.ext_req, cond: Condition.conjunction([cond_ext_req.cond, nested_cond_ext_req.cond], @arch) ) end end end end end if @memo. = list @memo..freeze else @memo. = list @memo..freeze end end end |
#contributors ⇒ Array<Person>
Returns List of contributors to this extension version.
636 637 638 639 640 641 642 643 644 |
# File 'lib/udb/obj/extension.rb', line 636 def contributors return @contributors unless @contributors.nil? @contributors = [] @data["contributors"]&.each do |c| @contributors << Person.new(c) end @contributors end |
#csrs ⇒ Array<Csr>
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 |
# File 'lib/udb/obj/extension.rb', line 732 def csrs @csrs ||= begin pb = Udb.( "Finding csrs for #{self} [:bar] :current/:total", total: @arch.csrs.size, clear: true ) @arch.csrs.select do |csr| pb.advance if csr.defined_by_condition.mentions?(self, expand: false) (-csr.defined_by_condition & to_condition).unsatisfiable? && (-csr.defined_by_condition & requirements_condition).satisfiable? end end end end |
#defining_extension_requirements ⇒ Array<ConditionalExtensionRequirement>
826 827 828 829 |
# File 'lib/udb/obj/extension.rb', line 826 def defining_extension_requirements [] # combined_requirements_condition.implied_extension_requirements end |
#directly_defined_instructions ⇒ Array<Instruction>
excluding instructions required by a dependence
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 |
# File 'lib/udb/obj/extension.rb', line 668 def directly_defined_instructions @instructions ||= begin pb = Udb.( "Finding instructions for #{self} [:bar] :current/:total", total: @arch.instructions.size, clear: true ) @arch.instructions.select do |i| pb.advance i_defined = i.defined_by_condition if i_defined.mentions?(self, expand: false) version_implemented = to_condition preconditions_met = requirements_condition (-i_defined & version_implemented).unsatisfiable? && \ (-i_defined & preconditions_met).satisfiable? end end end end |
#directly_defined_instructions_set ⇒ Set<Instruction>
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.
693 694 695 |
# File 'lib/udb/obj/extension.rb', line 693 def directly_defined_instructions_set @instructions_set ||= Set.new(directly_defined_instructions) end |
#eql?(other) ⇒ Boolean
608 609 610 611 612 613 614 |
# File 'lib/udb/obj/extension.rb', line 608 def eql?(other) if other.is_a?(ExtensionVersion) self.==(other) else false end end |
#exception_codes ⇒ Array<ExceptionCode>
the list of exception codes that require this extension version (or a compatible version) in order to be defined
1179 1180 1181 1182 1183 1184 1185 1186 1187 |
# File 'lib/udb/obj/extension.rb', line 1179 def exception_codes @exception_codes ||= @arch.exception_codes.select do |ecode| # define every extension version except this one (and compatible), # and test if the condition can be satisfied ecode.defined_by_condition.satisfied_by_ext_req?(@arch.extension_requirement(@name, "~> #{@version_spec}"), include_requirements: false) || ecode.defined_by_condition.satisfiability_depends_on_ext_req?(@arch.extension_requirement(@name, "~> #{@version_spec}")) end end |
#ext_conflicts(expand:) ⇒ Array<ConditionalExtensionRequirement>
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 |
# File 'lib/udb/obj/extension.rb', line 1153 def ext_conflicts(expand:) # make a condition for the version, expand it, and then report what comes out, minus self if @memo. ||= unconditional_extension_conflicts(expand:).map { |ext_req| ConditionalExtensionRequirement.new(ext_req:, cond: AlwaysTrueCondition.new(@arch)) } else @memo. ||= unconditional_extension_conflicts(expand:).map { |ext_req| ConditionalExtensionRequirement.new(ext_req:, cond: AlwaysTrueCondition.new(@arch)) } end end |
#ext_requirements(expand:) ⇒ Array<ConditionalExtensionRequirement>
list of requirements that must be met to implement this ExtensionVersion If conditional, the requirement only applies when the condition is true
1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 |
# File 'lib/udb/obj/extension.rb', line 1139 def ext_requirements(expand:) # make a condition for the version, expand it, and then report what comes out, minus self if @memo. ||= unconditional_extension_requirements(expand:).map { |ext_req| ConditionalExtensionRequirement.new(ext_req:, cond: AlwaysTrueCondition.new(@arch)) } \ + conditional_extension_requirements(expand:) else @memo. ||= unconditional_extension_requirements(expand:).map { |ext_req| ConditionalExtensionRequirement.new(ext_req:, cond: AlwaysTrueCondition.new(@arch)) } \ + conditional_extension_requirements(expand:) end end |
#hash ⇒ Integer
617 618 619 |
# File 'lib/udb/obj/extension.rb', line 617 def hash @memo.key ||= [@name, @version_spec].hash end |
#implied_csrs ⇒ Array<Csr>
752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 |
# File 'lib/udb/obj/extension.rb', line 752 def implied_csrs @implied_csrs ||= begin pb = Udb.( "Finding implied csrs for #{self} [:bar] :current/:total", total: @arch.csrs.size, clear: true ) @arch.csrs.select do |csr| pb.advance if csr.defined_by_condition.mentions?(self, expand: true) (-csr.defined_by_condition & requirements_condition).unsatisfiable? end end end end |
#implied_instructions ⇒ Array<Instruction>
698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 |
# File 'lib/udb/obj/extension.rb', line 698 def implied_instructions @implied_instructions ||= begin pb = Udb.( "Finding implied instructions for #{self} [:bar] :current/:total", total: @arch.instructions.size, clear: true ) @arch.instructions.select do |i| pb.advance next if directly_defined_instructions_set.include?(i) (-i.defined_by_condition & to_condition).unsatisfiable? end end end |
#implied_instructions_set ⇒ Set<Instruction>
727 728 729 |
# File 'lib/udb/obj/extension.rb', line 727 def implied_instructions_set @implied_instructions_set ||= Set.new(implied_instructions) end |
#in_scope_csrs(design) ⇒ Array<Csr>
Returns 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.
1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 |
# File 'lib/udb/obj/extension.rb', line 1203 def in_scope_csrs(design) raise ArgumentError, "Require an PortfolioDesign object but got a #{design.class} object" unless design.is_a?(PortfolioDesign) return @in_scope_csrs unless @in_scope_csrs.nil? @in_scope_csrs = @arch.csrs.select do |csr| csr.defined_by_condition.satisfiability_depends_on_ext_req?(to_ext_req) && (csr.base.nil? || (design.possible_xlens.include?(csr.base))) end end |
#in_scope_instructions(design) ⇒ Array<Instruction>
Returns 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.
1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 |
# File 'lib/udb/obj/extension.rb', line 1217 def in_scope_instructions(design) raise ArgumentError, "Require an PortfolioDesign object but got a #{design.class} object" unless design.is_a?(PortfolioDesign) return @in_scope_instructions unless @in_scope_instructions.nil? @in_scope_instructions = @arch.instructions.select do |inst| inst.defined_by_condition.satisfiability_depends_on_ext_req?(to_ext_req) && (inst.base.nil? || (design.possible_xlens.include?(inst.base))) end end |
#inspect ⇒ Object
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.
530 531 532 |
# File 'lib/udb/obj/extension.rb', line 530 def inspect to_s end |
#interrupt_codes ⇒ Array<InterruptCode>
the list of interrupt codes that require this extension version (or a compatible version) in order to be defined
1192 1193 1194 1195 1196 1197 1198 |
# File 'lib/udb/obj/extension.rb', line 1192 def interrupt_codes @interrupt_codes ||= @arch.interrupt_codes.select do |icode| icode.defined_by_condition.satisfied_by_ext_req?(@arch.extension_requirement(@name, "~> #{@version_spec}"), include_requirements: false) || icode.defined_by_condition.satisfiability_depends_on_ext_req?(@arch.extension_requirement(@name, "~> #{@version_spec}")) end end |
#params ⇒ Array<Parameter, ParameterWithValue>
Returns The list of parameters for this extension version.
648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 |
# File 'lib/udb/obj/extension.rb', line 648 def params @params ||= begin if valid? && ext.versions.size == 1 ext.params elsif !valid? [] else ext.params.select do |p| # c = self and not any other version of the extension (-p.defined_by_condition & to_condition).unsatisfiable? && \ (-p.defined_by_condition & requirements_condition).satisfiable? end end end end |
#ratification_date ⇒ String?
626 |
# File 'lib/udb/obj/extension.rb', line 626 def ratification_date = @data["ratification_date"] |
#requirements_condition ⇒ AbstractCondition
the combination of this extension version requirement along with the overall extension requirements
806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 |
# File 'lib/udb/obj/extension.rb', line 806 def requirements_condition @requirements_condition ||= if @data.key?("requirements") && ext.data.key?("requirements") Condition.new( { "allOf" => [ @data.fetch("requirements"), ext.data.fetch("requirements") ] }, @arch ) elsif !@data.key?("requirements") ext.general_extension_requirements_condition else version_specific_requirements_condition end end |
#state ⇒ String
Returns The state of the extension version (‘ratified’, ‘developemnt’, etc).
623 |
# File 'lib/udb/obj/extension.rb', line 623 def state = T.cast(@data.fetch("state"), String) |
#to_condition ⇒ AbstractCondition
561 562 563 564 |
# File 'lib/udb/obj/extension.rb', line 561 def to_condition @memo.condition ||= Condition.new(condition_hash, @arch) end |
#to_ext_req ⇒ ExtensionRequirement
1229 1230 1231 |
# File 'lib/udb/obj/extension.rb', line 1229 def to_ext_req @ext_req ||= @arch.extension_requirement(name, "= #{version_str}") end |
#to_h ⇒ Hash{String => T.untyped}
1234 1235 1236 1237 1238 1239 1240 |
# File 'lib/udb/obj/extension.rb', line 1234 def to_h @h ||= { "name" => @name, "version" => "= #{version_str}" } end |
#to_rvi_s ⇒ String
Returns formatted like the RVI manual.
780 781 782 |
# File 'lib/udb/obj/extension.rb', line 780 def to_rvi_s "#{name}#{@version_spec.to_rvi_s}" end |
#to_s ⇒ String
Returns Ext@Version.
786 787 788 |
# File 'lib/udb/obj/extension.rb', line 786 def to_s "#{name}@#{@version_spec.canonical}" end |
#to_term ⇒ ExtensionTerm
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.
556 557 558 |
# File 'lib/udb/obj/extension.rb', line 556 def to_term @memo.term ||= ExtensionTerm.new(@name, "=", @version_str) end |
#unconditional_extension_conflicts(expand:) ⇒ Array<ExtensionRequirement>
return all ExtensionRequirements that this ExtensionVersion unconditionally conflicts with When expand is false, just return the list of ExtensionRequirements directly mentioned by the extension When expand is true, also include ExtensionRequirements that are required by those directly mentioned by the extension
(i.e., collect the list from the transitive closure of requirements)
909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 |
# File 'lib/udb/obj/extension.rb', line 909 def unconditional_extension_conflicts(expand:) if && !@memo..nil? @memo. elsif ! && !@memo..nil? @memo. else list = begin requirements_condition.ext_req_terms(expand:).select do |ext_req| (requirements_condition & ext_req.to_condition).unsatisfiable? end # req = requirements_condition.to_logic_tree(expand:) # expand_req = requirements_condition.to_logic_tree(expand: true) # # find all unconditional reqs -- that is, # # reqs that must always be satisfied for requirements to be met # unconditional_terms = # req.terms.select do |term| # next if term.is_a?(ParameterTerm) || term.is_a?(XlenTerm) # raise "?" if term.is_a?(FreeTerm) # next if term.name == name # # see if req is unsatisfiable when term is present # cb = LogicNode.make_replace_cb do |node| # if node.type == LogicNodeType::Term && node.node_children.fetch(0).is_a?(ExtensionTerm) # node_term = T.cast(node.node_children.fetch(0), ExtensionTerm) # if node_term.name == name # LogicNode::True # elsif node_term.name == term.name # LogicNode::True # else # node # end # else # node # end # end # !expand_req.replace_terms(cb).satisfiable? # end # T.cast(unconditional_terms, T::Array[ExtensionTerm]).map { |t| t.to_ext_req(@arch) } end if @memo. = list @memo..freeze else @memo. = list @memo..freeze end end end |
#unconditional_extension_requirements(expand:) ⇒ Array<ExtensionRequirement>
return all ExtensionRequirements that this ExtensionVersion unconditionally depends on When expand is false, just return the list of ExtensionRequirements directly mentioned by the extension When expand is true, also include ExtensionRequirements that are required by those directly mentioned by the extension
(i.e., collect the list from the transitive closure of requirements)
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 885 886 887 888 889 |
# File 'lib/udb/obj/extension.rb', line 836 def unconditional_extension_requirements(expand:) if && !@memo..nil? @memo. elsif ! && !@memo..nil? @memo. else list = begin requirements_condition.ext_req_terms(expand:).select do |ext_req| # is requirements_condition satisfiable when ext_req is not met? (requirements_condition & -ext_req.to_condition).unsatisfiable? end # req = requirements_condition.to_logic_tree(expand:) # expand_req = requirements_condition.to_logic_tree(expand: true) # # find all unconditional reqs -- that is, # # reqs that must always be satisfied for requirements to be met # unconditional_terms = # req.terms.select do |term| # next if term.is_a?(ParameterTerm) || term.is_a?(XlenTerm) # raise "?" if term.is_a?(FreeTerm) # next if term.name == name # # see if req is satisfiable when term is absent # cb = LogicNode.make_replace_cb do |node| # if node.type == LogicNodeType::Term && node.node_children.fetch(0).is_a?(ExtensionTerm) # node_term = T.cast(node.node_children.fetch(0), ExtensionTerm) # if node_term.name == name # LogicNode::True # elsif node_term.name == term.name # LogicNode::False # else # node # end # else # node # end # end # !expand_req.replace_terms(cb).satisfiable? # end # T.cast(unconditional_terms, T::Array[ExtensionTerm]).map { |t| t.to_ext_req(@arch) } end if @memo. = list @memo..freeze else @memo. = list @memo..freeze end end end |
#unconditional_extension_version_conflicts ⇒ Array<ExtensionVersion>
return the exhaustive, transitive list of all known extension versions that unconditionally conflict with self
894 895 896 897 898 899 900 901 902 |
# File 'lib/udb/obj/extension.rb', line 894 def unconditional_extension_version_conflicts @unconditional_extension_version_conflicts ||= @arch.extension_versions.select do |ext_ver| next if ext_ver.name == name (to_condition & ext_ver.to_condition).unsatisfiable? # !Condition.conjunction([to_condition, ext_ver.to_condition], @arch).satisfiable? end end |
#url ⇒ String?
632 |
# File 'lib/udb/obj/extension.rb', line 632 def url = @data["url"] |
#valid? ⇒ Boolean
true if the extension version is defined in the database, regardless of config false otherwise
527 |
# File 'lib/udb/obj/extension.rb', line 527 def valid? = !@ext.nil? |
#version_specific_requirements_condition ⇒ AbstractCondition
Returns Condition that must be met for this version to be allowed.
792 793 794 795 796 797 798 799 800 801 802 |
# File 'lib/udb/obj/extension.rb', line 792 def version_specific_requirements_condition @requirements_condition ||= @data.key?("requirements") \ ? Condition.new( @data.fetch("requirements"), @arch, input_file: Pathname.new(ext.__source), input_line: ext.source_line(["versions", ext.data.fetch("versions").index { |v| VersionSpec.new(v["version"]) == version_spec }]) ) : AlwaysTrueCondition.new(@arch) end |