Class: NotifierPlugin::AdapterGenerator::EntryPort

Inherits:
Object
  • Object
show all
Defined in:
lib/tecsgen/plugin/NotifierPlugin.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(port, prefix) ⇒ EntryPort

Returns a new instance of EntryPort.

Parameters:

  • port (Port)

    結合先のセルのセルタイプの受け口.



128
129
130
131
132
133
134
135
136
137
# File 'lib/tecsgen/plugin/NotifierPlugin.rb', line 128

def initialize(port, prefix)
  @port = port
  @global_name = "#{prefix}_#{@port.get_celltype.get_global_name}_#{@port.get_name}"

  # 受け口関数名.siHandlerBodyを想定しているので,関数名はmainで固定である.
  @entry_fn_name = "#{@port.get_celltype.get_global_name}_#{@port.get_name}_main"

  @props = [] # Array<EntryProperty>
  @prop_map = {} # Hash<EntryProperty, Integer>
end

Instance Attribute Details

#global_nameString (readonly)

Returns グローバルに一意(なものとして扱えるよう)な識別子..

Returns:

  • (String)

    グローバルに一意(なものとして扱えるよう)な識別子.



140
141
142
# File 'lib/tecsgen/plugin/NotifierPlugin.rb', line 140

def global_name
  @global_name
end

#portPort (readonly)

Returns:



143
144
145
# File 'lib/tecsgen/plugin/NotifierPlugin.rb', line 143

def port
  @port
end

Instance Method Details

#adapter_handle_for_entry_property(ep) ⇒ String

指定したEntryPropertyに対応するアダプタ関数ハンドルを取得する.

Parameters:

Returns:

  • (String)

    アダプタ関数ハンドル.



149
150
151
152
153
154
155
# File 'lib/tecsgen/plugin/NotifierPlugin.rb', line 149

def adapter_handle_for_entry_property(ep)
  index = @prop_map.fetch(ep)
  return [
    "#{@global_name}_#{index}_fp",
    "#{@global_name}_#{index}_arg"
  ]
end

#generate(context) ⇒ Object

ソース・ヘッダーの記述を生成する.

Parameters:



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
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/tecsgen/plugin/NotifierPlugin.rb', line 220

def generate(context)
  header_file = context.header_file
  return if @props.empty?

  ct = @port.get_celltype

  header_file.print "/*\n * #{@global_name}\n"

  cells = @props.group_by {|prop| prop.cell }
  subscripts = @props.group_by {|prop| prop.subscript }
  no_cellidx = false
  if !(ct.has_INIB? || ct.has_CB?)
    # CB, INIB最適化により,CB, INIBが両方不要になったケース.
    # CELLIDXが不要であるので,セルについて一般化しても意味
    # はないので,添字による一般化を選択する.
    generalize_by_cell_idx = false
    no_cellidx = true

    # 全てのセルを同一視する.
    cells = { @props[0].cell => @props }

    header_file.print " * No INIB & CB: generalized by subscript\n"
  elsif @port.get_array_size
    # 一般化パターンの分類を行うために,受け口側セルや添字の
    # パターン数を分析して,最適な方を選択する.
    generalize_by_cell_idx = cells.length >= subscripts.length
    if generalize_by_cell_idx
      header_file.print " * more cells than subscripts: generalized by cell\n"
    else
      header_file.print " * more subscripts than cells: generalized by subscript\n"
    end
  else
    # 常にCELLIDXで一般化
    generalize_by_cell_idx = true
    header_file.print " * non-array entry port: generalized by cell\n"
  end

  header_file.print " */\n\n"

  if generalize_by_cell_idx
    # CELLIDXについて一般化
    subscripts.each {|subscript, props|
      if subscript
        fn_name = "#{@global_name}_adap_#{subscript}"
      else
        # 受け口配列でない場合
        fn_name = "#{@global_name}_adap"
      end

      generate_inner context, fn_name,
        :generic, subscript, ct

      props.each {|prop|
        handle = adapter_handle_for_entry_property(prop)

        # セルのCELLIDXを得る
        if ct.has_INIB? || ct.has_CB?
          idx = ct.get_name_array(prop.cell)[7]
        else
          idx = "0"
        end
        header_file.print "\#define #{handle[0]} &#{fn_name}\n"
        header_file.print "\#define #{handle[1]} #{idx}\n\n"
      }
    }
  else
    # 添字について一般化
    cells.each {|cell, props|
      if no_cellidx
        # CB/INIB なし
        fn_name = "#{@global_name}_adap"
      else
        fn_name = "#{@global_name}_adap_#{cell.get_global_name}"
      end

      generate_inner context, fn_name,
        cell, :generic

      props.each {|prop|
        handle = adapter_handle_for_entry_property(prop)

        header_file.print "\#define #{handle[0]} &#{fn_name}\n"
        header_file.print "\#define #{handle[1]} #{prop.subscript || 0}\n\n"
      }
    }
  end
end

#generate_inner(context, fn_name, cell, subscript, callee_ct = nil) ⇒ Object

結合先の情報に応じたアダプタ関数をソース・ヘッダーに出力する.一般化指定は,‘cell`または`subscript`の一方のみ行うことができる.

Parameters:

  • context (AdapterGenerator)
  • fn_name (String)

    関数名.

  • cell (Cell, Symbol)

    セル.セルについて一般化する場合は ‘:generic`

  • subscript (Integer, Symbol, nil)

    添字.添字について一般化する場合は ‘:generic`

  • 呼び先のセルタイプ、cell==:generic (Celltype)

    の場合のみ有効



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
# File 'lib/tecsgen/plugin/NotifierPlugin.rb', line 166

def generate_inner(context, fn_name, cell, subscript, callee_ct=nil)
  source_file = context.source_file
  header_file = context.header_file

  source_file.print "void #{fn_name}(intptr_t extinf) {\n"

  params = []
  ct = @port.get_celltype

  # シングルトンセルタイプ以外では,CELLIDXの指定が必要.
  unless ct.is_singleton?
    if cell == :generic
      params << "(#{callee_ct.get_global_name}_IDX)extinf"
      # params << "(CELLIDX)extinf"
    else
      # セルのCELLIDXを得る
      if ct.has_INIB? || ct.has_CB?
        params << ct.get_name_array(cell)[7]
      else
        params << "0"
      end
    end
  end

  # 受け口配列の添字.
  if @port.get_array_size
    if subscript == :generic
      params << "(int_t)extinf"
    else
      params << subscript.to_s
    end
  end

  params_str = params.join(", ")

  source_file.print "\t#{@entry_fn_name}(#{params_str});\n"
  source_file.print "}\n\n"

  header_file.print "extern void #{fn_name}(intptr_t extinf);\n\n"
end

#make_adapter_handle(join) ⇒ Array

指定したJoinに対応するアダプタ関数ハンドルを取得する.

Returns:

  • (Array)

    アダプタ関数ハンドル.



209
210
211
212
213
214
215
216
# File 'lib/tecsgen/plugin/NotifierPlugin.rb', line 209

def make_adapter_handle(join)
  prop = EntryProperty.from_join(join)
  unless @prop_map.has_key?(prop)
    @prop_map[prop] = @props.length
    @props << prop
  end
  return adapter_handle_for_entry_property(prop)
end