URL
https://opencores.org/ocsvn/soc_maker/soc_maker/trunk
Subversion Repositories soc_maker
[/] [soc_maker/] [trunk/] [lib/] [soc_maker/] [component.rb] - Rev 6
Go to most recent revision | Compare with Previous | Blame | View Log
###############################################################
#
# File: component.rb
#
# Author: Christian Hättich
#
# Project: System-On-Chip Maker
#
# Target: Linux / Windows / Mac
#
# Language: ruby
#
#
###############################################################
#
#
# Copyright (C) 2014 Christian Hättich - feddischson [ at ] opencores.org
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#
###############################################################
#
# Description:
# This class represents an abstract component.
# It is one of the central classes and holds data,
# which is used to describe and instanciate a core or SOC.
#
# The following fields are defined and used
# by CoreDef and SOCDef
# - name : name of the core (mandatory)
# - version : version of the core (mandatory)
# - toplevel : toplevel name (mandatory)
# - description : description of this core
# - date : creation date
# - license : license of this core
# - licensefile : location of the license file
# - author : author of this core
# - authormail : author-mail of this core
# - vccmd : a version control command, which is used
# to download the files
# - interfaces : interfaces which are implemented
# see SOCMaker::IfcSpc
# - inst_parameters : hash of instantiation parameters
# see SOCMaker::Parameter
# - static_parameters : hash of static parameters
# see SOCMaker::SParameter
########
#
# TODO
#
#
###############################################################
module SOCMaker
class Component
include ERR
include YAML_EXT
attr_accessor :name
attr_accessor :version
attr_accessor :toplevel
attr_accessor :description
attr_accessor :date
attr_accessor :license
attr_accessor :licensefile
attr_accessor :author
attr_accessor :authormail
attr_accessor :vccmd
attr_accessor :interfaces
attr_accessor :functions
attr_accessor :inst_parameters
attr_accessor :static_parameters
def initialize( name, version, toplevel, options = {} )
init_with( { 'name' => name,
'version' => version,
'toplevel' => toplevel }.merge( options ) )
end
def encode_with( coder )
%w[ name version description date license licensefile
author authormail vccmd toplevel interfaces
functions inst_parameters static_parameters ].
each { |v| coder[ v ] = instance_variable_get "@#{v}" }
end
def init_with( coder )
serr_if( coder[ 'name' ] == nil,
'Name not defined',
field: 'name' )
@name = coder[ 'name' ]
verr_if( !@name.is_a?( String ),
'The name must be of type string',
field: 'name' )
serr_if( @name.size == 0,
'Name not defined (size == 0)',
field: 'name' )
verr_if( !!SOCMaker::conf[ :name_regex ].match( @name ) == false,
'The core name is invalid',
instance: @name,
field: 'name' )
serr_if( coder[ 'version' ] == nil,
'Version not defined',
instance: @name,
field: 'version' )
@version = coder[ 'version' ]
serr_if( @version.size == 0,
'Version not defined (size == 0)',
instance: @name,
field: 'version' )
# cast from numeric to string, if not given as string
@version = @version.to_s if @version.is_a? ( Numeric )
verr_if( !@version.is_a?( String ),
'The name must be of type string or numeric',
field: 'name' )
serr_if( coder[ 'toplevel' ] == nil,
'Toplevel not defined',
instance: @name,
field: 'toplevel' )
@toplevel = coder[ 'toplevel' ]
verr_if( !@toplevel.is_a?( String ),
"toplevel must be of type string",
instance: @name,
field: "toplevel" )
serr_if( @toplevel.size == 0,
'Toplevel not defined (size == 0 )',
instance: @name,
field: 'toplevel' )
# set non-nil values
# -> we don't need to check for nil in the rest of the
# processing
@description = coder[ 'description' ] || ""
@date = coder[ 'date' ] || ""
@license = coder[ 'license' ] || ""
@licensefile = coder[ 'licensefile' ] || ""
@author = coder[ 'author' ] || ""
@authormail = coder[ 'authormail' ] || ""
@vccmd = coder[ 'vccmd' ] || ""
@interfaces = coder[ 'interfaces' ] || {}
@functions = coder[ 'functions' ] || {}
@inst_parameters = coder[ 'inst_parameters' ] || {}
@static_parameters = coder[ 'static_parameters' ] || {}
# ensure, that these fields are of type String
%w[ description date license licensefile
author authormail vccmd ].each do |n|
verr_if( !instance_variable_get( '@'+n ).is_a?( String ),
"#{n} must be of type String",
instance: @name,
field: n )
end
# ensure, that these fields are of type Hash
%w[ interfaces inst_parameters
functions static_parameters ].each do |n|
verr_if( !instance_variable_get( '@'+n ).is_a?( Hash ),
"#{n} must be of type Hash",
instance: @name,
field: n )
end
# check interfaces
@interfaces.each do |ifc_name, ifc|
serr_if( ifc == nil,
'Interface not defined',
instance: @name+":"+ifc_name.to_s )
serr_if( !ifc.is_a?( SOCMaker::IfcDef ),
'Interface definition is not SOCMaker::IfcDef (use SOCM_IFC)',
instance: @name+":"+ifc_name.to_s )
end
# check instance parameters
@inst_parameters.each do |name, param |
serr_if( param == nil,
'Instance parameter not defined',
instance: @name+":"+name.to_s )
serr_if( !param.is_a?( SOCMaker::Parameter ),
'Instance parameter not SOCMaker::Parameter (use SOCM_PARAM)',
instance: @name+":"+name.to_s )
end
# check instance parameters
@static_parameters.each do |name, sparam |
serr_if( sparam == nil,
'Static parameter not defined',
instance: @name+":"+name.to_s )
serr_if( !sparam.is_a?( SOCMaker::SParameter ),
'Static parameter not SOCMaker::Parameter (use SOCM_SPARAM)',
instance: @name+":"+name.to_s )
end
end
def get_files
unless self.vccmd.nil? or @vccmd.size == 0
#puts"cd #{@dir} && #{@vccmd}"
system( "cd #{@dir} && #{vccmd} " )
end
end
def generics
@inst_parameters.each_with_index do |(name, val), i|
yield( name.to_s, val.type, val.default, i == @inst_parameters.size-1 )
end
end
def get_and_ensure_dst_dir!( core_name )
dst_dir = File.expand_path(
File.join(
SOCMaker::conf[ :build_dir ],
SOCMaker::conf[ :hdl_dir ],
core_name ) )
FileUtils.mkdir_p dst_dir
return dst_dir
end
#
# Iterates over interface list.
# For each interface, all ports are processed.
# For each port within each interface, we lookup the port defn
# and yield the call block with
# - port-name
# - port-definition
# - info if last
# as argument
#
#
#
def ports( *args )
if args.size == 0
@interfaces.values.each_with_index do | ifc, i_ifc; ifc_def|
# get interface definition
ifc_def = SOCMaker::lib.get_ifc( ifc.name, ifc.version )
# loop over ports in this interface
ifc.ports.each_with_index do |(port_name, port_def), i_port; port_dir|
# the reference to the port in the definition
defn_ref = port_def.defn
port_dir = ifc_def.ports[ defn_ref.to_sym ]
perr_if( port_dir == nil,
"Can't find #{defn_ref} in interface " +
"definition #{ifc_def.name} version " +
ifc_def.version + "==>>" + ifc_def.to_yaml )
# An xor mechanism between port_dir and ifc=>dir is used
# to determine the direction of a port, for example:
# If the interface is declared as input (1) and a port is declared as input (1)
# the resulting direction will be an output 1^1 = 0.
# But if the overall interface direction is an output (0) and a port is declared
# as input, the resulting direction will an input 0^1 = 1.
# This allows to define a port-direction in the interface definition,
# and toggle the directions on core-definition level.
# (name, direction, length, is_last)
yield( port_name.to_s,
port_dir ^ ifc.dir,
port_def.len,
( (i_port == ifc.ports.size-1 ) and (i_ifc == @interfaces.size-1 ) ) )
end
end
elsif args.size == 1
# get interface (input is the name as string )
ifc = @interfaces[ args.first.to_sym ]
ifc_def = SOCMaker::lib.get_ifc( ifc.name, ifc.version )
ifc.ports.each do |port_name, port_def; port_dir|
port_def = port_def.defn
port_dir = ifc_def.ports[ port_def.to_sym ]
if port_dir == nil
perr_if( port_dir==nil,
"Can't find #{port_def} in" +
"interface definition #{ifc_def.name} " +
"version #{ifc_def.version}" )
end
yield( port_def.to_s,
port_name.to_s,
port_dir ^ ifc.dir )
end
else
end
end
def implements_port?( ifc_name, port_spec_name )
tmp = @interfaces[ ifc_name.to_sym ].
ports.select{ |key,hash| hash.defn == port_spec_name.to_s }.keys
perr_if( tmp.size > 1,
"The port #{port_spec_name} of interface #{ifc_name} is implemented
multiple times" )
return tmp.size == 1
end
def param_ok?( param_name, param_value )
param = inst_parameters[ param_name.to_sym ]
param = static_parameters[ param_name.to_sym ] if param == nil
return false if param == nil
end
def verify( is_soc = false )
# check interfaces
@interfaces.each do |ifc_name, ifc|
ifc.verify
end
# check instance parameters
@inst_parameters.each do |name, param |
param.verify
end
# check instance parameters
@static_parameters.each do |name, sparam |
sparam.verify
end
end
def ==(o)
tmp = ( o.class == self.class )
return tmp if !tmp
%w[ name version description date license licensefile
author authormail vccmd toplevel interfaces
functions inst_parameters static_parameters ].
each do |v|
return false if instance_variable_get( "@#{v}" ) != o.instance_variable_get( "@#{v}" )
end
return true
end
def to_s
"version: #{@version}\n" +
"toplevel: #{@toplevel}\n" +
"description: #{@description}\n" +
"date: #{@date}\n" +
"license: #{@license}\n" +
"licensefile: #{@licensefile}\n" +
"author: #{@author}\n" +
"authormail: #{@authormail}\n" +
"vccmd: #{@vccmd}\n" +
"interfaces: #{@interfaces}\n" +
"functions: #{@functions}\n" +
"inst_parameters: #{@inst_parameters}\n" +
"static_parameters: #{@static_parameters}\n"
end
end # class CoreDef
end # module SOCMaker
# vim: noai:ts=2:sw=2
Go to most recent revision | Compare with Previous | Blame | View Log