Class: Instruction::DecodeVariable

Inherits:
Object
  • Object
show all
Defined in:
lib/arch_obj_models/instruction.rb

Overview

decode field constructions from YAML file, rather than riscv-opcodes eventually, we will move so that all instructions use the YAML file,

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(inst, field_data) ⇒ DecodeVariable

Returns a new instance of DecodeVariable.



381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
# File 'lib/arch_obj_models/instruction.rb', line 381

def initialize(inst, field_data)
  @inst = inst
  @name = field_data["name"]
  @left_shift = field_data["left_shift"].nil? ? 0 : field_data["left_shift"]
  @sext = field_data["sign_extend"].nil? ? false : field_data["sign_extend"]
  @alias = field_data["alias"].nil? ? nil : field_data["alias"]
  extract_location(field_data["location"])
  @excludes =
    if field_data.key?("not")
      if field_data["not"].is_a?(Array)
        field_data["not"]
      else
        [field_data["not"]]
      end
    else
      []
    end
  @decode_variable =
    if @alias.nil?
      name
    else
      @decode_variable = [name, @alias]
    end
end

Instance Attribute Details

#aliasObject (readonly)

alias of this field, or nil if none

used, e.g., when a field reprsents more than one variable (like rs1/rd for destructive instructions)



272
273
274
# File 'lib/arch_obj_models/instruction.rb', line 272

def alias
  @alias
end

#excludesArray<Integer> (readonly)

Returns Specific values that are prohibited for this variable.

Returns:

  • (Array<Integer>)

    Specific values that are prohibited for this variable



280
281
282
# File 'lib/arch_obj_models/instruction.rb', line 280

def excludes
  @excludes
end

#left_shiftObject (readonly)

amount the field is left shifted before use, or nil is there is no left shift

For example, if the field is offset, left_shift is 3



277
278
279
# File 'lib/arch_obj_models/instruction.rb', line 277

def left_shift
  @left_shift
end

#nameObject (readonly)

the name of the field



267
268
269
# File 'lib/arch_obj_models/instruction.rb', line 267

def name
  @name
end

Instance Method Details

#bitsObject

returns bits of the encoding that make up the field, as an array

 Each item of the array is either:
   - A number, to represent a single bit
   - A range, to represent a continugous range of bits

The array is ordered from encoding MSB (at index 0) to LSB (at index n-1)


425
426
427
428
429
# File 'lib/arch_obj_models/instruction.rb', line 425

def bits
  @encoding_fields.map do |ef|
    ef.range.size == 1 ? ef.range.first : ef.range
  end
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


406
407
408
# File 'lib/arch_obj_models/instruction.rb', line 406

def eql?(other)
  @name.eql?(other.name)
end

#extractObject

return code to extract the field



447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
# File 'lib/arch_obj_models/instruction.rb', line 447

def extract
  ops = []
  so_far = 0
  bits.each do |b|
    if b.is_a?(Integer)
      op = "$encoding[#{b}]"
      ops << op
      so_far += 1
    elsif b.is_a?(Range)
      op = "$encoding[#{b.end}:#{b.begin}]"
      ops << op
      so_far += b.size
    end
  end
  ops << "#{@left_shift}'d0" unless @left_shift.zero?
  ops =
    if ops.size > 1
      "{#{ops.join(', ')}}"
    else
      ops[0]
    end
  ops = "sext(#{ops})" if sext?
  ops
end

#extract_location(location) ⇒ Object



296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/arch_obj_models/instruction.rb', line 296

def extract_location(location)
  @encoding_fields = []

  if location.is_a?(Integer)
    @encoding_fields << EncodingField.new("", location..location)
    return
  end

  location_string = location
  parts = location_string.split("|")
  parts.each do |part|
    if part =~ /^([0-9]+)$/
      bit = ::Regexp.last_match(1)
      @encoding_fields << EncodingField.new("", bit.to_i..bit.to_i)
    elsif part =~ /^([0-9]+)-([0-9]+)$/
      msb = ::Regexp.last_match(1)
      lsb = ::Regexp.last_match(2)
      raise "range must be specified 'msb-lsb'" unless msb.to_i >= lsb.to_i

      @encoding_fields << EncodingField.new("", lsb.to_i..msb.to_i)
    else
      raise "location format error"
    end
  end
end

#grouped_encoding_fieldsObject

array of constituent encoding fields



357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
# File 'lib/arch_obj_models/instruction.rb', line 357

def grouped_encoding_fields
  sorted_encoding_fields = @encoding_fields.sort { |a, b| b.range.last <=> a.range.last }
  # need to group encoding_fields if they are consecutive
  grouped_fields = [sorted_encoding_fields[0].range]
  sorted_encoding_fields[1..].each do |ef|
    if (ef.range.last + 1) == grouped_fields.last.first
      grouped_fields[-1] = (ef.range.first..grouped_fields.last.last)
    else
      grouped_fields << ef.range
    end
  end
  if grouped_fields.size == 1
    if grouped_fields.last.size == size
      [EncodingField.new(pretty_name, grouped_fields[0])]
    else
      [EncodingField.new("#{pretty_name}[#{inst_range_to_var_range(grouped_fields[0])}]", grouped_fields[0])]
    end
  else
    grouped_fields.map do |f|
      EncodingField.new("#{pretty_name}[#{inst_range_to_var_range(f)}]", f)
    end
  end
end

#hashObject



410
411
412
# File 'lib/arch_obj_models/instruction.rb', line 410

def hash
  @name.hash
end

#inst_pos_to_var_posObject



322
323
324
325
326
327
328
329
330
331
332
333
334
# File 'lib/arch_obj_models/instruction.rb', line 322

def inst_pos_to_var_pos
  s = size
  map = Array.new(32, nil)
  @encoding_fields.each do |ef|
    ef.range.to_a.reverse.each do |ef_i|
      raise "unexpected" if s <= 0

      map[ef_i] = s - 1
      s -= 1
    end
  end
  map
end

#pretty_nameString

Returns Name, along with any != constraints,.

Examples:

pretty_name #=> "rd != 0"
pretty_name #=> "rd != {0,2}"

Returns:

  • (String)

    Name, along with any != constraints,



286
287
288
289
290
291
292
293
294
# File 'lib/arch_obj_models/instruction.rb', line 286

def pretty_name
  if excludes.empty?
    name
  elsif excludes.size == 1
    "#{name} != #{excludes[0]}"
  else
    "#{name} != {#{excludes.join(',')}}"
  end
end

#sext?Boolean

true if the field should be sign extended

Returns:

  • (Boolean)


442
443
444
# File 'lib/arch_obj_models/instruction.rb', line 442

def sext?
  @sext
end

#sizeInteger

Returns the number of bits in the field, _including any implicit bits_.

Returns:

  • (Integer)

    the number of bits in the field, _including any implicit bits_



432
433
434
# File 'lib/arch_obj_models/instruction.rb', line 432

def size
  size_in_encoding + @left_shift
end

#size_in_encodingObject

the number of bits in the field, _not including any implicit ones_



437
438
439
# File 'lib/arch_obj_models/instruction.rb', line 437

def size_in_encoding
  bits.reduce(0) { |sum, f| sum + (f.is_a?(Integer) ? 1 : f.size) }
end

#split?Boolean

returns true if the field is encoded across more than one groups of bits

Returns:

  • (Boolean)


415
416
417
# File 'lib/arch_obj_models/instruction.rb', line 415

def split?
  @encoding_fields.size > 1
end