Class: Udb::Extension

Inherits:
TopLevelDatabaseObject show all
Includes:
Comparable
Defined in:
lib/udb/obj/extension.rb,
lib/udb/condition.rb

Overview

Extension definition

Defined Under Namespace

Classes: ConditionallyApplicableParameter

Instance Method Summary collapse

Constructor Details

This class inherits a constructor from Udb::TopLevelDatabaseObject

Instance Method Details

#<=>(other_ext) ⇒ Integer?

Parameters:

  • other_ext (Object)

Returns:

  • (Integer, nil)


404
405
406
407
# File 'lib/udb/obj/extension.rb', line 404

def <=>(other_ext)
  return nil unless other_ext.is_a?(Extension)
  name <=> other_ext.name
end

#all_csrs_that_must_be_implementedArray<Csr>

Returns:



273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
# File 'lib/udb/obj/extension.rb', line 273

def all_csrs_that_must_be_implemented
  @all_csrs_that_must_be_implemented ||=
    begin
      pb =
        Udb.create_progressbar(
          "Finding all required csrs for #{name} [:bar] :current/:total",
          total: @arch.csrs.size,
          clear: true
        )
      @arch.csrs.select do |csr|
        pb.advance

        (-csr.defined_by_condition & to_condition).unsatisfiable_by_arch?(@arch)
      end
    end
end

#all_instructions_that_must_be_implementedObject



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/udb/obj/extension.rb', line 207

def all_instructions_that_must_be_implemented
  @all_instructions_that_must_be_implemented ||=
    begin
      pb =
        Udb.create_progressbar(
          "Finding all required instructions for #{name} [:bar] :current/:total",
          total: @arch.instructions.size,
          clear: true
        )
      @arch.instructions.select do |i|
        pb.advance

        (-i.defined_by_condition & to_condition).unsatisfiable_by_arch?(@arch)
      end
    end
end

#all_params_that_must_be_implementedArray<Parameter>

Returns List of parameters that must be defined if some version of this extension is defined.

Returns:

  • (Array<Parameter>)

    List of parameters that must be defined if some version of this extension is defined



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/udb/obj/extension.rb', line 161

def all_params_that_must_be_implemented
  @all_params_that_must_be_implemented ||=
    begin
      pb =
        Udb.create_progressbar(
          "Finding implied params for #{name} [:bar] :current/:total",
          total: cfg_arch.params.size,
          clear: true
        )
      cfg_arch.params.select do |p|
        pb.advance
        param_defined = p.defined_by_condition

        (-param_defined & to_condition).unsatisfiable_by_arch?(cfg_arch)
      end
    end
end

#compact_priv_typeString

Returns Either unpriv or priv.

Returns:

  • (String)

    Either unpriv or priv



30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/udb/obj/extension.rb', line 30

def compact_priv_type
  case priv_type
  when "unprivileged"
    "unpriv"
  when "privileged"
    "priv"
  else
    if priv_type.nil? || priv_type.empty?
      raise ArgumentError, "Extension #{name} missing its type in database (must be privileged or unprivileged)"
    else
      raise ArgumentError, "Extension #{name} has illegal privileged/unprivileged type of #{priv_type}"
    end
  end
end

#companyObject

Returns:

  • if the company isn't known

  • (Company, nil)

    Company that developed the extension



48
49
50
51
52
# File 'lib/udb/obj/extension.rb', line 48

def company
  if @data.key?("company")
    @company ||= Company.new(@data["company"])
  end
end

#conditional_paramsArray<ConditionallyApplicableParameter>



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/udb/obj/extension.rb', line 116

def conditional_params
  @cond_params ||=
    begin
      pb =
        Udb.create_progressbar(
          "Finding conditional params for #{name} [:bar] :current/:total",
          total: cfg_arch.params.size,
          clear: true
        )
      cfg_arch.params.filter_map do |p|
        pb.advance
        next if params.include?(p)
        next unless p.defined_by_condition.mentions?(self)
        next unless (p.defined_by_condition & self.to_condition).satisfiable?

        cond = p.defined_by_condition.partial_eval(ext_reqs: [self.to_ext_req]).minimize(expand: false)
        ConditionallyApplicableParameter.new(cond:, param: p)
      end
    end
end

#conflicting_extensionsObject

Returns list of extensions that conflict with self.

Returns:

  • list of extensions that conflict with self



201
202
203
204
205
# File 'lib/udb/obj/extension.rb', line 201

def conflicting_extensions
  @cfg_arch.extensions.select do |ext|
    (to_condition & ext.to_condition).unsatisfiable?
  end
end

#csrsArray<Csr>

not including those defined by requirements of this extension

Returns:

  • (Array<Csr>)

    the list of CSRs implemented by any version of this extension (may be empty),



310
311
312
# File 'lib/udb/obj/extension.rb', line 310

def csrs
  @csrs ||= all_csrs_that_must_be_implemented - implied_csrs
end

#csrs_that_must_be_implementedArray<Csr>

Returns the list of csrs that must be defined when any version of this extension is defined includes both those defined directly by self and those implied by self's requirements.

Returns:

  • (Array<Csr>)

    the list of csrs that must be defined when any version of this extension is defined includes both those defined directly by self and those implied by self's requirements



344
345
346
# File 'lib/udb/obj/extension.rb', line 344

def csrs_that_must_be_implemented
  @csrs_that_must_be_implemented ||= csrs + implied_csrs
end

#doc_licensenil, Hash{String => String}

Returns:

  • (nil)

    if the license isn't known

  • (Hash{String => String}, nil)

    The name and URL of a document license the doc falls under



57
58
59
# File 'lib/udb/obj/extension.rb', line 57

def doc_license
  @data["doc_license"]
end

#exception_codesArray<ExceptionCode>

returns list of exception codes that are defined by any version of this extension

Returns:



411
412
413
414
415
416
417
418
419
420
421
# File 'lib/udb/obj/extension.rb', line 411

def exception_codes
  @exception_codes ||=
    @cfg_arch.exception_codes.select do |ecode|
      if ecode.defined_by_condition.mentions?(self)
        ecode.defined_by_condition.satisfied_by_ext_req?(to_ext_req, include_requirements: false) ||
          ecode.defined_by_condition.satisfiability_depends_on_ext_req?(to_ext_req)
      else
        false
      end
    end
end

#general_extension_requirements_conditionAbstractCondition

Returns a condition representing the requirements that apply to all versions of this extension.

Returns:

  • (AbstractCondition)

    a condition representing the requirements that apply to all versions of this extension



187
188
189
190
191
192
# File 'lib/udb/obj/extension.rb', line 187

def general_extension_requirements_condition
  @general_extension_requirements_condition ||=
    @data.key?("requirements") \
      ? Condition.new(@data.fetch("requirements"), @cfg_arch, input_file: Pathname.new(__source), input_line: source_line(["requirements"]))
      : AlwaysTrueCondition.new(@cfg_arch)
end

#implied_csrsArray<Csr>

a requirement of the extension directly defines the csr

This list may be empty

Returns:

  • (Array<Csr>)

    the list of csrs implemented indirectly by any version of this extension because



290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/udb/obj/extension.rb', line 290

def implied_csrs
  @implied_csrs ||=
    begin
      pb =
        Udb.create_progressbar(
          "Finding implied csrs for #{name} [:bar] :current/:total",
          total: @arch.csrs.size,
          clear: true
        )
      @arch.csrs.select do |csr|
        pb.advance

        (-csr.defined_by_condition & requirements_condition).unsatisfiable_by_arch?(@arch)
      end
    end
end

#implied_instructionsArray<Instruction>

a requirement of the extension directly defines the instruction

For example, the "C" extension implies c.addi because c.addi is directly defined by Zca and C requires Zca to be implemented

This list may be empty

Returns:

  • (Array<Instruction>)

    the list of instructions implemented indirectly by any version of this extension because



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/udb/obj/extension.rb', line 232

def implied_instructions
  @implied_instructions ||=
    begin
      pb =
        Udb.create_progressbar(
          "Finding implied instructions for #{name} [:bar] :current/:total",
          total: @arch.instructions.size,
          clear: true
        )
      @arch.instructions.select do |i|
        pb.advance

        (-i.defined_by_condition & requirements_condition).unsatisfiable_by_arch?(@arch)
      end
    end
end

#implied_instructions_setSet<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.

Returns:



268
269
270
# File 'lib/udb/obj/extension.rb', line 268

def implied_instructions_set
  @implied_instructions_set ||= Set.new(implied_instructions)
end

#implied_paramsArray<Parameter>

Returns List of parameters that must be defined if this extension is defined due to one of the extension's requirements excluding those required because of a requirement of extension def implied_params.

Returns:

  • (Array<Parameter>)

    List of parameters that must be defined if this extension is defined due to one of the extension's requirements excluding those required because of a requirement of extension def implied_params



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/udb/obj/extension.rb', line 140

def implied_params
  @implied_params ||=
    begin
      pb =
        Udb.create_progressbar(
          "Finding implied params for #{name} [:bar] :current/:total",
          total: cfg_arch.params.size,
          clear: true
        )
      cfg_arch.params.select do |p|
        pb.advance
        param_defined = p.defined_by_condition
        preconditions_met = requirements_condition

        (-param_defined & preconditions_met).unsatisfiable_by_arch?(cfg_arch)
      end
    end
end

#instructionsArray<Instruction>

Returns the list of instructions implemented directly by any version of this extension (may be empty) Direct means that the instruction must be defined when the extension is implemented and may not be implemented when just the extension's requirements are met

In other words, direct is the set of instructions that are defined without transitivity.

Returns:

  • (Array<Instruction>)

    the list of instructions implemented directly by any version of this extension (may be empty) Direct means that the instruction must be defined when the extension is implemented and may not be implemented when just the extension's requirements are met

    In other words, direct is the set of instructions that are defined without transitivity



255
256
257
# File 'lib/udb/obj/extension.rb', line 255

def instructions
  @instructions ||= all_instructions_that_must_be_implemented - implied_instructions
end

#instructions_setSet<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.

Returns:



261
262
263
# File 'lib/udb/obj/extension.rb', line 261

def instructions_set
  @instructions_set ||= Set.new(instructions)
end

#interrupt_codesArray<InterruptCode>

returns list of interrupt codes that are defined by any version of this extension

Returns:



425
426
427
428
429
430
431
432
433
434
435
# File 'lib/udb/obj/extension.rb', line 425

def interrupt_codes
  @interrupt_codes ||=
    @cfg_arch.interrupt_codes.select do |icode|
      if icode.defined_by_condition.mentions?(self)
        icode.defined_by_condition.satisfied_by_ext_req?(to_ext_req, include_requirements: false) ||
          icode.defined_by_condition.satisfiability_depends_on_ext_req?(to_ext_req)
      else
        false
      end
    end
end

#long_nameString

Returns Long name of the extension.

Returns:

  • (String)

    Long name of the extension



22
# File 'lib/udb/obj/extension.rb', line 22

def long_name = @data.fetch("long_name")

#max_versionExtensionVersion

Returns Maximum defined version of this extension.

Returns:



91
92
93
# File 'lib/udb/obj/extension.rb', line 91

def max_version
  T.must(versions.max { |a, b| T.must(a.version_spec <=> b.version_spec) })
end

#min_ratified_versionExtensionVersion?

Returns Mimumum defined ratified version of this extension, or nil if there is none.

Returns:

  • (ExtensionVersion, nil)

    Mimumum defined ratified version of this extension, or nil if there is none



97
98
99
100
101
# File 'lib/udb/obj/extension.rb', line 97

def min_ratified_version
  return nil if ratified_versions.empty?

  ratified_versions.min { |a, b| T.must(a.version_spec <=> b.version_spec) }
end

#min_versionExtensionVersion

Returns Mimumum defined version of this extension.

Returns:



85
86
87
# File 'lib/udb/obj/extension.rb', line 85

def min_version
  T.must(versions.min { |a, b| T.must(a.version_spec <=> b.version_spec) })
end

#mmrsArray<Mmr>

Returns the list of MMRs implemented by any version of this extension (may be empty).

Returns:

  • (Array<Mmr>)

    the list of MMRs implemented by any version of this extension (may be empty)



350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/udb/obj/extension.rb', line 350

def mmrs
  @mmrs ||=
    begin
      pb =
        Udb.create_progressbar(
          "Finding mmrs for #{name} [:bar] :current/:total",
          total: cfg_arch.mmrs.size,
          clear: true
        )
      cfg_arch.mmrs.select do |mmr|
        pb.advance
        mmr_defined = mmr.defined_by_condition
        next unless mmr_defined.mentions?(self)
        requirement_met = to_condition
        preconditions_met = requirements_condition

        # mmr is defined exclusively by self if:
        (
          (-mmr_defined & requirement_met) # it must be defined when self is met, and
        ).unsatisfiable? &
        (
          (-mmr_defined & preconditions_met)  # it may not be defined when only self's requirements are met
        ).satisfiable?
      end
    end
end

#paramsArray<Parameter>

Returns List of parameters that must be defined if some version of this extension is defined, excluding those required because of a requirement of extension.

Returns:

  • (Array<Parameter>)

    List of parameters that must be defined if some version of this extension is defined, excluding those required because of a requirement of extension



106
107
108
# File 'lib/udb/obj/extension.rb', line 106

def params
  @params ||= all_params_that_must_be_implemented - implied_params
end

#priv_typeString

Returns Either unprivileged or privileged.

Returns:

  • (String)

    Either unprivileged or privileged



26
# File 'lib/udb/obj/extension.rb', line 26

def priv_type = @data.fetch("type")

#ratifiedBoolean

Returns Any version ratified?.

Returns:

  • (Boolean)

    Any version ratified?



81
# File 'lib/udb/obj/extension.rb', line 81

def ratified = ratified_versions.any?

#ratified_versionsArray<ExtensionVersion>

Returns Ratified versions hash from config.

Returns:



75
76
77
# File 'lib/udb/obj/extension.rb', line 75

def ratified_versions
  versions.select { |v| v.state == "ratified" }
end

#reachable_functionsArray<Idl::FunctionDefAst>

return the set of reachable functions from any of this extensions's CSRs or instructions in the given evaluation context

Returns:

  • (Array<Idl::FunctionDefAst>)

    Array of IDL functions reachable from any instruction or CSR in the extension



381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
# File 'lib/udb/obj/extension.rb', line 381

def reachable_functions
  return @reachable_functions unless @reachable_functions.nil?

  funcs = T.let([], T::Array[Idl::FunctionDefAst])

  Udb.logger.info "Finding all reachable functions from extension #{name}"

  cache = T.let({ 32 => {}, 64 => {}, nil => {} }, T::Hash[Integer, Idl::AstNode::ReachableFunctionCacheType])

  instructions.each do |inst|
    funcs += inst.reachable_functions(32, cache.fetch(32)) if inst.defined_in_base?(32)
    funcs += inst.reachable_functions(64, cache.fetch(64)) if inst.defined_in_base?(64)
  end

  csrs.each do |csr|
    funcs += csr.reachable_functions(32, cache) if csr.defined_in_base?(32)
    funcs += csr.reachable_functions(64, cache) if csr.defined_in_base?(64)
  end

  @reachable_functions = funcs.uniq
end

#requirements_conditionAbstractCondition

Returns a condition representing the requirements that apply to all versions of this extension (not just the generic requirements).

Returns:

  • (AbstractCondition)

    a condition representing the requirements that apply to all versions of this extension (not just the generic requirements)



196
197
198
# File 'lib/udb/obj/extension.rb', line 196

def requirements_condition
  @requirements_condition ||= to_ext_req.requirements_condition
end

#to_conditionCondition

returns a condition representing any version of this extension being implemented

Returns:



181
182
183
# File 'lib/udb/obj/extension.rb', line 181

def to_condition
  @condition ||= Condition.new({ "extension" => { "name" => name } }, @cfg_arch)
end

#to_ext_reqExtensionRequirement

returns an ext req that will be satisfied by any known version of this extension



439
440
441
# File 'lib/udb/obj/extension.rb', line 439

def to_ext_req
  @ext_req ||= @cfg_arch.extension_requirement(name, ">= 0")
end

#versionsArray<ExtensionVersion>

Returns versions hash from config, sorted by version number.

Returns:

  • (Array<ExtensionVersion>)

    versions hash from config, sorted by version number



63
64
65
66
67
68
69
70
71
# File 'lib/udb/obj/extension.rb', line 63

def versions
  return @versions unless @versions.nil?

  @versions = @data["versions"].map do |v|
    cfg_arch.extension_version(name, v["version"])
  end
  @versions.sort!
  @versions
end