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.
735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 |
# File 'lib/udb/obj/instruction.rb', line 735 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)
598 599 600 |
# File 'lib/udb/obj/instruction.rb', line 598 def alias @alias end |
#encoding_fields ⇒ Object (readonly)
Returns the value of attribute encoding_fields.
608 609 610 |
# File 'lib/udb/obj/instruction.rb', line 608 def encoding_fields @encoding_fields end |
#excludes ⇒ Array<Integer> (readonly)
Returns Specific values that are prohibited for this variable.
606 607 608 |
# File 'lib/udb/obj/instruction.rb', line 606 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
603 604 605 |
# File 'lib/udb/obj/instruction.rb', line 603 def left_shift @left_shift end |
#location ⇒ String (readonly)
611 612 613 |
# File 'lib/udb/obj/instruction.rb', line 611 def location @location end |
#name ⇒ Object (readonly)
the name of the field
593 594 595 |
# File 'lib/udb/obj/instruction.rb', line 593 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)
779 780 781 782 783 |
# File 'lib/udb/obj/instruction.rb', line 779 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.
676 677 678 679 680 681 682 683 684 685 686 687 688 |
# File 'lib/udb/obj/instruction.rb', line 676 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
760 761 762 |
# File 'lib/udb/obj/instruction.rb', line 760 def eql?(other) @name.eql?(other.name) end |
#extract ⇒ Object
return code to extract the field
810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 |
# File 'lib/udb/obj/instruction.rb', line 810 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
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 |
# File 'lib/udb/obj/instruction.rb', line 633 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
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 |
# File 'lib/udb/obj/instruction.rb', line 711 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
764 765 766 |
# File 'lib/udb/obj/instruction.rb', line 764 def hash @name.hash end |
#inst_pos_to_var_pos ⇒ Object
659 660 661 662 663 664 665 666 667 668 669 670 671 |
# File 'lib/udb/obj/instruction.rb', line 659 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.
615 616 617 |
# File 'lib/udb/obj/instruction.rb', line 615 def location_bits Instruction.ary_from_location(@location) end |
#overlaps?(other) ⇒ Boolean
801 802 803 804 805 806 807 |
# File 'lib/udb/obj/instruction.rb', line 801 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,.
623 624 625 626 627 628 629 630 631 |
# File 'lib/udb/obj/instruction.rb', line 623 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
796 797 798 |
# File 'lib/udb/obj/instruction.rb', line 796 def sext? @sext end |
#size ⇒ Integer
Returns the number of bits in the field, _including any implicit bits_.
786 787 788 |
# File 'lib/udb/obj/instruction.rb', line 786 def size size_in_encoding + @left_shift end |
#size_in_encoding ⇒ Object
the number of bits in the field, _not including any implicit zeros_
791 792 793 |
# File 'lib/udb/obj/instruction.rb', line 791 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
769 770 771 |
# File 'lib/udb/obj/instruction.rb', line 769 def split? @encoding_fields.size > 1 end |