Module: VerilogGen

Defined in:
lib/verilog_gen/proxy.rb,
lib/verilog_gen/pin.rb,
lib/verilog_gen/port.rb,
lib/verilog_gen/hookup.rb,
lib/verilog_gen/version.rb,
lib/verilog_gen/hdl_module.rb

Overview

Wrapper routines to import design into ruby.

Defined Under Namespace

Classes: HdlModule, Pin, Port

Constant Summary collapse

VERSION =
"0.0.2"
@@verilog_leaf_created =

Return the created class for subsequent access.

{}

Class Method Summary collapse

Class Method Details

.add_new_connect_port(klass, pin_name, port_lst) ⇒ Object

Note:

The name of the connect port is the name of the pin and the width of the port is the super width.

Adds a connect port to the hdl module class.

Returns:

  • nil



51
52
53
54
55
# File 'lib/verilog_gen/hookup.rb', line 51

def self.add_new_connect_port(klass, pin_name, port_lst)
  lhs, rhs = super_port_width(port_lst)
  p = port_lst[0].create_connect_port(pin_name, lhs, rhs) 
  klass.ports[pin_name] = p
end

.create_connect_ports(klass) ⇒ Fixnum

Note:

An input port is created if the children pins are inputs. A output port is created if the children pins are output. If mixture of input and output pins, then no ports are created. The width of the port is the superset of the width.

Create ports to provide connectivity to the child instances.

Parameters:

  • klass (Object)

    HdlModule

Returns:

  • (Fixnum)

    number of ports created in the class.



121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/verilog_gen/hookup.rb', line 121

def self.create_connect_ports(klass)
  num_connect_ports = 0
  pin_connections = get_child_pins_connectivity(klass)
  pin_connections.each do |pin_name, port_lst|
    if unconnected_input_ports?(port_lst)
      add_new_connect_port(klass, pin_name, port_lst)
      num_connect_ports += 1
    elsif unconnected_output_ports?(port_lst)
      add_new_connect_port(klass, pin_name, port_lst)
      num_connect_ports += 1
    end
  end 
  num_connect_ports 
end

.create_missing_pins(instance) ⇒ Fixnum

Note:

Ports with existing pins are skippped.

Create pins for unconnected ports in current instance.

Parameters:

  • instance (Object)

    of hdl module

Returns:

  • (Fixnum)

    Number of pins added



61
62
63
64
65
66
67
68
69
70
# File 'lib/verilog_gen/hookup.rb', line 61

def self.create_missing_pins(instance)
  num_pins_created = 0
  instance.class.ports.each do |port_name, port|
    unless instance.pins.key? port_name
      instance.pins[port_name] = Pin.new(port)
      num_pins_created += 1
    end
  end
  num_pins_created
end

.create_missing_pins_depth_first(instance) ⇒ nil

Note:

Idempotent since port that have pins are skipped.

Create missing pins for all children below the instance. Use depth first to build all the leaf and then the rest of the modules.

Parameters:

  • instance (Object)

    of the design.

Returns:

  • (nil)


78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/verilog_gen/hookup.rb', line 78

def self.create_missing_pins_depth_first(instance)
  if instance.class.proxy
    # Leaf do not change the ports. hence we don't need to do it again.
    # But it is harmless if all ports are already connected. 
    create_missing_pins instance
  else 
    instance.class.child_instances.each do |child_name, child|
      create_missing_pins_depth_first child
    end
    # If new pins are created then we would need to create the connect ports
    # in the current class. 
    num_new_ports = create_connect_ports(instance.class) 

    # Run custom user connect
    instance.class.connect

    # If we added new ports to the class then all instantiaton must get new pins.
    create_missing_pins instance if num_new_ports > 0
  end
end

.get_child_pins_connectivity(klass) ⇒ Hash

Create connectivity map for children of a hdl module.

Parameters:

  • klass (Object)

    of the hdl module.

Returns:

  • (Hash)

    hash of array. PinName => [Port0, Port 10.….]



103
104
105
106
107
108
109
110
111
# File 'lib/verilog_gen/hookup.rb', line 103

def self.get_child_pins_connectivity(klass)
  pin_connections = Hash.new {|hash, key| hash[key] = Array.new }
  klass.child_instances.each do |child_name, child|
    child.pins.each do |port_name, pin|
      pin_connections[pin.name].push pin.port
    end
  end
  pin_connections
end

.hookup(top_level_class) ⇒ Object

Note:

Start with each child instance.

Connect child instances and create hookup ports.

Parameters:

  • top_level_class (Object)

    of the design.



141
142
143
144
145
146
147
148
149
150
151
# File 'lib/verilog_gen/hookup.rb', line 141

def self.hookup(top_level_class)
  top_level_class.child_instances.each do |instance_name, instance|
    create_missing_pins_depth_first(instance)
  end
  # Run custom user connect
  top_level_class.connect

  # Create the primary connect ports
  create_connect_ports(top_level_class) 

end

.leaf(klass, params = {}) ⇒ Object

Note:

Invoke vscan to create the leaf proxy. Once a class is created then subsequent access will return prev value.

Parameters:

  • Class (String)

    name of hdl leaf.

  • parameter (Hash)

    to pass to vscan.

  • file_name (Hash)

    name of the rtl file.

Returns:

  • Hdl module class.



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/verilog_gen/proxy.rb', line 14

def self.leaf(klass, params = {})
  options = { parameter: "", file_name: klass.snakecase + ".v" }
  params.each do |key, value|
    raise ArgumentError, "invalid valid value of leaf '#{key}'" \
      unless options.key? key
    options[key] = params[key]
  end
    
  key = klass + options[:parameter]
  unless @@verilog_leaf_created.key?(key)
    puts "Running vscan #{options[:parameter]} -class #{klass} #{options[:file_name]}"
    output = `vscan #{options[:parameter]} -class #{klass} \
                                          #{options[:file_name]}`
    eval output, binding, __FILE__, __LINE__
    @@verilog_leaf_created[key] = Object.const_get("VerilogGen::#{klass}")
  end
  @@verilog_leaf_created[key]
end

.super_port_width(port_lst) ⇒ Array

Find the super width from a list of ports. @note:

Assumes that all ports in the list are of same endiannes..
FIXME: For this it looks at the port in the middle.
Should scan all the ports to detect it.

Parameters:

  • list (Array)

    of ports

Returns:

  • (Array)

    lhs, rhs



32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/verilog_gen/hookup.rb', line 32

def self.super_port_width(port_lst)
  sample_port = port_lst[port_lst.size/2]
  lhs_values = []
  rhs_values = []
  port_lst.each do |port|
    lhs_values << port.lhs
    rhs_values << port.rhs
  end
  if sample_port.lhs > sample_port.rhs
    return lhs_values.max, rhs_values.min
  else
    return lhs_values.min, rhs_values.max
  end
end

.unconnected_input_ports?(port_lst) ⇒ Boolean

Check if all the ports in the list are inputs.

Parameters:

  • port_lst (Array)

    is the list of ports

Returns:

  • (Boolean)

    True if all are inputs.



6
7
8
9
10
11
12
# File 'lib/verilog_gen/hookup.rb', line 6

def self.unconnected_input_ports?(port_lst)
  return false if port_lst.empty?
  port_lst.each do |port|
    return false unless port.direction == "input"
  end
  return true
end

.unconnected_output_ports?(port_lst) ⇒ Boolean

Check if all the ports in the list are outputs.

Parameters:

  • port_lst (Array)

    is the list of ports

Returns:

  • (Boolean)

    True if all are outputs.



17
18
19
20
21
22
23
# File 'lib/verilog_gen/hookup.rb', line 17

def self.unconnected_output_ports?(port_lst)
  return false if port_lst.empty?
  port_lst.each do |port|
    return false unless port.direction == "output"
  end
  return true
end