Class: HDLRuby::Low::SignalI

Inherits:
Object
  • Object
show all
Includes:
Hparent, Low2Symbol
Defined in:
lib/HDLRuby/hruby_low.rb,
lib/HDLRuby/hruby_low2c.rb,
lib/HDLRuby/hruby_low2hdr.rb,
lib/HDLRuby/hruby_low2sym.rb,
lib/HDLRuby/hruby_low2vhd.rb,
lib/HDLRuby/hruby_verilog.rb,
lib/HDLRuby/hruby_low2high.rb,
lib/HDLRuby/hruby_low_mutable.rb,
lib/HDLRuby/hruby_low_resolve.rb,
lib/HDLRuby/hruby_low_skeleton.rb,
lib/HDLRuby/hruby_low_fix_types.rb,
lib/HDLRuby/hruby_low_without_namespace.rb

Overview

Describes a signal.

Direct Known Subclasses

High::SignalI, SignalC

Constant Summary collapse

@@signal_id =

The id of a signal in the simulator.

0

Constants included from Low2Symbol

Low2Symbol::Low2SymbolPrefix, Low2Symbol::Low2SymbolTable, Low2Symbol::Symbol2LowTable

Instance Attribute Summary collapse

Attributes included from Hparent

#parent

Instance Method Summary collapse

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

#hierarchy, #no_parent!, #scope

Constructor Details

#initialize(name, type, val = nil) ⇒ SignalI

Creates a new signal named +name+ typed as +type+. If +val+ is provided, it will be the initial value of the signal.



2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
# File 'lib/HDLRuby/hruby_low.rb', line 2622

def initialize(name,type,val = nil)
    # Check and set the name.
    @name = name.to_sym
    # Check and set the type.
    if type.is_a?(Type) then
        @type = type
    else
        raise AnyError, "Invalid class for a type: #{type.class}."
    end
    # Check and set the initial value if any.
    if val then
        unless val.is_a?(Expression) then
            raise AnyError, "Invalid class for a constant: #{val.class}"
        end
        @value = val
        val.parent = self
    # For memory optimization: no  initialization if not used.
    # else
    #     @value = nil
    end
end

Instance Attribute Details

#nameObject (readonly)

The name of the signal



2611
2612
2613
# File 'lib/HDLRuby/hruby_low.rb', line 2611

def name
  @name
end

#typeObject (readonly)

The type of the signal



2614
2615
2616
# File 'lib/HDLRuby/hruby_low.rb', line 2614

def type
  @type
end

#valueObject (readonly)

The initial value of the signal if any.



2617
2618
2619
# File 'lib/HDLRuby/hruby_low.rb', line 2617

def value
  @value
end

Instance Method Details

#add_signal(sig) ⇒ Object

Adds sub signal +sig+



2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
# File 'lib/HDLRuby/hruby_low.rb', line 2651

def add_signal(sig)
    # puts "add sub=#{sig.name} in signal=#{self}"
    # Sets the hash of sub signals if none.
    @signals = HashName.new unless @signals
    # Check and add the signal.
    unless sig.is_a?(SignalI)
        raise AnyError,
              "Invalid class for a signal instance: #{sig.class}"
    end
    # if @signals.include?(sig) then
    #     raise AnyError, "SignalI #{sig.name} already present."
    # end
    # Set its parent.
    sig.parent = self
    # And add it
    @signals.add(sig)
end

#cloneObject

Clones (deeply)



2720
2721
2722
# File 'lib/HDLRuby/hruby_low.rb', line 2720

def clone
    return SignalI.new(self.name,self.type)
end

#each_deep(&ruby_block) ⇒ Object

Iterates over each object deeply.

Returns an enumerator if no ruby block is given.



2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
# File 'lib/HDLRuby/hruby_low.rb', line 2690

def each_deep(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_deep) unless ruby_block
    # A ruby block? First apply it to current.
    ruby_block.call(self)
    # Then apply on the type.
    self.type.each_deep(&ruby_block)
    # Then apply on the value.
    self.value.each_deep(&ruby_block) if self.value
end

#each_signal(&ruby_block) ⇒ Object

Iterates over the sub signals.

Returns an enumerator if no ruby block is given.



2677
2678
2679
2680
2681
2682
# File 'lib/HDLRuby/hruby_low.rb', line 2677

def each_signal(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_signal) unless ruby_block
    # A ruby block? Apply it on each sub signal instance if any.
    @signals.each(&ruby_block) if @signals
end

#explicit_types!Object

Explicit the types conversions in the signal.



61
62
63
64
65
66
67
68
69
70
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 61

def explicit_types!
    # Is there a value?
    value = self.value
    if value then
        # Yes recurse on it.
        self.set_value!(value.explicit_types(self.type))
    end
    # No, nothing to do.
    return self
end

#get_by_name(name) ⇒ Object

Find an inner object by +name+. NOTE: return nil if not found.



117
118
119
# File 'lib/HDLRuby/hruby_low_resolve.rb', line 117

def get_by_name(name)
    return self.get_signal(name)
end

#get_signal(name) ⇒ Object

Gets a sub signal by name.



2670
2671
2672
# File 'lib/HDLRuby/hruby_low.rb', line 2670

def get_signal(name)
    return @signals ? @signals[name] : nil
end

#immutable?Boolean

Tells if the signal is immutable (cannot be written.)

Returns:

  • (Boolean)


2645
2646
2647
2648
# File 'lib/HDLRuby/hruby_low.rb', line 2645

def immutable?
    # By default, signals are not immutable.
    false
end

#replace_names!(former, nname) ⇒ Object

Replaces recursively +former+ name by +nname+ until it is redeclared.



412
413
414
415
416
417
418
419
# File 'lib/HDLRuby/hruby_low_without_namespace.rb', line 412

def replace_names!(former,nname)
    # Recurse on the type.
    self.type.each_type_deep do |type|
        if type.respond_to?(:name) && type.name == former then
            type.set_name!(nname)
        end
    end
end

#set_name!(name) ⇒ Object

Sets the name.



470
471
472
473
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 470

def set_name!(name)
    # Check and set the name.
    @name = name.to_sym
end

#set_type!(type) ⇒ Object

Sets the type.



476
477
478
479
480
481
482
483
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 476

def set_type!(type)
    # Check and set the type.
    if type.is_a?(Type) then
        @type = type
    else
        raise AnyError, "Invalid class for a type: #{type.class}."
    end
end

#set_value!(value) ⇒ Object

Sets the value (can also be nil for removing the value).



486
487
488
489
490
491
492
493
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 486

def set_value!(value)
    # Check and set teh value.
    unless value == nil || value.is_a?(Expression) then
        raise AnyError, "Invalid class for a constant: #{value.class}"
    end
    @value = value
    value.parent = self unless value == nil
end

#to_c(res, level = 0) ⇒ Object

Generates the C text of the equivalent HDLRuby code. +level+ is the hierachical level of the object. def to_c(level = 0)



901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
# File 'lib/HDLRuby/hruby_low2c.rb', line 901

def to_c(res,level = 0)
    # First generate the sub signals if any.
    if self.each_signal.any? then
        self.each_signal do |signal|
            signal.to_c(res,level)
        end
        # return res
    end

    # No sub signals, generate for the current one.

    # puts "Signal.to_c with signal #{self.name} and c_name: #{Low2C.obj_name(self)}"
    # Declare the global variable holding the signal.
    res << "SignalI "
    self.to_c_signal(res,level+1)
    res << ";\n\n"

    # The header of the signal generation.
    res << " " * level*3
    res << "SignalI " << Low2C.make_name(self) << "() {\n"

    # res << " " * level*3
    # res << "Value l,r,d;\n"
    # res << " " * (level+1)*3
    # res << "unsigned long long i;\n"
    res << " " * (level+1)*3
    res << "SignalI signalI = malloc(sizeof(SignalIS));\n"
    res << " " * (level+1)*3
    res << "signalI->kind = SIGNALI;\n";
    res << "signalI->id = #{@@signal_id};\n"
    @@signal_id = @@signal_id+1;

    # Sets the global variable of the signal.
    res << "\n"
    res << " " * (level+1)*3
    self.to_c_signal(res,level+1)
    res << " = signalI;\n"

    # Set the owner if any.
    if self.parent then
        res << " " * (level+1)*3
        res << "signalI->owner = (Object)"
        res << Low2C.obj_name(self.parent) << ";\n"
    else
        res << "signalI->owner = NULL;\n"
    end

    # Set the name
    res << " " * (level+1)*3
    res << "signalI->name = \"#{self.name}\";\n"
    # Set the type.
    res << " " * (level+1)*3
    # res << "signalI->type = #{self.type.to_c(level+2)};\n"
    res << "signalI->type = "
    self.type.to_c(res,level+2)
    res << ";\n"

    # Generate and set the sub signals if any.
    res << " " * (level+1)*3
    num_sig = self.each_signal.to_a.size
    res << "signalI->num_signals = #{num_sig};\n"
    if num_sig > 0 then
        res << " " * (level+1)*3
        res << "signalI->signals = calloc(sizeof(SignalI),#{num_sig});\n"
        self.each_signal.with_index do |sig,i|
            res << " " * (level+1)*3
            res << "#{Low2C.obj_name(sig)} = #{Low2C.make_name(sig)}();\n"
            res << " " * (level+1)*3
            res << "signalI->signals[#{i}] = #{Low2C.obj_name(sig)};\n"
        end
    end

    # Set the current and the next value.
    res << " " * (level+1)*3
    res << "signalI->c_value = make_value(signalI->type,0);\n"
    res << " " * (level+1)*3
    res << "signalI->c_value->signal = signalI;\n"
    res << " " * (level+1)*3
    res << "signalI->f_value = make_value(signalI->type,0);\n"
    res << " " * (level+1)*3
    res << "signalI->f_value->signal = signalI;\n"
    if self.value then
        # There is an initial value.
        res << " " * (level+1)*3
        res << "copy_value("
        self.value.to_c_expr(res,level+2)
        res << ",signalI->c_value);\n"
        res << "copy_value("
        self.value.to_c_expr(res,level+2)
        res << ",signalI->f_value);\n"
    end

    # Initially the signal can be overwritten by anything.
    res << " " * (level+1)*3
    res << "signalI->fading = 1;\n"

    # Initialize the lists of behavior activated on this signal to 0.
    res << " " * (level+1)*3
    res << "signalI->num_any = 0;\n"
    res << " " * (level+1)*3
    res << "signalI->any = NULL;\n"
    res << " " * (level+1)*3
    res << "signalI->num_pos = 0;\n"
    res << " " * (level+1)*3
    res << "signalI->pos = NULL;\n"
    res << " " * (level+1)*3
    res << "signalI->num_neg = 0;\n"
    res << " " * (level+1)*3
    res << "signalI->neg = NULL;\n"

    # Register the signal for global processing.
    res << " " * (level+1)*3
    res << "register_signal(signalI);\n"


    # Generate the return of the signal.
    res << "\n"
    res << " " * (level+1)*3
    res << "return signalI;\n"

    # Close the signal.
    res << " " * level*3
    res << "};\n\n"
    return res
end

#to_c_alias(res, target, level = 0) ⇒ Object

Generates the C text of the equivalent HDLRuby code in case the signals is actually an alias to another signal. +other+ is the target signal of the alias. +level+ is the hierachical level of the object.



1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
# File 'lib/HDLRuby/hruby_low2c.rb', line 1057

def to_c_alias(res,target,level = 0)
    # puts "Signal.to_c_alias with name: #{Low2C.obj_name(self)}"
    # The resulting string.
    # res = ""

    # Declare the global variable holding the signal.
    res << "SignalI "
    self.to_c_signal(res,level+1)
    res << ";\n\n"

    # The header of the signal generation.
    res << " " * level*3
    res << "SignalI " << Low2C.make_name(self) << "() {\n"

    res << "SignalI signalI = #{Low2C.obj_name(target)};\n"

    # Sets the global variable of the signal.
    res << "\n"
    res << " " * (level+1)*3
    self.to_c_signal(res,level+1)
    res << " = signalI;\n"

    # Generate the return of the signal.
    res << "\n"
    res << " " * (level+1)*3
    res << "return signalI;\n"

    # Close the signal.
    res << " " * level*3
    res << "};\n\n"
    return res
end

#to_c_signal(res, level = 0) ⇒ Object

Generates the C text for an access to the signal. +level+ is the hierachical level of the object. def to_c_signal(level = 0)



886
887
888
889
890
891
892
893
894
895
896
# File 'lib/HDLRuby/hruby_low2c.rb', line 886

def to_c_signal(res,level = 0)
    # res = Low2C.obj_name(self)
    res << Low2C.obj_name(self)
    # # Accumulate the names of each parent until there is no one left.
    # obj = self.parent
    # while(obj) do
    #     res << "_" << Low2C.obj_name(obj)
    #     obj = obj.parent
    # end
    return res
end

#to_ch(res) ⇒ Object

Generates the content of the h file. def to_ch



1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
# File 'lib/HDLRuby/hruby_low2c.rb', line 1029

def to_ch(res)
    # First generate the sub signals if any.
    if self.each_signal.any? then
        self.each_signal do |signal|
            signal.to_ch(res)
        end
        # return res
    end

    # No sub sub signal, generate for the current signal.
    # res = ""
    # puts "to_ch for SignalI: #{self.to_c_signal()}"
    # Declare the global variable holding the signal.
    # res << "extern SignalI #{self.to_c_signal()};\n\n"
    res << "extern SignalI "
    self.to_c_signal(res)
    res << ";\n\n"

    # Generate the access to the function making the behavior.
    res << "extern SignalI " << Low2C.make_name(self) << "();\n\n"

    return res;
end

#to_hdr(level = 0) ⇒ Object

Generates the text of the equivalent hdr text. +level+ is the hierachical level of the object.



309
310
311
# File 'lib/HDLRuby/hruby_low2hdr.rb', line 309

def to_hdr(level = 0)
    return Low2HDR.hdr_use_name(self.name)
end

#to_highObject

Creates a new high signal.



178
179
180
181
182
183
184
185
186
187
188
# File 'lib/HDLRuby/hruby_low2high.rb', line 178

def to_high
    # Is there an initial value?
    if (self.value) then
        # Yes, create a new high signal with it.
        return HDLRuby::High::SignalI.new(self.name,self.type.to_high,
                                      self.val.to_high)
    else
        # No, create a new high signal with it.
        return HDLRuby::High::SignalI.new(self.name,self.type.to_high)
    end
end

#to_verilogObject

Converts the system to Verilog code.



1890
1891
1892
1893
1894
1895
# File 'lib/HDLRuby/hruby_verilog.rb', line 1890

def to_verilog
    # Convert unusable characters and return them.
    vname = name_to_verilog(self.name)
    # self.properties[:verilog_name] = vname
    return "#{vname}"
end

#to_vhdl(level = 0) ⇒ Object

Generates the text of the equivalent HDLRuby::High code. +level+ is the hierachical level of the object.

Raises:



874
875
876
877
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 874

def to_vhdl(level = 0)
    # Should never be here.
    raise AnyError, "Internal error: to_vhdl should be implemented in class :#{self.class}"
end

#widthObject

Gets the bit width.



2715
2716
2717
# File 'lib/HDLRuby/hruby_low.rb', line 2715

def width
    return @type.width
end