Class: SOCMaker::CoreDef

Inherits:
Object
  • Object
show all
Includes:
ERR, YAML_EXT
Defined in:
lib/soc_maker/core_def.rb

Overview

This class represents a core definition. It is one of the central classes and holds data, which is used to describe and instanciate a IP core. In general, instances of this class desribe a core, it’s interface and parameters as well as the files, which are required for synthesis/simulation.

In addition to this core, there exist SOCMaker::CoreInst, which represents a concret instanciation of a definition.

Direct Known Subclasses

SOCDef

Instance Attribute Summary collapse

Attributes included from YAML_EXT

#src_dir

Class Method Summary collapse

Instance Method Summary collapse

Methods included from YAML_EXT

#save_yaml

Methods included from ERR

#consistence_error, #consistence_error_if, #init_error, #init_error_if, #processing_error, #processing_error_if

Constructor Details

#initialize(name, id, toplevel, optional = {}) ⇒ CoreDef

Constructor: the three attributes name, id and toplevel are required. All other attributes can be given as a optinal hash.

name

Name of this core (string)

id

Id of this core (string)

toplevel

Toplevel name of this core (string)

optional

Non-mandatory values, which can be set during initialization.



116
117
118
119
120
# File 'lib/soc_maker/core_def.rb', line 116

def initialize( name, id, toplevel, optional = {} )
  init_with( { 'name'      => name, 
               'id'        => id, 
               'toplevel'  => toplevel }.merge( optional ) )
end

Instance Attribute Details

#authorObject

author of this core



77
78
79
# File 'lib/soc_maker/core_def.rb', line 77

def author
  @author
end

#authormailObject

author-mail of this core



80
81
82
# File 'lib/soc_maker/core_def.rb', line 80

def authormail
  @authormail
end

#dateObject

creation date



68
69
70
# File 'lib/soc_maker/core_def.rb', line 68

def date
  @date
end

#descriptionObject

description of this core



65
66
67
# File 'lib/soc_maker/core_def.rb', line 65

def description
  @description
end

#functionsObject

reserved and not implemented



89
90
91
# File 'lib/soc_maker/core_def.rb', line 89

def functions
  @functions
end

#hdlfilesObject

Hash of SOCMaker::HDLFile



102
103
104
# File 'lib/soc_maker/core_def.rb', line 102

def hdlfiles
  @hdlfiles
end

#idObject

ID of the core (mandatory, stored as hash key)



59
60
61
# File 'lib/soc_maker/core_def.rb', line 59

def id
  @id
end

#id_cleanObject

the ID, but withou commata and as string, can be used for creating paths and so on



99
100
101
# File 'lib/soc_maker/core_def.rb', line 99

def id_clean
  @id_clean
end

#inst_parametersObject

hash of instantiation parameters see SOCMaker::Parameter



92
93
94
# File 'lib/soc_maker/core_def.rb', line 92

def inst_parameters
  @inst_parameters
end

#interfacesObject

interfaces which are implemented see SOCMaker::IfcSpc



86
87
88
# File 'lib/soc_maker/core_def.rb', line 86

def interfaces
  @interfaces
end

#licenseObject

license of this core



71
72
73
# File 'lib/soc_maker/core_def.rb', line 71

def license
  @license
end

#licensefileObject

location of the license file



74
75
76
# File 'lib/soc_maker/core_def.rb', line 74

def licensefile
  @licensefile
end

#nameObject

name of the core (mandatory)



56
57
58
# File 'lib/soc_maker/core_def.rb', line 56

def name
  @name
end

#static_parametersObject

hash of static parameters see SOCMaker::SParameter



95
96
97
# File 'lib/soc_maker/core_def.rb', line 95

def static_parameters
  @static_parameters
end

#toplevelObject

toplevel name (mandatory)



62
63
64
# File 'lib/soc_maker/core_def.rb', line 62

def toplevel
  @toplevel
end

#vccmdObject

a version control command, which is used to download the files



83
84
85
# File 'lib/soc_maker/core_def.rb', line 83

def vccmd
  @vccmd
end

Class Method Details

.core_cnt(core_id_array) ⇒ Object

Method, which counts the core occurence:

core_id_array

An array with id’s, for example [ ‘id1’, ‘id1’, ‘id2’, ‘id3’ ]

return

A Hash with id => #ofOccurence mapping, for example { ‘id1’ => 2, ‘id2’ => 1, ‘id3’ => 1 }



487
488
489
490
491
492
493
# File 'lib/soc_maker/core_def.rb', line 487

def self.core_cnt( core_id_array )
  cnt_hash = Hash.new( 0 )
  core_id_array.each do |v|
    cnt_hash[v] += 1
  end
  return cnt_hash
end

.get_and_ensure_dst_dir!(dir_name) ⇒ Object

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

./build_dir/hdl_dir/dir_name
dir_name

Name of the target directory



507
508
509
510
511
512
513
514
515
# File 'lib/soc_maker/core_def.rb', line 507

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

Instance Method Details

#==(o) ⇒ Object

Equality operator



446
447
448
449
450
451
452
453
454
455
456
457
458
# File 'lib/soc_maker/core_def.rb', line 446

def ==(o)

  tmp    = ( o.class   == self.class )
  return tmp if !tmp

  %w[ name id description date license licensefile 
      author authormail vccmd toplevel interfaces 
      functions inst_parameters static_parameters hdlfiles ].
        each do |v| 
    return false if instance_variable_get( "@#{v}" ) != o.instance_variable_get( "@#{v}" )
  end
  return true
end

#add_interface(ifc_name, ifc_id, dir, ports) ⇒ Object



428
429
430
431
432
433
434
435
# File 'lib/soc_maker/core_def.rb', line 428

def add_interface( ifc_name, ifc_id, dir, ports )
  processing_error_if( @interfaces.has_key?( ifc_name.to_sym ),
      "Interface name #{ifc_name} already exist",
      name: ifc_name,
      id_to_add: ifc_id )
  @interfaces[ ifc_name.to_sym ] = SOCMaker::IfcDef.new( ifc_name, ifc_id, dir, ports );

end

#all_core_idObject

This method is required to allow recursive search of all IDs and returns only it’s ID (because there are no sub-cores).



568
569
570
# File 'lib/soc_maker/core_def.rb', line 568

def all_core_id
  [ @id ]
end

#all_static_parametersObject

This method is required to allow recursive static parameter collection. Because this is a sigle core and doesn’t have sub-cores (which might have some static parameters), an empty hash is returned.



525
526
527
# File 'lib/soc_maker/core_def.rb', line 525

def all_static_parameters
  Hash.new()
end

#consistence_checkObject

Runs a consistence check: Iterate over all interfaces and check, if the interface is in the SOCMaker::Lib. The method also checks also, if the ports defined by this core is also defined in the interface.



307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
# File 'lib/soc_maker/core_def.rb', line 307

def consistence_check
  @interfaces.values.each_with_index do | ifc, i_ifc; ifc_spc|

    # get interface definition
    ifc_spc = SOCMaker::lib.get_ifc( ifc.id )



    # check if all refereces (to the ports) exist
    ifc.ports.each_with_index do |(port_name, port_def), i_port |
      spc_ref      = port_def.spc_ref.to_sym
      consistence_error_if( 
          !ifc_spc.ports.has_key?( spc_ref ), 
          "Can't find #{port_def} in" + 
          "interface definition #{ifc_spc.name} ",
          id: ifc_spc.id,
          portname: port_name )
    end


    # check, if all mandatory ports are implemented by this interface
    ifc_spc.ports.each do | port_name, port |
      consistence_error_if( 
          port[ :mandatory ] == true &&  
          ifc.ports.select{ |key,port_def| port_def.spc_ref.to_sym == port_name }.size == 0,  
        "Mandatory port #{port_name} is not implemented in interface #{ifc.name}",
        port: port_name,
        interface: ifc.name )
    end

  end

end

#core_definition(inst) ⇒ Object



438
439
440
# File 'lib/soc_maker/core_def.rb', line 438

def core_definition( inst )
  return nil;
end

#deploy(options = {}) ⇒ Object

Method to deploy this core: all files are copied and deployed:

  • all hdl-files

  • all files with static-parameters

options

Optinal arguments: usually the static parameters are passed via options[ :static ]



539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
# File 'lib/soc_maker/core_def.rb', line 539

def deploy( options={} )
  options = { static: {} }.merge( options )

  # create destination directory name and ensure, that it is exist
  dst_dir  = CoreDef::get_and_ensure_dst_dir!( dir_name )



  # copy each file into destination dir
  @hdlfiles.each do |file, val|
    file_path = File.join( @src_dir, val.path )
    dst_path = File.join( dst_dir, val.path )
    SOCMaker::logger.proc( "copy #{file_path} to #{ dst_path} " )
    FileUtils.mkdir_p(File.dirname(dst_path))
    FileUtils.cp( file_path, dst_path )
  end

  # deploy all static-parameter files
  @static_parameters.each do |file, sparam|
    sparam.deploy( options[ :static ][ @id ], @src_dir, dst_dir )
  end

end

#dir_nameObject

The directory name of this core (returns @id_clean)



268
269
270
# File 'lib/soc_maker/core_def.rb', line 268

def dir_name
  @id_clean
end

#encode_with(coder) ⇒ Object

Encoder method (to yaml)

coder

An instance of the Psych::Coder to encode this class to a YAML file



127
128
129
130
131
132
133
134
135
136
# File 'lib/soc_maker/core_def.rb', line 127

def encode_with( coder )
  init_error_if !coder.is_a?( Psych::Coder ), 
              'coder is not given as Psych::Coder'
  %w[ name description date license licensefile 
      author authormail vccmd toplevel interfaces 
      functions inst_parameters static_parameters hdlfiles ].
        each { |v| coder[ v ] = instance_variable_get "@#{v}" }

  coder[ "id" ] = @id.to_s
end

#genericsObject

Iterates over all generic values of this core and yield the call block with

  • generic name

  • generic type

  • generic default

  • is-last value



352
353
354
355
356
357
358
359
360
361
362
363
364
365
# File 'lib/soc_maker/core_def.rb', line 352

def generics
  @inst_parameters.each_with_index do |(name, val), i|

    _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

#ifc_specification(ifc_name) ⇒ Object

Method to get an interface specification, used by this core. The interface is identified by it’s name (within this core)

ifc_name

Interface name (within this core, not the ID)



280
281
282
# File 'lib/soc_maker/core_def.rb', line 280

def ifc_specification( ifc_name )
  SOCMaker::lib.get_ifc( @interfaces[ ifc_name ].id )
end

#init_with(coder) ⇒ Object

Initialization method (from yaml)

coder

An instance of the Psych::Coder to init this class from a YAML file



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/soc_maker/core_def.rb', line 144

def init_with( coder )
  init_error_if !( coder.is_a?( Hash ) || coder.is_a?( Psych::Coder ) ), 
              'coder is not given as Hash neither as Psych::Coder'

  @name     = coder[ 'name'     ]
  @toplevel = coder[ 'toplevel' ]

  # check name
  init_error 'Name must be of type string',     field: 'name' if !@name.is_a?( String )
  init_error 'Name is not defined (size == 0)', field: 'name' if @name.size  == 0

  # check id
  init_error 'Id must be of type string', 
                field: 'id' if !coder[ 'id' ].is_a?( String )

  @id       = coder[ 'id'       ].to_sym

  init_error 'Id not defined (size == 0)', 
      instance: @name, 
      field:    'id'        if @id.size == 0
  @id_clean = coder[ 'id' ].split(',').join("_")





  init_error "toplevel must be of type string",
    instance: @name, 
    field:    "toplevel"    if !@toplevel.is_a?( String )

  init_error 'Toplevel not defined (size == 0 )',
    instance: @name, 
    field:    'toplevel'    if @toplevel.size  == 0




  # 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' ] || {}
  @hdlfiles          = coder[ 'hdlfiles'          ] || {}


  # ensure, that these fields are of type String
  %w[ description date license licensefile 
      author authormail vccmd ].each do |n|

    init_error "#{n} must be of type String", 
      instance: @name, 
      field:    n               if !instance_variable_get( '@'+n ).is_a?( String )
  end

  # ensure, that these fields are of type Hash
  %w[ interfaces inst_parameters
      functions  static_parameters ].each do |n|
    init_error "#{n} must be of type Hash", 
        instance: @name, 
        field:    n             if  !instance_variable_get( '@'+n ).is_a?( Hash )

  end



  # check interfaces
  @interfaces.each do |ifc_name, ifc|
    init_error 'Interface not defined', 
          instance: @name,
          interface: ifc_name   if ifc == nil

    init_error 'Interface definition is not SOCMaker::IfcDef (please use SOCM_IFC)', 
          instance:  @name,
          interface: ifc_name   if  !ifc.is_a?( SOCMaker::IfcDef )
  end

  # check instance parameters
  @inst_parameters.each do |name, param |

    init_error  'Instance parameter not SOCMaker::Parameter (please use SOCM_PARAM)', 
          instance: @name, 
          parameter: name       if !param.is_a?( SOCMaker::Parameter )
  end

  # check instance parameters
  @static_parameters.each do |name, sparam |

    init_error 'Static parameter not SOCMaker::Parameter (please use SOCM_SPARAM)', 
          instance: @name,
          parameter: name       if !sparam.is_a?( SOCMaker::SParameter )
  end


  init_error  'HDL files argument is not of type Hash',
    instance: @name, 
    field:    'hdlfiles' if !@hdlfiles.is_a?( Hash )


  # check hdl files
  @hdlfiles.each do |file_name, file_info |

    init_error 'HDL file not defined', 
          instance:   @name,
          filename:   file_name if file_info == nil

    init_error 'HDL file is not of type SOCMaker::HDLFile (use SOCM_HDL_FILE)', 
          instance: @name,
          filename: file_name if !file_info.is_a?( SOCMaker::HDLFile )
  end

end

#ports(*args) ⇒ Object

Iterates over interface list (if no argument is given) or all specified interfaces. For each interface, all ports are processed. For each port within each interface, we lookup the port spc_ref and yield the call block with

  • port-name

  • port length

  • default value

  • the spec-reference

  • is-last value

as argument

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.

args

An optional list of interface names



393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
# File 'lib/soc_maker/core_def.rb', line 393

def ports( *args )

  if args.size == 0
    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_spc|

    # get interface specification
    ifc_spc = SOCMaker::lib.get_ifc( ifc.id )

    # loop over ports in this interface 
    ifc.ports.each_with_index do |(port_name, port_def), i_port |

      # the reference to the port in the definition
      spc_ref      = port_def.spc_ref.to_sym

      _port_name    = port_name.to_s
      if ifc_spc.ports[ spc_ref ][:dir] != 2
        _port_dir     = ifc_spc.ports[ spc_ref ][:dir] ^ ifc.dir
      else
        _port_dir     = 2
      end
      _port_length  = port_def.len
      _port_default = ifc_spc.ports[ spc_ref ][ :default  ]
      _is_last      = ( (i_port == ifc.ports.size-1 ) and (i_ifc == ifc_sel.size-1 ) )
      yield(  _port_name, _port_dir, _port_length, _port_default, port_def.spc_ref, _is_last )
    end
  end
end

#to_sObject

Returns a string describing this instance



463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
# File 'lib/soc_maker/core_def.rb', line 463

def to_s
  "id:                #{@id}\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

#update_vcsObject

Runs the Version Control System command via system(.…)



288
289
290
291
292
293
# File 'lib/soc_maker/core_def.rb', line 288

def update_vcs
  unless self.vccmd.nil? or @vccmd.size == 0
    #puts"cd #{@dir} && #{@vccmd}" 
    system( "cd #{@src_dir} && #{vccmd}" )
  end
end