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



4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
# File 'lib/HDLRuby/hruby_high.rb', line 4603

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.



4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
# File 'lib/HDLRuby/hruby_high.rb', line 4640

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.



4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
# File 'lib/HDLRuby/hruby_high.rb', line 4625

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.



4589
4590
4591
4592
4593
4594
4595
4596
4597
# File 'lib/HDLRuby/hruby_high.rb', line 4589

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



1812
1813
1814
1815
1816
1817
# File 'lib/HDLRuby/hruby_high.rb', line 1812

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.



4564
4565
4566
4567
4568
4569
4570
4571
# File 'lib/HDLRuby/hruby_high.rb', line 4564

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)


4617
4618
4619
# File 'lib/HDLRuby/hruby_high.rb', line 4617

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

.in_system?Boolean

Tells if within a system type.

Returns:

  • (Boolean)


4584
4585
4586
# File 'lib/HDLRuby/hruby_high.rb', line 4584

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.



4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
# File 'lib/HDLRuby/hruby_high.rb', line 4374

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.



4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
# File 'lib/HDLRuby/hruby_high.rb', line 4397

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.



5247
5248
5249
# File 'lib/HDLRuby/hruby_high.rb', line 5247

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.



5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
# File 'lib/HDLRuby/hruby_high.rb', line 5260

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)


5252
5253
5254
5255
5256
# File 'lib/HDLRuby/hruby_high.rb', line 5252

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

.names_popObject

Pops from the name stack.



5242
5243
5244
# File 'lib/HDLRuby/hruby_high.rb', line 5242

def self.names_pop
    NameStack.pop
end

.names_pushObject

Pushes on the name stack.



5237
5238
5239
# File 'lib/HDLRuby/hruby_high.rb', line 5237

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



85
86
87
# File 'lib/HDLRuby/hruby_rcsim.rb', line 85

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:



4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
# File 'lib/HDLRuby/hruby_high.rb', line 4673

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.



4576
4577
4578
4579
4580
4581
# File 'lib/HDLRuby/hruby_high.rb', line 4576

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)


4534
4535
4536
# File 'lib/HDLRuby/hruby_high.rb', line 4534

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

.space_index(namespace) ⇒ Object

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



4539
4540
4541
# File 'lib/HDLRuby/hruby_high.rb', line 4539

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

.space_insert(index, namespace) ⇒ Object

Inserts +namespace+ at +index+.



4521
4522
4523
# File 'lib/HDLRuby/hruby_high.rb', line 4521

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

.space_popObject

Pops a namespace.



4526
4527
4528
4529
4530
4531
# File 'lib/HDLRuby/hruby_high.rb', line 4526

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



4513
4514
4515
4516
4517
4518
# File 'lib/HDLRuby/hruby_high.rb', line 4513

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.



4666
4667
4668
4669
# File 'lib/HDLRuby/hruby_high.rb', line 4666

def self.space_reg(name,&ruby_block)
    # print "registering #{name} in #{Namespaces[-1]}\n"
    Namespaces[-1].add_method(name,&ruby_block)
end

.space_topObject

Gets the top of the namespaces stack.



4544
4545
4546
# File 'lib/HDLRuby/hruby_high.rb', line 4544

def self.space_top
    Namespaces[-1]
end

.space_top=(top) ⇒ Object

sets the top namespace.



4549
4550
4551
4552
4553
4554
# File 'lib/HDLRuby/hruby_high.rb', line 4549

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.



4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
# File 'lib/HDLRuby/hruby_high.rb', line 4652

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.



4558
4559
4560
# File 'lib/HDLRuby/hruby_high.rb', line 4558

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.



2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
# File 'lib/HDLRuby/hruby_high.rb', line 2200

def function(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|
            # sub do
            sub(HDLRuby.uniq_name(name)) do
                HDLRuby::High.top_user.instance_exec(*args,*other_block,
                                                     &ruby_block)
                # ruby_block.call(*args)
            end
        end
    else
        define_method(name.to_sym) do |*args,&other_block|
            # sub do
            sub(HDLRuby.uniq_name(name)) do
                HDLRuby::High.top_user.instance_exec(*args,*other_block,
                                                     &ruby_block)
                # ruby_block.call(*args,*other_block)
            end
        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.



2186
2187
2188
2189
2190
2191
2192
2193
# File 'lib/HDLRuby/hruby_high.rb', line 2186

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

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

Sets the current this to +obj+.

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



3621
3622
3623
3624
3625
3626
3627
# File 'lib/HDLRuby/hruby_high.rb', line 3621

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



2127
2128
2129
# File 'lib/HDLRuby/hruby_high.rb', line 2127

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.



2173
2174
2175
2176
2177
2178
2179
# File 'lib/HDLRuby/hruby_high.rb', line 2173

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.



3631
3632
3633
3634
# File 'lib/HDLRuby/hruby_high.rb', line 3631

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.



2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
# File 'lib/HDLRuby/hruby_high.rb', line 2135

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