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 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 34 def initialize(str,sign = nil) # Maybe str is an numeric. if str.is_a?(Numeric) then # Yes, convert it to a binary string. str = str.to_s(2) # And fix the sign. if str[0] == "-" then str = str[1..-1] 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 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
471 472 473 474 475 476 477 478 479 480 481 482 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 471 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.
466 467 468 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 466 def self.bitwise_add0(s0,s1) return BitString.new("x"*(s0.width+1)) end |
.bitwise_and(s0, s1) ⇒ Object
Bitwise and
531 532 533 534 535 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 531 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.
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 739 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.
734 735 736 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 734 def self.bitwise_cp0(s0,s1) return UNKNOWN end |
.bitwise_div(s0, s1) ⇒ Object
Bitwise mod.
800 801 802 803 804 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 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 800 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.
795 796 797 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 795 def self.bitwise_div0(s0,s1) return BitString.new("x"*(s0.width)) end |
.bitwise_eq(s0, s1) ⇒ Object
Bitwise eq.
589 590 591 592 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 589 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.
584 585 586 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 584 def self.bitwise_eq0(s0,s1) return UNKNOWN end |
.bitwise_ge(s0, s1) ⇒ Object
Bitwise ge.
721 722 723 724 725 726 727 728 729 730 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 721 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.
716 717 718 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 716 def self.bitwise_ge0(s0,s1) return UNKNOWN end |
.bitwise_gt(s0, s1) ⇒ Object
Bitwise gt.
692 693 694 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 692 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.
687 688 689 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 687 def self.bitwise_gt0(s0,s1) return UNKNOWN end |
.bitwise_le(s0, s1) ⇒ Object
Bitwise le.
703 704 705 706 707 708 709 710 711 712 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 703 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.
698 699 700 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 698 def self.bitwise_le0(s0,s1) return UNKNOWN end |
.bitwise_lt(s0, s1) ⇒ Object
Bitwise lt.
601 602 603 604 605 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 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 601 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.
596 597 598 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 596 def self.bitwise_lt0(s0,s1) return UNKNOWN end |
.bitwise_mod0(s0, s1) ⇒ Object
Bitwise mod without processing of the x and z states.
901 902 903 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 901 def self.bitwise_mod0(s0,s1) return BitString.new("x"*(s1.width)) end |
.bitwise_mul(s0, s1) ⇒ Object
Bitwise mul.
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 765 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.
760 761 762 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 760 def self.bitwise_mul0(s0,s1) return BitString.new("x"*(s0.width+s1.width)) end |
.bitwise_neg(s) ⇒ Object
Bitwise negation
521 522 523 524 525 526 527 528 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 521 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.
516 517 518 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 516 def self.bitwise_neg0(s) return BitString.new("x"*(s.width+1)) end |
.bitwise_not(s) ⇒ Object
Bitwise not
550 551 552 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 550 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
538 539 540 541 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 538 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.
511 512 513 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 511 def self.bitwise_pos(s) return s end |
.bitwise_shl(s0, s1) ⇒ Object
Bitwise shift left.
555 556 557 558 559 560 561 562 563 564 565 566 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 555 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.
569 570 571 572 573 574 575 576 577 578 579 580 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 569 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
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 490 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.
485 486 487 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 485 def self.bitwise_sub0(s0,s1) return BitString.new("x"*(s0.width+1)) end |
.bitwise_xor(s0, s1) ⇒ Object
Bitwise xor
544 545 546 547 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 544 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.
973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 973 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).
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 1007 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.
949 950 951 952 953 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 949 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+
956 957 958 959 960 961 962 963 964 965 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 956 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).
1078 1079 1080 1081 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 1078 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).
1055 1056 1057 1058 1059 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 1055 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).
1066 1067 1068 1069 1070 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 1066 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.
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 1039 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.
943 944 945 946 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 943 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.
919 920 921 922 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 919 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.
127 128 129 130 131 132 133 134 135 136 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 127 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.
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 142 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.
247 248 249 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 247 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.
199 200 201 202 203 204 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 199 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.
189 190 191 192 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 189 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.
113 114 115 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 113 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
96 97 98 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 96 def negative? return @str[0] == "1" end |
#nonzero? ⇒ Boolean
Tells if the bit string is not zero.
108 109 110 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 108 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.
89 90 91 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 89 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.
211 212 213 214 215 216 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 211 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.
219 220 221 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 219 def sign return @str[0] end |
#sign? ⇒ Boolean
Tell if the sign is specified.
224 225 226 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 224 def sign? return (@str[0] == "0" or @str[0] == "1") end |
#specified? ⇒ Boolean
Tell if the bit string is fully specified
242 243 244 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 242 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.
930 931 932 933 934 935 936 937 938 939 940 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 930 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.
231 232 233 234 235 236 237 238 239 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 231 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).
118 119 120 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 118 def to_s return @str.clone end |
#to_verilog ⇒ Object
Converts the system to Verilog code.
1303 1304 1305 |
# File 'lib/HDLRuby/hruby_verilog.rb', line 1303 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.
179 180 181 182 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 179 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.
168 169 170 171 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 168 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.
80 81 82 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 80 def width return @str.size end |
#zero? ⇒ Boolean
Tells if the bit string is zero.
NOTE: return false if the bit string is undefined.
103 104 105 |
# File 'lib/HDLRuby/hruby_bstr.rb', line 103 def zero? return ! @str.each_char.any? {|b| b != "0" } end |