Line 31... |
Line 31... |
#
|
#
|
#
|
#
|
###############################################################
|
###############################################################
|
#
|
#
|
# Description:
|
# 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
|
# TODO
|
#
|
#
|
#
|
#
|
###############################################################
|
###############################################################
|
|
|
|
|
|
|
module SOCMaker
|
module SOCMaker
|
|
|
|
|
|
|
|
######
|
|
#
|
|
# This class represents an abstract component.
|
|
# It is one of the central classes and holds data,
|
|
# which is used to describe a core or System-On-Chip (SOC).
|
|
#
|
|
#
|
class Component
|
class Component
|
include ERR
|
include ERR
|
include YAML_EXT
|
include YAML_EXT
|
|
|
|
|
|
# name of the core (mandatory)
|
attr_accessor :name
|
attr_accessor :name
|
|
|
|
# version of the core (mandatory)
|
attr_accessor :version
|
attr_accessor :version
|
|
|
|
# toplevel name (mandatory)
|
attr_accessor :toplevel
|
attr_accessor :toplevel
|
|
|
|
# description of this core
|
attr_accessor :description
|
attr_accessor :description
|
|
|
|
# creation date
|
attr_accessor :date
|
attr_accessor :date
|
|
|
|
# license of this core
|
attr_accessor :license
|
attr_accessor :license
|
|
|
|
# location of the license file
|
attr_accessor :licensefile
|
attr_accessor :licensefile
|
|
|
|
# author of this core
|
attr_accessor :author
|
attr_accessor :author
|
|
|
|
# author-mail of this core
|
attr_accessor :authormail
|
attr_accessor :authormail
|
|
|
|
# a version control command, which is used to download the files
|
attr_accessor :vccmd
|
attr_accessor :vccmd
|
|
|
|
# interfaces which are implemented see SOCMaker::IfcSpc
|
attr_accessor :interfaces
|
attr_accessor :interfaces
|
|
|
attr_accessor :functions
|
attr_accessor :functions
|
|
|
|
# hash of instantiation parameters see SOCMaker::Parameter
|
attr_accessor :inst_parameters
|
attr_accessor :inst_parameters
|
|
|
|
# hash of static parameters see SOCMaker::SParameter
|
attr_accessor :static_parameters
|
attr_accessor :static_parameters
|
def initialize( name, version, toplevel, options = {} )
|
|
|
|
|
#
|
|
# Constructor
|
|
# The three attributes are required, and all other attributes
|
|
# can be given as a optinal hash
|
|
#
|
|
# *name*:: Name of this component
|
|
# *version*:: Version of this component
|
|
# *toplevel*:: Toplevel name of this component
|
|
# *optional*:: Non-mandatory values, which can be set during initialization.
|
|
#
|
|
#
|
|
def initialize( name, version, toplevel, optional = {} )
|
init_with( { 'name' => name,
|
init_with( { 'name' => name,
|
'version' => version,
|
'version' => version,
|
'toplevel' => toplevel }.merge( options ) )
|
'toplevel' => toplevel }.merge( optional ) )
|
end
|
end
|
|
|
|
#
|
|
# Encoder function (to yaml)
|
|
#
|
|
# +coder+:: An instance of the Psych::Coder to encode this class to a YAML file
|
|
#
|
def encode_with( coder )
|
def encode_with( coder )
|
%w[ name version description date license licensefile
|
%w[ name version description date license licensefile
|
author authormail vccmd toplevel interfaces
|
author authormail vccmd toplevel interfaces
|
functions inst_parameters static_parameters ].
|
functions inst_parameters static_parameters ].
|
each { |v| coder[ v ] = instance_variable_get "@#{v}" }
|
each { |v| coder[ v ] = instance_variable_get "@#{v}" }
|
end
|
end
|
|
|
|
#
|
|
# Initialization function (from yaml)
|
|
#
|
|
# +coder+:: An instance of the Psych::Coder to init this class from a YAML file
|
|
#
|
|
#
|
def init_with( coder )
|
def init_with( coder )
|
|
|
serr_if( coder[ 'name' ] == nil,
|
serr_if( coder[ 'name' ] == nil,
|
'Name not defined',
|
'Name not defined',
|
field: 'name' )
|
field: 'name' )
|
Line 216... |
Line 257... |
end
|
end
|
|
|
end
|
end
|
|
|
|
|
|
#
|
|
# Runs a consistency check:
|
|
# Iterate over all interfaces and check, if the interface is
|
|
# in the SOCMaker::Lib.
|
|
# The function also checks also, if the ports defined by this
|
|
# core is also defined in the interface.
|
|
#
|
def consistency_check
|
def consistency_check
|
@interfaces.values.each_with_index do | ifc, i_ifc; ifc_def|
|
@interfaces.values.each_with_index do | ifc, i_ifc; ifc_def|
|
|
|
# get interface definition
|
# get interface definition
|
ifc_def = SOCMaker::lib.get_ifc( ifc.name, ifc.version )
|
ifc_def = SOCMaker::lib.get_ifc( ifc.name, ifc.version )
|
Line 234... |
Line 282... |
end
|
end
|
|
|
end
|
end
|
|
|
|
|
def get_files
|
#
|
|
# Runs the Version Control System command via system(....)
|
|
#
|
|
def update_vcs
|
unless self.vccmd.nil? or @vccmd.size == 0
|
unless self.vccmd.nil? or @vccmd.size == 0
|
#puts"cd #{@dir} && #{@vccmd}"
|
#puts"cd #{@dir} && #{@vccmd}"
|
system( "cd #{@dir} && #{vccmd} " )
|
system( "cd #{@dir} && #{vccmd} " )
|
end
|
end
|
end
|
end
|
|
|
|
|
|
|
|
|
|
|
|
# Iterates over all generic values of this component
|
|
# and yield the call block with
|
|
# - generic name
|
|
# - generic type
|
|
# - generic default
|
|
# - is-last value
|
def generics
|
def generics
|
@inst_parameters.each_with_index do |(name, val), i|
|
@inst_parameters.each_with_index do |(name, val), i|
|
yield( name.to_s, val.type, val.default, i == @inst_parameters.size-1 )
|
|
|
_generic_name = name.to_s
|
|
_generic_type = val.type
|
|
_generic_default = val.default
|
|
_is_last = i == @inst_parameters.size-1
|
|
yield( _generic_name ,
|
|
_generic_type ,
|
|
_generic_default,
|
|
_is_last )
|
|
|
end
|
end
|
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.
|
# Iterates over interface list (if no argument is given)
|
|
# or all specified interfaces.
|
# For each interface, all ports are processed.
|
# For each interface, all ports are processed.
|
# For each port within each interface, we lookup the port defn
|
# For each port within each interface, we lookup the port defn
|
# and yield the call block with
|
# and yield the call block with
|
# - port-name
|
# - port-name
|
# - port-definition
|
# - port length
|
# - info if last
|
# - default value
|
|
# - is-last value
|
# as argument
|
# as argument
|
#
|
#
|
# An xor mechanism between port_dir and ifc=>dir is used
|
# An xor mechanism between port_dir and ifc=>dir is used
|
# to determine the direction of a port, for example:
|
# 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)
|
# If the interface is declared as input (1) and a port is declared as input (1)
|
Line 279... |
Line 340... |
# as input, the resulting direction will an input 0^1 = 1.
|
# as input, the resulting direction will an input 0^1 = 1.
|
# This allows to define a port-direction in the interface definition,
|
# This allows to define a port-direction in the interface definition,
|
# and toggle the directions on core-definition level.
|
# and toggle the directions on core-definition level.
|
#
|
#
|
#
|
#
|
|
# *args*:: An optional list of interface names
|
def ports( *args )
|
def ports( *args )
|
|
|
if args.size == 0
|
if args.size == 0
|
@interfaces.values.each_with_index do | ifc, i_ifc; ifc_def|
|
@ifc_sel = @interfaces
|
|
else
|
|
@ifc_sel = @interfaces.select{ |k,v| args.include?( k.to_s ) }
|
|
end
|
|
|
|
@ifc_sel.values.each_with_index do | ifc, i_ifc; ifc_def|
|
|
|
# get interface definition
|
# get interface definition
|
ifc_def = SOCMaker::lib.get_ifc( ifc.name, ifc.version )
|
ifc_def = SOCMaker::lib.get_ifc( ifc.name, ifc.version )
|
|
|
# loop over ports in this interface
|
# loop over ports in this interface
|
ifc.ports.each_with_index do |(port_name, port_def), i_port; port_dir|
|
ifc.ports.each_with_index do |(port_name, port_def), i_port |
|
|
|
# the reference to the port in the definition
|
# the reference to the port in the definition
|
defn_ref = port_def.defn.to_sym
|
defn_ref = port_def.defn.to_sym
|
perr_if( !ifc_def.ports.has_key?( defn_ref ),
|
perr_if( !ifc_def.ports.has_key?( defn_ref ),
|
"Can't find #{port_def} in" +
|
"Can't find #{port_def} in" +
|
"interface definition #{ifc_def.name} " +
|
"interface definition #{ifc_def.name} " +
|
"version #{ifc_def.version}" )
|
"version #{ifc_def.version}" )
|
yield( port_name.to_s,
|
|
ifc_def.ports[ defn_ref ][:dir] ^ ifc.dir,
|
|
port_def.len,
|
|
ifc_def.ports[ defn_ref ][ :default ],
|
|
( (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 )
|
_port_name = port_name.to_s
|
ifc = @interfaces[ args.first.to_sym ]
|
_port_dir = ifc_def.ports[ defn_ref ][:dir] ^ ifc.dir
|
ifc_def = SOCMaker::lib.get_ifc( ifc.name, ifc.version )
|
_port_length = port_def.len
|
|
_port_default = ifc_def.ports[ defn_ref ][ :default ]
|
# loop over all ports of this interface
|
_is_last = ( (i_port == ifc.ports.size-1 ) and (i_ifc == @ifc_sel.size-1 ) )
|
ifc.ports.each_with_index do |(port_name, port_def),i_port; port_dir|
|
yield( _port_name, _port_dir, _port_length, _port_default, _is_last )
|
defn_ref = port_def.defn.to_sym
|
|
perr_if( !ifc_def.ports.has_key?( defn_ref ),
|
|
"Can't find #{defn_ref} in" +
|
|
"interface definition #{ifc_def.name} " +
|
|
"version #{ifc_def.version}" )
|
|
yield( port_name.to_s,
|
|
ifc_def.ports[ defn_ref ][:dir] ^ ifc.dir,
|
|
port_def.len,
|
|
ifc_def.ports[ defn_ref ][ :default ],
|
|
( (i_port == ifc.ports.size-1 ) )
|
|
)
|
|
#yield( port_def.to_s,
|
|
#port_name.to_s,
|
|
#port_dir ^ ifc.dir,
|
|
#port_default )
|
|
end
|
end
|
|
|
else
|
|
# TODO
|
|
end
|
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
|
end
|
|
|
|
|
|
|
|
#
|
|
# Equality operator
|
|
#
|
def ==(o)
|
def ==(o)
|
|
|
tmp = ( o.class == self.class )
|
tmp = ( o.class == self.class )
|
return tmp if !tmp
|
return tmp if !tmp
|
|
|
Line 370... |
Line 393... |
return false if instance_variable_get( "@#{v}" ) != o.instance_variable_get( "@#{v}" )
|
return false if instance_variable_get( "@#{v}" ) != o.instance_variable_get( "@#{v}" )
|
end
|
end
|
return true
|
return true
|
end
|
end
|
|
|
|
#
|
|
# Returns a string describing this instance
|
|
#
|
def to_s
|
def to_s
|
"version: #{@version}\n" +
|
"version: #{@version}\n" +
|
"toplevel: #{@toplevel}\n" +
|
"toplevel: #{@toplevel}\n" +
|
"description: #{@description}\n" +
|
"description: #{@description}\n" +
|
"date: #{@date}\n" +
|
"date: #{@date}\n" +
|
Line 387... |
Line 413... |
"inst_parameters: #{@inst_parameters}\n" +
|
"inst_parameters: #{@inst_parameters}\n" +
|
"static_parameters: #{@static_parameters}\n"
|
"static_parameters: #{@static_parameters}\n"
|
end
|
end
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
# Creates a core directory, if it doesn't exist.
|
|
# The path of the target directoy depends
|
|
# on SOCMaker::conf[ :build_dir ] and
|
|
# on SOCMaker::conf[ :hdl_dir ].
|
|
# The resulting path is
|
|
# ./#{SOCMaker::conf[ :build_dir ]}/#{SOCMaker::conf[ :hdl_dir ]}/dir_name
|
|
#
|
|
# *dir_name*:: Name of the target directory
|
|
#
|
|
def self.get_and_ensure_dst_dir!( dir_name )
|
|
dst_dir = File.expand_path(
|
|
File.join(
|
|
SOCMaker::conf[ :build_dir ],
|
|
SOCMaker::conf[ :hdl_dir ],
|
|
dir_name ) )
|
|
FileUtils.mkdir_p dst_dir
|
|
return dst_dir
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end # class CoreDef
|
end # class CoreDef
|
end # module SOCMaker
|
end # module SOCMaker
|
|
|
|
|
# vim: noai:ts=2:sw=2
|
# vim: noai:ts=2:sw=2
|