Module: HDLRuby::High

Defined in:
lib/HDLRuby/hruby_high.rb,
lib/HDLRuby/hruby_rsim.rb,
lib/HDLRuby/hruby_error.rb,
lib/HDLRuby/hruby_rcsim.rb,
lib/HDLRuby/hruby_rsim_vcd.rb,
lib/HDLRuby/hruby_rsim_mute.rb,
lib/HDLRuby/hruby_high_fullname.rb

Overview

Library for enhancing the Ruby simulator with muted output support

Defined Under Namespace

Modules: BlockHierarchy, HArrow, HBlock, HExpression, HRef, HScope_missing, HStatement, HbasicType, High2C, Hinner, HmetaControl, Hmissing, Hmux, Htype, HvectorType, RCSimBehavior, RCSimBlock, SimSignal, SingletonExtend, Soft, Std, WithFullname Classes: AnyError, Behavior, Binary, Block, Case, Cast, Chunk, Code, Concat, Configure, Connection, Delay, Event, Expression, If, Namespace, NotDefinedError, Operation, Print, Program, Ref, RefConcat, RefIndex, RefName, RefObject, RefRange, RefThis, Scope, Select, SignalC, SignalI, Statement, StringE, SystemI, SystemT, TimeBehavior, TimeBlock, TimeRepeat, TimeTerminate, TimeWait, Transmit, Type, TypeDef, TypeFloat, TypeGen, TypeSigned, TypeStruct, TypeTuple, TypeUnsigned, TypeVector, UIError, Unary, Value, When

Constant Summary collapse

Low =

Base = HDLRuby::Base

HDLRuby::Low
Void =

The void type

define_type(:void)
Bit =

The bit type.

define_type(:bit)
Signed =

The signed bit type.

define_type(:signed)
Unsigned =

The unsigned bit type.

define_type(:unsigned)
Float =

The float bit type

define_type(:float)
StringT =

The string type

define_type(:string)
Universe =

The universe, i.e., the top system type.

SystemT.new(:"") {}
NameStack =

The stack of names for creating new names without conflicts.

[ Set.new ]
Integer =

Standard vector types.

TypeSigned.new(:integer,63..0)
Char =
TypeSigned.new(:char,7..0)
Natural =
TypeUnsigned.new(:natural,63..0)
Bignum =
TypeSigned.new(:bignum,HDLRuby::Infinity..0)
Real =
TypeFloat.new(:float)
RCSim =
RCSimCinterface
@@rsim_object_idstr =

Converts a HDLRuby object to a VCD id string.

{ }
@@rsim_object_idstr_count =
0

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.booting?Boolean

Tells HDLRuby is currently booting.

Returns:

  • (Boolean)


17
18
19
# File 'lib/HDLRuby/hruby_high.rb', line 17

def self.booting?
    true
end

.cur_behaviorObject

Gets the enclosing behavior if any.



5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
# File 'lib/HDLRuby/hruby_high.rb', line 5088

def self.cur_behavior
    # return @@cur_behavior
    if in_behavior? then
        user = top_user
        while(user && !user.is_a?(Behavior)) do
            user = user.parent
        end
        return user
    else
        return nil
    end
end

.cur_block(level = 0) ⇒ Object

Gets the enclosing block if any.

NOTE: level allows to get an upper block of the currently enclosing block.



5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
# File 'lib/HDLRuby/hruby_high.rb', line 5125

def self.cur_block(level = 0)
    if Namespaces[-1-level].user.is_a?(Scope) then
        raise AnyError, 
              "Not within a block: #{Namespaces[-1-level].user.class}"
    elsif Namespaces[-1-level].user.is_a?(Block) then
        return Namespaces[-1-level].user
    else
        return cur_block(level+1)
    end
end

.cur_scope(level = 0) ⇒ Object

Gets the enclosing scope if any.

NOTE: level allows to get an upper scope of the currently enclosing scope.



5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
# File 'lib/HDLRuby/hruby_high.rb', line 5110

def self.cur_scope(level = 0)
    if level < 0 then
        raise AnyError, "Not within a scope: #{Namespaces[-1].user.class}"
    end
    if Namespaces[-1-level].user.is_a?(Scope) then
        return Namespaces[-1-level].user
    else
        return cur_scope(level+1)
    end
end

.cur_systemObject

Gets the enclosing system type if any.



5074
5075
5076
5077
5078
5079
5080
5081
5082
# File 'lib/HDLRuby/hruby_high.rb', line 5074

def self.cur_system
    if Namespaces.size <= 1 then
        raise AnyError, "Not within a system type."
    else
        return Namespaces.reverse_each.find do |space|
            space.user.is_a?(Scope) and space.user.parent.is_a?(SystemT)
        end.user.parent
    end
end

.define_type(name) ⇒ Object

Defines a basic type name.



2036
2037
2038
2039
2040
2041
# File 'lib/HDLRuby/hruby_high.rb', line 2036

def self.define_type(name)
    name = name.to_sym
    type = Type.new(name)
    self.send(:define_method,name) { type }
    return type
end

.from_users(method) ⇒ Object

Gather the result of the execution of method from all the users of the namespaces.



5049
5050
5051
5052
5053
5054
5055
5056
# File 'lib/HDLRuby/hruby_high.rb', line 5049

def self.from_users(method)
    Namespaces.reverse_each.reduce([]) do |res,space|
        user = space.user
        if user.respond_to?(method) then
            res += [*user.send(method)]
        end
    end
end

.in_behavior?Boolean

Tell if we are in a behavior.

Returns:

  • (Boolean)


5102
5103
5104
# File 'lib/HDLRuby/hruby_high.rb', line 5102

def self.in_behavior?
    top_user.is_a?(Block)
end

.in_system?Boolean

Tells if within a system type.

Returns:

  • (Boolean)


5069
5070
5071
# File 'lib/HDLRuby/hruby_high.rb', line 5069

def self.in_system?
    return Namespaces.size > 1
end

.make_block(mode = nil, name = :"", &ruby_block) ⇒ Object

Creates a block executed in mode, with possible name, that can be timed or not depending on the enclosing object and build it by executing the enclosing ruby_block.

NOTE: not a method to include since it can only be used with a behavior or a block. Hence set as module method.



4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
# File 'lib/HDLRuby/hruby_high.rb', line 4856

def self.make_block(mode = nil, name = :"", &ruby_block)
    unless mode then
        # No type of block given, get a default one.
        if top_user.is_a?(Block) then
            # There is an upper block, use its mode.
            mode = top_user.mode
        else
            # There is no upper block, use :par as default.
            mode = :par
        end
    end
    if top_user.is_a?(TimeBlock) then
        return TimeBlock.new(mode,name,&ruby_block)
    else
        return Block.new(mode,name,&ruby_block)
    end
end

.make_time_block(mode = nil, name = :"", &ruby_block) ⇒ Object

Creates a specifically timed block in mode, with possible name and build it by executing the enclosing ruby_block.

NOTE: not a method to include since it can only be used with a behavior or a block. Hence set as module method.



4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
# File 'lib/HDLRuby/hruby_high.rb', line 4879

def self.make_time_block(mode = nil, name = :"", &ruby_block)
    unless mode then
        # No type of block given, get a default one.
        if top_user.is_a?(Block) then
            # There is an upper block, use its mode.
            mode = block.mode
        else
            # There is no upper block, use :par as default.
            mode = :par
        end
    end
    return TimeBlock.new(mode,name,&ruby_block)
end

.names_add(name) ⇒ Object

Adds a name to the top of the stack.



5791
5792
5793
# File 'lib/HDLRuby/hruby_high.rb', line 5791

def self.names_add(name)
    NameStack[-1].add(name.to_s)
end

.names_create(base) ⇒ Object

Creates and adds the new name from base that do not collides with the exisiting names.



5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
# File 'lib/HDLRuby/hruby_high.rb', line 5804

def self.names_create(base)
    base = base.to_s.clone
    # Create a non-conflicting name
    if self.names_has?(base) then
        count = 0
        while (self.names_has?(base + count.to_s)) do
            count += 1
        end
        base << count.to_s
    end
    # Add and return it
    self.names_add(base)
    # puts "created name: #{base}"
    return base.to_sym
end

.names_has?(name) ⇒ Boolean

Checks if a name is present in the stack.

Returns:

  • (Boolean)


5796
5797
5798
5799
5800
# File 'lib/HDLRuby/hruby_high.rb', line 5796

def self.names_has?(name)
    NameStack.find do |names|
        names.include?(name)
    end 
end

.names_popObject

Pops from the name stack.



5786
5787
5788
# File 'lib/HDLRuby/hruby_high.rb', line 5786

def self.names_pop
    NameStack.pop
end

.names_pushObject

Pushes on the name stack.



5781
5782
5783
# File 'lib/HDLRuby/hruby_high.rb', line 5781

def self.names_push
    NameStack.push(Set.new)
end

.rcsim(top, name, outpath, outmode) ⇒ Object

Starts the simulation for top system top. NOTE: name is the name of the simulation, outpath is the path where the output is to save, and outmode is the output mode as follows: 0: standard 1: mute 2: vcd



87
88
89
# File 'lib/HDLRuby/hruby_rcsim.rb', line 87

def self.rcsim(top,name,outpath,outmode)
    RCSim.rcsim_main(top.rcsystemT,outpath +"/" + name,outmode)
end

.space_call(name, *args, &ruby_block) ⇒ Object

Looks up and calls method name from the namespace stack with arguments args and block ruby_block.

Raises:



5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
# File 'lib/HDLRuby/hruby_high.rb', line 5163

def self.space_call(name,*args,&ruby_block)
    # print "space_call with name=#{name}\n"
    # Ensures name is a symbol.
    name = name.to_sym
    # Look from the top of the namespace stack.
    Namespaces.reverse_each do |space|
        # puts "space=#{space.singleton_methods}"
        if space.respond_to?(name) then
            # print "Found is space user with class=#{space.user.class}\n"
            # The method is found, call it.
            return space.send(name,*args,&ruby_block)
        elsif space.user.respond_to?(name) then
            # The method is found in the user, call it.
            return space.user.send(name,*args,&ruby_block)
        end
    end
    # Look in the global methods.
    if HDLRuby::High.respond_to?(name) then
        # Found.
        return HDLRuby::High.send(name,*args,&ruby_block)
    end
    # Not found.
    raise NotDefinedError,
          "undefined HDLRuby construct, local variable or method `#{name}'."
end

.space_each(&ruby_block) ⇒ Object

Iterates over each namespace.

Returns an enumerator if no ruby block is given.



5061
5062
5063
5064
5065
5066
# File 'lib/HDLRuby/hruby_high.rb', line 5061

def self.space_each(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:space_each) unless ruby_block
    # A block? Apply it on each system instance.
    Namespaces.each(&ruby_block)
end

.space_include?(namespace) ⇒ Boolean

Tells if namespace in included within the stack.

Returns:

  • (Boolean)


5019
5020
5021
# File 'lib/HDLRuby/hruby_high.rb', line 5019

def self.space_include?(namespace)
    return Namespaces.include?(namespace)
end

.space_index(namespace) ⇒ Object

Gets the index of a namespace within the stack.



5024
5025
5026
# File 'lib/HDLRuby/hruby_high.rb', line 5024

def self.space_index(namespace)
    return Namespaces.index(namespace)
end

.space_insert(index, namespace) ⇒ Object

Inserts namespace at index.



5006
5007
5008
# File 'lib/HDLRuby/hruby_high.rb', line 5006

def self.space_insert(index,namespace)
    Namespaces.insert(index.to_i,namespace.to_namespace)
end

.space_popObject

Pops a namespace.



5011
5012
5013
5014
5015
5016
# File 'lib/HDLRuby/hruby_high.rb', line 5011

def self.space_pop
    if Namespaces.size <= 1 then
        raise AnyError, "Internal error: cannot pop further namespaces."
    end
    Namespaces.pop
end

.space_push(namespace) ⇒ Object

Pushes namespace.



4998
4999
5000
5001
5002
5003
# File 'lib/HDLRuby/hruby_high.rb', line 4998

def self.space_push(namespace)
    # Emsure namespace is really a namespace.
    namespace = namespace.to_namespace
    # Adds the namespace to the top.
    Namespaces.push(namespace)
end

.space_reg(name, &ruby_block) ⇒ Object

Registers hardware referencing method name to the current namespace.



5151
5152
5153
5154
5155
5156
5157
5158
5159
# File 'lib/HDLRuby/hruby_high.rb', line 5151

def self.space_reg(name,&ruby_block)
    # print "registering #{name} in #{Namespaces[-1]}\n"
    # Check the name class. 
    unless name.is_a?(String) or name.is_a?(Symbol) then
      raise AnyError, 
        "Invalid class for a name, string or symbol expected but got: #{name.class}"
    end
    Namespaces[-1].add_method(name,&ruby_block)
end

.space_topObject

Gets the top of the namespaces stack.



5029
5030
5031
# File 'lib/HDLRuby/hruby_high.rb', line 5029

def self.space_top
    Namespaces[-1]
end

.space_top=(top) ⇒ Object

sets the top namespace.



5034
5035
5036
5037
5038
5039
# File 'lib/HDLRuby/hruby_high.rb', line 5034

def self.space_top=(top)
    unless top.is_a?(Namespace) then
        raise "Invalid class for a Namspace: #{top.class}"
    end
    Namespaces[-1] = top
end

.top_block(level = 0) ⇒ Object

Gets the top enclosing block if any.



5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
# File 'lib/HDLRuby/hruby_high.rb', line 5137

def self.top_block(level = 0)
    blk = cur_block(level)
    unless blk.is_a?(Block)
        raise AnyError,
            "Not within a block: #{blk.user.class}"
    end
    if Namespaces[-1-level-1].user.is_a?(Scope) then
        return blk
    else
        return top_block(level+1)
    end
end

.top_userObject

Gets construct whose namespace is the top of the namespaces stack.



5043
5044
5045
# File 'lib/HDLRuby/hruby_high.rb', line 5043

def self.top_user
    self.space_top.user
end

.vcd_bitstr(str) ⇒ Object

Converts a bit string to a vcd format.



15
16
17
18
19
20
21
# File 'lib/HDLRuby/hruby_rsim_vcd.rb', line 15

def self.vcd_bitstr(str)
    if str.length > 1 then
        return "b" + str + " "
    else
        return str
    end
end

.vcd_idstr(obj) ⇒ Object



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

def self.vcd_idstr(obj)
    idstr = @@rsim_object_idstr[obj]
    unless idstr then
        # Must generate a new id string.
        chars = []
        id = @@rsim_object_idstr_count
        @@rsim_object_idstr_count += 1
        loop do
            chars << ((id % (127-33)) + 33).chr
            break if ((id=id/(127-33)) == 0)
        end
        idstr = chars.join
        @@rsim_object_idstr[obj] = idstr
    end
    return idstr
end

.vcd_name(name) ⇒ Object

Converts a HDLRuby name to a VCD name.



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

def self.vcd_name(name)
    return name.to_s.gsub(/[^a-zA-Z0-9_$]/,"$")
end

Instance Method Details

#curry_with_context(*args, &ruby_block) ⇒ Object

Reimplementation of the Proc's curry that transmit the context for execution.



31
32
33
34
35
# File 'lib/HDLRuby/hruby_high.rb', line 31

def curry_with_context(*args,&ruby_block)
    return proc do |cxt,*new_args|
        cxt.instance_exec(*(args+new_args),&ruby_block)
    end
end

#function(name, &ruby_block) ⇒ Object

Declares a function named name using ruby_block as body.

NOTE: a function is a short-cut for a method that creates a scope.



2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
# File 'lib/HDLRuby/hruby_high.rb', line 2427

def function(name, &ruby_block)
    warn("Construct 'function' is deprecated, use 'hdef' instead.")
    # Ensure there is a block.
    ruby_block = proc {} unless block_given?
    if HDLRuby::High.in_system? then
        define_singleton_method(name.to_sym) do |*args,&other_block|
            sub(HDLRuby.uniq_name(name)) do
                HDLRuby::High.top_user.instance_exec(*args,*other_block,
                                                     &ruby_block)
            end
        end
    else
        define_method(name.to_sym) do |*args,&other_block|
            sub(HDLRuby.uniq_name(name)) do
                HDLRuby::High.top_user.instance_exec(*args,*other_block,
                                                     &ruby_block)
            end
        end
    end
end

#hdef(name, &ruby_block) ⇒ Object

Declares a function named name using ruby_block as body.

NOTE: a function is a short-cut for a method that creates a scope.



2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
# File 'lib/HDLRuby/hruby_high.rb', line 2451

def hdef(name, &ruby_block)
    # Ensure there is a block.
    ruby_block = proc {} unless block_given?
    if HDLRuby::High.in_system? then
        define_singleton_method(name.to_sym) do |*args,&other_block|
            res = nil
            sub(HDLRuby.uniq_name(name)) do
                res = HDLRuby::High.top_user.instance_exec(*args,
                                        *other_block, &ruby_block)
            end
            unless res.respond_to?(:to_expr) then
              raise AnyError, 
                "The last statement of a function must be an expression: #{res}"
            end
            res
        end
    else
        define_method(name.to_sym) do |*args,&other_block|
            res = nil
            sub(HDLRuby.uniq_name(name)) do
                res = HDLRuby::High.top_user.instance_exec(*args,
                                        *other_block, &ruby_block)
            end
            unless res.respond_to?(:to_expr) then
              raise AnyError, 
                "The last statement of a function must be an expression: #{res}"
            end
            res
        end
    end
end

#infinityObject

Gets the infinity.



25
26
27
# File 'lib/HDLRuby/hruby_high.rb', line 25

def infinity
    return HDLRuby::Infinity
end

#instance(name, *includes, &ruby_block) ⇒ Object

Declares a high-level system instance named name, with includes mixins system types and using ruby_block for instantiating.

NOTE: this is for generating directly an instance without declaring it system type.



2413
2414
2415
2416
2417
2418
2419
2420
# File 'lib/HDLRuby/hruby_high.rb', line 2413

def instance(name, *includes, &ruby_block)
    # Ensure there is a block.
    ruby_block = proc {} unless block_given?
    # Creates the system type.
    systemT = system(:"",*includes,&ruby_block)
    # Instantiate it with +name+.
    return systemT.instantiate(name) 
end

#require_verilog(filename) ⇒ Object

Require a verilog file.



2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
# File 'lib/HDLRuby/hruby_high.rb', line 2487

def require_verilog(filename)
  # Converts the file to HDLRuby.
  if Kernel.system("v2hdr", "#{filename}", "#{filename}.rb") then
    # Success, require the resulting file.
    require "#{Dir.pwd}/#{filename}.rb"
  else
    # Failure.
    raise AnyError, 
      "Could not load Verilog HDL file: #{filename}."
  end
end

#set_this(obj = proc { RefThis.new }) ⇒ Object

Sets the current this to obj.

NOTE: do not use a this= style to avoid confusion.



4043
4044
4045
4046
4047
4048
4049
# File 'lib/HDLRuby/hruby_high.rb', line 4043

def set_this(obj = proc { RefThis.new })
    if (obj.is_a?(Proc)) then
        @@this = obj
    else
        @@this = proc { RefObject.new(RefThis.new,obj) }
    end
end

#struct(content) ⇒ Object

Creates an unnamed structure type from a content.



2351
2352
2353
# File 'lib/HDLRuby/hruby_high.rb', line 2351

def struct(content)
    return TypeStruct.new(:"",:little,content)
end

#system(name = :"", *includes, &ruby_block) ⇒ Object

Declares a high-level system type named name, with includes mixins system types and using ruby_block for instantiating.



2400
2401
2402
2403
2404
2405
2406
# File 'lib/HDLRuby/hruby_high.rb', line 2400

def system(name = :"", *includes, &ruby_block)
    # Ensure there is a block.
    ruby_block = proc {} unless block_given?
    # print "system name=#{name} ruby_block=#{ruby_block}\n"
    # Creates the resulting system.
    return SystemT.new(name,*includes,&ruby_block)
end

#thisObject

Gives access to the this reference.



4053
4054
4055
4056
# File 'lib/HDLRuby/hruby_high.rb', line 4053

def this
    # RefThis.new
    @@this.call
end

#typedef(name, &ruby_block) ⇒ Object

Declares a high-level generic type named name, and using ruby_block for construction.



2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
# File 'lib/HDLRuby/hruby_high.rb', line 2359

def typedef(name, &ruby_block)
    # Ensure there is a block.
    ruby_block = proc {} unless block_given?
    type = TypeGen.new(name,&ruby_block)
    if HDLRuby::High.in_system? then
        # Must be inside a scope.
        unless HDLRuby::High.top_user.is_a?(Scope) then
            raise AnyError, "A local type cannot be declared within a #{HDLRuby::High.top_user.class}."
        end
        define_singleton_method(name.to_sym) do |*args|
            if (args.size < ruby_block.arity) then
            # if (args.size < ruby_block.parameters.size) then
                # Not enough arguments get generic type as is.
                type
            else
                # There are arguments, specialize the type.
                gtype = type.generate(*args)
                # And add it as a local type of the system.
                HDLRuby::High.top_user.add_type(gtype)
                gtype
            end
        end
    else
        define_method(name.to_sym) do |*args|
            if (args.size < ruby_block.arity) then
            # if (args.size < ruby_block.parameters.size) then
                # Not enough arguments, get generic type as is.
                type
            else
                # There are arguments, specialize the type.
                type.generate(*args)
            end
        end
    end
end