Class: HDLRuby::High::SystemI

Inherits:
Low::SystemI show all
Includes:
SingletonExtend, WithFullname
Defined in:
lib/HDLRuby/hruby_high.rb,
lib/HDLRuby/hruby_rsim.rb,
lib/HDLRuby/hruby_rcsim.rb,
lib/HDLRuby/hruby_high_fullname.rb

Overview

Describes a system instance.

NOTE: an instance can actually represented muliple layers of systems, the first one being the one actually instantiated in the final RTL code. This layering can be used for describing software or partial (re)configuration.

Constant Summary collapse

High =
HDLRuby::High

Constants included from Low::Low2Symbol

Low::Low2Symbol::Low2SymbolPrefix, Low::Low2Symbol::Low2SymbolTable, Low::Low2Symbol::Symbol2LowTable

Instance Attribute Summary collapse

Attributes inherited from Low::SystemI

#name, #systemT

Attributes included from Low::Hparent

#parent

Instance Method Summary collapse

Methods included from WithFullname

#fullname

Methods included from SingletonExtend

#eigen_extend

Methods inherited from Low::SystemI

#add_systemT, #each_arrow_deep, #each_behavior, #each_behavior_deep, #each_block_deep, #each_connection, #each_connection_deep, #each_deep, #each_inner, #each_inout, #each_input, #each_output, #each_sensitive_deep, #each_signal, #each_signal_deep, #each_statement_deep, #each_systemI, #each_systemT, #eql?, #get_by_name, #get_inner, #get_inout, #get_input, #get_output, #get_signal, #get_signal_splits, #get_systemI, #hash, #replace_names!, #set_name!, #set_systemT, #to_c, #to_ch, #to_hdr, #to_high, #to_vhdl, #with_port!, #with_var!

Methods included from Low::Low2Symbol

#to_sym

Methods included from Low::Hparent

#absolute_ref, #hierarchy, #no_parent!, #scope

Constructor Details

#initialize(name, systemT) ⇒ SystemI

Creates a new system instance of system type +systemT+ named +name+.



2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
# File 'lib/HDLRuby/hruby_high.rb', line 2480

def initialize(name, systemT)
    # Check the validity of the name.
    unless name.is_a?(String) or name.is_a?(Symbol)
        raise AnyError, 
          "Missing instance name for system instantiation."
    end
    # Initialize the system instance structure.
    super(name,systemT)

    # Sets the hdl-like access to the system instance.
    obj = self # For using the right self within the proc
    High.space_reg(name) { obj }
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m, *args, &ruby_block) ⇒ Object

Missing methods are looked for in the public namespace of the system type.



2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
# File 'lib/HDLRuby/hruby_high.rb', line 2642

def method_missing(m, *args, &ruby_block)
    # print "method_missing in class=#{self.class} with m=#{m}\n"
    # Maybe its a signal reference.
    signal = self.systemT.get_signal_with_included(m)
    if signal then
        # Yes, create the reference.
        return RefObject.new(self.to_ref,signal)
    else
        # No try elsewhere
        self.public_namespace.send(m,*args,&ruby_block)
    end
end

Instance Attribute Details

#rcsystemIObject (readonly)

Extends the SystemI class for hybrid Ruby-C simulation.



483
484
485
# File 'lib/HDLRuby/hruby_rcsim.rb', line 483

def rcsystemI
  @rcsystemI
end

Instance Method Details

#call(*connects) ⇒ Object

Connects signals of the system instance according to +connects+.

NOTE: +connects+ can be a hash table where each entry gives the correspondance between a system's signal name and an external signal to connect to, or a list of signals that will be connected in the order of declaration.



2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
# File 'lib/HDLRuby/hruby_high.rb', line 2516

def call(*connects)
    # Checks if it is a connection through is a hash.
    if connects.size == 1 and connects[0].respond_to?(:to_h) and
        !connects[0].is_a?(HRef) then
        # Yes, perform a connection by name
        connects = connects[0].to_h
        # Performs the connections.
        connects.each do |key,value|
            # Gets the signal corresponding to connect.
            signal = self.systemT.get_signal_with_included(key)
            # Check if it is an output.
            isout = self.systemT.get_output_with_included(key)
            # Convert it to a reference.
            # puts "key=#{key} value=#{value} signal=#{signal}"
            ref = RefObject.new(self.to_ref,signal)
            # Make the connection.
            if isout then
                value <= ref
            else
                ref <= value
            end
        end
    else
        # No, perform a connection is order of declaration
        # But first check if there are not too many of them.
      if connects.size > 
        self.systemT.each_signal_with_included.to_a.size then
            raise AnyError, "Too many connections to instance " +
              "#{self.name}: got #{connects.size} " +
              "but expecting at most " +
              "#{self.systemT.each_signal_with_included.to_a.size}"
        end
        connects.each.with_index do |csig,i|
        # Now do the connection.
            # puts "systemT inputs=#{systemT.each_input.to_a.size}"
            # Gets i-est signal to connect
            ssig = self.systemT.get_interface_with_included(i)
            # Check if it is an output.
            isout = self.systemT.get_output_with_included(ssig.name)
            # puts "ssig=#{ssig.name} isout=#{isout}"
            # Convert it to a reference.
            ssig = RefObject.new(self.to_ref,ssig)
            # Make the connection.
            if isout then
                csig <= ssig
                # csig.to_ref <= ssig
            else
                ssig <= csig
                # ssig <= csig.to_expr
            end
        end
    end
end

#choice(configuration = {}) ⇒ Object

Adds alternative system +systemT+



2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
# File 'lib/HDLRuby/hruby_high.rb', line 2591

def choice(configuration = {})
    # Process the argument.
    configuration.each do |k,v|
        k = k.to_sym
        unless v.is_a?(SystemT) then
            raise "Invalid class for a system type: #{v.class}"
        end
        # Create an eigen system.
        eigen = v.instantiate(HDLRuby.uniq_name(self.name)).systemT
        # Ensure its interface corresponds.
        my_signals = self.each_signal.to_a
        if (eigen.each_signal.with_index.find { |sig,i|
            !sig.eql?(my_signals[i])
        }) then
        raise "Invalid system for configuration: #{systemT.name}." 
        end
        # Add it.
        # At the HDLRuby::High level
        @choices = { self.name => self.systemT } unless @choices
        @choices[k] = eigen
        # At the HDLRuby::Low level
        self.add_systemT(eigen)
    end
end

#configure(sys) ⇒ Object

(Re)Configuration of system instance to systemT designated by +sys+. +sys+ may be the index or the name of the configuration, the first configuration being named by the systemI name.



2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
# File 'lib/HDLRuby/hruby_high.rb', line 2619

def configure(sys)
    if sys.respond_to?(:to_i) then
        # The argument is an index.
        # Create the (re)configuration node.
        High.top_user.add_statement(
            Configure.new(RefObject.new(RefThis.new,self),sys.to_i))
    else
        # The argument is a name (should be).
        # Get the index corresponding to the name.
        num = @choices.find_index { |k,_| k == sys.to_sym }
        unless num then
            raise "Invalid name for configuration: #{sys.to_s}"
        end
        # Create the (re)configuration node.
        High.top_user.add_statement(
            Configure.new(RefObject.new(RefThis.new,self),num))
    end
end

#get_export(name) ⇒ Object

Gets an exported element (signal or system instance) by +name+.



2571
2572
2573
# File 'lib/HDLRuby/hruby_high.rb', line 2571

def get_export(name)
    return @systemT.get_export(name)
end

#init_sim(systemT) ⇒ Object

Initialize the simulation for system +systemT+.



670
671
672
673
# File 'lib/HDLRuby/hruby_rsim.rb', line 670

def init_sim(systemT)
    # Recurse on the Eigen system.
    self.systemT.init_sim(systemT)
end

#namespaceObject

Gets the private namespace.



2664
2665
2666
# File 'lib/HDLRuby/hruby_high.rb', line 2664

def namespace
    self.systemT.namespace
end

#open(&ruby_block) ⇒ Object

Opens for extension.

NOTE: actually executes +ruby_block+ in the context of the systemT.



2580
2581
2582
2583
2584
2585
2586
2587
2588
# File 'lib/HDLRuby/hruby_high.rb', line 2580

def open(&ruby_block)
    # Ensure there is a block.
    ruby_block = proc {} unless block_given?
    # Extend the eigen system.
    @systemT.run(&ruby_block)
    # Update the methods.
    @systemT.eigenize(self)
    self.eigen_extend(@systemT.public_namespace)
end

#public_namespaceObject

Gets the public namespace.



2659
2660
2661
# File 'lib/HDLRuby/hruby_high.rb', line 2659

def public_namespace
    self.systemT.public_namespace
end

#to_low(name = self.name) ⇒ Object

Converts the instance to HDLRuby::Low and set its +name+.



2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
# File 'lib/HDLRuby/hruby_high.rb', line 2670

def to_low(name = self.name)
    # puts "to_low with #{self} (#{self.name}) #{self.systemT}"
    # Converts the system of the instance to HDLRuby::Low
    systemTL = self.systemT.to_low
    # Creates the resulting HDLRuby::Low instance
    systemIL = HDLRuby::Low::SystemI.new(High.names_create(name),
                                     systemTL)
    # # For debugging: set the source high object 
    # systemIL.properties[:low2high] = self.hdr_id
    # self.properties[:high2low] = systemIL
    # Adds the other systemTs.
    self.each_systemT do |systemTc|
        if systemTc != self.systemT
            systemTcL = systemTc.to_low
            systemIL.add_systemT(systemTcL)
        end
    end
    return systemIL
end

#to_rcsim(rcowner) ⇒ Object

Generate the C description of the signal comming from object whose C description is +rcowner+



487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
# File 'lib/HDLRuby/hruby_rcsim.rb', line 487

def to_rcsim(rcowner)
    # puts "to_rcsim for systemI=#{self.name}(#{self})"
    # Create the system instance C object.
    @rcsystemI = RCSim.rcsim_make_systemI(self.name.to_s,
                                          self.systemT.to_rcsim)
    # # Set the owner of the systemT.
    # RCSim.rcsim_set_owner(self.systemT.rcsystemT,@rcsystemI)
    # Set the owner of the systemT as the same as the systemI since
    # it is an Eigen system.
    RCSim.rcsim_set_owner(self.systemT.rcsystemT,rcowner)

    # Set the owner.
    RCSim.rcsim_set_owner(@rcsystemI,rcowner)

    # Add the alternate system types.
    if self.each_systemI.any? then
        RCSim.rcsim_add_systemI_systemTs(@rcsystemI,
                                         self.each_systemT.select do|sys|
            sys != self.systemT
        end.map do |sys|
            # sys.to_rcsim(@rcsystemI)
            sys.to_rcsim(rcowner)
        end)
    end

    return @rcsystemI
end

#to_refObject

Converts to a new reference.



2500
2501
2502
2503
2504
2505
2506
2507
2508
# File 'lib/HDLRuby/hruby_high.rb', line 2500

def to_ref
    if self.name.empty? then
        # No name, happens if inside the systemI so use this.
        return this
    else
        # A name.
        return RefObject.new(this,self)
    end
end

#typeObject

The type of a systemI: for now Void (may change in the future).



2495
2496
2497
# File 'lib/HDLRuby/hruby_high.rb', line 2495

def type
    return void
end