Module: HDLRuby

Defined in:
lib/HDLRuby.rb,
lib/HDLRuby/hdrcc.rb,
lib/HDLRuby/hdrlib.rb,
lib/HDLRuby/version.rb,
lib/HDLRuby/hruby_low.rb,
lib/HDLRuby/hruby_bstr.rb,
lib/HDLRuby/hruby_check.rb,
lib/HDLRuby/hruby_error.rb,
lib/HDLRuby/hruby_tools.rb,
lib/HDLRuby/hruby_types.rb,
lib/HDLRuby/hruby_values.rb,
lib/HDLRuby/hruby_low2sym.rb,
lib/HDLRuby/hruby_decorator.rb,
lib/HDLRuby/hruby_serializer.rb

Overview

High-level libraries for describing digital hardware.

Defined Under Namespace

Modules: Hdecorator, High, Low, LowDB, Prefix, Serializer, Tprocess, Unit, Verilog, Vprocess Classes: AnyError, BitString, Checker, HDRLoad, Properties

Constant Summary collapse

VERSION =
"3.2.0"
Infinity =

Some useful constants

+1.0/0.0
TO_BASICS =

The classes meant to support to_basic.

[
 # Low::SystemT, Low::SignalT, Low::Behavior, Low::TimeBehavior,
 Low::SystemT,
 Low::Scope,
 Low::Type, # Low::TypeNumeric,
 Low::TypeDef,
 Low::TypeVector,
 Low::TypeSigned, Low::TypeUnsigned, Low::TypeFloat,
 Low::TypeTuple, Low::TypeStruct,
 Low::Behavior, Low::TimeBehavior, 
 Low::Event, Low::Block, Low::TimeBlock, 
 Low::Program, Low::Code, 
 Low::SignalI, Low::SignalC,
 Low::SystemI, Low::Connection, 
 Low::Transmit, Low::If, Low::Case, Low::When, Low::Cast,
 Low::TimeWait, Low::TimeRepeat,
 Low::Delay,
 # Low::Value, Low::Unary, Low::Binary, Low::Ternary, Low::Concat,
 Low::Value, Low::Unary, Low::Binary, Low::Select, Low::Concat,
 Low::RefConcat, Low::RefIndex, Low::RefRange,
 Low::RefName, Low::RefThis,

 BitString
]
TO_BASIC_NAMES =

The names of the classes of HDLRuby supporting to_basic

TO_BASICS.map { |klass| const_reduce(klass.to_s) }
TO_BASICS_TYPES =

The classes describing types (must be described only once)

[Low::SystemT,
Low::Type, Low::TypeDef,
Low::TypeVector, Low::TypeTuple, Low::TypeStruct]
FIELDS_TO_EXCLUDE =

The list of fields to exclude from serialization.

{ Low::SystemT => [:@interface,:@parent ] }
FIELDS_OF_REF =

The list of fields that correspond to reference.

{ Low::SystemI => [ :@systemT,:@systemTs ] }
REF_ARG_NAMES =

The name of the reference argument if any.

{ Low::SystemI    => ["systemT","systemTs"],
  Low::SignalI    => ["type"],
  Low::TypeVector => ["base"],
  Low::TypeTuple  => ["types"],
  Low::RefThis    => ["type"],
  Low::RefName    => ["type"],
  Low::RefIndex   => ["type"],
  Low::Unary      => ["type"],
  Low::Binary     => ["type"],
  Low::Select     => ["type"],
  Low::Value      => ["type"]
}
FROM_BASICS_REFS =

The table of the object that can be refered to, used when deserializing.

{ }
@@absoluteCounter =

Method and attribute for generating an absolute uniq name. Such names cannot be used in HDLRuby::High code, but can be used to generate such code.

-1 # The absolute name counter.
@@uniq_names =

The absolute name counter.

Set.new(Symbol.all_symbols.map {|sym| sym.to_s})
@@verbosity =

Display some messages depending on the verbosity mode.

1

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.basic_to_value(basic) ⇒ Object

Convert a +basic+ structure to a ruby object.



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/HDLRuby/hruby_serializer.rb', line 142

def self.basic_to_value(basic)
    # print "For basic=#{basic} (#{basic.class})\n"
    # Detect which kind of basic struture it is.
    if basic.is_a?(NilClass) or basic.is_a?(Numeric) or 
            basic.is_a?(Low::Value) then
        # Nil, Numeric or Value objects are kept as they are.
        return basic
    elsif basic.is_a?(Range) then
        # First and last of range are converted.
        return basic_to_value(basic.first)..basic_to_value(basic.last)
    elsif basic.is_a?(String) then
        # String objects are cloned for avoiding side effects.
        return basic.clone
    elsif basic.is_a?(Array) then
        # Array objects are kept as they are, but their content is converted
        # to basic.
        return basic.map { |elem| basic_to_value(elem) }
    elsif basic.is_a?(Hash) then
        # Is the hash representing a class?
        # print "basic.size = #{basic.size}\n"
        # if basic.size == 1 then
        #     print "name = #{HDLRuby.const_reduce(basic.keys[0])}\n"
        # end
        if is_basic_HDLRuby?(basic) then
            # Yes, rebuild the object.
            # First get the class.
            klass = HDLRuby.const_get(basic.keys[0])
            # print "klass=#{klass}\n"
            # The the content.
            content = basic.values[0]
            # Handle the case of the ranges
            content.each do |k,v|
                if k.to_sym == :range and v.is_a?(Array) then
                    content[k] = basic_to_value(v[0])..basic_to_value(v[1])
                end
            end
            # Single instance variables are set with the structure,
            # separate them from the multiple instances.
            multiples,singles = content.partition do |k,v|
                (v.is_a?(Hash) or v.is_a?(Array)) and !is_basic_HDLRuby?(v)
            end
            # Create the object.
            # Get the name of the reference used in the constructor if any
            ref = REF_ARG_NAMES[klass]
            # Process the arguments of the object constructor.
            singles.map! do |k,v|
                # puts "ref=#{ref} k=#{k} v=#{v}"
                elem = basic_to_value(v)
                # puts "elem=#{elem}"
                # if ref == k and elem.is_a?(String) then
                if ref and ref.include?(k) and elem.is_a?(String) then
                    # The argument is actually a reference, get the
                    # corresponding object.
                    elem = FROM_BASICS_REFS[elem.to_sym]
                end
                # puts "now elem=#{elem}"
                elem
            end
            # Build the object with the processed arguments.
            # object = klass.new(*singles.map{|k,v| basic_to_value(v) })
            # puts "klass=#{klass}, singles=#{singles.join("\n")}, multiples=#{multiples.join("\n")}"
            object = klass.new(*singles)
            # Adds the multiple instances.
            multiples.each do |k,v|
                # puts "k=#{k} v=#{v}"
                # Construct the add method: add_<key name without ending s>
                add_meth = ("add_" + k)[0..-2].to_sym
                # Treat the values a an array.
                v = v.values if v.is_a?(Hash)
                # puts "v=#{v}"
                v.each do |elem|
                    # object.send(add_meth, *basic_to_value(elem) )
                    elem = basic_to_value(elem)
                    # puts "ref=#{ref}, k=#{k}"
                    # puts "to add elem=#{elem}"
                    # if ref == k and elem.is_a?(String) then
                    if ref and ref.include?(k) and elem.is_a?(String) then
                        # The argument is actually a reference, get the
                        # corresponding object.
                        elem = FROM_BASICS_REFS[elem.to_sym]
                    end
                    # puts "adding elem=#{elem} to object=#{object}" if elem.is_a?(SystemT)
                    # In general it is enough to add the element to
                    # the object. However, in the case of a systemI,
                    # the main systemT is added to the list at
                    # the creation of the SystemI and is therefore
                    # not to be added.
                    if !object.is_a?(SystemI) || object.systemT != elem
                        object.send(add_meth, *elem )
                    end
                end
            end
            # Store the objects if it is named.
            if object.respond_to?(:name) then
                # puts "Registering name=#{object.name} with #{object}"
                FROM_BASICS_REFS[object.name] = object
            end
            # Returns the resulting object.
            return object
        else
            # No, this a standard hash, keep it as is but convert its 
            # contents.
            return basic.map do |k,v|
                [ basic_to_value(k), basic_to_value(v) ]
            end.to_h
        end
    else
        # Other cases should happen.
        raise AnyError, "Invalid class for a basic object: #{basic.class}."
    end
end

.const_reduce(name, num = 1) ⇒ Object

Reduce a constant +name+ to +num+ number of namespace levels.



9
10
11
12
# File 'lib/HDLRuby/hruby_serializer.rb', line 9

def self.const_reduce(name, num = 1)
    levels = name.split("::")
    return levels[-([num,levels.size].min)..-1].join("::")
end

.from_yaml(stream) ⇒ Object

Convert a stream to a HDLRuby list of objects.



256
257
258
259
260
261
# File 'lib/HDLRuby/hruby_serializer.rb', line 256

def self.from_yaml(stream)
    # Get the basic structure from the stream.
    basic = YAML.load_stream(stream)
    # Convert the basic structure to HDLRuby objects.
    return basic_to_value(basic)
end

.is_basic_HDLRuby?(basic) ⇒ Boolean

Tells if a +basic+ structure is a representation of an HDLRuby object.

Returns:

  • (Boolean)


73
74
75
76
# File 'lib/HDLRuby/hruby_serializer.rb', line 73

def self.is_basic_HDLRuby?(basic)
    return ( basic.is_a?(Hash) and basic.size == 1 and
        TO_BASIC_NAMES.include?(HDLRuby.const_reduce(basic.keys[0])) )
end

.show(*args) ⇒ Object

Display a common message.



76
77
78
# File 'lib/HDLRuby/hruby_tools.rb', line 76

def self.show(*args)
    puts(*args) if @@verbosity > 1
end

.show!(*args) ⇒ Object

Display a critical message.



71
72
73
# File 'lib/HDLRuby/hruby_tools.rb', line 71

def self.show!(*args)
    puts(*args) if @@verbosity > 0
end

.show?(*args) ⇒ Boolean

Display a minor message.

Returns:

  • (Boolean)


81
82
83
# File 'lib/HDLRuby/hruby_tools.rb', line 81

def self.show?(*args)
    puts(*args) if @@verbosity > 2
end

.uniq_name(base = "") ⇒ Object

Generates an absolute uniq name.



20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/HDLRuby/hruby_tools.rb', line 20

def self.uniq_name(base = "")
    @@absoluteCounter += 1
    name = base.to_s + ":#{@@absoluteCounter}"
    # if Symbol.all_symbols.find {|symbol| symbol.to_s == name } then
    if @@uniq_names.include?(name) then
        # The symbol exists, try again.
        return self.uniq_name
    else
        @@uniq_names.add(name)
        return name.to_sym
    end
    # return base.to_s + ":#{@@absoluteCounter}"
end

.value_to_basic(ref, value, types = {}, generated = [[]]) ⇒ Object

Converts a +value+ to a basic structure easy-to-write YAML string.

Other parameters: +top+:: indicates if the object is the top of the description or not. If it is the top, the namespace it comes from is kept. +types+:: contains the type objects which will have to be converted separately. def self.value_to_basic(value, types = {}) Converts a +value+ to a basic structure easy-to-write YAML string.

Other parameters: +ref+:: indicates if the object is a reference or not. +types+:: contains the type objects which will have to be converted separately. +generated+:: is the stack of the generated named objects in the current context.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/HDLRuby/hruby_serializer.rb', line 96

def self.value_to_basic(ref, value, types = {}, generated = [[]])
    # Depending on the class.
    if value.is_a?(Symbol) then
        # Symbol objects are converted to strings.
        return value.to_s
    elsif value.is_a?(String) then
        # String objects are cloned for avoid side effects.
        return value.clone
    elsif value.is_a?(Numeric) or value.is_a?(NilClass) then
        # Nil and Numeric objects are kept as they are.
        return value
    elsif  value.is_a?(Range)
        # Convert to an array made of the converted first and last.
        return [value_to_basic(ref,value.first,types,generated),
                value_to_basic(ref,value.last,types,generated)]
    elsif value.is_a?(Array) then
        # Arrays are kept as they are, but their content is converted
        # to basic.
        return value.map { |elem| value_to_basic(ref,elem,types,generated) }
    # elsif value.is_a?(Base::HashName) then
    elsif value.is_a?(Low::HashName) then
        # Hash name, convert it to an array.
        return value.map { |v| value_to_basic(ref,v,types,generated) }
    elsif value.is_a?(Hash) then
        # Maybe the hash is empty.
        if value.empty? then
            return { }
        end
        # Convert its content to basic.
        return value.map do |k,v|
            [value_to_basic(ref,k,types,generated),
             value_to_basic(ref,v,types,generated)]
        end.to_h
    else
        # For the other cases, only HDLRuby classes supporting to_basic
        # are supported.
        unless TO_BASICS.include?(value.class) then
            raise AnyError, "Invalid class for converting to basic structure: #{value.class}"
        end
        # return value.to_basic(false,types)
        return value.to_basic(false,ref,types,generated)
    end
end

.verbosity=(val) ⇒ Object

Sets the verbosity.



66
67
68
# File 'lib/HDLRuby/hruby_tools.rb', line 66

def self.verbosity=(val)
    @@verbosity = val.to_i
end

Instance Method Details

#error_manager(files, &code) ⇒ Object

Execution context for processing error messages in +code+. The relevant error message to are assumed to be the ones whose file name is one given in +files+.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/HDLRuby/hruby_error.rb', line 27

def error_manager(files,&code)
    begin
        code.call
    rescue ::StandardError => e
        # pp e.backtrace
        # Keep the relevant 
        e.backtrace.select! do |mess|
            files.find {|file| mess.include?(File.basename(file))}
        end
        puts "#{e.backtrace[0]}: #{e.message}"
        e.backtrace[1..-1].each { |mess| puts "   from #{mess}"}
        exit
    rescue 
        raise "Big Bad Bug"
    end
end