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.



5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
# File 'lib/HDLRuby/hruby_high.rb', line 5037

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.



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

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.



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

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.



5023
5024
5025
5026
5027
5028
5029
5030
5031
# File 'lib/HDLRuby/hruby_high.rb', line 5023

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.



2006
2007
2008
2009
2010
2011
# File 'lib/HDLRuby/hruby_high.rb', line 2006

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.



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

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)


5051
5052
5053
# File 'lib/HDLRuby/hruby_high.rb', line 5051

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

.in_system?Boolean

Tells if within a system type.

Returns:

  • (Boolean)


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

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.



4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
# File 'lib/HDLRuby/hruby_high.rb', line 4805

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.



4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
# File 'lib/HDLRuby/hruby_high.rb', line 4828

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.



5696
5697
5698
# File 'lib/HDLRuby/hruby_high.rb', line 5696

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.



5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
# File 'lib/HDLRuby/hruby_high.rb', line 5709

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)


5701
5702
5703
5704
5705
# File 'lib/HDLRuby/hruby_high.rb', line 5701

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

.names_popObject

Pops from the name stack.



5691
5692
5693
# File 'lib/HDLRuby/hruby_high.rb', line 5691

def self.names_pop
    NameStack.pop
end

.names_pushObject

Pushes on the name stack.



5686
5687
5688
# File 'lib/HDLRuby/hruby_high.rb', line 5686

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:



5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
# File 'lib/HDLRuby/hruby_high.rb', line 5112

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.



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

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)


4968
4969
4970
# File 'lib/HDLRuby/hruby_high.rb', line 4968

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

.space_index(namespace) ⇒ Object

Gets the index of a namespace within the stack.



4973
4974
4975
# File 'lib/HDLRuby/hruby_high.rb', line 4973

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

.space_insert(index, namespace) ⇒ Object

Inserts namespace at index.



4955
4956
4957
# File 'lib/HDLRuby/hruby_high.rb', line 4955

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

.space_popObject

Pops a namespace.



4960
4961
4962
4963
4964
4965
# File 'lib/HDLRuby/hruby_high.rb', line 4960

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.



4947
4948
4949
4950
4951
4952
# File 'lib/HDLRuby/hruby_high.rb', line 4947

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.



5100
5101
5102
5103
5104
5105
5106
5107
5108
# File 'lib/HDLRuby/hruby_high.rb', line 5100

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.



4978
4979
4980
# File 'lib/HDLRuby/hruby_high.rb', line 4978

def self.space_top
    Namespaces[-1]
end

.space_top=(top) ⇒ Object

sets the top namespace.



4983
4984
4985
4986
4987
4988
# File 'lib/HDLRuby/hruby_high.rb', line 4983

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.



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

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.



4992
4993
4994
# File 'lib/HDLRuby/hruby_high.rb', line 4992

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.



2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
# File 'lib/HDLRuby/hruby_high.rb', line 2395

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.



2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
# File 'lib/HDLRuby/hruby_high.rb', line 2419

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.



2381
2382
2383
2384
2385
2386
2387
2388
# File 'lib/HDLRuby/hruby_high.rb', line 2381

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.



2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
# File 'lib/HDLRuby/hruby_high.rb', line 2455

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.



4002
4003
4004
4005
4006
4007
4008
# File 'lib/HDLRuby/hruby_high.rb', line 4002

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.



2321
2322
2323
# File 'lib/HDLRuby/hruby_high.rb', line 2321

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.



2368
2369
2370
2371
2372
2373
2374
# File 'lib/HDLRuby/hruby_high.rb', line 2368

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

#thisObject

Gives access to the this reference.



4012
4013
4014
4015
# File 'lib/HDLRuby/hruby_high.rb', line 4012

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.



2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
# File 'lib/HDLRuby/hruby_high.rb', line 2329

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
                # 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
                # Not enough arguments, get generic type as is.
                type
            else
                # There are arguments, specialize the type.
                type.generate(*args)
            end
        end
    end
end