Class: Udb::Instruction::DecodeVariable
- Inherits:
-
Object
- Object
- Udb::Instruction::DecodeVariable
- Extended by:
- T::Sig
- Defined in:
- lib/udb/obj/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
-
#alias ⇒ Object
readonly
alias of this field, or nil if none.
-
#encoding_fields ⇒ Object
readonly
Returns the value of attribute encoding_fields.
-
#excludes ⇒ Array<Integer>
readonly
Specific values that are prohibited for this variable.
-
#left_shift ⇒ Object
readonly
amount the field is left shifted before use, or nil is there is no left shift.
- #location ⇒ String readonly
-
#name ⇒ Object
readonly
the name of the field.
Instance Method Summary collapse
-
#bits ⇒ Object
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.
-
#encoding_repl(encoding, value) ⇒ String
Encoding, with the decode variable replaced with value.
- #eql?(other) ⇒ Boolean
-
#extract ⇒ Object
return code to extract the field.
- #extract_location(location) ⇒ Object
-
#grouped_encoding_fields ⇒ Object
array of constituent encoding fields.
- #hash ⇒ Object
-
#initialize(name, field_data) ⇒ DecodeVariable
constructor
A new instance of DecodeVariable.
- #inst_pos_to_var_pos ⇒ Object
-
#location_bits ⇒ Array<Integer>
Any array containing every encoding index covered by this variable.
- #overlaps?(other) ⇒ Boolean
-
#pretty_name ⇒ String
Name, along with any != constraints,.
-
#sext? ⇒ Boolean
true if the field should be sign extended.
-
#size ⇒ Integer
The number of bits in the field, _including any implicit bits_.
-
#size_in_encoding ⇒ Object
the number of bits in the field, _not including any implicit zeros_.
-
#split? ⇒ Boolean
returns true if the field is encoded across more than one groups of bits.
Constructor Details
#initialize(name, field_data) ⇒ DecodeVariable
Returns a new instance of DecodeVariable.
738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 |
# File 'lib/udb/obj/instruction.rb', line 738 def initialize(name, field_data) @name = 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"] @location = field_data["location"] 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
#alias ⇒ Object (readonly)
alias of this field, or nil if none
used, e.g., when a field represents more than one variable (like rs1/rd for destructive instructions)
601 602 603 |
# File 'lib/udb/obj/instruction.rb', line 601 def alias @alias end |
#encoding_fields ⇒ Object (readonly)
Returns the value of attribute encoding_fields.
611 612 613 |
# File 'lib/udb/obj/instruction.rb', line 611 def encoding_fields @encoding_fields end |
#excludes ⇒ Array<Integer> (readonly)
Returns Specific values that are prohibited for this variable.
609 610 611 |
# File 'lib/udb/obj/instruction.rb', line 609 def excludes @excludes end |
#left_shift ⇒ Object (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
606 607 608 |
# File 'lib/udb/obj/instruction.rb', line 606 def left_shift @left_shift end |
#location ⇒ String (readonly)
614 615 616 |
# File 'lib/udb/obj/instruction.rb', line 614 def location @location end |
#name ⇒ Object (readonly)
the name of the field
596 597 598 |
# File 'lib/udb/obj/instruction.rb', line 596 def name @name end |
Instance Method Details
#bits ⇒ Object
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)
782 783 784 785 786 |
# File 'lib/udb/obj/instruction.rb', line 782 def bits @encoding_fields.map do |ef| ef.range.size == 1 ? ef.range.first : ef.range end end |
#encoding_repl(encoding, value) ⇒ String
Returns encoding, with the decode variable replaced with value.
679 680 681 682 683 684 685 686 687 688 689 690 691 |
# File 'lib/udb/obj/instruction.rb', line 679 def encoding_repl(encoding, value) raise ArgumentError, "Expecting string" unless encoding.is_a?(String) raise ArgumentError, "Expecting Integer" unless value.is_a?(Integer) new_encoding = encoding.dup inst_pos_to_var_pos.each_with_index do |pos, idx| next if pos.nil? raise "Bad encoding" if idx >= encoding.size new_encoding[encoding.size - idx - 1] = ((value >> pos) & 1).to_s end new_encoding end |
#eql?(other) ⇒ Boolean
763 764 765 |
# File 'lib/udb/obj/instruction.rb', line 763 def eql?(other) @name.eql?(other.name) end |
#extract ⇒ Object
return code to extract the field
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 |
# File 'lib/udb/obj/instruction.rb', line 813 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 += T.must(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
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 |
# File 'lib/udb/obj/instruction.rb', line 636 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_fields ⇒ Object
array of constituent encoding fields
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 |
# File 'lib/udb/obj/instruction.rb', line 714 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 |
#hash ⇒ Object
767 768 769 |
# File 'lib/udb/obj/instruction.rb', line 767 def hash @name.hash end |
#inst_pos_to_var_pos ⇒ Object
662 663 664 665 666 667 668 669 670 671 672 673 674 |
# File 'lib/udb/obj/instruction.rb', line 662 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 |
#location_bits ⇒ Array<Integer>
Returns Any array containing every encoding index covered by this variable.
618 619 620 |
# File 'lib/udb/obj/instruction.rb', line 618 def location_bits Instruction.ary_from_location(@location) end |
#overlaps?(other) ⇒ Boolean
804 805 806 807 808 809 810 |
# File 'lib/udb/obj/instruction.rb', line 804 def overlaps?(other) if other.is_a?(Instruction::Opcode) location_bits.any? { |i| other.range.cover?(i) } else location_bits.intersect?(other.location_bits) end end |
#pretty_name ⇒ String
Returns Name, along with any != constraints,.
626 627 628 629 630 631 632 633 634 |
# File 'lib/udb/obj/instruction.rb', line 626 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
799 800 801 |
# File 'lib/udb/obj/instruction.rb', line 799 def sext? @sext end |
#size ⇒ Integer
Returns the number of bits in the field, _including any implicit bits_.
789 790 791 |
# File 'lib/udb/obj/instruction.rb', line 789 def size size_in_encoding + @left_shift end |
#size_in_encoding ⇒ Object
the number of bits in the field, _not including any implicit zeros_
794 795 796 |
# File 'lib/udb/obj/instruction.rb', line 794 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
772 773 774 |
# File 'lib/udb/obj/instruction.rb', line 772 def split? @encoding_fields.size > 1 end |