module HDLRuby
Module including the classes implementing the high-level and low-level libraries for describing digital hardware.
HDLRuby
compiler interface program
High-level libraries for describing digital hardware.
Constants
- FIELDS_OF_REF
The list of fields that correspond to reference.
- FIELDS_TO_EXCLUDE
The list of fields to exclude from serialization.
- FROM_BASICS_REFS
The table of the object that can be refered to, used when deserializing.
- Infinity
Some useful constants
- REF_ARG_NAMES
The name of the reference argument if any.
- TO_BASICS
The classes meant to support to_basic.
- TO_BASICS_TYPES
The classes describing types (must be described only once)
- TO_BASIC_NAMES
The names of the classes of
HDLRuby
supporting to_basic- VERSION
Public Class Methods
Convert a basic
structure to a ruby object.
# File lib/HDLRuby/hruby_serializer.rb, line 141 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
Reduce a constant name
to num
number of namespace levels.
# 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
Convert a stream to a HDLRuby
list of objects.
# File lib/HDLRuby/hruby_serializer.rb, line 255 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
Tells if a basic
structure is a representation of an HDLRuby
object.
# File lib/HDLRuby/hruby_serializer.rb, line 72 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
Generates an absolute uniq name.
# File lib/HDLRuby/hruby_tools.rb, line 15 def self.uniq_name(base = "") @@absoluteCounter += 1 name = base.to_s + ":#{@@absoluteCounter}" if Symbol.all_symbols.find {|symbol| symbol.to_s == name } then # The symbol exists, try again. return self.uniq_name else return name.to_sym end end
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.
# File lib/HDLRuby/hruby_serializer.rb, line 95 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
Public Instance Methods
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
.
# 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
Converts a value to a valid bit if possible.
# File lib/HDLRuby/hruby_bstr.rb, line 10 def make_bit(value) value = value.to_s.downcase unless ["0","1","x","z"].include?(value) raise "Invalid value for a bit: #{value}" end return value end