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 Attribute Summary

Attributes inherited from DatabaseObject

#arch, #data, #data_path, #name

Instance Method Summary collapse

Methods inherited from TopLevelDatabaseObject

create_json_schemer_resolver, #initialize, #key?, #keys, #validate

Methods inherited from DatabaseObject

#__source, #cfg_arch, #cfg_arch?, #clone, #defer, #defined_by_condition, #description, #initialize, #inspect, #kind, #source_line

Constructor Details

This class inherits a constructor from Udb::TopLevelDatabaseObject

Instance Method Details

#<=>(other_ext) ⇒ Object



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

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

#all_csrs_that_must_be_implementedObject



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_implementedObject



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_typeObject



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



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_paramsObject



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

#csrsObject



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_implementedObject



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_licenseObject



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

def doc_license
  @data["doc_license"]
end

#exception_codesObject



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_conditionObject



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_csrsObject



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_instructionsObject



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_setObject



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

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

#implied_paramsObject



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

#instructionsObject



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

def instructions
  @instructions ||= all_instructions_that_must_be_implemented - implied_instructions
end

#instructions_setObject



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

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

#interrupt_codesObject



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_nameObject



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

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

#max_versionObject



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_versionObject



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_versionObject



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

#mmrsObject



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

#paramsObject



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

def params
  @params ||= all_params_that_must_be_implemented - implied_params
end

#priv_typeObject



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

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

#ratifiedObject



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

def ratified = ratified_versions.any?

#ratified_versionsObject



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

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

#reachable_functionsObject



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_conditionObject



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

def requirements_condition
  @requirements_condition ||= to_ext_req.requirements_condition
end

#to_conditionObject



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_reqObject



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

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

#versionsObject



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