Class: HDLRuby::BitString
- Inherits:
-
Object
- Object
- HDLRuby::BitString
- Defined in:
- lib/HDLRuby/hruby_bstr.rb,
lib/HDLRuby/hruby_verilog.rb
Overview
Used to output bitstring. Enhance HDLRuby with generation of verilog code.
Constant Summary collapse
- TRUE =
A few common bit strings.
BitString.new("01")
- FALSE =
BitString.new("00")
- UNKNOWN =
BitString.new("xx")
- ZERO =
BitString.new("00")
- ONE =
BitString.new("01")
- TWO =
BitString.new("010")
- THREE =
BitString.new("011")
- MINUS_ONE =
BitString.new("11")
- MINUS_TWO =
BitString.new("10")
- MINUS_THREE =
BitString.new("101")
- NOT_T =
Not truth table
{ "0" => "1", "1" => "0", "z" => "x", "x" => "x" }
- AND_T =
And truth table: 0, 1, 2=z, 3=x
{ "0" => {"0"=>"0", "1"=>"0", "z"=>"0", "x"=>"0"}, # 0 line "1" => {"0"=>"0", "1"=>"1", "z"=>"x", "x"=>"x"}, # 1 line "z" => {"0"=>"0", "1"=>"x", "z"=>"x", "x"=>"x"}, # z line "x" => {"0"=>"0", "1"=>"x", "z"=>"x", "x"=>"x"} }
- OR_T =
Or truth table: 0, 1, 2=z, 3=x
{ "0" => {"0"=>"0", "1"=>"1", "z"=>"x", "x"=>"x"}, # 0 line "1" => {"0"=>"1", "1"=>"1", "z"=>"1", "x"=>"1"}, # 1 line "z" => {"0"=>"x", "1"=>"1", "z"=>"x", "x"=>"x"}, # z line "x" => {"0"=>"x", "1"=>"1", "z"=>"x", "x"=>"x"} }
- XOR_T =
Xor truth table: 0, 1, 2=z, 3=x
{ "0" => {"0"=>"0", "1"=>"1", "z"=>"x", "x"=>"x"}, # 0 line "1" => {"0"=>"1", "1"=>"0", "z"=>"x", "x"=>"x"}, # 1 line "z" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"}, # z line "x" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"} }
- XOR3_T =
Double xor truth table: 0, 1, 2=z, 3=x
{ "0" => { "0" => {"0"=>"0", "1"=>"1", "z"=>"x", "x"=>"x"}, "1" => {"0"=>"1", "1"=>"0", "z"=>"x", "x"=>"x"}, "z" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"}, "x" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"} }, # 0 line "1" => { "0" => {"0"=>"1", "1"=>"0", "z"=>"x", "x"=>"x"}, "1" => {"0"=>"0", "1"=>"1", "z"=>"x", "x"=>"x"}, "z" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"}, "x" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"} }, # 1 line "z" => { "0" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"}, "1" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"}, "z" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"}, "x" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"} }, # z line "x" => { "0" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"}, "1" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"}, "z" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"}, "x" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"} } }
- MAJ_T =
Majority truth table: 0, 1, 2=z, 3=x
{ "0" => { "0" => {"0"=>"0", "1"=>"0", "z"=>"0", "x"=>"0"}, "1" => {"0"=>"0", "1"=>"1", "z"=>"x", "x"=>"x"}, "z" => {"0"=>"0", "1"=>"x", "z"=>"x", "x"=>"x"}, "x" => {"0"=>"0", "1"=>"x", "z"=>"x", "x"=>"x"} }, # "0" line "1" => { "0" => {"0"=>"0", "1"=>"1", "z"=>"x", "x"=>"x"}, "1" => {"0"=>"1", "1"=>"1", "z"=>"1", "x"=>"1"}, "z" => {"0"=>"x", "1"=>"1", "z"=>"x", "x"=>"x"}, "x" => {"0"=>"x", "1"=>"1", "z"=>"x", "x"=>"x"} }, # "1" line "z" => { "0" => {"0"=>"0", "1"=>"x", "z"=>"x", "x"=>"x"}, "1" => {"0"=>"x", "1"=>"1", "z"=>"x", "x"=>"x"}, "z" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"}, "x" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"} }, # z line "x" => { "0" => {"0"=>"0", "1"=>"x", "z"=>"x", "x"=>"x"}, "1" => {"0"=>"x", "1"=>"1", "z"=>"x", "x"=>"x"}, "z" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"}, "x" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"} } }
- LT_T =
Lower than truth table: 0, 1, 2=z, 3=x
{ "0" => {"0"=>"0", "1"=>"1", "z"=>"x", "x"=>"x"}, # 0 line "1" => {"0"=>"0", "1"=>"0", "z"=>"x", "x"=>"x"}, # 1 line "z" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"}, # z line "x" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"} }
- GT_T =
Greater than truth table: 0, 1, 2=z, 3=x
{ "0" => {"0"=>"0", "1"=>"0", "z"=>"x", "x"=>"x"}, # 0 line "1" => {"0"=>"1", "1"=>"0", "z"=>"x", "x"=>"x"}, # 1 line "z" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"}, # z line "x" => {"0"=>"x", "1"=>"x", "z"=>"x", "x"=>"x"} }
- BITWISE =
Table of bitwise operations
{ :+ => :bitwise_add0, :- => :bitwise_sub0, :-@ => :bitwise_neg0, :+@ => :bitwise_pos, :* => :bitwise_mul0, :/ => :bitwise_div0, :% => :bitwise_mod0, :** => :bitwise_pow0, :& => :bitwise_and, :| => :bitwise_or, :^ => :bitwise_xor, :~ => :bitwise_not, :<< => :bitwise_shl, :>> => :bitwise_shr, :== => :bitwise_eq0, :< => :bitwise_lt0, :> => :bitwise_gt0, :<= => :bitwise_le0, :>= => :bitwise_ge0, :<=>=> :bitwise_cp0 }
- @@unknown =
The counter of unknown bits.
1
Class Method Summary collapse
-
.bitwise_add(s0, s1) ⇒ Object
Bitwise addition.
-
.bitwise_add0(s0, s1) ⇒ Object
Bitwise addition without processing of the x and z states.
-
.bitwise_and(s0, s1) ⇒ Object
Bitwise and.
-
.bitwise_cp(s0, s1) ⇒ Object
Bitwise cp.
-
.bitwise_cp0(s0, s1) ⇒ Object
Bitwise cp without processing of the x and z states.
-
.bitwise_div(s0, s1) ⇒ Object
Bitwise mod.
-
.bitwise_div0(s0, s1) ⇒ Object
Bitwise div without processing of the x and z states.
-
.bitwise_eq(s0, s1) ⇒ Object
Bitwise eq.
-
.bitwise_eq0(s0, s1) ⇒ Object
Bitwise eq without processing of the x and z states.
-
.bitwise_ge(s0, s1) ⇒ Object
Bitwise ge.
-
.bitwise_ge0(s0, s1) ⇒ Object
Bitwise ge without processing of the x and z states.
-
.bitwise_gt(s0, s1) ⇒ Object
Bitwise gt.
-
.bitwise_gt0(s0, s1) ⇒ Object
Bitwise gt without processing of the x and z states.
-
.bitwise_le(s0, s1) ⇒ Object
Bitwise le.
-
.bitwise_le0(s0, s1) ⇒ Object
Bitwise le without processing of the x and z states.
-
.bitwise_lt(s0, s1) ⇒ Object
Bitwise lt.
-
.bitwise_lt0(s0, s1) ⇒ Object
Bitwise lt without processing of the x and z states.
-
.bitwise_mod0(s0, s1) ⇒ Object
Bitwise mod without processing of the x and z states.
-
.bitwise_mul(s0, s1) ⇒ Object
Bitwise mul.
-
.bitwise_mul0(s0, s1) ⇒ Object
Bitwise mul without processing of the x and z states.
-
.bitwise_neg(s) ⇒ Object
Bitwise negation.
-
.bitwise_neg0(s) ⇒ Object
Bitwise negation without processing of the x and z states.
-
.bitwise_not(s) ⇒ Object
Bitwise not.
-
.bitwise_or(s0, s1) ⇒ Object
Bitwise or.
-
.bitwise_pos(s) ⇒ Object
Bitwise positive sign: does nothing.
-
.bitwise_shl(s0, s1) ⇒ Object
Bitwise shift left.
-
.bitwise_shr(s0, s1) ⇒ Object
Bitwise shift right.
-
.bitwise_sub(s0, s1) ⇒ Object
Bitwise subtraction.
-
.bitwise_sub0(s0, s1) ⇒ Object
Bitwise subtraction without processing of the x and z states.
-
.bitwise_xor(s0, s1) ⇒ Object
Bitwise xor.
-
.list_add!(l0, l1) ⇒ Object
Adds +l1+ to +l0+.
-
.list_add_1!(l0) ⇒ Object
Adds 1 to +l0+.
-
.list_and_unknown(l) ⇒ Object
Compute the and between +l+ and an unknown value.
-
.list_not(l) ⇒ Object
Compute the not of +l+.
-
.list_shl!(l, x) ⇒ Object
Left shifts +l+ +x+ times.
-
.list_shl_1!(l) ⇒ Object
Left shifts +l+ once.
-
.list_shr_1!(l) ⇒ Object
Right shifts +l+ once.
-
.list_sub!(l0, l1) ⇒ Object
Subtracts +l1+ from +l0+.
-
.list_to_bstr(l) ⇒ Object
Converts list of bits +l+ to a bit string.
-
.new_unknown ⇒ Object
Creates a new uniq unknown bit.
Instance Method Summary collapse
-
#[](index) ⇒ Object
Gets a bit by +index+.
-
#[]=(index, value) ⇒ Object
Sets the bit at +index+ to +value+.
-
#coerce(other) ⇒ Object
Coerces.
-
#each(&ruby_block) ⇒ Object
Iterates over the bits.
-
#extend(width) ⇒ Object
Extend to +width+.
-
#initialize(str, sign = nil) ⇒ BitString
constructor
Creates a new bit string from +str+ with +sign+.
-
#maybe_zero? ⇒ Boolean
Tells if the bit string could be zero.
-
#negative? ⇒ Boolean
Tells if the bit string is strictly negative.
-
#nonzero? ⇒ Boolean
Tells if the bit string is not zero.
-
#positive? ⇒ Boolean
Tells if the bit string is strictly.
-
#reverse_each(&ruby_block) ⇒ Object
Reverse iterates over the bits.
-
#sign ⇒ Object
Gets the sign of the bit string.
-
#sign? ⇒ Boolean
Tell if the sign is specified.
-
#specified? ⇒ Boolean
Tell if the bit string is fully specified.
-
#to_list ⇒ Object
Converts to a list of bits where unknown or high z bits are differentiate from each other.
-
#to_numeric ⇒ Object
Convert the bit string to a Ruby Numeric.
-
#to_s ⇒ Object
(also: #str)
Converts to a string (sign bit is comprised).
-
#to_verilog ⇒ Object
Converts the system to Verilog code.
-
#trim(width) ⇒ Object
Trims to +width+.
-
#trunc(width) ⇒ Object
Truncs to +width+.
-
#width ⇒ Object
(also: #size)
Gets the bitwidth.
-
#zero? ⇒ Boolean
Tells if the bit string is zero.
Constructor Details
#initialize(str, sign = nil) ⇒ BitString
Creates a new bit string from +str+ with +sign+.
NOTE:
- +sign+ can be "0", "1", "z" and "x", is positive when "0" and negative when "1".
- when not present it is assumed to be within str.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 34 def initialize(str,sign = nil) # puts "str=#{str}" # Maybe str is an numeric. if str.is_a?(Numeric) then # Yes, convert it to a binary string. num = str str = num.to_s(2) # And fix the sign. if str[0] == "-" then # str = str[1..-1] str = (2**str.size+num).to_s(2) puts "str=#{str}" sign = "-" else sign = "+" end # puts "str=#{str} sign=#{sign}" end # Process the sign sign = sign.to_s unless sign.is_a?(Integer) case sign when 0, "0","+" then @str = "0" when 1, "1","-" then @str = "1" when 2, "z","Z" then @str = "z" when 3, "x","X" then @str = "x" when nil, "" then @str = "" # The sign is in str else raise "Invalid bit string sign: #{sign}" end # Check and set the value of the bit string. if str.respond_to?(:to_a) then # Str is a bit list: convert it to a string. str = str.to_a.map do |e| case e when 0 then "0" when 1 then "1" when 2 then "z" when 3 then "x" else e end end.reverse.join end @str += str.to_s.downcase # puts "@str=#{@str}" unless @str.match(/^[0-1zx]+$/) then raise "Invalid value for creating a bit string: #{str}" end end |
Class Method Details
.bitwise_add(s0, s1) ⇒ Object
Bitwise addition
476 477 478 479 480 481 482 483 484 485 486 487 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 476 def self.bitwise_add(s0,s1) res = "" # The result list of bits c = "0" # The current carry s0.each.zip(s1.each) do |b0,b1| res << XOR3_T[b0][b1][c] c = MAJ_T[b0][b1][c] end # Compute the sign extension (the sign bit of s0 and s1 is used # again) res << XOR3_T[s0.sign][s1.sign][c] return BitString.new(res.reverse) end |
.bitwise_add0(s0, s1) ⇒ Object
Bitwise addition without processing of the x and z states.
471 472 473 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 471 def self.bitwise_add0(s0,s1) return BitString.new("x"*(s0.width+1)) end |
.bitwise_and(s0, s1) ⇒ Object
Bitwise and
536 537 538 539 540 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 536 def self.bitwise_and(s0,s1) res = s0.each.zip(s1.each).map { |b0,b1| AND_T[b0][b1] }.join # puts "s0=#{s0}, s1=#{s1}, res=#{res}" return BitString.new(res.reverse) end |
.bitwise_cp(s0, s1) ⇒ Object
Bitwise cp.
744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 744 def self.bitwise_cp(s0,s1) # Compare the signs. if s0.sign == "0" and s1.sign == "1" then return ONE elsif s0.sign == 0 and s1.sign == "1" then return MINUS_ONE end # Compare the other bits. sub = self.bitwise_sub(s0,s1) if sub.negative? then return MINUS_ONE elsif sub.zero? then return ZERO elsif sub.positive? then return ONE else return UNKNOWN end end |
.bitwise_cp0(s0, s1) ⇒ Object
Bitwise cp without processing of the x and z states.
739 740 741 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 739 def self.bitwise_cp0(s0,s1) return UNKNOWN end |
.bitwise_div(s0, s1) ⇒ Object
Bitwise mod.
805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 805 def self.bitwise_div(s0,s1) width = s0.width # The zero cases. if s0.zero? then return res elsif s1.maybe_zero? then return UNKNOWN.extend(width) end # Handle the sign: the division is only performed on positive # numbers. # NOTE: we are sure that s0 and s1 are not zero since these # cases have been handled before. sign = nil if s0.sign == "0" then if s1.sign == "0" then sign = "0" elsif s1.sign == "1" then sign = "1" s1 = -s1 else # Unknown sign, unkown result. return UNKNOWN.extend(width) end elsif s0.sign == "1" then s0 = -s0 if s1.sign == "0" then sign = "1" elsif s1.sign == "1" then sign = "0" s1 = -s1 else # Unknwown sign, unknown result. return UNKNOWN.extend(width) end else # Unknown sign, unknown result. return UNKNOWN.extend(width) end # Convert s0 and s1 to list of bits of widths of s0 and s1 -1 # (the largest possible value). # s0 will serve as current remainder. s0 = BitString.new(s0) if s0.is_a?(Numeric) s1 = BitString.new(s1) if s1.is_a?(Numeric) s0 = s0.extend(s0.width+s1.width-1) s1 = s1.extend(s0.width) s0 = s0.to_list s1 = s1.to_list puts "first s1=#{s1}" # Adujst s1 to the end of s0 and the corresponding 0s in front of q msb = s0.reverse.index {|b| b != 0} steps = s0.size-msb self.list_shl!(s1,steps-1) q = [ 0 ] * (width-steps) # Apply the non-restoring division algorithm. sub = true puts "steps= #{steps} s0=#{s0} s1=#{s1} q=#{q}" (steps).times do |i| if sub then self.list_sub!(s0,s1) else self.list_add!(s0,s1) end puts "s0=#{s0}" # Is the result positive? if s0[-1] == 0 then # Yes, the next step is a subtraction and the current # result bit is one. sub = true q.unshift(1) elsif s0[-1] == 1 then # No, it is negative the next step is an addition and the # current result bit is zero. sub = false q.unshift(0) else # Unknown sign, the remaining of q is unknown. (steps-i).times { q.unshift(self.new_unknown) } # Still, can add the positive sign bit. q.push(0) break end self.list_shr_1!(s1) end # Generate the resulting bit string. puts "q=#{q}" q = self.list_to_bstr(q) puts "q=#{q}" # Set the sign. if sign == "1" then q = (-q).trunc(width) elsif q.zero? then q = 0 else q = q.extend(width) end # Return the result. return q end |
.bitwise_div0(s0, s1) ⇒ Object
Bitwise div without processing of the x and z states.
800 801 802 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 800 def self.bitwise_div0(s0,s1) return BitString.new("x"*(s0.width)) end |
.bitwise_eq(s0, s1) ⇒ Object
Bitwise eq.
594 595 596 597 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 594 def self.bitwise_eq(s0,s1) return UNKNOWN unless (s0.specified? and s1.specified?) return s0.str == s1.str ? TRUE : FALSE end |
.bitwise_eq0(s0, s1) ⇒ Object
Bitwise eq without processing of the x and z states.
589 590 591 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 589 def self.bitwise_eq0(s0,s1) return UNKNOWN end |
.bitwise_ge(s0, s1) ⇒ Object
Bitwise ge.
726 727 728 729 730 731 732 733 734 735 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 726 def self.bitwise_ge(s0,s1) lt = self.bitwise_lt(s0,s1) if lt.eql?(TRUE) then return FALSE elsif lt.eql?(FALSE) then return TRUE else return UNKNOWN end end |
.bitwise_ge0(s0, s1) ⇒ Object
Bitwise ge without processing of the x and z states.
721 722 723 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 721 def self.bitwise_ge0(s0,s1) return UNKNOWN end |
.bitwise_gt(s0, s1) ⇒ Object
Bitwise gt.
697 698 699 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 697 def self.bitwise_gt(s0,s1) return self.bitwise_lt(s1,s0) end |
.bitwise_gt0(s0, s1) ⇒ Object
Bitwise gt without processing of the x and z states.
692 693 694 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 692 def self.bitwise_gt0(s0,s1) return UNKNOWN end |
.bitwise_le(s0, s1) ⇒ Object
Bitwise le.
708 709 710 711 712 713 714 715 716 717 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 708 def self.bitwise_le(s0,s1) gt = self.bitwise_gt(s0,s1) if gt.eql?(TRUE) then return FALSE elsif gt.eql?(FALSE) then return TRUE else return UNKNOWN end end |
.bitwise_le0(s0, s1) ⇒ Object
Bitwise le without processing of the x and z states.
703 704 705 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 703 def self.bitwise_le0(s0,s1) return UNKNOWN end |
.bitwise_lt(s0, s1) ⇒ Object
Bitwise lt.
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 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 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 606 def self.bitwise_lt(s0,s1) # # Handle the zero cases. # if s0.zero? then # return TRUE if s1.positive? # return FALSE if s1.negative? or s1.zero? # return UNKNOWN # elsif s1.zero? then # return TRUE if s0.negative? # return FALSE if s0.positive? or s0.zero? # return UNKNOWN # end # # Handle the unspecified sign cases. # unless s0.sign? then # # Check both sign cases. # lt_pos = self.bitwise_lt(s0[-1] = "1",s1) # lt_neg = self.bitwise_lt(s0[-1] = "0",s1) # # At least one of the results is unspecified. # return UNKNOWN unless (lt_pos.specified? and lt_neg.specified?) # # Both results are specified and identical. # return lt_pos if lt_pos == lt_neg # # Results are different. # return UNKNOWN # end # unless s1.sign? then # # Check both sign cases. # lt_pos = self.bitwise_lt(s0,s1[-1] = "1") # lt_neg = self.bitwise_lt(s0,s1[-1] = "0") # # At least one of the results is unspecified. # return UNKNOWN unless (lt_pos.specified? and lt_neg.specified?) # # Both results are specified and identical. # return lt_pos if lt_pos == lt_neg # # Results are different. # return UNKNOWN # end # # Signs are specificied. # # Depending on the signs # if s0.positive? then # if s1.positive? then # # s0 and s1 are positive, need to compare each bit. # s0.reverse_each.zip(s1.reverse_each) do |b0,b1| # # puts "b0=#{b0} b1=#{b1}, LT_T[b0][b1]=#{LT_T[b0][b1]}" # case LT_T[b0][b1] # when "x" then return UNKNOWN # when "1" then return TRUE # when "0" then # return FALSE if GT_T[b0][b1] == "1" # end # end # elsif s1.negative? then # # s0 is positive and s1 is negative. # return FALSE # else # # The sign of s1 is undefined, comparison is undefined too. # return UNKNOWN # end # elsif s0.negative? then # if s1.positive? then # # s0 is negative and s1 is positive # return TRUE # elsif s1.negative? then # # s0 and s1 are negative, need to compare each bit. # s0.reverse_each.zip(s1.reverse_each) do |b0,b1| # case GT_T[b0][b1] # when "x" then return UNKNOWN # when "1" then return FALSE # when "0" then # return TRUE if LT_T[b0][b1] == "1" # end # end # end # else # # The sign of s0 is undefined, comparison is undefined too. # return UNKNOWN # end # Check the sign of the subtraction between s0 and s1. case (s0-s1).sign when "0" then return FALSE when "1" then return TRUE else return UNKNOWN end end |
.bitwise_lt0(s0, s1) ⇒ Object
Bitwise lt without processing of the x and z states.
601 602 603 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 601 def self.bitwise_lt0(s0,s1) return UNKNOWN end |
.bitwise_mod0(s0, s1) ⇒ Object
Bitwise mod without processing of the x and z states.
906 907 908 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 906 def self.bitwise_mod0(s0,s1) return BitString.new("x"*(s1.width)) end |
.bitwise_mul(s0, s1) ⇒ Object
Bitwise mul.
770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 770 def self.bitwise_mul(s0,s1) # Initialize the result to ZERO of combined s0 and s1 widths res = ZERO.extend(s0.width + s1.width) # The zero cases. if s0.zero? or s1.zero? then return res end # Convert s1 and res to lists of bits which support computation # between unknown bits of same values. s1 = s1.extend(res.width).to_list res = res.to_list # The other cases: perform a multiplication with shifts and adds. s0.each.lazy.take(s0.width).each do |b| case b when "1" then self.list_add!(res,s1) when "x","z" then self.list_add!(res,self.list_and_unknown(s1)) end # puts "res=#{res} s1=#{s1}" self.list_shl_1!(s1) end # Add the sign row. case s0.sign when "1" then self.list_sub!(res,s1) when "x","z" then self.list_sub!(res,list_and_unknown(s1)) end # Return the result. return self.list_to_bstr(res) end |
.bitwise_mul0(s0, s1) ⇒ Object
Bitwise mul without processing of the x and z states.
765 766 767 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 765 def self.bitwise_mul0(s0,s1) return BitString.new("x"*(s0.width+s1.width)) end |
.bitwise_neg(s) ⇒ Object
Bitwise negation
526 527 528 529 530 531 532 533 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 526 def self.bitwise_neg(s) # -s = ~s + 1 # # Not s. # s = BitString.bitwise_not(s) # # Add 1. # return BitString.bitwise_add(s,ONE.extend(s.width)) return ~s + 1 end |
.bitwise_neg0(s) ⇒ Object
Bitwise negation without processing of the x and z states.
521 522 523 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 521 def self.bitwise_neg0(s) return BitString.new("x"*(s.width+1)) end |
.bitwise_not(s) ⇒ Object
Bitwise not
555 556 557 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 555 def self.bitwise_not(s) return BitString.new(s.each.map { |b| NOT_T[b] }.join.reverse) end |
.bitwise_or(s0, s1) ⇒ Object
Bitwise or
543 544 545 546 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 543 def self.bitwise_or(s0,s1) res = s0.each.zip(s1.each). map { |b0,b1| OR_T[b0][b1] }.join return BitString.new(res.reverse) end |
.bitwise_pos(s) ⇒ Object
Bitwise positive sign: does nothing.
516 517 518 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 516 def self.bitwise_pos(s) return s end |
.bitwise_shl(s0, s1) ⇒ Object
Bitwise shift left.
560 561 562 563 564 565 566 567 568 569 570 571 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 560 def self.bitwise_shl(s0,s1) # puts "s0=#{s0} s1=#{s1}" return BitString.new("x" * s0.width) unless s1.specified? s1 = s1.to_numeric if s1 >= 0 then return BitString.new(s0.str + "0" * s1) elsif -s1 > s0.width then return ZERO else return s0.trim(s0.width+s1) end end |
.bitwise_shr(s0, s1) ⇒ Object
Bitwise shift right.
574 575 576 577 578 579 580 581 582 583 584 585 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 574 def self.bitwise_shr(s0,s1) # puts "s0=#{s0} s1=#{s1}" return BitString.new("x" * s0.width) unless s1.specified? s1 = s1.to_numeric if s1 <= 0 then return BitString.new(s0.str + "0" * -s1) elsif s1 > s0.width then return ZERO else return s0.trim(s0.width-s1) end end |
.bitwise_sub(s0, s1) ⇒ Object
Bitwise subtraction
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 495 def self.bitwise_sub(s0,s1) # # Negate s1. # s1 = BitString.bitwise_neg(s1).trunc(s0.width) # # puts "s1.width = #{s1.width} s0.width = #{s0.width}" # # Add it to s0: but no need to add a bit since neg already added # # one. # return BitString.bitwise_add(s0,s1) # Perform the computation is a way to limit the propagation of # unspecified bits. # Is s1 specified? if s1.specified? then # Yes, perform -s1+s0 return (-s1 + s0) else # No, perform s0+1+NOT(s1). # puts "s0=#{s0} s0+1=#{s0+1} not s1=#{bitwise_not(s1)}" return (s0 + 1 + bitwise_not(s1)).trunc(s0.width+1) end end |
.bitwise_sub0(s0, s1) ⇒ Object
Bitwise subtraction without processing of the x and z states.
490 491 492 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 490 def self.bitwise_sub0(s0,s1) return BitString.new("x"*(s0.width+1)) end |
.bitwise_xor(s0, s1) ⇒ Object
Bitwise xor
549 550 551 552 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 549 def self.bitwise_xor(s0,s1) res = s0.each.zip(s1.each). map { |b0,b1| XOR_T[b0][b1] }.join return BitString.new(res.reverse) end |
.list_add!(l0, l1) ⇒ Object
Adds +l1+ to +l0+.
NOTE:
- l0 is contains the result.
- The result has the same size as +l0+ (no sign extension).
- Assumes +l0+ and +l1+ have the same size.
978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 978 def self.list_add!(l0,l1) # puts "add l0=#{l0} l1=#{l1}" c = 0 # Current carry. l0.each_with_index do |b0,i| b1 = l1[i] # puts "i=#{i} b0=#{b0} b1=#{b1} c=#{c}" if b0 == b1 then # The sum is c. l0[i] = c # The carry is b0. c = b0 elsif b0 == c then # The sum is b1. l0[i] = b1 # The carry is b0. c = b0 elsif b1 == c then # The sum is b0. l0[i] = b0 # The carry is b1. c = b1 else l0[i] = self.new_unknown c = self.new_unknown end end return l0 end |
.list_add_1!(l0) ⇒ Object
Adds 1 to +l0+.
NOTE:
- l0 is contains the result.
- The result has the same size as +l0+ (no sign extension).
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 1012 def self.list_add_1!(l0) c = 1 # Current carry. l0.each_with_index do |b0,i| if c == 0 then # The sum is b0. l0[i] = b0 # The carry is unchanged. elsif b0 == 0 then # The sum is c. l0[i] = c # The carry is 0. c = 0 elsif b0 == c then # The sum is 0. l0[i] = 0 # The carry is b0. c = b0 else # Both sum and carry are unknown l0[i] = BitString.new_unknown c = BitString.new_unknown end end return l0 end |
.list_and_unknown(l) ⇒ Object
Compute the and between +l+ and an unknown value.
954 955 956 957 958 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 954 def self.list_and_unknown(l) return l.map do |b| b == 0 ? 0 : BitString.new_unknown end end |
.list_not(l) ⇒ Object
Compute the not of +l+
961 962 963 964 965 966 967 968 969 970 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 961 def self.list_not(l) return l.map do |b| case b when 0 then 1 when 1 then 0 else BitString.new_unknown end end end |
.list_shl!(l, x) ⇒ Object
Left shifts +l+ +x+ times.
NOTE:
- l contains the result.
- The result has the same size as +l+ (no sign extension).
1083 1084 1085 1086 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 1083 def self.list_shl!(l,x) l.pop(x) l.unshift(*([0]*x)) end |
.list_shl_1!(l) ⇒ Object
Left shifts +l+ once.
NOTE:
- l contains the result.
- The result has the same size as +l+ (no sign extension).
1060 1061 1062 1063 1064 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 1060 def self.list_shl_1!(l) l.pop l.unshift(0) return l end |
.list_shr_1!(l) ⇒ Object
Right shifts +l+ once.
NOTE:
- l contains the result.
- The result has the same size as +l+ (no sign extension).
1071 1072 1073 1074 1075 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 1071 def self.list_shr_1!(l) l.shift l.push(0) return l end |
.list_sub!(l0, l1) ⇒ Object
Subtracts +l1+ from +l0+.
NOTE:
- l0 is contains the result.
- The result has the same size as +l0+ (no sign extension).
- Assumes +l0+ and +l1+ have the same size.
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 1044 def self.list_sub!(l0,l1) # Adds 1 to l0. BitString.list_add_1!(l0) # Adds ~l1 to l0. # puts "l0=#{l0} l1=#{l1} ~l1=#{self.list_not(l1)}}" self.list_add!(l0,self.list_not(l1)) # puts "l0=#{l0}" # puts "now l0=#{l0}" return l0 end |
.list_to_bstr(l) ⇒ Object
Converts list of bits +l+ to a bit string.
948 949 950 951 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 948 def self.list_to_bstr(l) str = l.reverse_each.map { |b| b > 1 ? "x" : b }.join return BitString.new(str) end |
.new_unknown ⇒ Object
Creates a new uniq unknown bit.
924 925 926 927 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 924 def self.new_unknown @@unknown += 1 return @@unknown end |
Instance Method Details
#[](index) ⇒ Object
Gets a bit by +index+.
NOTE: If the index is larger than the bit string width, returns the bit sign.
132 133 134 135 136 137 138 139 140 141 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 132 def [](index) # Handle the negative index case. if index < 0 then return self[self.width+index] end # Process the index. index = index > @str.size ? @str.size : index # Get the corresponding bit. return @str[-index-1] end |
#[]=(index, value) ⇒ Object
Sets the bit at +index+ to +value+.
NOTE: when index is larger than the bit width, the bit string is sign extended accordingly.
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 147 def []=(index,value) # Handle the negative index case. if index < 0 then return self[self.width+index] = value end # Duplicate the bit string content to ensure immutability. str = @str.clone # Process the index. if index >= str.size then # Overflow, sign extend the bit string. str += str[-1] * (index-str.size+1) end # Checks and convert the value value = make_bit(value) # Sets the value to a copy of the bit string. str[-index-1] = value # Return the result as a new bit string. return BitString.new(str) end |
#coerce(other) ⇒ Object
Coerces.
252 253 254 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 252 def coerce(other) return [BitString.new(other),self] end |
#each(&ruby_block) ⇒ Object
Iterates over the bits.
NOTE: the sign bit in comprised.
Returns an enumerator if no ruby block is given.
204 205 206 207 208 209 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 204 def each(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each) unless ruby_block # A block? Apply it on each bit. @str.each_char.reverse_each(&ruby_block) end |
#extend(width) ⇒ Object
Extend to +width+.
NOTE:
- if the width is already larger than +width+, do nothing.
- preserves the sign.
194 195 196 197 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 194 def extend(width) return self if width <= @str.size - 1 return BitString.new(@str[0] * (width-@str.size+1) + @str) end |
#maybe_zero? ⇒ Boolean
Tells if the bit string could be zero.
118 119 120 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 118 def maybe_zero? return ! self.nonzero? end |
#negative? ⇒ Boolean
Tells if the bit string is strictly negative.
NOTE: return false if the sign is undefined
101 102 103 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 101 def negative? return @str[0] == "1" end |
#nonzero? ⇒ Boolean
Tells if the bit string is not zero.
113 114 115 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 113 def nonzero? return @str.each_char.any? {|b| b == "1" } end |
#positive? ⇒ Boolean
Tells if the bit string is strictly.
NOTE: return false if the sign is undefined of if it is unknown if the result is zero or not.
94 95 96 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 94 def positive? return (@str[0] == "0" and self.nonzero?) end |
#reverse_each(&ruby_block) ⇒ Object
Reverse iterates over the bits.
NOTE: the sign bit in comprised.
Returns an enumerator if no ruby block is given.
216 217 218 219 220 221 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 216 def reverse_each(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:reverse_each) unless ruby_block # A block? Apply it on each bit. @str.each_char(&ruby_block) end |
#sign ⇒ Object
Gets the sign of the bit string.
224 225 226 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 224 def sign return @str[0] end |
#sign? ⇒ Boolean
Tell if the sign is specified.
229 230 231 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 229 def sign? return (@str[0] == "0" or @str[0] == "1") end |
#specified? ⇒ Boolean
Tell if the bit string is fully specified
247 248 249 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 247 def specified? return ! @str.match(/[xz]/) end |
#to_list ⇒ Object
Converts to a list of bits where unknown or high z bits are differentiate from each other.
NOTE:
- the sign bit is also added to the list.
- the distinction between z and x is lost.
935 936 937 938 939 940 941 942 943 944 945 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 935 def to_list return @str.each_char.reverse_each.map.with_index do |b,i| case b when "0" then 0 when "1" then 1 when "z","x" then BitString.new_unknown else raise "Internal error: invalid bit in bitstring: #{b}" end end end |
#to_numeric ⇒ Object
Convert the bit string to a Ruby Numeric.
NOTE: the result will be wrong is the bit string is unspecified.
236 237 238 239 240 241 242 243 244 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 236 def to_numeric res = 0 # Process the bits. @str[1..-1].each_char { |b| res = res << 1 | b.to_i } # Process the sign. res = res - (2**(@str.size-1)) if @str[0] == "1" # Return the result. return res end |
#to_s ⇒ Object Also known as: str
Converts to a string (sign bit is comprised).
123 124 125 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 123 def to_s return @str.clone end |
#to_verilog ⇒ Object
Converts the system to Verilog code.
1499 1500 1501 |
# File 'lib/HDLRuby/hruby_verilog.rb', line 1499 def to_verilog return "#{self.to_s}" end |
#trim(width) ⇒ Object
Trims to +width+.
NOTE:
- trim remove the begining of the bit string.
- if the width is already smaller than +width+, do nothing.
- do not preserve the sign, but keep the last bit as sign bit.
184 185 186 187 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 184 def trim(width) return self if width >= @str.size-1 return BitString.new(@str[0..width]) end |
#trunc(width) ⇒ Object
Truncs to +width+.
NOTE:
- trunc remove the end of the bit string.
- if the width is already smaller than +width+, do nothing.
- do not preserve the sign, but keep the last bit as sign bit.
173 174 175 176 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 173 def trunc(width) return self if width >= @str.size-1 return BitString.new(@str[(@str.size-width-1)..-1]) end |
#width ⇒ Object Also known as: size
Gets the bitwidth.
85 86 87 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 85 def width return @str.size end |
#zero? ⇒ Boolean
Tells if the bit string is zero.
NOTE: return false if the bit string is undefined.
108 109 110 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 108 def zero? return ! @str.each_char.any? {|b| b != "0" } end |