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.



5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
# File 'lib/HDLRuby/hruby_high.rb', line 5009

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.



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

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.



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

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.



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

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+.



1982
1983
1984
1985
1986
1987
# File 'lib/HDLRuby/hruby_high.rb', line 1982

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.



4970
4971
4972
4973
4974
4975
4976
4977
# File 'lib/HDLRuby/hruby_high.rb', line 4970

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)


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

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

.in_system?Boolean

Tells if within a system type.

Returns:

  • (Boolean)


4990
4991
4992
# File 'lib/HDLRuby/hruby_high.rb', line 4990

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.



4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
# File 'lib/HDLRuby/hruby_high.rb', line 4777

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.



4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
# File 'lib/HDLRuby/hruby_high.rb', line 4800

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.



5668
5669
5670
# File 'lib/HDLRuby/hruby_high.rb', line 5668

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.



5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
# File 'lib/HDLRuby/hruby_high.rb', line 5681

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)


5673
5674
5675
5676
5677
# File 'lib/HDLRuby/hruby_high.rb', line 5673

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

.names_popObject

Pops from the name stack.



5663
5664
5665
# File 'lib/HDLRuby/hruby_high.rb', line 5663

def self.names_pop
    NameStack.pop
end

.names_pushObject

Pushes on the name stack.



5658
5659
5660
# File 'lib/HDLRuby/hruby_high.rb', line 5658

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:



5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
# File 'lib/HDLRuby/hruby_high.rb', line 5084

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.



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

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)


4940
4941
4942
# File 'lib/HDLRuby/hruby_high.rb', line 4940

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

.space_index(namespace) ⇒ Object

Gets the index of a +namespace+ within the stack.



4945
4946
4947
# File 'lib/HDLRuby/hruby_high.rb', line 4945

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

.space_insert(index, namespace) ⇒ Object

Inserts +namespace+ at +index+.



4927
4928
4929
# File 'lib/HDLRuby/hruby_high.rb', line 4927

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

.space_popObject

Pops a namespace.



4932
4933
4934
4935
4936
4937
# File 'lib/HDLRuby/hruby_high.rb', line 4932

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+.



4919
4920
4921
4922
4923
4924
# File 'lib/HDLRuby/hruby_high.rb', line 4919

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.



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

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.



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

def self.space_top
    Namespaces[-1]
end

.space_top=(top) ⇒ Object

sets the top namespace.



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

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.



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

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.



4964
4965
4966
# File 'lib/HDLRuby/hruby_high.rb', line 4964

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.



2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
# File 'lib/HDLRuby/hruby_high.rb', line 2371

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.



2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
# File 'lib/HDLRuby/hruby_high.rb', line 2395

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.



2357
2358
2359
2360
2361
2362
2363
2364
# File 'lib/HDLRuby/hruby_high.rb', line 2357

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.



2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
# File 'lib/HDLRuby/hruby_high.rb', line 2431

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.



3974
3975
3976
3977
3978
3979
3980
# File 'lib/HDLRuby/hruby_high.rb', line 3974

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+.



2297
2298
2299
# File 'lib/HDLRuby/hruby_high.rb', line 2297

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.



2344
2345
2346
2347
2348
2349
2350
# File 'lib/HDLRuby/hruby_high.rb', line 2344

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.



3984
3985
3986
3987
# File 'lib/HDLRuby/hruby_high.rb', line 3984

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.



2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
# File 'lib/HDLRuby/hruby_high.rb', line 2305

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