Method: HDLRuby::High::Std.included

Defined in:
lib/HDLRuby/std/fixpoint.rb

.included(base) ⇒ Object

Redefines the include to add fixed point generation through the Type class.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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
83
# File 'lib/HDLRuby/std/fixpoint.rb', line 15

def self.included(base)
    # Performs the previous included
    res = self.send(:_included_fixpoint,base)
    # Now modify the Type class if not already modified.
    unless ::HDLRuby::High::Type.instance_methods.include?(:"_[]_fixpoint") then
        ::HDLRuby::High::Type.class_eval do
            # Saves the former type generation method.
            alias_method :"_[]_fixpoint", :[]

            # Redefine the type generation method for supporting fixed point
            # type generation.
            def [](*args)
                if args.size == 1 then
                    return self.send(:"_[]_fixpoint",*args)
                else
                    # Handle the arguments and compute the fix point sizes.
                    arg0,arg1 = *args
                    if arg0.respond_to?(:to_i) then
                        isize = arg0
                    else
                        isize = (arg0.first-arg0.last).abs+1
                    end
                    if arg1.respond_to?(:to_i) then
                        fsize = arg1
                    else
                        fsize = (arg1.first-arg1.last).abs+1
                    end
                    # Build the type.
                    case(self.name)
                    when :bit
                        typ = bit[isize+fsize].typedef(::HDLRuby.uniq_name)
                    when :unsigned
                        typ = unsigned[isize+fsize].typedef(::HDLRuby.uniq_name)
                    when :signed
                        typ = signed[isize+fsize].typedef(::HDLRuby.uniq_name)
                    else
                        raise "Invalid type for generating a fixed point type: #{self.name}"
                    end
                    # Redefine the multiplication and division for fixed point.
                    typ.define_operator(:*) do |left,right|
                        if (typ.signed?) then
                            ((left.as(signed[isize+fsize*2])*right) >> fsize).as(typ)
                        else
                            ((left.as(bit[isize+fsize*2])*right) >> fsize).as(typ)
                        end
                    end
                    typ.define_operator(:/) do |left,right|
                        if (typ.signed?) then
                            (left.as(signed[isize+fsize*2]) << fsize) / right
                        else
                            (left.as(bit[isize+fsize*2]) << fsize) / right
                        end
                    end
                    # Define the removal of the point.
                    typ.define_singleton_method(:no_point) do
                        if (typ.signed?) then
                            signed[typ.width]
                        else
                            bit[typ.width]
                        end
                    end
                    # Return the resulting typ.
                    typ
                end
            end
            return res
        end
    end
end