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.
758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 |
# File 'lib/udb/obj/instruction.rb', line 758 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)
621 622 623 |
# File 'lib/udb/obj/instruction.rb', line 621 def alias @alias end |
#encoding_fields ⇒ Object (readonly)
Returns the value of attribute encoding_fields.
631 632 633 |
# File 'lib/udb/obj/instruction.rb', line 631 def encoding_fields @encoding_fields end |
#excludes ⇒ Array<Integer> (readonly)
Returns Specific values that are prohibited for this variable.
629 630 631 |
# File 'lib/udb/obj/instruction.rb', line 629 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
626 627 628 |
# File 'lib/udb/obj/instruction.rb', line 626 def left_shift @left_shift end |
#location ⇒ String (readonly)
634 635 636 |
# File 'lib/udb/obj/instruction.rb', line 634 def location @location end |
#name ⇒ Object (readonly)
the name of the field
616 617 618 |
# File 'lib/udb/obj/instruction.rb', line 616 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)
802 803 804 805 806 |
# File 'lib/udb/obj/instruction.rb', line 802 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.
699 700 701 702 703 704 705 706 707 708 709 710 711 |
# File 'lib/udb/obj/instruction.rb', line 699 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
783 784 785 |
# File 'lib/udb/obj/instruction.rb', line 783 def eql?(other) @name.eql?(other.name) end |
#extract ⇒ Object
return code to extract the field
833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 |
# File 'lib/udb/obj/instruction.rb', line 833 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
656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 |
# File 'lib/udb/obj/instruction.rb', line 656 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
734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 |
# File 'lib/udb/obj/instruction.rb', line 734 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
787 788 789 |
# File 'lib/udb/obj/instruction.rb', line 787 def hash @name.hash end |
#inst_pos_to_var_pos ⇒ Object
682 683 684 685 686 687 688 689 690 691 692 693 694 |
# File 'lib/udb/obj/instruction.rb', line 682 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.
638 639 640 |
# File 'lib/udb/obj/instruction.rb', line 638 def location_bits Instruction.ary_from_location(@location) end |
#overlaps?(other) ⇒ Boolean
824 825 826 827 828 829 830 |
# File 'lib/udb/obj/instruction.rb', line 824 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,.
646 647 648 649 650 651 652 653 654 |
# File 'lib/udb/obj/instruction.rb', line 646 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
819 820 821 |
# File 'lib/udb/obj/instruction.rb', line 819 def sext? @sext end |
#size ⇒ Integer
Returns the number of bits in the field, _including any implicit bits_.
809 810 811 |
# File 'lib/udb/obj/instruction.rb', line 809 def size size_in_encoding + @left_shift end |
#size_in_encoding ⇒ Object
the number of bits in the field, _not including any implicit zeros_
814 815 816 |
# File 'lib/udb/obj/instruction.rb', line 814 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
792 793 794 |
# File 'lib/udb/obj/instruction.rb', line 792 def split? @encoding_fields.size > 1 end |