OpenCores
URL https://opencores.org/ocsvn/soc_maker/soc_maker/trunk

Subversion Repositories soc_maker

[/] [soc_maker/] [trunk/] [lib/] [soc_maker/] [core_inst.rb] - Blame information for rev 7

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 feddischso
###############################################################
2
#
3
#  File:      core_inst.rb
4
#
5
#  Author:    Christian Hättich
6
#
7
#  Project:   System-On-Chip Maker
8
#
9
#  Target:    Linux / Windows / Mac
10
#
11
#  Language:  ruby
12
#
13
#
14
###############################################################
15
#
16
#
17
#   Copyright (C) 2014  Christian Hättich  - feddischson [ at ] opencores.org
18
#
19
#   This program is free software: you can redistribute it and/or modify
20
#   it under the terms of the GNU General Public License as published by
21
#   the Free Software Foundation, either version 3 of the License, or
22
#   (at your option) any later version.
23
#
24
#   This program is distributed in the hope that it will be useful,
25
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
26
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
#   GNU General Public License for more details.
28
#
29
#   You should have received a copy of the GNU General Public License
30
#   along with this program.  If not, see .
31
#
32
#
33
###############################################################
34
#
35
#   Description:
36
#     This class represents a core instantiation within
37
#     a SOC. It contains a params (parameters) hash,
38
#     which defines, which parameters are set to which values.
39
#     The type field is used to identify the SOCMaker::CoreDef
40
#     and the field @defn is initialized as reference to
41
#     the corresponding CoreDef instance.
42
#
43
#
44
###############################################################
45
 
46
 
47
module SOCMaker
48
class CoreInst
49
  include ERR
50
 
51
 
52
 
53
  attr_accessor :defn
54
  attr_accessor :type
55
  attr_accessor :params
56
 
57
  def initialize(  type, params = {} )
58
    init_with(  'type'   => type,
59
                'params' => params  )
60 7 feddischso
 
61 3 feddischso
  end
62
  def encode_with( coder )
63
    %w[ type params ].
64
      each { |v| coder[ v ] = instance_variable_get "@#{v}" }
65
  end
66
 
67
  def init_with( coder )
68
 
69
    serr_if( coder[ 'type' ] == nil,
70
      "no type is provided for a core instance",
71
      field: "type" )
72
 
73
    @type = coder[ 'type' ]
74
 
75
    @params = coder[ 'params' ] || {}
76
    serr_if( !@params.is_a?( Hash ), 'Parameters are not given as hash',
77
      field: 'params' )
78
 
79
  end
80
 
81
  def ports
82 7 feddischso
    puts "HELP" + @defn.name
83
    p @ports
84 3 feddischso
    @ports.each_with_index do |(name, port_def), i|
85 7 feddischso
      yield( name.to_s, port_def[ :dir ], port_def[ :len ], i==@ports.size-1 )
86 3 feddischso
    end
87
  end
88
 
89
 
90
  def generics
91
    @defn.generics do |name, type, default_value, is_last|
92
      value = @params[ name.to_sym ];
93
      value = value
94
      value = default_value if value == nil
95
      yield( name.to_s, type, value, is_last )
96
    end
97
  end
98
 
99
 
100
 
101
 
102 5 feddischso
 
103 3 feddischso
 
104 7 feddischso
  #
105
  # Get a port, identified by the interface and port name
106
  #
107
  #  +ifc_name+::       name of the interface
108
  #  +port_spec_name+:: name of the port
109
  #
110 3 feddischso
  def get_port( ifc_name, port_spec_name )
111
    tmp = @defn.interfaces[ ifc_name.to_sym ].
112
        ports.select{ |key,hash| hash.defn == port_spec_name.to_s }.
113
        keys.first.to_s
114
    return [ tmp, @ports[ tmp.to_sym ] ]
115
  end
116
 
117
 
118 7 feddischso
  # TODO do we need this?
119
# def implements_port?( ifc_name, port_spec_name )
120
#   @defn.implements_port?( ifc_name, port_spec_name )
121
# end
122 3 feddischso
 
123
 
124 7 feddischso
  def consistency_check
125
 
126 3 feddischso
    @defn = SOCMaker::lib.get_core( @type )
127
 
128
 
129
    # check, if the instance parameters in the core definition
130
    @params.each do |param_name, value|
131
      verr_if(  @defn.inst_parameters[ param_name ] == nil,
132
                "Parameter not found: " + param_name.to_s,
133
        field: 'params' )
134
    end
135
 
136
    ## auto-complete parameters with default values
137
    @defn.inst_parameters.each do |param_name, param|
138
 
139
      # auto-complete to default values
140
      @params[ param_name ] ||= param.default
141
    end
142
 
143
 
144
#   @_params ||= {}
145
#   if @params != nil
146
#     @params.each do |name, val|
147
#
148
#       param_type = defn.inst_parameters[ name ].type
149
#
150
#       if val.is_a? String
151
#         eval_match = SOCMaker::conf[ :eval_regex ].match( val )
152
#         #TODO error handling
153
#         if eval_match
154
#           #eval_func = eval_match.captures[0]
155
#           @_params[ name ] = { value: eval( eval_str ).to_s, type: param_type }
156
#         else
157
#           @_params[ name ] = { value: val, type: param_type }
158
#         end
159
#       else
160
#         @_params[ name ] = { value: val, type: param_type }
161
#       end
162
#     end
163
#   end
164
 
165
    @ports ||= {}
166
    @defn.ports do |port_name, port_dir, port_len, is_last |
167
      if port_len.is_a?( String )
168
        param_match = SOCMaker::conf[ :length_regex ].match( port_len )
169
 
170
        if param_match and @params[ port_len.to_sym ] != nil
171
          tmp =@params[ port_len.to_sym ]
172
          tmp = tmp.to_i if tmp.is_a?( String )
173
          @ports[ port_name.to_sym ] = { len: tmp, dir: port_dir }
174
        else
175
          SOCMaker::logger.error( "Failed to evaluate #{port_len} for port #{port_name}" )
176
        end
177
      else
178
        @ports[ port_name.to_sym ] = { len: port_len, dir: port_dir }
179
      end
180
    end
181
 
182
    lerr_if( @defn == nil, 'Core not found in lib',
183
      field:    'cores'    )
184 7 feddischso
 
185
 
186
    @defn.consistency_check
187
 
188 3 feddischso
 
189
  end
190
 
191
 
192 6 feddischso
 
193 7 feddischso
  #
194
  # Returns the length of a port within an interface.
195
  # If no instance is given, we know that it is
196
  # a toplevel interface.
197
  # Otherwise we check for this and we do a recursive call.
198
  # If this port is within a interface of a core, we
199
  # pass the call to the core-definition of this instance, which
200
  # knows all cores.
201
  #
202
  # +ifc_name+::        name of the interface
203
  # +port_spec_name+::  name of the port
204
  # +inst+::            name of the instance (optional), default is nil
205
  #
206
  def get_port_len( ifc_name, port_spec_name, inst = nil )
207
    if inst == nil
208
      tmp = @defn.interfaces[ ifc_name.to_sym ].
209
          ports.select{ |key,hash| hash.defn == port_spec_name.to_s }.
210
          keys.first.to_s
211
      return tmp.size == 0 ? 0 : @ports[ tmp.to_sym ][ :len ]
212
    else
213
      if inst == @defn.name.to_sym
214
        return get_port_len( ifc_name, port_spec_name )
215
      else
216
        return @defn.get_port_len( ifc_name, port_spec_name, inst )
217
      end
218
    end
219
  end
220
 
221
 
222
  #
223
  # Returns the core definition for an instance (identified by its name)
224
  #
225
  # +inst+:: name of the instance
226
  #
227 6 feddischso
  def get_core_def( inst )
228 7 feddischso
      if inst == @defn.name
229
        return @defn
230
      else
231
        tmp = @defn.get_core_def( inst )
232
        perr_if( tmp == nil, "#Processing error: {inst} not found by get_core_def" )
233 6 feddischso
        return tmp
234
      end
235
  end
236
 
237
 
238 7 feddischso
  #
239
  # Returns a core instance, identified by its name.
240
  # If it is not a sub-core, we return our self
241
  #
242
  # +inst+::  name of the instance
243
  #
244
  def get_core_inst( inst )
245
    if @defn.cores[ inst ] != nil
246
      return @defn.cores[ inst ]
247
    else
248
      return self
249
    end
250
  end
251 6 feddischso
 
252
 
253 7 feddischso
  #
254
  # Generate toplevel hdl file for this instance.
255
  # This assumes, that this instance represents a SOC with
256
  # further instances.
257
  #
258
  #
259
  # +coder+:: A HDL coder, which is used to create the auto-generated HDL (optional).
260
  #           If no coder is given, a VHDLCoder is used.
261
  #
262
  #
263
  def gen_toplevel( coder = VHDLCoder.new )
264 6 feddischso
 
265
 
266
    #
267 7 feddischso
    # Get filename
268 6 feddischso
    #
269 7 feddischso
    file_name = coder.filename( @defn.name )
270 6 feddischso
 
271
    SOCMaker::logger.proc( "START of creating top-level '" + file_name + "'" )
272
 
273
 
274
 
275 7 feddischso
#   SOCMaker::logger.proc( "verifying first ..." )
276
#
277
#   # TODO: this is a fix, that the parameters in core_inst.ports are updated.
278
#   #       A good approach for verifying, which checks the whole consistency, needs
279
#   #       to be done
280
#   @defn.cores.each do |inst_name, inst|
281
#     inst.verify
282
#   end
283 6 feddischso
 
284
 
285
    #
286
    # Create a unique list of cores and
287 7 feddischso
    # add for each core a component statement (vhdl only).
288 6 feddischso
    # Even if there are multiple instances of a core,
289
    # we need to decalre it only once
290
    #
291
    @defn.cores.values.uniq{|x| x.type }.each do |inst; spec|
292
 
293
      spec = SOCMaker::lib.get_core( inst.type  )
294
      SOCMaker::lib.check_nil( spec, "Can't find #{ inst.type } in SOC library" )
295
 
296 7 feddischso
      coder.add_core_component( inst.type, spec )
297 6 feddischso
    end
298
 
299 7 feddischso
    #
300
    # Instanciate each core
301
    #
302 6 feddischso
    @defn.cores.each do |inst_name, inst|
303 7 feddischso
      coder.add_core_instance( inst_name.to_s, inst )
304 6 feddischso
    end
305
 
306
 
307
 
308
    # Iterate over all connections:
309
    #  - create signal instances
310
    #  - add assignments
311
    #
312
    @defn.cons.each do |con_name, con_def|
313
      gen_toplevel_con(   con_name.to_s,
314
                          con_def[ :rule ],
315
                          con_def[ :mapping ][0],
316
                          con_def[ :mapping ][1],
317 7 feddischso
                          coder  )
318 6 feddischso
 
319
    end
320
 
321 7 feddischso
 
322
    #
323
    # Write content to the file
324
    #
325 6 feddischso
    SOCMaker::logger.proc( "writing top-level" )
326
    file_dir  = File.join( SOCMaker::conf[ :build_dir ],
327
                           SOCMaker::conf[ :hdl_dir   ] )
328
    ::FileUtils.mkdir_p file_dir
329 7 feddischso
    File.open( File.join( file_dir, file_name ), 'w' ) do |f|
330
      f.write( coder.get_hdl_code( self, @defn.name ) )
331 6 feddischso
    end
332 7 feddischso
    SOCMaker::logger.proc( "END of creating top-level hdl code for #{@defn.name}" )
333 6 feddischso
 
334
  end
335
 
336
 
337 7 feddischso
 
338
 
339
  #
340
  # This function is called during the toplevel generation
341
  # for each connection.
342
  #
343
  # +name+::   The name of the connection
344
  # +rule+::   The combination rule (obsolete/unused)
345
  # +src+::    Source hash with instance name as key and interface name as value
346
  # +dst+::    Destination hash with instance name as key and interface name as value
347
  # +coder+::  The HDL coder which is used
348
  #
349 6 feddischso
  def gen_toplevel_con( name, rule, src, dst, coder )
350
 
351
    src_inst            = {};
352
    dst_inst            = {};
353
 
354 7 feddischso
    #
355
    # Get the interface specification by using the 1st source entry
356
    # and searching for the core-definition.
357
    #
358 6 feddischso
    ifc_spec = SOCMaker::lib.get_ifc(
359
      get_core_def( src.keys.first.to_s ).interfaces[ src.values.first ].name,
360
      get_core_def( src.keys.first.to_s ).interfaces[ src.values.first ].version )
361 7 feddischso
 
362
 
363
    #
364
    # Get the maximum required signal length
365
    #
366
    # For each signal in the interface specification,
367
    # we create a list. The list has an entry for each source
368
    # and destination signal, which defines the length.
369
    #
370
    # In the second step, the maximum in each list is extracted.
371
    #
372 6 feddischso
    length_tmp  = {};
373
    ifc_spec.ports.keys.each do |_name|
374
      length_tmp[ _name ] = []
375
      dst.each do |inst_name, ifc_name|
376 7 feddischso
        length_tmp[ _name ] << get_port_len( ifc_name, _name, inst_name )
377 6 feddischso
      end
378
      src.each do |inst_name, ifc_name|
379 7 feddischso
        length_tmp[ _name ] << get_port_len( ifc_name, _name, inst_name )
380 6 feddischso
      end
381
    end
382
    max_length = Hash[ length_tmp.map{ |key, arr| [ key, arr.max ] } ]
383
 
384
 
385 7 feddischso
    #
386
    # Prepare a hash for all sources and destinations, where
387
    # the instance name is the key and the core-instance is
388
    # the value.
389
    #
390 6 feddischso
    src.keys.each do |inst_name|
391 7 feddischso
      src_inst[ inst_name ]            = get_core_inst( inst_name )
392 6 feddischso
    end
393
    dst.keys.each do |inst_name|
394 7 feddischso
      dst_inst[ inst_name ]            = get_core_inst( inst_name )
395 6 feddischso
    end
396
 
397 7 feddischso
    #
398
    # create the declaraion and assignments
399
    #
400
    coder.add_ifc_connection( ifc_spec, name, max_length, src_inst, dst_inst, src, dst )
401 6 feddischso
 
402
  end
403
 
404
 
405 7 feddischso
  #
406
  # Returns a string describing this instance
407
  #
408 5 feddischso
  def to_s
409
    "type:     #{type}\n"   +
410
    "params:   #{params}\n"
411
  end
412 3 feddischso
 
413 7 feddischso
  #
414
  # Equal operator
415
  #
416 3 feddischso
  def ==(o)
417
    o.class     == self.class   &&
418
    o.type      == self.type    &&
419
    o.params    == self.params
420
  end
421
 
422
 
423
end # CoreInst
424
end # SOCMaker
425
 
426
 
427
 
428
# vim: noai:ts=2:sw=2

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.