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



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

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.



2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
# File 'lib/HDLRuby/hruby_high.rb', line 2618

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.



2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
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
# File 'lib/HDLRuby/hruby_high.rb', line 2492

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+



2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
# File 'lib/HDLRuby/hruby_high.rb', line 2567

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.



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

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



2547
2548
2549
# File 'lib/HDLRuby/hruby_high.rb', line 2547

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.



2640
2641
2642
# File 'lib/HDLRuby/hruby_high.rb', line 2640

def namespace
    self.systemT.namespace
end

#open(&ruby_block) ⇒ Object

Opens for extension.

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



2556
2557
2558
2559
2560
2561
2562
2563
2564
# File 'lib/HDLRuby/hruby_high.rb', line 2556

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.



2635
2636
2637
# File 'lib/HDLRuby/hruby_high.rb', line 2635

def public_namespace
    self.systemT.public_namespace
end

#to_low(name = self.name) ⇒ Object

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



2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
# File 'lib/HDLRuby/hruby_high.rb', line 2646

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.



2476
2477
2478
2479
2480
2481
2482
2483
2484
# File 'lib/HDLRuby/hruby_high.rb', line 2476

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



2471
2472
2473
# File 'lib/HDLRuby/hruby_high.rb', line 2471

def type
    return void
end