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 ⇒ Object
readonly
Returns the value of attribute location.
-
#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 ⇒ Object
- #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.
789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 |
# File 'lib/udb/obj/instruction.rb', line 789 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)
652 653 654 |
# File 'lib/udb/obj/instruction.rb', line 652 def alias @alias end |
#encoding_fields ⇒ Object (readonly)
Returns the value of attribute encoding_fields.
662 663 664 |
# File 'lib/udb/obj/instruction.rb', line 662 def encoding_fields @encoding_fields end |
#excludes ⇒ Array<Integer> (readonly)
Returns Specific values that are prohibited for this variable.
660 661 662 |
# File 'lib/udb/obj/instruction.rb', line 660 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
657 658 659 |
# File 'lib/udb/obj/instruction.rb', line 657 def left_shift @left_shift end |
#location ⇒ Object (readonly)
Returns the value of attribute location.
665 666 667 |
# File 'lib/udb/obj/instruction.rb', line 665 def location @location end |
#name ⇒ Object (readonly)
the name of the field
647 648 649 |
# File 'lib/udb/obj/instruction.rb', line 647 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)
833 834 835 836 837 |
# File 'lib/udb/obj/instruction.rb', line 833 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.
730 731 732 733 734 735 736 737 738 739 740 741 742 |
# File 'lib/udb/obj/instruction.rb', line 730 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
814 815 816 |
# File 'lib/udb/obj/instruction.rb', line 814 def eql?(other) @name.eql?(other.name) end |
#extract ⇒ Object
return code to extract the field
864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 |
# File 'lib/udb/obj/instruction.rb', line 864 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}, #{size})" if sext? ops end |
#extract_location(location) ⇒ Object
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 |
# File 'lib/udb/obj/instruction.rb', line 687 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
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 |
# File 'lib/udb/obj/instruction.rb', line 765 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
818 819 820 |
# File 'lib/udb/obj/instruction.rb', line 818 def hash @name.hash end |
#inst_pos_to_var_pos ⇒ Object
713 714 715 716 717 718 719 720 721 722 723 724 725 |
# File 'lib/udb/obj/instruction.rb', line 713 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 ⇒ Object
669 670 671 |
# File 'lib/udb/obj/instruction.rb', line 669 def location_bits Instruction.ary_from_location(@location) end |
#overlaps?(other) ⇒ Boolean
855 856 857 858 859 860 861 |
# File 'lib/udb/obj/instruction.rb', line 855 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,.
677 678 679 680 681 682 683 684 685 |
# File 'lib/udb/obj/instruction.rb', line 677 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
850 851 852 |
# File 'lib/udb/obj/instruction.rb', line 850 def sext? @sext end |
#size ⇒ Integer
Returns the number of bits in the field, _including any implicit bits_.
840 841 842 |
# File 'lib/udb/obj/instruction.rb', line 840 def size size_in_encoding + @left_shift end |
#size_in_encoding ⇒ Object
the number of bits in the field, _not including any implicit zeros_
845 846 847 |
# File 'lib/udb/obj/instruction.rb', line 845 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
823 824 825 |
# File 'lib/udb/obj/instruction.rb', line 823 def split? @encoding_fields.size > 1 end |