source: EcnlProtoTool/trunk/asp3_dcre/tecsgen/tecslib/core/componentobj.rb@ 321

Last change on this file since 321 was 321, checked in by coas-nagasima, 7 years ago

文字コードを設定

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby;charset=UTF-8
File size: 252.7 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# TECS Generator
4# Generator for TOPPERS Embedded Component System
5#
6# Copyright (C) 2008-2016 by TOPPERS Project
7#--
8# 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
9# ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
10# 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
11# (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
12# 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
13# スコード中に含まれていること.
14# (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
15# 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
16# 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
17# の無保証規定を掲載すること.
18# (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
19# 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
20# と.
21# (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
22# 作権表示,この利用条件および下記の無保証規定を掲載すること.
23# (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
24# 報告すること.
25# (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
26# 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
27# また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
28# 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
29# 免責すること.
30#
31# 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
32# よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
33# に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
34# アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
35# の責任を負わない.
36#
37# $Id$
38#++
39
40# STAGE:
41# このメンテナンス状況はよろしくない
42# B bnf.y.rb から呼出される
43# P parse 段階で呼出される(bnf.y.rb から直接呼出されるわけではないが、構文木生成を行う)
44# S P の中から呼出されるが、構文木生成するわけではなく意味チェックする
45# G コード生成(この段階で、構文木は完全である.不完全ならエラーで打ちきられている)
46# factory の第一引数 "format" の後ろの引数
47
48# mikan 以下は ruby の mix in で実現できるかもしれない
49# Nestable を継承した場合、クラス変数は Nestable のものが共有される(別にしたかった)
50# class Nestable
51# @@nest_stack_index = -1
52# @@nest_stack = []
53# @@current_object = nil
54#
55# def self.push
56# @@nest_stack_index += 1
57# @@nest_stack[ @nest_stack_index ] = @@current_object
58# @@current_object = nil
59# end
60#
61# def pop
62# @@current_object = @@nest_stack[ @@nest_stack_index ]
63# @nest_stack_index -= 1
64# if @@nest_stack_index < -1 then
65# raise TooManyRestore
66# end
67# end
68# end
69#
70
71class Signature < NSBDNode # < Nestable
72# @name:: Symbol
73# @global_name:: Symbol
74# @function_head_list:: NamedList : FuncHead のインスタンスが要素
75# @func_name_to_id:: {String} : 関数名を添字とする配列で id を記憶する.id は signature の出現順番 (1から始まる)
76# @context:: string : コンテキスト名
77# @b_callback:: bool: callback : コールバック用のシグニチャ
78# @b_deviate:: bool: deviate : 逸脱(pointer level mismatch を出さない)
79# @b_checked_as_allocator_signature:: bool: アロケータシグニチャとしてチェック済み
80# @b_empty:: Bool: 空(関数が一つもない状態)
81
82 @@nest_stack_index = -1
83 @@nest_stack = []
84 @@current_object = nil
85
86 def self.push
87 @@nest_stack_index += 1
88 @@nest_stack[ @@nest_stack_index ] = @@current_object
89 @@current_object = nil
90 end
91
92 def self.pop
93 @@current_object = @@nest_stack[ @@nest_stack_index ]
94 @@nest_stack_index -= 1
95 if @@nest_stack_index < -1 then
96 raise "TooManyRestore"
97 end
98 end
99
100 # STAGE: P
101 # このメソッドは parse 中のみ呼び出される
102 def self.get_current
103 @@current_object
104 end
105
106 #
107 # STAGE: B
108 def initialize( name )
109 super()
110 @name = name
111 Namespace.new_signature( self )
112 set_namespace_path # @NamespacePath の設定
113 if "#{Namespace.get_global_name}" == "" then
114 @global_name = @name
115 else
116 @global_name = :"#{Namespace.get_global_name}_#{@name}"
117 end
118
119 @func_name_to_id = {}
120 @context = nil
121 @b_callback = false
122 @b_deviate = false
123 @b_empty = false
124 @b_checked_as_allocator_signature = false
125 @@current_object = self
126 set_specifier_list( Generator.get_statement_specifier )
127 end
128
129 #
130 # STAGE: B
131 def end_of_parse( function_head_list )
132 @function_head_list = function_head_list
133
134 # id を割付ける
135 id = 1
136 function_head_list.get_items.each{ |f|
137 @func_name_to_id[ f.get_name ] = id
138 id += 1
139 }
140 if id == 1 then
141 @b_empty = true
142 end
143
144 @@current_object = nil
145 return self
146 end
147
148 #=== Signature# signature の指定子を設定
149 # STAGE: B
150 #spec_list:: [ [ :CONTEXT, String ], ... ]
151 # s[0] s[1]
152 def set_specifier_list( spec_list )
153 return if spec_list == nil # 空ならば何もしない
154
155 spec_list.each { |s|
156 case s[0] # statement_specifier
157 when :CALLBACK
158 @b_callback = true
159 when :CONTEXT # [context("non-task")] etc
160 if @context then
161 cdl_error( "S1001 context specifier duplicate" )
162 end
163 # @context = s[1].gsub( /\A\"(.*)\"$/, "\\1" )
164 @context = CDLString.remove_dquote s[1]
165 case @context
166 when "non-task", "task", "any"
167 else
168 cdl_warning( "W1001 \'$1\': unknown context type. usually specifiy task, non-task or any" , @context )
169 end
170 when :DEVIATE
171 @b_deviate = true
172 else
173 cdl_error( "S1002 \'$1\': unknown specifier for signature" , s[0] )
174 end
175 }
176 end
177
178 def get_name
179 @name
180 end
181
182 def get_global_name
183 @global_name
184 end
185
186 def get_function_head_array
187 if @function_head_list then
188 return @function_head_list.get_items
189 else
190 return nil
191 end
192 end
193
194 def get_function_head( func_name )
195 return @function_head_list.get_item( func_name.to_sym )
196 end
197
198 #=== Signature# 関数名から signature 内の id を得る
199 def get_id_from_func_name func_name
200 @func_name_to_id[ func_name ]
201 end
202
203 #=== Signature# context を得る
204 # context 文字列を返す "task", "non-task", "any"
205 # 未指定時のデフォルトとして task を返す
206 def get_context
207 if @context then
208 return @context
209 else
210 return "task"
211 end
212 end
213
214 #=== Signature# signaure のすべての関数のすべてのパラメータをたどる
215 #block:: ブロックを引数に取る
216 # ブロックは2つの引数を受け取る Decl, ParamDecl ( Decl: 関数ヘッダ )
217 # Port クラスにも each_param がある(同じ働き)
218 def each_param # ブロック引数 { |func_decl, param_decl| }
219 fha = get_function_head_array # 呼び口または受け口のシグニチャの関数配列
220 return if fha == nil # nil なら文法エラーで有効値が設定されなかった
221
222 pr = Proc.new # このメソッドのブロック引数を pr に代入
223 fha.each{ |fh| # fh: FuncHead # 関数配列中の各関数頭部
224 fd = fh.get_declarator # fd: Decl (関数頭部からDeclarotorを得る)
225 if fd.is_function? then # fd が関数でなければ、すでにエラー
226 fd.get_type.get_paramlist.get_items.each{ |par| # すべてのパラメータについて
227 pr.call( fd, par )
228 }
229 end
230 }
231 end
232
233 #=== Signature# 正当なアロケータ シグニチャかテストする
234 # alloc, dealloc 関数を持つかどうか、第一引き数がそれぞれ、整数、ポインタ、第二引き数が、ポインタへのポインタ、なし
235 def is_allocator?
236
237 # 一回だけチェックする
238 if @b_checked_as_allocator_signature == true then
239 return true
240 end
241 @b_checked_as_allocator_signature = true
242
243 fha = get_function_head_array # 呼び口または受け口のシグニチャの関数配列
244 if fha == nil then # nil なら文法エラーで有効値が設定されなかった
245 return false
246 end
247
248 found_alloc = false; found_dealloc = false
249 fha.each{ |fh| # fh: FuncHead # 関数配列中の各関数頭部
250 fd = fh.get_declarator # fd: Decl (関数頭部からDeclarotorを得る)
251 if fd.is_function? then # fd が関数でなければ、すでにエラー
252 func_name = fd.get_name.to_sym
253 if func_name == :alloc then
254 found_alloc = true
255 params = fd.get_type.get_paramlist.get_items
256 if params then
257 if ! params[0].instance_of?( ParamDecl ) ||
258 ! params[0].get_type.get_original_type.kind_of?( IntType ) ||
259 params[0].get_direction != :IN then
260 # 第一引数が int 型でない
261 if ! params[0].instance_of?( ParamDecl ) ||
262 ! params[0].get_type.kind_of?( PtrType ) ||
263 ! params[0].get_type.get_type.kind_of?( PtrType ) ||
264 params[0].get_type.get_type.get_type.kind_of?( PtrType ) ||
265 params[0].get_direction != :OUT then
266 # 第一引数がポインタ型でもない
267 cdl_error3( @locale, "S1003 $1: \'alloc\' 1st parameter neither [in] integer type nor [out] double pointer type", @name )
268 end
269 elsif ! params[1].instance_of?( ParamDecl ) ||
270 ! params[1].get_type.kind_of?( PtrType ) ||
271 ! params[1].get_type.get_type.kind_of?( PtrType ) ||
272 params[1].get_type.get_type.get_type.kind_of?( PtrType ) ||
273 params[0].get_direction != :IN then
274 # (第一引数が整数で) 第二引数がポインタでない
275 cdl_error3( @locale, "S1004 $1: \'alloc\' 2nd parameter not [in] double pointer" , @name )
276 end
277 else
278 cdl_error3( @locale, "S1005 $1: \'alloc\' has no parameter, unsuitable for allocator signature" , @name )
279 end
280 elsif func_name == :dealloc then
281 found_dealloc = true
282 params = fd.get_type.get_paramlist.get_items
283 if params then
284 if ! params[0].instance_of?( ParamDecl ) ||
285 ! params[0].get_type.kind_of?( PtrType ) ||
286 params[0].get_type.get_type.kind_of?( PtrType ) ||
287 params[0].get_direction != :IN then
288 cdl_error3( @locale, "S1006 $1: \'dealloc\' 1st parameter not [in] pointer type" , @name )
289# elsif params[1] != nil then # 第二引き数はチェックしない
290# cdl_error3( @locale, "S1007 Error message is changed to empty" )
291# cdl_error3( @locale, "S1007 $1: \'dealloc\' cannot has 2nd parameter" , @name )
292 end
293 else
294 cdl_error3( @locale, "S1008 $1: \'dealloc\' has no parameter, unsuitable for allocator signature" , @name )
295 end
296 end
297 if found_alloc && found_dealloc then
298 return true
299 end
300 end
301 }
302 if ! found_alloc then
303 cdl_error3( @locale, "S1009 $1: \'alloc\' function not found, unsuitable for allocator signature" , @name )
304 end
305 if ! found_dealloc then
306 cdl_error3( @locale, "S1010 $1: \'dealloc\' function not found, unsuitable for allocator signature" , @name )
307 end
308 return false
309 end
310
311 #== Signature# 引数で参照されている Descriptor 型のリストを作成する
312 #RETURN:: Hash { Signature => ParamDecl }: 複数の ParamDecl から参照されている場合、最後のものしか返さない
313 def get_descriptor_list
314 desc_list = { }
315 # p "has_desc #{@name}"
316 fha = get_function_head_array # 呼び口または受け口のシグニチャの関数配列
317 if fha == nil then # nil の場合、自己参照によるケースと仮定
318 return desc_list
319 end
320 fha.each{ |fh|
321 fd = fh.get_declarator # fd: Decl (関数頭部からDeclarotorを得る)
322 if fd.is_function? then # fd が関数でなければ、すでにエラー
323 params = fd.get_type.get_paramlist.get_items
324 if params then
325 params.each{ |param|
326 t = param.get_type.get_original_type
327 while( t.kind_of? PtrType )
328 t = t.get_referto
329 end
330 # p "has_desc #{param.get_name} #{t}"
331 if t.kind_of? DescriptorType then
332 desc_list[t] = param
333 end
334 }
335 end
336 end
337 }
338 return desc_list
339 end
340
341 #=== Signature# 引数に Descriptor があるか?
342 def has_descriptor?
343 # p "has_desc #{@name}"
344 fha = get_function_head_array # 呼び口または受け口のシグニチャの関数配列
345 if fha == nil then # nil の場合、自己参照によるケースと仮定
346 return true
347 end
348 fha.each{ |fh|
349 fd = fh.get_declarator # fd: Decl (関数頭部からDeclarotorを得る)
350 if fd.is_function? then # fd が関数でなければ、すでにエラー
351 params = fd.get_type.get_paramlist.get_items
352 if params then
353 params.each{ |param|
354 t = param.get_type.get_original_type
355 while( t.kind_of? PtrType )
356 t = t.get_referto
357 end
358 # p "has_desc #{param.get_name} #{t}"
359 if t.kind_of? DescriptorType then
360 return true
361 end
362 }
363 end
364 end
365 }
366 return false
367 end
368
369 #=== Signature# コールバックか?
370 # 指定子 callback が指定されていれば true
371 def is_callback?
372 @b_callback
373 end
374
375 #=== Signature# 逸脱か?
376 # 指定子 deviate が指定されていれば true
377 def is_deviate?
378 @b_deviate
379 end
380
381 #=== Signature# 空か?
382 def is_empty?
383 @b_empty
384 end
385
386 #=== Signature# Push Pop Allocator が必要か?
387 # Transparent RPC の場合 oneway かつ in の配列(size_is, count_is, string のいずれかで修飾)がある
388 def need_PPAllocator?( b_opaque = false )
389 fha = get_function_head_array # 呼び口または受け口のシグニチャの関数配列
390 fha.each{ |fh|
391 fd = fh.get_declarator
392 if fd.get_type.need_PPAllocator?( b_opaque ) then
393 # p "#{fd.get_name} need_PPAllocator: true"
394 @b_need_PPAllocator = true
395 return true
396 end
397 # p "#{fd.get_name} need_PPAllocator: false"
398 }
399 return false
400 end
401
402 def show_tree( indent )
403 indent.times { print " " }
404 puts "Signature: name: #{@name} context: #{@context} deviate : #{@b_deviate} PPAllocator: #{@b_PPAllocator} #{self}"
405 (indent+1).times { print " " }
406 puts "namespace_path: #{@NamespacePath}"
407 (indent+1).times { print " " }
408 puts "function head list:"
409 @function_head_list.show_tree( indent + 2 )
410 end
411
412end
413
414class Celltype < NSBDNode # < Nestable
415# @name:: Symbol
416# @global_name:: Symbol
417# @name_list:: NamedList item: Decl (attribute, var), Port
418# @port:: Port[]
419# @attribute:: Decl[]
420# @var:: Decl[]
421# @require:: [[cp_name,Celltype|Cell,Port],...]
422# @factory_list:: Factory[]
423# @ct_factory_list:: Factory[] : celltype factory
424# @cell_list:: Cell[] : 定義のみ (V1.0.0.2 以降)
425# @singleton:: bool
426# @idx_is_id:: bool
427# @idx_is_id_act:: bool: actual value
428# @active:: bool
429# @b_reuse:: bool : reuse 指定されて import された(template 不要)
430# @generate:: [ Symbol, String, Plugin ] = [ PluginName, option, Plugin ] Plugin は生成後に追加される
431#
432# @n_attribute_ro:: int >= 0 none specified
433# @n_attribute_rw:: int >= 0 # of [rw] specified attributes (obsolete)
434# @n_attribute_omit : int >= 0 # of [omit] specified attributes
435# @n_var:: int >= 0
436# @n_var_size_is:: int >= 0 # of [size_is] specified vars # mikan count_is
437# @n_var_omit:: int >= 0 # of [omit] specified vars # mikan var の omit は有?
438# @n_var_init:: int >= 0 # of vars with initializer
439# @n_call_port:: int >= 0
440# @n_call_port_array:: int >= 0
441# @n_call_port_omitted_in_CB:: int >= 0 最適化で省略される呼び口
442# @n_entry_port:: int >= 0
443# @n_entry_port_array:: int >= 0
444# @n_entry_port_inline:: int >= 0
445# @n_cell_gen:: int >= 0 生成するセルの数.コード生成の頭で算出する.意味解析段階では参照不可
446# @id_base:: Integer : cell の ID の最小値(最大値は @id_base + @n_cell)
447#
448# @b_cp_optimized:: bool : 呼び口最適化実施
449# @plugin:: PluginObject このセルタイプがプラグインにより生成された CDL から生成された場合に有効。
450# generate の指定は @generate にプラグインが保持される
451#
452# @included_header:: Hash : include されたヘッダファイル
453# @domain_roots::Hash { DomainTypeName(Symbol) => [ Region ] } ドメインタイプ名と Region の配列 (optimize.rb で設定)
454# ルートリージョンはドメイン名が nil
455
456 include PluginModule
457
458 @@nest_stack_index = -1
459 @@nest_stack = []
460 @@current_object = nil
461 @@celltype_list = []
462
463 def self.push
464 @@nest_stack_index += 1
465 @@nest_stack[ @@nest_stack_index ] = @@current_object
466 @@current_object = nil
467 end
468
469 def self.pop
470 @@current_object = @@nest_stack[ @@nest_stack_index ]
471 @@nest_stack_index -= 1
472 if @@nest_stack_index < -1 then
473 raise "TooManyRestore"
474 end
475 end
476
477 def initialize( name )
478 super()
479 @@current_object = self
480 @name = name
481 if "#{Namespace.get_global_name}" != "" then
482 @global_name = :"#{Namespace.get_global_name}_#{@name}"
483 else
484 @global_name = name
485 end
486
487 @name_list = NamedList.new( nil, "symbol in celltype #{name}" )
488 @port = []
489 @attribute = []
490 @var = []
491 @require = []
492 @factory_list = []
493 @ct_factory_list = []
494 @cell_list = []
495 @singleton = false
496 @active = false
497 @generate = nil
498
499 @n_attribute_ro = 0
500 @n_attribute_rw = 0
501 @n_attribute_omit = 0
502 @n_var = 0
503 @n_var_omit = 0
504 @n_var_size_is = 0
505 @n_var_init = 0
506 @n_call_port = 0
507 @n_call_port_array = 0
508 @n_call_port_omitted_in_CB = 0
509 @n_entry_port = 0
510 @n_entry_port_array = 0
511 @n_entry_port_array_ns = 0
512 @n_entry_port_inline = 0
513 @n_cell_gen = 0
514
515 @b_cp_optimized = false
516
517 @plugin = Generator.get_plugin
518 # plugin の場合 PluginObject が返される
519 # 元の Generator から呼出された Generator の中でパースおよび意味チェックされている
520
521 # if @plugin then
522 # # plugin 生成されるセルタイプは再利用ではない #833 不具合修正
523 # @b_reuse = false
524 # else
525 @b_reuse = Generator.is_reuse?
526 # end
527
528 if $idx_is_id then
529 @idx_is_id = true
530 else
531 @idx_is_id = false
532 end
533 @idx_is_id_act = @idx_is_id
534
535 Namespace.new_celltype( self )
536 set_namespace_path # @NamespacePath の設定
537 set_specifier_list( Generator.get_statement_specifier )
538
539 if @singleton then
540 @idx_is_id_act = false
541 end
542
543 @included_header = {}
544 @domain_roots = {}
545 @@celltype_list << self
546 end
547
548 def get_name
549 @name
550 end
551
552 #== Celltype#ドメインルートを返す
553 # @domain_roots の説明を参照
554 def get_domain_roots
555 @domain_roots
556 end
557
558 # Celltype# end_of_parse
559 def end_of_parse
560 # 属性・変数のチェック
561 check_attribute
562
563 # アロケータ呼び口を内部生成
564 generate_allocator_port
565
566 # リレーアロケータ、内部アロケータの設定
567 @port.each { |p|
568 p.set_allocator_instance
569 }
570
571 if @n_entry_port == 0 && @active == false && @factory_list.length == 0 &&
572 ( @singleton && @ct_factory_list.length == 0 || ! @singleton )then
573 cdl_warning( "W1002 $1: non-active celltype has no entry port & factory" , @name )
574 end
575
576 if @generate then
577 celltype_plugin
578 end
579
580 @@current_object = nil
581 end
582
583 def self.new_port( port )
584 @@current_object.new_port( port )
585 end
586
587 def new_port( port )
588 port.set_owner self
589 @port << port
590 @name_list.add_item( port )
591 if port.get_port_type == :CALL then
592 @n_call_port += 1
593 @n_call_port_array += 1 if port.get_array_size != nil
594 else
595 @n_entry_port += 1
596 @n_entry_port_array += 1 if port.get_array_size != nil
597 @n_entry_port_array_ns += 1 if port.get_array_size == "[]"
598 @n_entry_port_inline += 1 if port.is_inline?
599 end
600 port.set_celltype self
601 end
602
603 def get_port_list
604 @port
605 end
606
607 def self.new_attribute( attribute )
608 @@current_object.new_attribute( attribute )
609 end
610
611 #=== Celltype# new_attribute for Celltype
612 #attribute:: [Decl]
613 def new_attribute( attribute )
614 @attribute += attribute
615 attribute.each { |a|
616 a.set_owner self
617 @name_list.add_item( a )
618 if( a.is_omit? )then
619 @n_attribute_omit += 1
620 elsif( a.is_rw? )then
621 @n_attribute_rw += 1
622 else
623 @n_attribute_ro += 1
624 end
625 if a.get_initializer then
626 # 登録後にチェックしても問題ない(attr を参照できないので、自己参照しない)
627 a.get_type.check_init( @locale, a.get_identifier, a.get_initializer, :ATTRIBUTE )
628 end
629 }
630 end
631
632 #=== Celltype# celltype の attribute/var のチェック
633 # STAGE: S
634 #
635 # このメソッドは celltype のパースが完了した時点で呼出される.
636 def check_attribute
637 # attribute の size_is 指定が妥当かチェック
638 (@attribute+@var).each{ |a|
639 if a.get_size_is then
640 if ! a.get_type.kind_of?( PtrType ) then
641 # size_is がポインタ型以外に指定された
642 cdl_error( "S1011 $1: size_is specified for non-pointer type" , a.get_identifier )
643 else
644
645 # 参照する変数が存在し、計算可能な型かチェックする
646 size = a.get_size_is.eval_const( @name_list ) # C_EXP の可能性あり
647 init = a.get_initializer
648 if init then
649 if ! init.instance_of?( Array ) then
650 # 初期化子が配列ではない
651 cdl_error( "S1012 $1: unsuitable initializer, need array initializer" , a.get_identifier )
652 elsif size.kind_of?( Integer ) && size < init.length then
653 # size_is 指定された個数よりも初期化子の配列要素が多い
654 cdl_error( "S1013 $1: too many initializer, $2 for $3" , a.get_identifier, init.length, size )
655 # elsif a.get_size_is.eval_const( nil ) == nil # C_EXP の可能性あり
656 end
657
658 end
659 end
660 else
661 if a.get_type.kind_of?( PtrType ) then
662 if a.get_initializer.instance_of?( Array ) ||
663 ( a.get_initializer.instance_of?( Expression ) &&
664 a.get_initializer.eval_const2(@name_list).instance_of?( Array ) ) then
665 # size_is 指定されていないポインタが Array で初期化されていたら、エラー
666 cdl_error( "S1159 $1: non-size_is pointer cannot be initialized with array initializer" , a.get_identifier )
667 end
668 end
669 end
670 }
671 end
672
673 def get_attribute_list
674 @attribute
675 end
676
677 #=== Celltype# アロケータ呼び口を生成
678 # send, receive 引数のアロケータを呼出すための呼び口を生成
679 def generate_allocator_port
680 @port.each { |port|
681 # ポートのすべてのパラメータを辿る
682 port.each_param { |port, fd, par|
683 case par.get_direction # 引数の方向指定子 (in, out, inout, send, receive )
684 when :SEND, :RECEIVE
685 if par.get_allocator then
686 cp_name = :"#{port.get_name}_#{fd.get_name}_#{par.get_name}" # アロケータ呼び口の名前
687 # ポート名 関数名 パラメータ名
688 # alloc_sig_path = [ par.get_allocator.get_name ] # mikan Namespace アロケータ呼び口のシグニチャ #1
689 alloc_sig_path = par.get_allocator.get_namespace_path
690 array_size = port.get_array_size # 呼び口または受け口配列のサイズ
691 created_port = Port.new( cp_name, alloc_sig_path, :CALL, array_size ) # 呼び口を生成
692 created_port.set_allocator_port( port, fd, par )
693 if port.is_optional? then
694 created_port.set_optional
695 end
696 if port.is_omit? then
697 created_port.set_omit
698 end
699 new_port( created_port ) # セルタイプに新しい呼び口を追加
700 # else
701 # already error "not found or not signature" in class ParamDecl
702 end
703 end
704 }
705 }
706 end
707
708 def get_name_list
709 @name_list
710 end
711
712 def self.new_var( var )
713 @@current_object.new_var( var )
714 end
715
716 #=== Celltype# 新しい内部変数
717 #var:: [Decl]
718 def new_var( var )
719 @var += var
720 var.each { |i| # i: Decl
721 i.set_owner self
722 if i.is_omit? then
723 @n_var_omit += 1
724 else
725 @n_var += 1
726 end
727 @name_list.add_item( i )
728
729 # size_is 指定された配列? mikan count_is
730 if i.get_size_is then
731 @n_var_size_is += 1
732 end
733
734 if i.get_initializer then
735 i.get_type.check_init( @locale, i.get_identifier, i.get_initializer, :VAR, @name_list )
736 @n_var_init += 1
737 end
738 }
739 end
740
741 def get_var_list
742 @var
743 end
744
745 #=== Celltype# celltype の指定子を設定
746 def set_specifier_list( spec_list )
747 return if spec_list == nil
748
749 spec_list.each { |s|
750 case s[0]
751 when :SINGLETON
752 @singleton = true
753 when :IDX_IS_ID
754 @idx_is_id = true
755 when :ACTIVE
756 @active = true
757 when :GENERATE
758 if @generate then
759 cdl_error( "S1014 generate specifier duplicate" )
760 end
761 @generate = [ s[1], s[2] ] # [ PluginName, "option" ]
762 else
763 cdl_error( "S1015 $1 cannot be specified for composite" , s[0] )
764 end
765 }
766 end
767
768 #
769 def self.new_require( ct_or_cell_nsp, ep_name, cp_name = nil )
770 @@current_object.new_require( ct_or_cell_nsp, ep_name.to_sym, cp_name )
771 end
772
773 def new_require( ct_or_cell_nsp, ep_name, cp_name )
774 # Require: set_owner するものがない
775 obj = Namespace.find( ct_or_cell_nsp ) #1
776 if obj.instance_of? Celltype then
777 # Celltype 名で指定
778 ct = obj
779 elsif obj.instance_of? Cell then
780 # Cell 名で指定
781 ct = obj.get_celltype
782 elsif obj == nil then
783 cdl_error( "S1016 $1 not found" , ct_or_cell_nsp.get_path_str )
784 return
785 else
786 cdl_error( "S1017 $1 : neither celltype nor cell" , ct_or_cell_nsp.get_path_str )
787 return
788 end
789
790 if( ! ct.is_singleton? ) then
791 # シングルトンではない
792 cdl_error( "S1018 $1 : not singleton cell" , obj.get_name )
793 end
794
795 # 受け口を探す
796 obj2 = ct.find( ep_name )
797 if( ( ! obj2.instance_of? Port ) || obj2.get_port_type != :ENTRY ) then
798 cdl_error( "S1019 \'$1\' : not entry port" , ep_name )
799 return
800 elsif obj2.get_array_size then
801 cdl_error( "S1020 \'$1\' : required port cannot be array" , ep_name )
802 return
803 end
804
805 if obj2.get_signature == nil then
806 # signature が未定義:既にエラー
807 return
808 end
809
810 require_call_port_prefix = :_require_call_port
811 if cp_name == nil then
812 # 関数名重複チェック
813 @require.each{ |req|
814 unless req[0].to_s =~ /^#{require_call_port_prefix}/ then
815 next # 名前ありの require は関数名重複チェックしない
816 end
817 port = req[2]
818 if port.get_signature == obj2.get_signature then
819 # 同じ signature (すべて同じ関数名を持つ)個別に出すのではなく、まとめてエラーとする
820 cdl_error( "S1021 $1 : require cannot have same signature with \'$2\'" , obj2.get_name, port.get_name )
821 next
822 end
823 port.get_signature.get_function_head_array.each{ |f|
824 # mikan ここは、namedList からの検索にならないの?(効率が悪い)
825 obj2.get_signature.get_function_head_array.each{ |f2|
826 if( f.get_name == f2.get_name ) then
827 cdl_error( "S1022 $1.$2 : \'$3\' conflict function name in $4.$5" , obj.get_name, obj2.get_name, f.get_name, req[1].get_name, req[2].get_name )
828 end
829 }
830 }
831 }
832 end
833
834 if cp_name == nil then
835 b_has_name = false
836 cp_name = :"#{require_call_port_prefix}_#{ct.get_name}_#{obj2.get_name}"
837 else
838 b_has_name = true
839 end
840 # require を追加
841 @require << [ cp_name, obj, obj2 ] # [ lhs:cp_name, rhs:Celltype, rhs:Port ]
842
843 # require port を追加 (呼び口として追加する。ただし require をセットしておく)
844 port = Port.new( cp_name, obj2.get_signature.get_namespace_path, :CALL )
845 port.set_require( b_has_name )
846 self.new_port port
847 end
848
849 def self.new_factory( factory )
850 @@current_object.new_factory( factory )
851 end
852
853 def new_factory( factory )
854 factory.set_owner self
855 if factory.get_f_celltype then
856 @ct_factory_list << factory
857 else
858 @factory_list << factory
859 end
860
861 factory.check_arg( self )
862
863 end
864
865 #=== Celltype# セルタイププラグイン (generate 指定子)
866 def celltype_plugin
867
868 load_plugin( @generate[0], CelltypePlugin )
869
870 plugin_name = @generate[0]
871 option = @generate[1]
872 plugin_object = nil
873 eval_str = "plugin_object = #{plugin_name}.new( self, option )"
874 if $verbose then
875 print "new celltype : #{eval_str}\n"
876 end
877
878 begin
879 eval( eval_str ) # plugin を生成
880 plugin_object.set_locale @locale
881 @generate[ 2 ] = plugin_object
882 generate_and_parse plugin_object
883 rescue Exception => evar
884 cdl_error( "S1023 $1: fail to new" , plugin_name )
885 print "eval( #{eval_str} )\n"
886
887 print_exception( evar )
888 end
889 end
890
891 #=== Celltype# celltype に新しい cell を追加
892 #cell:: Cell
893 # 新しいセルをセルタイプに追加.
894 # セルの構文解釈の最後でこのメソドを呼出される.
895 # シングルトンセルが同じ linkunit に複数ないかチェック
896 def new_cell( cell )
897 # Celltype では Cell の set_owner しない
898 # シングルトンで、プロトタイプ宣言でない場合、コード生成対象リージョンの場合
899 if @singleton then
900 @cell_list.each{ |c|
901 if c.get_region.get_link_root == cell.get_region.get_link_root then
902 cdl_error( "S1024 $1: multiple cell for singleton celltype" , @name )
903 end
904 }
905 end
906 @cell_list << cell
907 if @plugin then
908 @plugin.new_cell cell
909 end
910 end
911
912 #=== Celltype# セルタイプは INIB を持つか?
913 # セルタイプが INIB を持つかどうかを判定する
914 # $rom == false のとき: INIB を持たない. (すべては CB に置かれる)
915 # $rom == true のとき、INIB に置かれるものが一つでも存在すれば INIB を持つ
916 # INIB に置かれるものは
917 # attribute (omit のものは除く.現仕様では rw のものはない)
918 # size_is を伴う var
919 # 呼び口(ただし、最適化で不要となるものは除く)
920 def has_INIB?
921# print "name=#{@name} @n_attribute_ro=#{@n_attribute_ro} @n_var_size_is=#{@n_var_size_is} @n_call_port=#{@n_call_port} @n_call_port_omitted_in_CB=#{@n_call_port_omitted_in_CB} @n_entry_port_array_ns=#{@n_entry_port_array_ns}\n"
922 return $rom && (@n_attribute_ro > 0 || @n_var_size_is > 0 || ( @n_call_port - @n_call_port_omitted_in_CB ) > 0 || @n_entry_port_array_ns > 0)
923# return $rom && (@n_attribute_ro > 0 || ( @n_call_port - @n_call_port_omitted_in_CB ) > 0)
924 end
925
926 #=== Celltype# セルタイプは CB を持つか?
927 # $rom == true のとき、いかのものが置かれる.それらの一つでも存在すれば CB を持つ
928 # size_is が指定されていない var
929 # rw 指定された attribute (現仕様では存在しない)
930 # $rom == false のとき、いかのものが置かれる.それらの一つでも存在すれば CB を持つ
931 # attribute
932 # var
933 # 呼び口(ただし、最適化で不要となるものは除く)
934 def has_CB?
935 if $rom then
936 return @n_attribute_rw > 0 || (@n_var-@n_var_size_is) > 0
937 # return @n_attribute_rw > 0 || @n_var > 0
938 else
939 return @n_attribute_rw > 0 || @n_attribute_ro > 0 || @n_var > 0 || (@n_call_port-@n_call_port_omitted_in_CB) > 0 || @n_entry_port_array_ns > 0
940 end
941 end
942
943 #=== Celltype# SET_CB_INIB_POINTER, INITIALIZE_CB が必要か
944 def need_CB_initializer?
945 @n_var_init > 0 || has_CB?
946 end
947
948 #=== Celltype# 逆require の結合を生成する
949 def create_reverse_require_join cell
950 @port.each{ |p|
951 p.create_reverse_require_join cell
952 }
953 end
954
955 #=== Celltype# singleton セルを得る
956 #region:: Region : singleton を探す Region
957 # 距離が最も近いものを返す
958 # mikan 本当は region の範囲の singleton を探す必要がある
959 def get_singleton_cell region
960 cell = nil
961 dist = 999999999 # mikan 制限値(これは十分すぎるほどデカイが)
962 # require: celltype で指定
963 @cell_list.each{ |c|
964 # 到達可能で最も近いセルを探す(複数の singleton があるかもしれない)
965 d = region.distance( c.get_region )
966 #debug
967 dbgPrint "distance #{d} from #{region.get_name} to #{c.get_name} in #{c.get_region.get_name}\n"
968 # print "DOMAIN: distance #{d} from #{region.get_name} to #{c.get_name} in #{c.get_region.get_name}\n"
969 if d != nil then
970 if d < dist then
971 cell = c
972 dist = d
973 end
974 end
975 }
976 return cell
977 end
978
979 def find( name )
980 @name_list.get_item( name )
981 end
982
983 #=== Celltype# セルタイププラグインを得る
984 def get_celltype_plugin
985 if @generate then
986 return @generate[2]
987 end
988 end
989
990 def get_global_name
991 @global_name
992 end
993
994 def is_singleton?
995 @singleton
996 end
997
998 def is_active?
999 @active
1000 end
1001
1002 #=== Celltype# アクティブではないか
1003 # このメソッドでは active の他に factory (singleton においては FACTORYを含む)がなければ inactive とする
1004 def is_inactive?
1005 if @active == false && @factory_list.length == 0 &&
1006 ( @singleton && @ct_factory_list.length == 0 || ! @singleton )then
1007 return true
1008 end
1009 return false
1010 end
1011
1012 def get_id_base
1013 @id_base
1014 end
1015
1016 def get_plugin
1017 @plugin
1018 end
1019
1020 def get_require
1021 @require
1022 end
1023
1024 #=== Celltype# コード生成する必要があるか判定
1025 # セルの個数が 0 ならセルタイプコードは生成不要
1026 def need_generate?
1027 @n_cell_gen > 0
1028 end
1029
1030 #=== Celltype# require 呼び口の結合を行う
1031 # STAGE: S
1032 # セルタイプの require 呼び口について、結合を行う
1033 # セルが生成されないかチェックを行う
1034 def set_require_join
1035 @require.each{ |req|
1036 cp_name = req[0]
1037 cell_or_ct = req[1]
1038 port = req[2]
1039 @cell_list.each{ |c|
1040 c.set_require_join( cp_name, cell_or_ct, port )
1041 }
1042 }
1043 end
1044
1045 def get_cell_list
1046 @cell_list
1047 end
1048
1049 #=== Celltype# inline 受け口しかないか?
1050 # 受け口が無い場合、すべての受け口が inline とはしない
1051 def is_all_entry_inline?
1052 @n_entry_port == @n_entry_port_inline && @n_entry_port > 0
1053 end
1054
1055 #=== Celltype.get_celltype_list
1056 def self.get_celltype_list
1057 @@celltype_list
1058 end
1059
1060 def show_tree( indent )
1061 indent.times { print " " }
1062 puts "Celltype: name=#{@name} global_name=#{@global_name}"
1063 (indent+1).times { print " " }
1064 puts "active=#{@active}, singleton=#{@singleton}, idx_is_id=#{@idx_is_id} plugin=#{@plugin.class} reuse=#{@b_reuse}"
1065 (indent+1).times { print " " }
1066 puts "namespace_path: #{@NamespacePath}"
1067 (indent+1).times { print " " }
1068 puts "port:"
1069 @port.each { |i| i.show_tree( indent + 2 ) }
1070 (indent+1).times { print " " }
1071 puts "attribute:"
1072 @attribute.each { |i| i.show_tree( indent + 2 ) }
1073 (indent+1).times { print " " }
1074 puts "var:"
1075 @var.each { |i| i.show_tree( indent + 2 ) }
1076# (indent+1).times { print " " }
1077# puts "require:" mikan
1078# @require.each { |i| i.show_tree( indent + 2 ) }
1079 (indent+1).times { print " " }
1080 puts "factory:"
1081 @factory_list.each { |i| i.show_tree( indent + 2 ) }
1082 (indent+1).times { print " " }
1083 puts "@n_attribute_ro #{@n_attribute_ro}"
1084 (indent+1).times { print " " }
1085 puts "@n_attribute_rw #{@n_attribute_rw}"
1086# @n_attribute_omit : int >= 0 # of [omit] specified cells
1087# @n_var:: int >= 0
1088# @n_var_size_is:: int >= 0 # of [size_is] specified cells # mikan count_is
1089# @n_var_omit:: int >= 0 # of [omit] specified cells # mikan var の omit は有?
1090# @n_call_port:: int >= 0
1091# @n_call_port_array:: int >= 0
1092# @n_call_port_omitted_in_CB:: int >= 0 最適化で省略される呼び口
1093# @n_entry_port:: int >= 0
1094# @n_entry_port_array:: int >= 0
1095 (indent+1).times { print " " }
1096 puts "@n_entry_port_inline #{@n_entry_port_inline}"
1097# @n_cell:: int >= 0 コード生成の頭で算出する.意味解析段階では参照不可
1098# @id_base:: Integer : cell の ID の最小値(最大値は @id_base + @n_cell)
1099
1100 end
1101end
1102
1103class Cell < NSBDNode # < Nestable
1104# @name:: Symbol : composite celltype の内側のインスタンスでは外のセル
1105# @global_name:: Symbol : C で使える名前(namespace を含む)
1106# @local_name:: str : cell celltype name { ... } の name
1107# @celltype:: Celltype | CompositeCelltype
1108# @join_list:: NamedList
1109# @reverse_join_list:: NamedList
1110# @b_defined:: definition flag (false if only prototype )
1111# @b_prototype:: bool: prototype specified in current parsing cell. (@b_defined is used to determine whether definition done)
1112# @b_duplicate:: bool: definition duplicate
1113# @b_checked:: bool: set_definition_join が済んでいる場合 true
1114# @require_joined_list:: {cp_name=>true}: set_require_join が済んでいる呼び口は true
1115# @f_ref:: refercenced from others
1116# @entry_array_max_subscript:: { @port=>Integer } : 受け口配列の配列添数の最大値(添数無し受け口配列対応)
1117# @plugin:: Plugin: avialble if cell is generated by plugin generated cdl code.
1118# @referenced_port_list:: { Port => Integer } : 受け口の参照数
1119# すべての意味解析(through, composite展開)が終わった後に設定する
1120# 逆require ポートに対して複数の結合がないかチェックする
1121# @generate:: [ Symbol, String, Plugin ] = [ PluginName, option, Plugin ] Plugin は生成後に追加される
1122#
1123# composite のためインスタンス変数
1124# @in_composite:: bool : true if in composite celltype
1125# @compositecelltypejoin_list:: NamedList : item= CompositeCelltypeJoin ( if @in_composite )
1126# @f_cloned:: bool : true if cloned (instantiate of composite consist cell)
1127# @my_clone:: Cell : Composite cell で in_composite = true の場合のみ有効(直前の clone を一時記憶)
1128# @cell_list:: Cell[local_name] : Composite cell で clone した後のリスト cell_list
1129# @cell_list2:: [ Cell ] : Composite cell で clone した後のリスト cell_list
1130# @cell_list2 は composite 内での出現順
1131#
1132# region のためのインスタンス変数
1133# @region:: Region (属するregion)
1134#
1135# allocator のためのインスタンス変数
1136# @alloc_list:: [ [ NORMAL_ALLOC, ep_name, func_name, param_name, expr ], ... ]
1137# 受け口側のアロケータへの結合を記憶。以下のメソッドで追加される
1138# set_specifier … cell 定義時にアロケータ指定されている場合
1139# create_relay_allocator_join … リレーアロケータの場合
1140#
1141# ID のためのインスタンス変数(optimize.rb にて設定)
1142# @id:: Integer : コード生成直前に設定 (プロトタイプ宣言の場合は -1 のまま放置)
1143# @id_specified::Integer : 指定された id
1144# @restrict_list::{ entry_name => { func_name, [ region_name, ... ] } }
1145
1146=begin
1147# Cell クラスは、以下のものを扱う
1148# 1)普通のセル
1149# 2)composite セルタイプのセル
1150# 3)composite セルタイプの内側のセル (@in_composite) # composite の内側の composite セルタイプのセルもある
1151#
1152# 2) は CellOfComposite クラスとして分けたほうがよいかもしれない
1153# expand (composite セルの展開) は CellOfComposite にのみ必要なメソッドである
1154# get_real_cell, get_real_port など @celltype.instance_of?( CompositeCelltype ) の判定がなくすっきりする
1155# ただ、分離しても、メンテナンスすべき範囲が切り離されてしまい、忘れやすくなる問題とのトレードオフかも
1156#
1157# 3) は CellInCompoiste クラスとして分けたほうがよいかもしれない
1158# @in_composite で判定している処理を切り離せる (上記 2) よりも分離は容易ではない)
1159# clone_for_composite は CellInCompoiste にのみ必要なメソッドである
1160# ただし、clone 後に Cell, CellOfComposite に変化する必要があるので、clone ではなく new する実装に変更する必要がある
1161#
1162=end
1163
1164 include PluginModule
1165
1166 @@nest_stack_index = -1
1167 @@nest_stack = []
1168 @@current_object = nil
1169
1170 # 定義されたすべてのセル(出現順. namespace に影響されない)
1171 @@cell_list = [] # composite の内部のセルを含まない
1172 @@cell_list2 = [] # composite の内部のセルを含む (元のセルを含む)
1173 # 意味解析後 make_cell_list2 にて設定される
1174
1175 def self.push
1176 @@nest_stack_index += 1
1177 @@nest_stack[ @@nest_stack_index ] = @@current_object
1178 @@current_object = nil
1179 end
1180
1181 def self.pop
1182 @@current_object = @@nest_stack[ @@nest_stack_index ]
1183 @@nest_stack_index -= 1
1184 if @@nest_stack_index < -1 then
1185 raise "TooManyRestore"
1186 end
1187 end
1188
1189
1190 # composite で clone されたもの(子孫まで含む)
1191 # Join.change_rhs_port にて CompoisteCelltype 内の Join の結合先を変更する際に使用
1192 @@cloned_cell_list = {}
1193 ### mikan BUG @@cloned_cell_list は composite の階層ごとに記憶していないため、同じ名前が内部に現れると、うまく動作しない
1194 # change_rhs_port の実装は、こんな回りくどいことをする必要はなかった。右辺に現れるセル名には、composite のセル名を前につなげるだけでよかった
1195
1196 def initialize( ct_path, in_composite = false )
1197 super()
1198 @region = Region.get_current
1199
1200 # celltype のplugin/存在をチェック
1201 object = Namespace.find( ct_path ) #1
1202 if object == nil then
1203 # mikan celltype の名前が不完全 "::ct1ct2" になる
1204 cdl_error( "S1027 \'$1\' celltype not found" , ct_path.get_path_str )
1205 elsif ! object.instance_of?( Celltype ) && ! object.instance_of?( CompositeCelltype ) then
1206 # mikan celltype の名前が不完全
1207 cdl_error( "S1028 \'$1\' not celltype" , ct_path.get_path_str )
1208 else
1209 @celltype = object
1210 end
1211
1212 @in_composite = in_composite
1213 if @in_composite then
1214 @compositecelltypejoin_list = NamedList.new( nil, "in cell '#{@name}'" )
1215 @plugin = nil
1216 else
1217 @compositecelltypejoin_list = nil
1218 @plugin = Generator.get_plugin
1219 end
1220
1221 @@current_object = self
1222 @b_defined = false
1223 @b_prototype = false
1224 @f_ref = false
1225 @f_cloned = false
1226 @alloc_list = []
1227 @id = -1
1228 @id_specified = nil
1229 @b_duplicate = false
1230 @b_checked = false
1231 @require_joined_list = {}
1232 @entry_array_max_subscript = {}
1233 @referenced_port_list = {}
1234 @restrict_list = {}
1235
1236 @cell_list = {}
1237 @cell_list2 = []
1238 end
1239
1240 def self.set_name( name )
1241 @@current_object.set_name( name )
1242 end
1243
1244 def set_name( name )
1245
1246 @name = name
1247 @local_name = name
1248 if "#{Namespace.get_global_name}" != "" then
1249 @global_name = :"#{Namespace.get_global_name}_#{name}"
1250 else
1251 @global_name = name
1252 end
1253
1254 # この時点ではプロトタイプか、定義か分らないが、自己参照のために登録
1255 # set_f_def で再度登録しなおす
1256 # Celltype への登録は、end_of_parse で行う
1257 if @in_composite then
1258 cell_prev = CompositeCelltype.find( name )
1259 if cell_prev == nil then
1260 CompositeCelltype.new_cell( self )
1261 end
1262 else
1263 # cell_prev = Namespace.find( [ name ] ) # 親まで捜しにいく
1264 cell_prev = Namespace.get_current.find( name )
1265 if cell_prev == nil then
1266 Namespace.new_cell( self )
1267 set_namespace_path # @NamespacePath の設定
1268 end
1269 end
1270
1271 if cell_prev then
1272 if ! cell_prev.instance_of?( Cell ) then
1273 cdl_error( "S1029 $1 mismatch with previous one" , name )
1274 # celltype が一致しているか ?
1275 elsif get_celltype != cell_prev.get_celltype then
1276 cdl_error( "S1030 $1: celltype mismatch with previous one" , name )
1277 else
1278 # region が一致しているか?
1279 if ! cell_prev.get_region.equal? get_region then
1280 cdl_error( "S1031 $1 region \'$2\' mismatch with previous one \'$3\'" , name, @region.get_name, cell_prev.get_region.get_name )
1281 end
1282
1283 @@current_object = cell_prev
1284 # この時点では、まだプロトタイプ宣言か定義か分らない
1285 # 以前が定義であって、今回も定義の場合、重複エラーである
1286 end
1287 end
1288
1289 @join_list = NamedList.new( nil, "in cell '#{@name}'" )
1290 @reverse_join_list = nil
1291
1292 # debug
1293 dbgPrint "Cell new_cell: #{@global_name} #{@in_composite} #{self}\n"
1294
1295 # 内部アロケータを @alloc_list に追加
1296 if @celltype.instance_of? CompositeCelltype then
1297 @celltype.get_internal_allocator_list.each{ |cell, cp_internal_name, port_name, fd_name, par_name, ext_alloc_ent|
1298 nsp = NamespacePath.new( @name, false )
1299 rhs = Expression.new( [:OP_DOT, [:IDENTIFIER, nsp], Token.new( ext_alloc_ent.to_s.to_sym, nil, nil, nil ) ] ) #1 構文解析段階なので locale 不要
1300
1301 @alloc_list << [:NORMAL_ALLOC,port_name,nil,fd_name,par_name,rhs]
1302# print "add alloc_list: #{port_name}.#{fd_name}.#{par_name}=#{rhs.to_s}\n"
1303 }
1304 end
1305 end
1306
1307 #=== Cell# cell の定義
1308 # 本体(join)の定義の直前に呼び出される
1309 def self.new_def
1310 @@current_object.new_def
1311 end
1312
1313 #=== Cell# cell の定義
1314 # 本体(join)の定義の直前に呼び出される
1315 # このメソッドは cell tCelltype Cell { }; '{', '}' の部分がある場合に呼出される
1316 def new_def
1317 set_specifier_list( Generator.get_statement_specifier )
1318
1319 # prototype 指定子ないか
1320 if ! @b_prototype then
1321 # 二重定義のチェック
1322 if @b_defined == true then
1323 cdl_error( "S1032 $1: duplicate cell" , @name )
1324 dbgPrint "previous: #{@prev_locale[0]}: line #{@prev_locale[1]} '#{@name}' defined here\n"
1325
1326 # セルの重複定義エラーの処置
1327 # 前の定義は捨てる
1328 @join_list = NamedList.new( nil, "in cell '#{@name}'" )
1329 end
1330
1331 @b_defined = true
1332 @prev_locale = @locale
1333 end
1334 end
1335
1336 def self.new_join( join, b_regular = false )
1337 @@current_object.new_join( join, b_regular )
1338 end
1339
1340 #=== Cell# 新しい結合をチェック
1341 # STAGE: P
1342 #
1343 #join:: Join : 新しい結合
1344 #b_regular:: bool : 通常の場所 (bnf.y.rb)からならば true, それ以外(allocator, require) では false
1345 def new_join( join, b_regular = false )
1346 join.set_owner self
1347
1348 # composite の新文法対応.
1349 # composite の中のセルで、attribute の定義である場合
1350 # cell 内の attr_ext = composite.attr; 構文を処理
1351 if @in_composite then
1352 if @celltype then
1353 if @celltype.find(join.get_name).instance_of?( Decl ) then # mikan a::b で指定されていたものがエラーにならないかも
1354 rhs = join.get_rhs
1355 if rhs.instance_of? Expression then
1356 ele = rhs.get_elements
1357 if( ele[0]==:IDENTIFIER )then # attr = attr_ext (右辺単項)か? #1
1358 if( CompositeCelltype.has_attribute?(ele[1].get_name ) )then # mikan a::b.ePort がエラーにならないかも
1359 ident = ele[1].get_name # 右辺は attribute.
1360 else
1361 # 右辺は attribute にないのであれば、定数のはず
1362 # 定数は下へ渡す (cell の join にする)
1363 ident = nil
1364 end
1365 else
1366 if join.get_rhs.eval_const2(nil) == nil then # 定数式ではないか?
1367 # 右辺が、単一のシンボルでない場合、現状は扱えない
1368 cdl_error( "S1033 rhs expression is not supported. Only attribute is permitted on current version." )
1369 return
1370 else
1371 # 定数は下へ渡す (cell の join にする)
1372 ident = nil
1373 end
1374 end
1375
1376 if ident then
1377 # attr = attr; のような参照はエラー (a = composite.a とする必要がある)
1378 if @celltype.find( ident ) then
1379 cdl_error( "S1034 $1 : cannot refer to $2\'s attribute here. Use \'composite.$3\' to refer to composite celltype\'s" , ident, @celltype.get_name, ident )
1380 end
1381 end
1382 elsif rhs.instance_of? Array then
1383 if rhs[0] == :COMPOSITE then # 右辺は composite.attr の形式
1384 ident = rhs[1].to_sym
1385 else
1386 ident = nil # 右辺は { 10, -10 } の形式
1387 end
1388 else
1389 ident = nil # 右辺は C_EXP の形式
1390 end
1391
1392 # ident が見つかった(右辺は単一の ident)
1393 if ident then
1394 # composite の旧文法の構文処理へ渡す.セル外の attr_ext = Cell.attr; 構文の処理に渡す
1395 # export_name, internal_cell_name, internal_cell_elem_name
1396 decl = CompositeCelltype.new_join( ident, @name, join.get_name, :ATTRIBUTE ) # mikan a::b.ePort がエラーにならないかも
1397 if ! decl.instance_of? Decl then
1398 return
1399 end
1400 ini = decl.get_initializer
1401 if ini == nil then
1402 return
1403 end
1404 # 以下の旧文法実装に渡す.
1405 # 旧文法では cell に初期値を与えることで、composite で属性の初期値を指定することができた
1406 # attribute で指定された初期値を cell の属性として処理させる
1407 join.change_rhs( ini )
1408 else
1409 # ident がない.定数式
1410 end
1411 else
1412 # celltype の属性として、この join の名前がない
1413 # 以下の join.set_definition の中でエラーとなる
1414 end
1415 else
1416 return # celltype がない.すでにエラー
1417 end
1418 elsif join.get_rhs.instance_of? Array then
1419 rhs = join.get_rhs
1420 if rhs[0] == :COMPOSITE then
1421 # composite の中でないのに attr = composite.attr が使われた
1422 cdl_error( "S1035 composite : cannot specify out of composite celltype definition" )
1423 return
1424 end
1425 end
1426
1427 # 以下 composite 文法変更前からある処理
1428
1429 # 既に左辺が同じ名前の初期化が存在するか?
1430 j = @join_list.get_item( join.get_name ) # mikan NamespacePath がパスを持っている
1431 if j.instance_of? Join then # mikan ここでは j が Join or Nil 以外は、ないはず
1432
1433 # debug
1434 dbgPrint "add_array_member: #{@name} port: #{j.get_port_name} rhs: #{j.get_rhs}, #{join.get_port_name} #{join.get_rhs}\n"
1435 # 呼び口配列(であると仮定して)要素を追加
1436 j.add_array_member join
1437
1438 else
1439 # join
1440 @join_list.add_item( join )
1441 end
1442
1443 # if get_owner then # error S1030 発生時 get_owner が見つからなくて例外になる
1444 # dbgPrint "Cell#new_join: #{get_owner.get_name}.#{@name}\n"
1445 # else
1446 # dbgPrint "Cell#new_join: \"owner not fund\".#{@name}\n"
1447 # end
1448 if ! @in_composite then
1449 if join.get_cell
1450 dbgPrint "new_join: #{@name} #{@region.get_name} => #{join.get_cell.get_name} #{join.get_cell.get_region.get_path_string}\n"
1451 end
1452# p "region: generate? #{@region.is_generate?}"
1453 end
1454
1455 end
1456
1457 #=== Cell.新しい逆結合
1458 def self.new_reverse_join( reverse_join )
1459 @@current_object.new_reverse_join( reverse_join )
1460 end
1461
1462 #=== Cell#新しい逆結合
1463 def new_reverse_join( reverse_join )
1464 dbgPrint( "new_reverse_join name=#{reverse_join.get_name}\n")
1465 b_cb = false
1466 if @celltype then
1467 ep_name = reverse_join.get_name
1468 port = @celltype.find ep_name
1469 if port && port.get_signature
1470 if port.get_signature.is_callback? then
1471 b_cb = true
1472 end
1473 end
1474 end
1475 if ! @b_prototype && ! b_cb then
1476 cdl_error( "S9999 '$1': reverse join can be used in prototype cell, or with callback signature", @name )
1477 end
1478 if @reverse_join_list == nil then
1479# @reverse_join_list = NamedList.new( reverse_join, "in cell '#{@name}'" )
1480 @reverse_join_list = [ reverse_join ]
1481 else
1482# @reverse_join_list.add_item( reverse_join )
1483 @reverse_join_list << reverse_join
1484 end
1485 end
1486
1487 #=== Cell#逆結合から結合を生成
1488 # STAGE: S
1489 def create_reverse_join
1490 if @b_checked then
1491 return
1492 end
1493
1494 if @reverse_join_list then
1495# @reverse_join_list.get_items.each{ |rj|
1496 @reverse_join_list.each{ |rj|
1497 # 逆結合の情報を得る
1498 ep_name = rj.get_name
1499 ep_subscript, cp_cell_nsp, cp_name, cp_subscript = rj.get_rhs_cell_and_port
1500
1501 # 呼び口側のセルと、そのセルタイプ
1502 cell = Namespace.find cp_cell_nsp
1503 if ! cell.instance_of? Cell then
1504 cdl_error( "S9999 '$1': not cell for reverse join", cp_cell_nsp.get_path_str )
1505 next
1506 end
1507 ct = cell.get_celltype
1508 if ct == nil then
1509 next
1510 end
1511
1512 ep_cell_nsp = get_namespace_path
1513 ep_subscript_val = ep_subscript ? ep_subscript.eval_const( nil ) : nil
1514 rhs = Expression.create_cell_join_expression( ep_cell_nsp, ep_subscript_val, ep_name, rj.get_locale )
1515 join = Join.new( cp_name, cp_subscript, rhs, rj.get_locale )
1516 cell.new_join( join )
1517 # join.set_definition( ct.find(join.get_name) )
1518 if cp_subscript then
1519 ss_str = "[#{cp_subscript}]"
1520 else
1521 ss_str = ""
1522 end
1523 dbgPrint "create_reverse_join: #{cell.get_name}.#{cp_name}#{ss_str} => #{ep_cell_nsp.get_path_str}.ep_name\n"
1524 }
1525 end
1526 end
1527
1528 def self.external_join( internal_cell_elem_name, export_name, b_composite )
1529 @@current_object.external_join( internal_cell_elem_name, export_name, b_composite )
1530 end
1531
1532 #=== Cell# cell 内に記述する呼び口の外部結合
1533 # internal_cell_elem_name:: string : 呼び口名
1534 # export_name:: string: composite の外部に公開する呼び口名
1535 # 呼び口を外部結合する.
1536 # このメソッドは、composite の中の cell でしか呼ばれない.
1537 def external_join( internal_cell_elem_name, export_name, b_composite )
1538
1539 # cCall => composite.cCall; ではないか?
1540 if( b_composite == false )then
1541 # cCall => cCall; のような場合
1542 if @celltype.find( export_name ) then
1543 cdl_error( "S1036 $1 : cannot refer to $2\'s here. Use \'composite.$3\' to refer to composite celltype\'s" , export_name, @celltype.get_name, export_name )
1544 end
1545 end
1546 # composite の旧文法における、cell 外の cCall = Cell.cCall; の構文処理に渡す
1547 CompositeCelltype.new_join( export_name, @name, internal_cell_elem_name, :CALL )
1548 end
1549
1550 def self.end_of_parse f_def
1551 cell = @@current_object
1552 cell.end_of_parse f_def
1553 @@current_object = nil
1554 return cell
1555 end
1556
1557 def end_of_parse f_def
1558 if @b_prototype then # prototype 指定子あったか?
1559 f_def = false # プロトタイプ宣言とする
1560 @b_prototype = false
1561 end
1562 if f_def == false then
1563 # cell tCelltype Cell; の形式の場合
1564 # f_def == true の場合 new_def で、呼出される
1565 set_specifier_list( Generator.get_statement_specifier )
1566 end
1567 set_f_def f_def
1568
1569 if @generate then
1570 cell_plugin
1571 end
1572 end
1573
1574 #=== Cell# プロトタイプ宣言(false)か定義(true)かを設定
1575 # このメソッドは構文解釈の最後に呼出される
1576 #f_def:: bool false if prototype, true if definition
1577 def set_f_def f_def
1578 if ! f_def then
1579 return
1580 end
1581
1582 if ! @in_composite then
1583 if @celltype.instance_of? Celltype then
1584 @celltype.new_cell self
1585 end
1586 @@cell_list << self
1587 end
1588 end
1589
1590 def set_f_ref
1591 dbgPrint "set_f_ref: #{@global_name}\n"
1592 @f_ref = true
1593
1594 # composite の内部セルを参照されたことにする
1595 # 今のところ問題ないが、未参照であるべきものまで参照されたことになる
1596 if @cell_list then
1597 @cell_list.each{ |cn,cell|
1598 cell.set_f_ref
1599 }
1600 end
1601 end
1602
1603 #=== Cell# cell の指定子を設定
1604 # STAGE: B
1605 #
1606 # bnf.y.rb の statement_specifiler_list
1607 #spec_list:: [ :ALLOCATOR, [ [ :NORMAL_ALLOC, ep_name, subscript, func_name, param_name, expr ], ... ] ]
1608 # s[0] s[1] a[0] a[1] a[2] a[3] a[4] a[5]
1609 # セルに指定されたアロケータ指定子
1610 # a[1] の subscript はこのメソッドの中で Expression から Integer に評価される
1611 # 受け口側に生成されるアロケータ呼び口の結合を内部生成する
1612 # 呼び口側は Port の create_allocator_join にて生成
1613 # リレーアロケータの場合 create_relay_allocator_join にて生成す
1614 def set_specifier_list( spec_list )
1615 return if spec_list == nil # 空ならば何もしない
1616
1617 dbgPrint( "set_spec_list: #{@name}\n" )
1618 b_generate = false # generate が指定された
1619
1620 spec_list.each{ |s|
1621 case s[0] # statement_specifier
1622 when :ALLOCATOR # [allocator(ePort.func.param=allocCell.eA,ePort.func2.param=allocCell.eA)]
1623 s[1].each { |a| # alloc_list : allocator の内部の ',' で区切られた部分の配列
1624 cp_name = :"#{a[0+1]}_#{a[2+1]}_#{a[3+1]}" # アロケータ呼び口の名前:'=' の左辺を '.' に変えて '_' で連結
1625 # p "#{a[0]} #{a[0+1]} #{a[2+1]} #{a[3+1]} #{cp_name}"
1626 if a[1+1] then
1627 subscript = a[1+1].eval_const nil
1628 a[1+1] = subscript
1629 else
1630 subscript = nil
1631 end
1632 # アロケータ呼び口の結合を生成
1633 join = Join.new( cp_name, subscript, a[4+1] ) # 構文解析段階なので locale 不要
1634 dbgPrint( "new allocator join #{cp_name} #{subscript} #{a[4+1]}\n" )
1635 Cell.new_join( join )
1636 @alloc_list << a
1637 }
1638 when :ID # [id(0)]
1639 if ! s[1].instance_of? Expression then
1640 cdl_error( "S1160 $1 must be constant for id", s[1].to_s )
1641 else
1642 id = s[1].eval_const nil
1643 if id == nil || Integer(id) != id then
1644 cdl_error( "S1161 $1 must be constant for id", s[1].to_s )
1645 elsif id == 0 then
1646 cdl_error( "S1162 $1: id cannot be 0", s[1].to_s )
1647 else
1648 @id_specified = id
1649 end
1650 end
1651 when :GENERATE # [generate(CellPlugin,"option")]
1652 if @generate then
1653 cdl_error( "S1163 generate specifier duplicate" )
1654 end
1655 @generate = [ s[1], s[2] ] # [ PluginName, "option" ]
1656 b_generate = true
1657 when :PROTOTYPE # [prototype]
1658 @b_prototype = true
1659 when :RESTRICT # [restrict]
1660 s[1].each{ |re|
1661 add_restrict re[0], re[1], re[2]
1662 }
1663 else
1664 cdl_error( "S1039 \'$1\': unknown specifier for cell" , s[0] )
1665 end
1666 }
1667 if @b_prototype then
1668 if b_generate then
1669 cdl_error( "S9999 '$1': generate and prototype specified simultaneously" , @name )
1670 end
1671 if @b_defined then
1672 cdl_error( "S9999 '$1': prototype specified after definition" , @name )
1673 end
1674 end
1675 end
1676
1677 def get_allocator_list
1678
1679 # 意味チェック(set_definition)されていない?
1680 # relay アロケータの場合、セルの意味チェックが行われていないと、@alloc_list が完成しない
1681 if @b_checked == false then
1682 set_definition_join
1683 end
1684 @alloc_list
1685 end
1686
1687 def get_specified_id
1688 @id_specified
1689 end
1690
1691 #=== id 指定子の値を設定
1692 # このメソッドは、プラグインで cell の生成順序を制御したい場合のために設けた
1693 # 通常の id 指定子では使っていない
1694 def set_specified_id id
1695 if Integer( id ) != id || id <= 0 then
1696 cdl_error( "S1164 '$1' set_specified_id: id not positive integer '$2'", @name, id )
1697 elsif @id_specified then
1698 cdl_error( "S1165 '$1' set_specified_id: id duplicate", @name )
1699 else
1700 @id_specified = id
1701 end
1702 end
1703
1704 #=== Cell# セルタイププラグイン (generate 指定子)
1705 def cell_plugin
1706
1707 load_plugin( @generate[0], CellPlugin )
1708
1709 plugin_name = @generate[0]
1710 option = @generate[1]
1711 plugin_object = nil
1712 eval_str = "plugin_object = #{plugin_name}.new( self, option )"
1713 if $verbose then
1714 print "new cell : #{eval_str}\n"
1715 end
1716
1717 begin
1718 eval( eval_str ) # plugin を生成
1719 plugin_object.set_locale @locale
1720 @generate[ 2 ] = plugin_object
1721 generate_and_parse plugin_object
1722 rescue Exception => evar
1723 cdl_error( "S1166 $1: fail to new", plugin_name )
1724 print "eval( #{eval_str} )\n"
1725
1726 print_exception( evar )
1727 end
1728 end
1729
1730 def add_compositecelltypejoin join
1731 @compositecelltypejoin_list.add_item join
1732 end
1733
1734 #=== Cell# cell を composite セルタイプのセル用に clone する
1735 #name:: string : 親 cell の名前 (cell tComposite cell1 での cell1)
1736 #global_name:: string : 親 cell の global_name
1737 #join_array:: Join[] : composite の cell の join で、この cell に対応するもの
1738 #ct_name:: string : 親セルのセルタイプ名
1739 #region:: Region : 元のセルが属する region
1740 #このメソッドは CompositeCelltype の expand から呼出される
1741 def clone_for_composite( name, global_name, namespacePath, join_array, ct_name, region, plugin, locale )
1742
1743 # debug
1744 dbgPrint "Cell#clone_for_composite : cloning: #{@name} #{global_name} b_defined=#{@b_defined}\n"
1745
1746 @my_clone = self.clone
1747 @@cloned_cell_list[ self ] = @my_clone
1748
1749 # clone したセルの内部に持つ名前情報を調整する
1750
1751 @my_clone.set_cloned( name, global_name, namespacePath, join_array, ct_name, region, plugin, locale )
1752
1753 # @celltype == nil は以前にセルタイプ未定義エラー
1754 if @b_defined == true && @celltype != nil then
1755 if @celltype.instance_of?( Celltype ) then
1756 # celltype に登録(コード生成の対象となる)
1757 @celltype.new_cell( @my_clone )
1758 end
1759 end
1760
1761 return @my_clone
1762 end
1763
1764 #=== Cell# clone されたセルの内部に持つ名前情報を調整する
1765 #name:: string : 親 cell の名前 (cell tComposite cell1 での cell1)
1766 #global_name:: string : 親 cell の global_name
1767 #join_array:: Join[] : composite の cell の join で、この cell に対応するもの
1768 #parent_ct_name:: string : 親セルのセルタイプ名(composite セルタイプ)
1769 # このメソッドはすぐ上の clone_for_composite から呼出され、clone されたセルを整える
1770 def set_cloned( name, global_name, namespacePath, join_array, parent_ct_name, region, plugin, locale )
1771
1772 # debug
1773 dbgPrint "cell.set_cloned : global_name: #{global_name} name: #{name} @name: #{@name}\n"
1774
1775 @global_name = :"#{global_name}_#{@name}"
1776 @name = :"#{name}_#{@name}"
1777 @NamespacePath = namespacePath.change_name @name
1778 @region = region
1779 @plugin = plugin
1780 @locale = locale
1781
1782 @in_composite = false
1783 @b_checked = false
1784 @f_cloned = true
1785
1786 # Namespace.new_cell( self ) # mikan namespace 対応
1787 region.new_cell( self ) # mikan namespace に cell を置けないことを仮定
1788
1789 # join_list : NamedList の clone を作る
1790 if @celltype then
1791 dbgPrint "set_cloned: #{@celltype.get_name} #{@name} #{region.get_name}\n"
1792 end
1793 @join_list = @join_list.clone_for_composite( parent_ct_name, name, locale )
1794 @referenced_port_list = {}
1795
1796 @alloc_list = []
1797 @require_joined_list = {}
1798 @entry_array_max_subscript = {}
1799 @cell_list = {}
1800 @cell_list2 = []
1801
1802 # このセルのグローバル名を与える
1803 # C_EXP の$id$ 置換はこのセルの名前になる
1804 join_array.each { |j|
1805 @join_list.change_item j
1806 }
1807
1808 # clone しようとするセルが composit セルタイプ?
1809 if @celltype.instance_of?( CompositeCelltype ) then
1810 # composite cell を再帰的に展開
1811 @cell_list, @cell_list2 = @celltype.expand( @name, @global_name, @NamespacePath, @join_list, @region, @plugin, @locale )
1812 end
1813
1814 end
1815
1816 #=== Cell# clone された cell の join_list の右辺の変更
1817 # 呼び口の右辺の cell を他の clone された cell に置換え
1818 def change_rhs_port
1819
1820 # debug
1821 dbgPrint "Cell change_rhs_port: global_name: #{@global_name}\n"
1822
1823 @join_list.get_items.each { |j|
1824 j.change_rhs_port( @@cloned_cell_list, @celltype )
1825 }
1826
1827 if @celltype.instance_of?( CompositeCelltype ) then
1828
1829 # 入れ子のセルについても変更
1830 @cell_list.each{ |name,c|
1831 c.change_rhs_port
1832 }
1833 end
1834 end
1835
1836 def get_f_def
1837 @b_defined
1838 end
1839
1840 def get_f_ref
1841 if @f_ref then
1842 return true
1843 else
1844 return false
1845 end
1846 end
1847
1848 def get_name
1849 @name
1850 end
1851
1852 def get_local_name
1853 @local_name
1854 end
1855
1856 def get_global_name
1857 @global_name
1858 end
1859
1860 def get_region
1861 @region
1862 end
1863
1864 def self.get_current
1865 @@current_object
1866 end
1867
1868 #=== Cell# 生成されるセルか?
1869 # 最適化、コード生成中に、対象となる region に属する場合 true を返す
1870 def is_generate?
1871 if $generating_region == nil then
1872 # 構文解釈、意味解析段階で呼ばれると例外発生
1873 raise "is_generate? called before optimizing"
1874 end
1875
1876 # print "Cell#is_generate?: #{@name} #{@region.get_name} #{$generating_region.get_name}\n"
1877 if $generating_region == @region.get_link_root then
1878 return true
1879 else
1880 return false
1881 end
1882 end
1883
1884 #=== Cell# composite 内部の複製されたセルか?
1885 # composite 定義の内部のセル (@in_composite = true) ではない
1886 def is_cloned?
1887 @f_cloned
1888 end
1889
1890 #=== Cell# composite 内部のセルか?
1891 def is_in_composite?
1892 @in_composite
1893 end
1894
1895 # composite cell の port に対応する内部の cell の port の名前(リンク時に必要な名前)
1896 def get_real_global_name port_name
1897 if @celltype.instance_of?( CompositeCelltype ) then
1898
1899 # debug
1900 dbgPrint "get_real_global_name: cell name: #{@name} #{@local_name} #{@global_name} #{port_name}\n"
1901 @cell_list.each{ |n,c|
1902 dbgPrint " name: #{n}\n"
1903 dbgPrint " get_name: #{c.get_name} local_name: #{c.get_local_name}\n" if c
1904 dbgPrint "\n\n"
1905 }
1906
1907 cj = @celltype.find_export( port_name )
1908
1909 # debug
1910 dbgPrint " composite join name: #{cj.get_name} cell: #{cj.get_cell_name} cell elem: #{cj.get_cell_elem_name}\n"
1911
1912 name = @cell_list[ "#{cj.get_cell_name}" ].get_real_global_name( cj.get_cell_elem_name )
1913 return name
1914
1915 else
1916 # debug
1917 dbgPrint " get_real_global_name: cell name: #{@global_name}\n"
1918
1919 return @global_name
1920 end
1921 end
1922
1923 #=== Cell# セルの受け口 port_name に対する実際のセル名、受け口名を '_' で連結
1924 # namespace 名 + '_' + セル名 + '_' + 受け口名 (このセルが composite ならば展開後のセル名、受け口名)
1925 def get_real_global_port_name port_name
1926
1927 # composite か?
1928 if @celltype.instance_of?( CompositeCelltype ) then
1929
1930 # debug
1931 dbgPrint "get_real_global_port_name: cell name: #{@name} #{@local_name} #{@global_name} #{port_name}\n"
1932 @cell_list.each{ |n,c|
1933 dbgPrint " name: #{n}\n"
1934 dbgPrint " get_name: #{c.get_name} local_name: #{c.get_local_name}\n" if c
1935 dbgPrint "\n"
1936 }
1937
1938 # セルタイプ内で port_name の CompositeCelltypeJoin を探す(コード生成段階では必ず見つかる)
1939 cj = @celltype.find_export( port_name )
1940
1941 # debug
1942 dbgPrint " composite join name: #{cj.get_name} cell: #{cj.get_cell_name} cell elem: #{cj.get_cell_elem_name}\n"
1943
1944 # composite の内部のセルに対し再帰的に get_real_global_port_name を適用
1945 name = @cell_list[ "#{cj.get_cell_name}" ].get_real_global_port_name( cj.get_cell_elem_name )
1946 return name
1947
1948 else
1949 # debug
1950 dbgPrint "get_real_global_port_name: cell name: #{@global_name}\n"
1951
1952 return "#{@global_name}_#{port_name}"
1953 end
1954 end
1955
1956 #=== Cell# PORT (celltype の定義) を得る
1957 def get_real_port( port_name )
1958
1959 # composite か?
1960 if @celltype.instance_of?( CompositeCelltype ) then
1961
1962 # セルタイプ内で port_name の CompositeCelltypeJoin を探す(コード生成段階では必ず見つかる)
1963 cj = @celltype.find_export( port_name )
1964
1965 # composite の内部のセルに対し再帰的に get_real_port を適用
1966 port = @cell_list[ "#{cj.get_cell_name}" ].get_real_port( cj.get_cell_elem_name )
1967 return port
1968 else
1969
1970 return @celltype.find( port_name )
1971 end
1972 end
1973
1974 #=== Cell# cell を得る
1975 # composite でなければ自分自身を返す
1976 def get_real_cell( port_name )
1977
1978 # composite か?
1979 if @celltype.instance_of?( CompositeCelltype ) then
1980
1981 # セルタイプ内で port_name の CompositeCelltypeJoin を探す(コード生成段階では必ず見つかる)
1982 cj = @celltype.find_export( port_name )
1983
1984 # composite の内部のセルに対し再帰的に get_real_port を適用
1985 cell = @cell_list[ "#{cj.get_cell_name}" ].get_real_cell( cj.get_cell_elem_name )
1986 return cell
1987 else
1988
1989 return self
1990 end
1991 end
1992
1993
1994 #=== Cell# 受け口のport の参照カウントをアップする
1995 #port_name:: Symbol : ポート名
1996 def port_referenced port
1997 if @referenced_port_list[ port ] then
1998 @referenced_port_list[ port ] += 1
1999 else
2000 @referenced_port_list[ port ] = 1
2001 end
2002
2003 # composite か?
2004 if @celltype.instance_of?( CompositeCelltype ) then
2005
2006 # セルタイプ内で port_name の CompositeCelltypeJoin を探す(コード生成段階では必ず見つかる)
2007 cj = @celltype.find_export( port.get_name )
2008
2009 dbgPrint " port_referenced: #{@celltype.get_name} #{@name} cj=#{cj&&(cj.get_name)||"nil"}\n"
2010
2011 if cj then # 既にエラー
2012 # composite の内部のセルに対し再帰的に get_real_port を適用
2013 cell = @cell_list[ "#{cj.get_cell_name}" ]
2014 if cell && cell.get_celltype then
2015 cell.port_referenced( cell.get_celltype.find( cj.get_cell_elem_name ) )
2016 end
2017 end
2018 end
2019 end
2020
2021 def get_internal_port_name port_name
2022 if @celltype.instance_of?( CompositeCelltype ) then
2023 cj = @celltype.find_export( port_name )
2024# return "#{@name}_#{cj.get_cell.get_internal_port_name cj.get_cell_elem_name}"
2025 return cj.get_cell.get_internal_port_name( cj.get_cell_elem_name )
2026 else
2027
2028 # debug
2029 dbgPrint " get_global_port_name: cell port: #{@global_name}_#{port_name}\n"
2030
2031 return "#{@global_name}_#{port_name}"
2032 end
2033 end
2034
2035 def get_celltype
2036 @celltype
2037 end
2038
2039 def get_join_list
2040 @join_list
2041 end
2042
2043 def set_id id
2044 @id = id
2045 end
2046
2047 def get_id
2048 @id
2049 end
2050
2051 def get_plugin
2052 @plugin
2053 end
2054
2055 def get_cell_list2
2056 list = []
2057 @cell_list2.each{ |cell|
2058 list << cell
2059 list += cell.get_cell_list2
2060 }
2061 return list
2062 end
2063
2064 #=== Cell# 受け口配列の添数の最大値を設定
2065 def set_entry_port_max_subscript( port, num )
2066 dbgPrint( "set_entry_port_max_subscript: #{@name}.#{port.get_name}: #{num}\n" )
2067 subscript = @entry_array_max_subscript[port]
2068
2069 if subscript == nil || num > subscript then
2070 @entry_array_max_subscript[port] = num
2071 set_entry_inner_port_max_subscript( port, num )
2072 end
2073 end
2074
2075 #=== Cell# composite の内側セルの受け口配列の添数の最大値を設定
2076 def set_entry_inner_port_max_subscript( port, num )
2077 if @cell_list == nil then # mikan これって問題ない?
2078 return # プロトタイプ宣言しかされていなくて、内側セルが展開されていない
2079 end
2080
2081 # composite の内側のセルに伝播
2082 if @celltype.instance_of? CompositeCelltype then
2083 cj = @celltype.find_export port.get_name
2084 if cj && @cell_list[ cj.get_cell_name.to_s ] then
2085 inner_cell = @cell_list[ cj.get_cell_name.to_s ]
2086 ct = inner_cell.get_celltype
2087 if ct then
2088 inner_port = ct.find( cj.get_cell_elem_name )
2089 inner_cell.set_entry_port_max_subscript( inner_port, num )
2090 end
2091 end
2092 end
2093 end
2094
2095 #=== Cell# 受け口配列の添数の最大値を返す
2096 # 長さは +1 する
2097 # 1つもない場合は -1 を返す
2098 def get_entry_port_max_subscript( port )
2099 subscript = @entry_array_max_subscript[port]
2100 if subscript == nil then
2101 subscript = -1
2102 end
2103 return subscript
2104 end
2105
2106 #=== Cell# リレーアロケータの結合を生成
2107 # STAGE: S
2108 # 呼び口側の結合を元に受け口側の結合を生成
2109 def create_relay_allocator_join
2110
2111 # celltype がなければチェックしない(既にエラー)
2112 return if @celltype == nil
2113
2114 # relay allocator を生成
2115 @celltype.get_port_list.each { |p|
2116 ail = p.get_allocator_instance
2117 if ail then
2118 dbgPrint "create_relay_allocator_join: #{@name}, #{p.get_name}\n"
2119 if p.get_array_size then
2120 # mikan relay allocator が array に対応できてもよいのでは?
2121 cdl_error( "S1040 array not supported for relay allocator" )
2122 next
2123 end
2124 ail.each{ |name,ai2|
2125 # ai2 = [ :INTERNAL_ALLOC|:RELAY_ALLOC, func_name, param_name, rhs_cp_name, rhs_func_name, rhs_param_name ]
2126 if ai2[0] == :RELAY_ALLOC then
2127 dbgPrint "create_relay_allocator_join: #{@name}, #{name}\n"
2128 # 呼び口側の結合を取り出す
2129 ja = @join_list.get_item( :"#{ai2[3]}_#{ai2[4]}_#{ai2[5]}" )
2130 if ja == nil then
2131 # 見つからない場合
2132 found = false
2133
2134 # composite 内で外部に結合されているか
2135 if @in_composite then
2136 @compositecelltypejoin_list.get_items.each { |cj|
2137 dbgPrint( "create relay_allocator in_composite\n" )
2138 dbgPrint(" #{cj.get_cell_name} #{@name} #{cj.get_cell_elem_name} #{ai2[3]}_#{ai2[4]}_#{ai2[5]}\n")
2139 if cj.get_cell_name == @name &&
2140 cj.get_cell_elem_name == :"#{ai2[3]}_#{ai2[4]}_#{ai2[5]}" then
2141 found = true
2142 dbgPrint "create_relay_allocator: found #{cj.get_cell_elem_name}\n"
2143 break
2144 end
2145 }
2146 end
2147
2148 if found == false then
2149 cdl_error( "S1041 \'$1_$2_$3\': not joined. cannot create internal join for relay allocator" , ai2[3], ai2[4], ai2[5] )
2150 print( " In cell #{get_name}\n" )
2151 # join が未結合であることのエラーは二度でる (S1043)
2152 end
2153 next # 打ち切る
2154 end
2155
2156 b_export = false
2157 # composite 内のセルでエクスポートされているかチェック
2158 # mikan エクスポート側と、こちら側で、リレー先が一致するかチェックが必要
2159 if @compositecelltypejoin_list then
2160 # export されているか調べる
2161 @compositecelltypejoin_list.get_items.each{ |cj|
2162 # 属性名と composite の export する名前は一致するか
2163 if p.get_name == cj.get_cell_elem_name then
2164 print "export : #{p.get_name}\n"
2165 b_export = true # 属性は export されているので、とりあえず未初期化とはしない
2166 break
2167 end
2168 }
2169 #
2170 end
2171
2172 # mikan 配列
2173 am = nil
2174 if am then
2175 am.each{ |ja2|
2176 rhs = ja2.get_rhs
2177 subscript = ja2.get_subscript
2178 if b_export == false then
2179 # CompositeCelltype の場合、内側のセルで生成させる
2180 join = Join.new( :"#{p.get_name}_#{ai2[1]}_#{ai2[2]}", subscript, rhs, @loacle )
2181 # p ( "#{p.get_name}_#{ai2[1]}_#{ai2[2]}", subscript, rhs )
2182 new_join( join )
2183 join.set_definition( @celltype.find(join.get_name) )
2184 # mikan relay mismatch チェックができていない(下方を参照)
2185 end
2186 @alloc_list << [ :NORMAL_ALLOC, p.get_name, subscript, ai2[1], ai2[2], rhs ]
2187 }
2188 else
2189 if b_export == false then
2190 # CompositeCelltype の場合、内側のセルで生成させる
2191 join = Join.new( :"#{p.get_name}_#{ai2[1]}_#{ai2[2]}", nil, ja.get_rhs, @locale )
2192 new_join( join )
2193 join.set_definition( @celltype.find(join.get_name) )
2194 if @celltype.instance_of? CompositeCelltype then
2195 jr = @join_list.get_item( :"#{ai2[3]}_#{ai2[4]}_#{ai2[5]}" )
2196 if jr.get_rhs_cell2 != join.get_rhs_cell2 || jr.get_rhs_port2 != join.get_rhs_port2 then
2197 cdl_error( "S1167 \'$1\': relay mismatch \'$2\'",
2198 "#{p.get_name}_#{ai2[1]}_#{ai2[2]}",
2199 "#{ai2[3]}_#{ai2[4]}_#{ai2[5]}" )
2200 # 本当は composite の呼び口と受け口の間で行うべきだが、内部で多段接続されている場合
2201 else
2202 dbgPrint "relay success: #{p.get_name}_#{ai2[1]}_#{ai2[2]}=>#{ai2[3]}_#{ai2[4]}_#{ai2[5]} #{jr.get_rhs_cell2.get_name}.#{jr.get_rhs_port2} \n"
2203 end
2204 end
2205 end
2206 @alloc_list << [ :NORMAL_ALLOC, p.get_name, nil, ai2[1], ai2[2], ja.get_rhs ]
2207 end
2208 dbgPrint "create_relay_allocator_join: #{p.get_name}_#{ai2[1]}_#{ai2[2]} #{ai2[3]}_#{ai2[4]}_#{ai2[5]}\n"
2209 end
2210 }
2211 end
2212 }
2213 end
2214
2215 #=== Cell# @@cell_list2 を作る
2216 # @@cell_list2 は、出現順に composite 内を含むセルのリスト
2217 def self.make_cell_list2
2218 @@cell_list.each{ |c|
2219 @@cell_list2 << c
2220 @@cell_list2 += c.get_cell_list2
2221 }
2222 end
2223
2224 #=== Cell# @@cell_list2 を得る
2225 # composite 内を含む (compositeも含む)
2226 # 意味解析後に作成される
2227 def self.get_cell_list2
2228 @@cell_list2
2229 end
2230
2231 #=== Cell# @@cell_list を得る
2232 #composite の中を含まない
2233 def self.get_cell_list
2234 @@cell_list
2235 end
2236
2237 #=== Cell# reverse_join を生成する
2238 def self.create_reverse_join
2239 @@cell_list.each{ |c|
2240 ct = c.get_celltype
2241 # if c.is_generate? then
2242 if ct then
2243 c.create_reverse_join
2244 end
2245 # end
2246 }
2247 end
2248
2249 #=== Cell# reverse_require_join を生成する
2250 def self.create_reverse_require_join
2251 @@cell_list2.each{ |c|
2252 ct = c.get_celltype
2253 # if c.is_generate? then
2254 if ct then
2255 # self への呼び口側の結合を生成
2256 ct.create_reverse_require_join c
2257 end
2258 # end
2259 }
2260 end
2261
2262 #=== Cell# 受け口のport の参照カウントを設定する
2263 # self は呼び元のセル
2264 # 呼び先セルの受け口の参照カウントをアップする
2265 def set_port_reference_count
2266 @join_list.get_items.each { |j|
2267 if j.get_definition.instance_of? Port then
2268 am = j.get_array_member2
2269 if am then # 呼び口配列
2270 am.each { |j2|
2271 next if j2 == nil # optional で一部が欠落しているケース
2272 cell = j2.get_rhs_cell2
2273 next if cell == nil # 右辺が見つからなかった.既にエラー
2274 port = cell.get_celltype.find( j2.get_rhs_port2 )
2275 dbgPrint( "set_port_reference_count: #{@name}.#{j2.get_name} => #{cell.get_name}.#{port.get_name}\n")
2276 cell.port_referenced port
2277 }
2278 else
2279 cell = j.get_rhs_cell2
2280 next if cell == nil # 右辺が見つからなかった.既にエラー
2281 port = cell.get_celltype.find( j.get_rhs_port2 )
2282 dbgPrint( "set_port_reference_count: #{@name}.#{j.get_name} => #{cell.get_name}.#{port.get_name}\n")
2283 cell.port_referenced port
2284 end
2285 end
2286 }
2287 end
2288
2289 #=== Cell# 結合(Join)のチェック
2290 # Join は呼び口の結合または attribute の初期化
2291 #
2292 # mikan このメソッドは、以下の4つのチェックからなるが、分割したほうがより適切な長さのメソッドになる
2293 # ・リレーアロケータの生成 => create_relay_allocator_join
2294 # ・未結合の呼び口のチェック
2295 # ・ポインタ型が配列で初期化される場合のチェック
2296 # ・未初期化の属性のチェック
2297 def check_join
2298
2299 # celltype がなければチェックしない(既にエラー)
2300 return if @celltype == nil
2301 return if @b_defined == false
2302 return if @f_cloned == true # 内部セルについては、composite の定義時にチェックされている
2303
2304 # debug
2305 # if @compositecelltypejoin_list then
2306 # p "check_join"
2307 # @compositecelltypejoin_list.get_items.each { |cj| p "#{cj.get_name} #{cj.get_name.object_id}" }
2308 # end
2309
2310 # 未結合の呼び口のチェック
2311 @celltype.get_port_list.each { |p|
2312
2313 # 呼び口でなければ、チェックしない
2314 next if p.get_port_type != :CALL
2315
2316 # debug
2317 dbgPrint "check_join: #{@name} #{get_celltype.get_name} #{p.get_name}\n"
2318
2319 # 結合リストの中から呼び口名に一致するものを取りだす
2320 j = @join_list.get_item( p.get_name )
2321
2322 if j == nil then
2323 # 未結合の呼び口
2324
2325 # composite celltype の内部の場合、composite celltype が export する呼び口に結合されているか探す
2326 found = false
2327 if @in_composite then
2328 # composite celltype の export するものすべてから探す
2329 # (export するものの右辺値から探すために get_item ではダメ)
2330 @compositecelltypejoin_list.get_items.each{ |cj|
2331 # 呼び口名と composite の export する名前は一致するか
2332 if p.get_name == cj.get_cell_elem_name then
2333 found = true
2334 end
2335 }
2336 end
2337
2338 # 呼び口配列の場合 optional で全ての要素が初期化されない場合に、ここへ来る
2339 if ! found && ! p.is_require? && ! p.is_optional? then
2340 if ! p.is_allocator_port? then
2341 cdl_error( "S1042 call port \'$1\' not initialized in cell \'$2\'" , p.get_name, @name )
2342 else
2343 cdl_error( "S1043 call port \'$1\' not initialized in cell \'$2\'. this call port is created by tecsgen. check allocator specifier" , p.get_name, @name )
2344 end
2345 end
2346 elsif p.get_array_size.kind_of? Integer then
2347 # 添数あり呼び口配列の場合、すべての添数要素が初期化されているかチェックする
2348
2349 am = j.get_array_member2
2350 if( am )then
2351 # join は配列
2352
2353 # 呼び口配列定義での配列の大きさ
2354 length = p.get_array_size
2355
2356 # 配列の大きさが呼び口配列定義と結合定義で一致するか?
2357 if am.length != length then
2358 if ! p.is_optional? || am.length >= length then
2359 # optional の場合、要素数が少なすぎるのは OK
2360 cdl_error( "S1044 $1: array initializer too many or few, $2 for $3" , p.get_name, am.length, length )
2361 end
2362
2363 # am の要素に nil を追加しておく (#_CPA_# のコード生成時、この配列要素数分生成)
2364 i = am.length
2365 while i < length
2366 am << nil
2367 i += 1
2368 end
2369 end
2370
2371# # 配列要素の抜けがないかチェック
2372# if am.length < length then # 満たない場合既にエラーだが要素のある範囲でチェック
2373# length = am.length
2374# end
2375 i = 0
2376 while( i < length )
2377 if am[i] == nil then
2378 if ! p.is_optional? then
2379 cdl_error( "S1045 $1[$2]: not initialized" , p.get_name, i )
2380 end
2381 else
2382 # 生成されないリージョンへの結合かチェック
2383 if ! @in_composite then
2384 am[i].check_region2
2385 end
2386 end
2387 i += 1
2388 end
2389
2390 # else
2391 # join が非配列であれば、既にエラー
2392 end
2393 elsif j.get_array_member then
2394 # 添数なし呼び口配列の場合
2395 am = j.get_array_member2
2396 length = am.length
2397 i = 0
2398 while i < length
2399 if am[i] == nil then
2400 if ! p.is_optional? then
2401 cdl_error( "S1046 $1[$2]: not initialized" , p.get_name, i )
2402 end
2403 end
2404 i += 1
2405 end
2406
2407 # 生成されないリージョンへの結合かチェック
2408 if ! @in_composite then
2409 am.each { |join|
2410 if join then
2411 join.check_region2
2412 end
2413 }
2414 end
2415 else
2416 # 呼び口[配列」でない場合
2417
2418 # 生成されないリージョンへの結合かチェック
2419 if ! @in_composite then
2420 j.check_region2
2421 end
2422
2423 end # j != nil
2424 }
2425
2426 # ポインタ型が配列で初期化される場合のチェック
2427 (@celltype.get_attribute_list+@celltype.get_var_list).each { |a|
2428 if a.get_size_is then
2429
2430 if a.instance_of? CompositeCelltypeJoin then
2431 # 既にエラーになっている
2432 # cdl_error( "S1047 size_is pointer cannot be exposed for composite attribute" )
2433 next
2434 end
2435
2436 if( ! a.get_type.kind_of?( PtrType ) ) then
2437 cdl_error( "S1048 $1: size_is specified for non-pointer type" , a.get_name )
2438 else
2439 size = a.get_size_is.eval_const( @join_list, @celltype.get_name_list )
2440 a.get_type.set_scs( a.get_size_is, nil, nil, nil, false )
2441 if( ! size.kind_of? Integer )then # C_EXP の可能性あり
2442 # mikan 多分ここでのエラー発生は不要、eval_const の中で変数が存在しない、型が不適切などのエラーになるはず
2443 cdl_error( "S1049 $1: size_is arg not constant" , a.get_name )
2444 else
2445 j = @join_list.get_item( a.get_identifier )
2446 if j then
2447 ini = j.get_rhs
2448 if ini then
2449 if ! ini.instance_of?( Array ) then
2450 cdl_error( "S1050 unsuitable initializer, need array initializer" )
2451 elsif size < ini.length then
2452 cdl_error( "S1051 too many initializer for array, $1 for $2" , ini.length, size )
2453 else
2454 # a.get_type.set_scs( a.get_size_is, nil, nil )
2455 end
2456 end
2457 else
2458 # size_is 引数がセルで指定されていて、初期化子がセルタイプで指定されているケースのチェック
2459 ini = a.get_initializer
2460 if ini.instance_of? Expression
2461 ini = ini.eval_const( @celltype.get_name_list )
2462 end
2463 if ini.instance_of? Array then
2464 if( ini.length > size )then
2465 cdl_error( "S1168 too many initializer for array, $1 for $2", ini.length, size )
2466 end
2467 end
2468 end
2469 end
2470 end
2471 else
2472 if ! a.instance_of? CompositeCelltypeJoin then
2473 # composite は size_is 指定できない
2474 if a.get_type.kind_of?( PtrType ) then
2475 j = @join_list.get_item( a.get_identifier )
2476 if j && j.get_rhs.instance_of?( Array ) then
2477 ## size_is 指定されていないポインタが Array で初期化されていたら、エラーとする
2478 cdl_error( "S1169 $1: non-size_is pointer cannot be initialized with array initializer" , a.get_identifier )
2479 end
2480 end
2481 end
2482 end
2483 }
2484
2485 # 未初期化の属性をチェック
2486 @celltype.get_attribute_list.each { |a|
2487 b_init = false
2488 # self.show_tree 1
2489 if a.get_initializer then # セルタイプで初期化されている
2490 b_init = true
2491 # @in_composite で export されている場合には、この初期値は使われない
2492 # export されている、いないに関わらず、初期化されていることが保証される
2493 elsif @join_list.get_item( a.get_name ) then # セルで初期化されている
2494 b_init = true
2495 elsif @in_composite && @compositecelltypejoin_list then
2496 # 属性が export されているか調べる。export されていれば未初期化とはしない
2497 # mikan リニアサーチ
2498 @compositecelltypejoin_list.get_items.each{ |cj|
2499 # 属性名と composite の export する名前は一致するか
2500 if a.get_name.to_sym == cj.get_cell_elem_name.to_sym then
2501 b_init = true # 属性は export されているので、とりあえず未初期化とはしない
2502 end
2503 }
2504 if b_init then
2505 # size_is の引数がマッチするかチェックする
2506 # 内部セルの size_is をエクスポートする size_is とマッチするかチェックする
2507 # 内部セルとエクスポートで名前を変えている可能性があるので、内部セルの size_is の名前を変換した上でチェックする
2508 if a.get_size_is then
2509 ### p "attr: get_size_is"
2510 cj = @compositecelltypejoin_list.get_item a.get_name.to_sym
2511 if cj.get_port_decl.instance_of? Decl then
2512 ### p "attr: get_size_is 2"
2513 # cj_size_is は、外部公開される attr の size_is
2514 cj_size_is = cj.get_port_decl.get_size_is
2515 if cj_size_is == nil then
2516 cdl_error( "S1170 \'$1\' has size_is but export attr \'$2\' doesn't have", a.get_name, cj.get_name )
2517 end
2518 exprs = a.get_size_is.to_s
2519 ### p "exprs : ", exprs
2520 remain = exprs
2521 inner_to_export = {}
2522 ### exprs に含まれる識別子を抜き出し、対応する export される名前を探す
2523 while remain != "" && remain != nil
2524 ### p "remain ", remain
2525 remain =~ /([^\w]*)([_A-Za-z][\w\d]*)/ # 変数名文字列を取り出す
2526 if $2 == nil then
2527 break
2528 end
2529 arg_name = $2.to_sym
2530 remain = $'
2531 ### p exprs, $1, $2, $'
2532 # size_is に含まれる変数は、composite で export されているか
2533 cj2 = nil
2534 @compositecelltypejoin_list.get_items.each{ |cj2t|
2535 if cj2t.get_cell_elem_name == arg_name then
2536 cj2 = cj2t
2537 end
2538 }
2539 if cj2 == nil then
2540 cdl_error( "S1171 \'$1\' size_is argument of \'$2\' not exported", a.get_name, cj.get_name )
2541 next
2542 end
2543 if cj2.get_port_decl.instance_of? Decl then
2544 decl2 = cj2.get_port_decl
2545 # 内部の名前と外部の名前の対応関係を記憶
2546 inner_to_export[arg_name] = decl2.get_name
2547 # else cj2 は Port (既にエラー)
2548 end
2549 end
2550 # 内部の名前を外部の名前で置換
2551 inner_to_export.each{ |arg_name, exp_name|
2552 ### p "changing #{arg_name}=>#{exp_name}"
2553 # exprs.gsub!( Regexp.new("#{arg_name}[^0-9A-Za-z_]"), exp_name.to_s )
2554 exprs.gsub!( Regexp.new("#{arg_name}(\\W)"), exp_name.to_s+"\\1" ) # 文字列末尾にないケース
2555 exprs.gsub!( Regexp.new("#{arg_name}\\Z"), exp_name.to_s ) # 文字列末尾にあるケース
2556 }
2557 ### p "changed: #{exprs} #{cj_size_is.to_s}"
2558 if exprs != cj_size_is.to_s then
2559 cdl_error( "S1172 \'$1\' size_is argument mismatch with exporting one \'$2\'", a.get_name, cj.get_name )
2560 end
2561 # else cj は Port (既にエラー)
2562 end
2563 end
2564 end
2565 end
2566
2567 if b_init == false then
2568 cdl_error( "S1052 attribute \'$1\' not initialized in cell \'$2\'" , a.get_name, @name )
2569 end
2570
2571 }
2572 end
2573
2574 #=== Cell# 逆 require をチェックする
2575 # 逆 require 指定された受け口に複数の結合がないかチェックする
2576 # composite の内部セル (f_cloned=true) もチェックする
2577 def check_reverse_require
2578 # celltype がなければチェックしない(既にエラー)
2579 return if @celltype == nil
2580 return if @b_defined == false
2581
2582 # p "check reverse require #{@name}"
2583 # 逆require 指定された受け口に複数の結合がないかチェック
2584 @referenced_port_list.each{ |port,count|
2585 # p port.class, count
2586 # p port.get_name, port.get_port_type, port.get_signature.get_name
2587 if port.is_reverse_required? && count > 1 then
2588 cdl_warning( "W1009 $1: fixed join entry port has multi join", port.get_name )
2589 end
2590 }
2591 end
2592
2593 #=== Cell# require 呼び口の結合を行う
2594 # STAGE: S
2595 #cp_name:: Symbol : 呼び口名
2596 #cell_or_t:: Celltype|Cell : celltype の require の右辺で指定されたセルタイプまたはセル
2597 #port:: Port : celltype の Port オブジェクト
2598 def set_require_join( cp_name, cell_or_ct, port )
2599
2600 # set_require_join は2度呼び出される
2601 # 2度目は post コードを生成した後 ##### いったん見合わせ(重複エラーを見逃す)
2602 # if @require_joined_list[ cp_name ] then
2603 # return
2604 # else
2605 # @require_joined_list[ cp_name ] = true
2606 # end
2607
2608 dbgPrint "set_require_join: #{@name}.#{cp_name} = #{cell_or_ct.get_name}.#{port.get_name}\n"
2609
2610 if cell_or_ct.instance_of? Celltype then
2611 # print "DOMAIN: not considered\n"
2612 cell = cell_or_ct.get_singleton_cell @region
2613 if cell == nil then
2614 cdl_error( "S1025 not found reachable cell for require \'$1\' in celltype \'$2\'" , port.get_name, cell_or_ct.get_name )
2615 return
2616 end
2617 else
2618 # require: cell で指定
2619 cell = cell_or_ct
2620 if @region.distance( cell.get_region ) == nil then
2621 cdl_error( "S1026 required cell \'$1\' not reachable" , cell.get_name )
2622 end
2623 end
2624
2625 if @join_list.get_item( cp_name ) then
2626 cdl_warning( "W1003 $1 : require call port overridden in $2" , cp_name, @name )
2627 else
2628 # require の join を生成(呼び口の結合)
2629# rhs = Expression.new( [ :OP_DOT, [ :IDENTIFIER, Token.new( cell.get_name, nil, nil, nil ) ],
2630 nsp = NamespacePath.new( cell.get_name, false, cell.get_namespace )
2631 nsp.set_locale @locale
2632 rhs = Expression.new( [ :OP_DOT, [ :IDENTIFIER, nsp ],
2633 Token.new( port.get_name, nil, nil, nil ) ], @locale ) #1
2634 join = Join.new( cp_name, nil, rhs, @locale )
2635 self.new_join( join )
2636
2637 join.set_definition( @celltype.find(join.get_name) )
2638 end
2639 end
2640
2641 #=== Cell# Join の definition の設定とチェック
2642 # STAGE: S
2643 def set_definition_join
2644 return if @celltype == nil # 既にエラー:打ち切る
2645 return if @b_defined == false # プロトタイプ宣言のみ
2646 return if @b_checked == true # 既に設定(チェック)済み
2647
2648 dbgPrint "set_definition_join in #{@name}\n"
2649
2650 # relay allocator をたどって再入しないよう、先頭で @b_checked を true にする
2651 @b_checked = true
2652
2653 if ! @f_cloned then
2654 check_restrict_list
2655
2656 # compoiste セルのクローンされたものは、set_definition 不要
2657 # 元の join は既に definition されている
2658 # 元のセルにおいて、代入チェックされているので、二重にチェック(through適用)されてしまう
2659 @join_list.get_items.each{ |join|
2660 dbgPrint " set_definition_join: checking #{@name}.#{join.get_name}\n"
2661 if join.get_array_member then
2662 port = @celltype.find(join.get_name)
2663 join.get_array_member2.each { |am|
2664 if am == nil then # 未結合の場合、エラーチェックは check_join
2665 if port && ! port.is_optional? then
2666 # テスト用にエラーメッセージ出力
2667 # cdl_error( "TEMPORAL set_definition_join: uninitialized array member" )
2668 end
2669 next
2670 end
2671 am.set_definition( port )
2672 }
2673 else
2674 join.set_definition( @celltype.find(join.get_name) )
2675 end
2676 }
2677 end
2678
2679 # リレー join は through プラグイン生成後にしかできない
2680 # through 後に結合先が入れ替えられる
2681 create_relay_allocator_join
2682
2683 # composite セルの展開
2684 if ! @in_composite && ! @f_cloned && @celltype.instance_of?( CompositeCelltype ) then
2685 # composite セルタイプ内の composite は展開しない
2686 # compoiste セル展開中の composite は展開しない (CompositeCelltype::expand 内で再帰的に expnad)
2687 expand
2688 end
2689
2690 # celltype に generate が指定されされているか
2691 celltype_plugin = @celltype.get_celltype_plugin
2692 if celltype_plugin then
2693 begin
2694 celltype_plugin.new_cell self
2695 rescue Exception => evar
2696 cdl_error( "S1037 $1: celltype plugin fail to new_cell" , celltype_plugin.class.name )
2697 print_exception( evar )
2698 end
2699 end
2700 end
2701
2702 #=== Cell# composite セルの展開
2703 # このセルが composite セルタイプ
2704 def expand
2705
2706 #debug
2707 dbgPrint "expanding #{@name} #{@celltype.get_name}\n"
2708
2709 # 展開されたセルのリスト
2710 @@cloned_cell_list = {}
2711
2712 # composite celltype の cell を展開
2713 @cell_list, @cell_list2 = @celltype.expand( @name, @global_name, @NamespacePath, @join_list, @region, @plugin, @locale )
2714
2715 # プロトタイプが参照されている場合、子も参照されていることにする
2716 if @f_ref then
2717 dbgPrint "expand: set_f_ref\n"
2718 set_f_ref
2719 end
2720
2721 # 呼び口の右辺のセルを clone したものに変更
2722 self.change_rhs_port
2723
2724 # プロトタイプ宣言で設定されていたものを反映する
2725 @entry_array_max_subscript.each{ |port,name|
2726 set_entry_inner_port_max_subscript( port, name )
2727 }
2728 end
2729
2730 #=== Cell#restrict を追加
2731 def add_restrict( entry_name, func_name, region_name_list )
2732 if @restrict_list[ entry_name ] then
2733 if @restrict_list[ entry_name ][ func_name ] then
2734 @restrict_list[ entry_name ][ func_name ].each{ |rn|
2735 if region_name_list.include? rn then
2736 # p func_name
2737 name = func_name ? entry_name : entry_name+"."+func_name
2738 cdl_warning( "W9999 $1 restrict region duplicate $2", name, rn )
2739 end
2740 }
2741 else
2742 @restrict_list[ entry_name ][ func_name ] = region_name_list
2743 end
2744 else
2745 func_list = { }
2746 func_list[ func_name ] = region_name_list
2747 @restrict_list[ entry_name ] = func_list
2748 end
2749 # pp @restrict_list
2750 end
2751
2752 #=== Cell#check_restrict_list
2753 def check_restrict_list
2754 @restrict_list.each{ |entry_name, func_hash|
2755 func_hash.each{ |func_name, region_list|
2756 region_list.each{ |rn|
2757 obj = Namespace.find [ rn ]
2758 if ( obj.kind_of? Region ) then
2759 if obj.get_domain_root != @region.get_domain_root then
2760 else
2761 cdl_warning( "W9999 $1 in same domain", rn )
2762 end
2763 else
2764 cdl_error( "S9999 $1 not region", region )
2765 end
2766 }
2767 }
2768 }
2769 end
2770
2771 #=== Cell#callable?
2772 def callable?( callee_cell, entry_name, func_name )
2773 res = callee_cell.callable_from?( entry_name, func_name, self )
2774 dbgPrint "callable? #{callee_cell.get_namespace_path}.#{entry_name}.#{func_name} from #{@NamespacePath} is #{res}\n"
2775 return res
2776 end
2777
2778 #=== Cell#callable_from? (private)
2779 def callable_from?( entry_name, func_name, caller_cell )
2780 if @restrict_list.length == 0 then
2781 return true
2782 end
2783
2784 if @restrict_list[entry_name] then
2785 if @restrict_list[entry_name][nil] &&
2786 @restrict_list[entry_name][nil].include?( caller_cell.get_region.get_domain_root.get_name )then
2787 return true
2788 end
2789 if @restrict_list[entry_name][func_name] &&
2790 @restrict_list[entry_name][func_name].include?( caller_cell.get_region.get_domain_root.get_name )then
2791 return true
2792 else
2793 return false
2794 end
2795 else
2796 return true
2797 end
2798 end
2799
2800 def show_tree( indent )
2801 indent.times { print " " }
2802 puts "Cell: name: #{@name} in_composite: #{@in_composite} def: #{@b_defined} ref: #{@f_ref} cloned: #{@f_cloned}"
2803 (indent+1).times { print " " }
2804 puts "Cell locale: #{@name}@#{@locale[0]}##{@locale[1]}"
2805 (indent+1).times { print " " }
2806 puts "id: #{@id} global_name: #{@global_name} region: #{@region.get_name} plugin: #{@plugin.class.name} #{self}"
2807 (indent+1).times { print " " }
2808 puts "namespace_path: #{@NamespacePath}"
2809
2810 if @celltype then
2811 (indent+1).times { print " " }
2812 puts "celltype: #{@celltype.get_name}"
2813 end
2814 @join_list.show_tree( indent + 1 )
2815 @entry_array_max_subscript.each{ |port, num|
2816 (indent+1).times { print " " }
2817 puts "entry array #{port.get_name}: max subscript=#{num}"
2818 }
2819 if @cell_list then # ここで @cell_list が nil なのは Bug
2820 (indent+1).times { print " " }
2821 puts "cloned cell list:"
2822 @cell_list.each { |n,c|
2823 (indent+2).times { print " " }
2824 puts "inner cell : #{n} = #{c.get_name}"
2825 }
2826 end
2827 if @compositecelltypejoin_list then
2828 @compositecelltypejoin_list.get_items.each{ |cj|
2829 cj.show_tree( indent+1 )
2830 }
2831 end
2832 if @alloc_list.length > 0 then
2833 (indent+1).times { print " " }
2834 puts "allocator list: "
2835 @alloc_list.each { |a|
2836 cp_name = :"#{a[0+1]}_#{a[2+1]}_#{a[3+1]}"
2837 if a[1+1] then
2838 # subscript = "[#{a[1+1].eval_const nil}]"
2839 subscript = "[#{a[1+1]}]"
2840 else
2841 subscript = ""
2842 end
2843 # アロケータ呼び口の結合を生成
2844 (indent+2).times { print " " }
2845 puts "#{cp_name}#{subscript} = #{a[4+1]}"
2846 }
2847 end
2848 @referenced_port_list.each{ |port,count|
2849 (indent+1).times { print " " }
2850 puts( "#{port.get_name} : #{count} times referenced" )
2851 }
2852 end
2853
2854end
2855
2856class CompositeCelltype < NSBDNode # < Nestable
2857# @name:: str
2858# @global_name:: str
2859# @cell_list:: NamedList Cell
2860# @export_name_list:: NamedList : CompositeCelltypeJoin
2861# @port_list:: CompositeCelltypeJoin[]
2862# @attr_list:: CompositeCelltypeJoin[]
2863# @b_singleton:: bool : 'singleton' specified
2864# @b_active:: bool : 'active' specified
2865# @real_singleton:: bool : has singleton cell in this composite celltype
2866# @real_active:: bool : has active cell in this composite celltype
2867# @name_list:: NamedList item: Decl (attribute), Port エクスポート定義
2868# @internal_allocator_list:: [ [cell, internal_cp_name, port_name, func_name, param_name, ext_alloc_ent], ... ]
2869
2870 @@nest_stack_index = -1
2871 @@nest_stack = []
2872 @@current_object = nil
2873
2874 def self.push
2875 @@nest_stack_index += 1
2876 @@nest_stack[ @@nest_stack_index ] = @@current_object
2877 @@current_object = nil
2878 end
2879
2880 def self.pop
2881 @@current_object = @@nest_stack[ @@nest_stack_index ]
2882 @@nest_stack_index -= 1
2883 if @@nest_stack_index < -1 then
2884 raise "TooManyRestore"
2885 end
2886 end
2887
2888 def initialize( name )
2889 super()
2890 @name = name
2891 @cell_list = NamedList.new( nil, "in composite celltype #{name}" )
2892 @export_name_list = NamedList.new( nil, "export in composite celltype #{name}" )
2893 @name_list = NamedList.new( nil, "in composite celltype #{name}" )
2894 @@current_object = self
2895
2896 @b_singleton = false
2897 @real_singleton = nil
2898 @b_active = false
2899 @real_active = nil
2900 if "#{Namespace.get_global_name}" == "" then
2901 @global_name = @name
2902 else
2903 @global_name = :"#{Namespace.get_global_name}_#{@name}"
2904 end
2905
2906 Namespace.new_compositecelltype( self )
2907 set_namespace_path # @NamespacePath の設定
2908
2909 @port_list = []
2910 @attr_list = []
2911 @internal_allocator_list = []
2912 set_specifier_list( Generator.get_statement_specifier )
2913 end
2914
2915 def self.end_of_parse
2916 @@current_object.end_of_parse
2917 @@current_object = nil
2918 end
2919
2920 # CompositeCelltype#end_of_parse
2921 def end_of_parse
2922
2923 # singleton に関するチェック
2924 if @b_singleton && @real_singleton == nil then
2925 cdl_warning( "W1004 $1 : specified singleton but has no singleton in this celltype" , @name )
2926 elsif ! @b_singleton && @real_singleton != nil then
2927 if ! @b_singleton then
2928 cdl_error( "S1053 $1 must be singleton. inner cell \'$2\' is singleton" , @name, @real_singleton.get_name )
2929 end
2930 end
2931
2932 # active に関するチェック
2933 if @b_active && @real_active == nil then
2934 cdl_error( "S1054 $1 : specified active but has no active in this celltype" , @name )
2935 elsif ! @b_active && @real_active != nil then
2936 cdl_error( "S1055 $1 must be active. inner cell \'$2\' is active" , @name, @real_active.get_name )
2937 end
2938
2939 # @allocator_instance を設定する
2940 @name_list.get_items.each{ |n|
2941 if n.instance_of? Port then
2942 n.set_allocator_instance
2943 end
2944 }
2945
2946 # リレーアロケータの entry 側
2947 @port_list.each{ |p|
2948 if p.get_port_type == :ENTRY then
2949 if p.get_allocator_instance == nil then
2950 next
2951 end
2952
2953 p.get_allocator_instance.each{ |name,ai|
2954 if ai[0] == :RELAY_ALLOC then
2955 self.new_join( :"#{p.get_name}_#{ai[4]}_#{ai[5]}", p.get_cell_name, :"#{p.get_cell_elem_name}_#{ai[4]}_#{ai[5]}", :CALL )
2956 end
2957 }
2958 end
2959 }
2960 # mikan relay が正しく抜けているかチェックされていない
2961
2962 # 意味解析
2963 @cell_list.get_items.each{ |c|
2964 c.set_definition_join
2965 }
2966
2967 # cell の未結合の呼び口がないかチェック
2968 @cell_list.get_items.each{ |c|
2969 c.check_join
2970 c.check_reverse_require
2971 }
2972
2973 # 呼び口の結合について、export と内部結合の両方がないかチェック
2974 # リレーアロケータ、内部アロケータの設定
2975 @port_list.each{ |p|
2976 p.check_dup_init
2977 }
2978
2979 # すべてのエクスポート定義に対応した呼び口、受け口、属性が存在するかチェック
2980 @name_list.get_items.each{ |n|
2981 if( @export_name_list.get_item( n.get_name ) == nil )then
2982 cdl_error( "S1056 $1 : cannot export, nothing designated" , n.get_name )
2983 end
2984 }
2985
2986 # 内部アロケータを設定する
2987 @internal_allocator_list.each{ |cell, cp_internal_name, port_name, fd_name, par_name, ext_alloc_ent|
2988 res = ext_alloc_ent.get_allocator_rhs_elements( :INTERNAL_ALLOC )
2989 ep_name = res[0]
2990 cj = @export_name_list.get_item( ep_name )
2991 internal_alloc_name_from_port_def = cj.get_cell_name
2992 internal_alloc_ep_name_from_port_def = cj.get_cell_elem_name
2993
2994 # puts "internal_allocator #{cell.get_name} #{cp_internal_name} #{port_name}.#{fd_name}.#{par_name}"
2995 cell.get_allocator_list.each{ |a|
2996 # puts "allocator_list of #{cell.get_name} #{a[0]} #{a[1]}.#{a[2]}.#{a[3]}.#{a[4]} #{a[5].to_s}"
2997 if cp_internal_name == :"#{a[1]}_#{a[3]}_#{a[4]}" then
2998 dbgPrint "internal_allocator {cp_internal_name} #{a[1]}_#{a[3]}_#{a[4]}\n"
2999 dbgPrint "internal_allocator: #{a[5]}, #{internal_alloc_name_from_port_def}.#{internal_alloc_ep_name_from_port_def}\n"
3000 if a[5].to_s != "#{internal_alloc_name_from_port_def}.#{internal_alloc_ep_name_from_port_def}" then
3001 cdl_error( "S1173 $1: allocator mismatch from $2's allocator", "#{port_name}.#{fd_name}.#{par_name}", cell.get_name )
3002 end
3003 end
3004 }
3005 }
3006 end
3007
3008 ### cell (CompositeCelltype)
3009 def self.new_cell( cell )
3010 @@current_object.new_cell( cell )
3011
3012 end
3013
3014 def new_cell( cell )
3015 cell.set_owner self # Cell (in_omposite)
3016 @cell_list.add_item( cell )
3017 if cell.get_celltype then # nil ならば、すでにセルタイプなしエラー
3018 if cell.get_celltype.is_singleton? then
3019 @real_singleton = cell
3020 end
3021 if cell.get_celltype.is_active? then
3022 @real_active = cell
3023 end
3024 end
3025 end
3026
3027 ### join
3028 def self.new_join( export_name, internal_cell_name,
3029 internal_cell_elem_name, type )
3030 @@current_object.new_join( export_name, internal_cell_name,
3031 internal_cell_elem_name, type )
3032
3033 end
3034
3035 #=== CompositeCelltype# CompositeCelltypeJoin を作成
3036 # STAGE: B
3037 #export_name:: Symbol : 外部に公開する名前
3038 #internal_cell_name:: Symbol : 内部セル名
3039 #internal_cell_elem_name:: Symbol : 内部セルの要素名(呼び口名、受け口名、属性名のいずれか)
3040 #type:: :CALL, :ENTRY, :ATTRIBUTE のいずれか(構文要素としてあるべきもの)
3041 #RETURN:: Decl | Port : エクスポート定義
3042 # new_join は
3043 # cCall => composite.cCall; (セル内)
3044 # attr = composite.attr; (セル内)
3045 # composite.eEnt => cell2.eEnt; (セル外)
3046 # の構文要素の出現に対して呼び出される
3047 def new_join( export_name, internal_cell_name,
3048 internal_cell_elem_name, type )
3049
3050 dbgPrint "new_join: #{export_name} #{internal_cell_name} #{internal_cell_elem_name}\n"
3051
3052 cell = @cell_list.get_item( internal_cell_name )
3053 if cell == nil then
3054 cdl_error( "S1057 $1 not found in $2" , internal_cell_name, @name )
3055 return
3056 end
3057
3058 celltype = cell.get_celltype
3059 return if celltype == nil # celltype == nil ならすでにエラー
3060
3061 # 内部セルのセルタイプから対応要素を探す
3062 # このメソッドは、構文上、呼び口、受け口、属性が記述できる箇所から呼出される
3063 # 構文上の呼出し位置(記述位置)と、要素が対応したものかチェック
3064 obj = celltype.find( internal_cell_elem_name )
3065 if obj.instance_of?( Decl ) then
3066 if obj.get_kind == :VAR then
3067 cdl_error( "S1058 \'$1\' : cannot export var" , internal_cell_elem_name )
3068 return
3069 elsif type != :ATTRIBUTE then
3070 cdl_error( "S1059 \'$1\' : exporting attribute. write in cell or use \'=\' to export attribute" , export_name )
3071 # return 次のエラーを避けるために処理続行し、付け加えてみる
3072 end
3073 elsif obj.instance_of?( Port ) then
3074 if obj.get_port_type != type then
3075 cdl_error( "S1060 \'$1\' : port type mismatch. $2 type is allowed here." , export_name, type )
3076 # return 次のエラーを避けるために処理続行し、付け加えてみる
3077 end
3078 else
3079 cdl_error( "S1061 \'$1\' : not defined" , internal_cell_elem_name )
3080 dbgPrint "S1061 CompositeCelltypeJoin#new_join: #{export_name} => #{internal_cell_name}.#{internal_cell_elem_name} #{type}\n"
3081 return
3082 end
3083
3084 # エクスポート定義と一致するかどうかチェック
3085 obj2 = @name_list.get_item( export_name )
3086 if( obj2 == nil )then
3087 cdl_error( "S1062 $1 has no export definition" , export_name )
3088 elsif obj2.instance_of?( Decl ) then
3089 if( ! obj.instance_of? Decl )then
3090 cdl_error( "S1063 $1 is port but previously defined as an attribute" , export_name )
3091 elsif ! obj.get_type.equal? obj2.get_type then
3092 cdl_error( "S1064 $1 : type \'$2$3\' mismatch with pprevious definition\'$4$5\'" , export_name, obj.get_type.get_type_str, obj.get_type.get_type_str_post, obj2.get_type.get_type_str, obj2.get_type.get_type_str_post )
3093 end
3094 elsif obj2.instance_of?( Port ) then
3095 if( obj.instance_of? Port )then
3096 if( obj.get_port_type != obj2.get_port_type )then
3097 cdl_error( "S1065 $1 : port type $2 mismatch with previous definition $3" , export_name, obj.get_port_type, obj2.get_port_type )
3098 elsif obj.get_signature != obj2.get_signature then
3099 if obj.get_signature != nil && obj2.get_signature != nil then
3100 # nil ならば既にエラーなので報告しない
3101 cdl_error( "S1066 $1 : signature \'$2\' mismatch with previous definition \'$3\'" , export_name, obj.get_signature.get_name, obj2.get_signature.get_name )
3102 end
3103 elsif obj.get_array_size != obj2.get_array_size then
3104 cdl_error( "S1067 $1 : array size mismatch with previous definition" , export_name )
3105 elsif obj.is_optional? != obj2.is_optional? then
3106 cdl_error( "S1068 $1 : optional specifier mismatch with previous definition" , export_name )
3107 elsif obj.is_omit? != obj2.is_omit? then
3108 cdl_error( "S9999 $1 : omit specifier mismatch with previous definition" , export_name )
3109 end
3110 else
3111 cdl_error( "S1069 $1 is an attribute but previously defined as a port" , export_name )
3112 end
3113 end
3114
3115 join = CompositeCelltypeJoin.new( export_name, internal_cell_name,
3116 internal_cell_elem_name, cell, obj2 )
3117 join.set_owner self # CompositeCelltypeJoin
3118 cell.add_compositecelltypejoin join
3119
3120 # debug
3121 dbgPrint "compositecelltype join: add #{cell.get_name} #{export_name} = #{internal_cell_name}.#{internal_cell_elem_name}\n"
3122
3123 if obj.instance_of?( Decl ) then
3124 # attribute
3125# # 内部から外部へ複数の結合がないかチェック
3126# found = false
3127# @attr_list.each{ |a|
3128# if a.get_name == join.get_name then
3129# found = true
3130# break
3131# end
3132# }
3133# if found == false then
3134 @attr_list << join
3135# end
3136 else
3137 # call/entry port
3138# # 内部から外部へ複数の結合がないかチェック
3139# found = false
3140# @port_list.each{ |port|
3141# if port.get_name == join.get_name then
3142# found = true
3143# break
3144# end
3145# }
3146# if found == false then
3147 @port_list << join
3148# end
3149 end
3150
3151 # join を @export_name_list に登録(重複チェックとともに,後で行われる CompositeCelltypeJoin の clone に備える)
3152 if obj.instance_of?( Decl ) && @export_name_list.get_item( export_name ) then
3153 # 既に存在する。追加しない。新仕様では、@export_name_list に同じ名前が含まれることがある。
3154 elsif obj.instance_of?( Port ) && obj.get_port_type == :CALL && @export_name_list.get_item( export_name ) then
3155 # 既に存在する。追加しない。新仕様では、@export_name_list に同じ名前が含まれることがある。
3156 else
3157 @export_name_list.add_item( join )
3158 end
3159
3160 # export するポートに含まれる send/receive パラメータのアロケータ(allocator)呼び口をセルと結合
3161 if obj2.instance_of? Port then
3162 obj2.each_param{ |port, fd, par|
3163 case par.get_direction # 引数の方向指定子 (in, out, inout, send, receive )
3164 when :SEND, :RECEIVE
3165 cp_name = :"#{port.get_name}_#{fd.get_name}_#{par.get_name}" # アロケータ呼び口の名前
3166 # ポート名 関数名 パラメータ名
3167 cp_internal_name = :"#{internal_cell_elem_name}_#{fd.get_name}_#{par.get_name}"
3168
3169 # リレーアロケータ or 内部アロケータ指定がなされている場合、アロケータ呼び口を追加しない
3170 # この時点では get_allocator_instance では得られないため tmp を得る
3171 if port.get_allocator_instance_tmp then
3172 found = false
3173 port.get_allocator_instance_tmp.each { |s|
3174 if s[1] == fd.get_name && s[2] == par.get_name then
3175 found = true
3176
3177 if s[0] == :INTERNAL_ALLOC then
3178 # 内部アロケータの場合 # mikan これは内部のセルに直結する。外部のポートに改めるべき
3179 @internal_allocator_list << [ cell, cp_internal_name, port.get_name, fd.get_name, par.get_name, s[3] ]
3180 end
3181 end
3182 }
3183 if found == true
3184 next
3185 end
3186 end
3187
3188 # 外部アロケータの場合
3189 new_join( cp_name, internal_cell_name, cp_internal_name, :CALL )
3190 end
3191 }
3192 end
3193
3194 # エクスポート定義を返す
3195 return obj2
3196 end
3197
3198 def self.has_attribute? attr
3199 @@current_object.has_attribute? attr
3200 end
3201
3202 def has_attribute? attr
3203 @name_list.get_item( attr ) != nil
3204 end
3205
3206 def self.new_port port
3207 @@current_object.new_port port
3208 end
3209
3210 #=== CompositeCelltype# new_port
3211 def new_port port
3212 port.set_owner self # Port (CompositeCelltype)
3213 dbgPrint "new_port: #{@owner.get_name}.#{port.get_name}\n"
3214 @name_list.add_item port
3215
3216 # export するポートに含まれる send/receive パラメータのアロケータ呼び口の export を生成してポートに追加
3217 # この時点では内部アロケータかどうか判断できないので、とりあえず生成しておく
3218 port.each_param { |port, fd, par|
3219 case par.get_direction # 引数の方向指定子 (in, out, inout, send, receive )
3220 when :SEND, :RECEIVE
3221 #### リレーアロケータ or 内部アロケータ指定がなされている場合、アロケータ呼び口を追加しない
3222 # 内部アロケータ指定がなされている場合、アロケータ呼び口を追加しない
3223 # この時点では get_allocator_instance では得られないため tmp を得る
3224 if port.get_allocator_instance_tmp then
3225 found = false
3226 port.get_allocator_instance_tmp.each { |s|
3227 if s[0] == :INTERNAL_ALLOC && s[1] == fd.get_name && s[2] == par.get_name then
3228 found = true
3229 break
3230 end
3231 }
3232 if found == true
3233 next
3234 end
3235 end
3236
3237 if par.get_allocator then
3238 cp_name = :"#{port.get_name}_#{fd.get_name}_#{par.get_name}" # アロケータ呼び口の名前
3239 # ポート名 関数名 パラメータ名
3240 alloc_sig_path = [ par.get_allocator.get_name ] # mikan Namespace アロケータ呼び口のシグニチャ
3241 array_size = port.get_array_size # 呼び口または受け口配列のサイズ
3242 created_port = Port.new( cp_name, alloc_sig_path, :CALL, array_size ) # 呼び口を生成
3243 created_port.set_allocator_port( port, fd, par )
3244 if port.is_omit? then
3245 created_port.set_omit
3246 end
3247 new_port( created_port ) # セルタイプに新しい呼び口を追加
3248 # else
3249 # already error
3250 end
3251 end
3252 }
3253 end
3254
3255 def self.new_attribute attr
3256 @@current_object.new_attribute attr
3257 end
3258
3259 #=== CompositeCelltype# new_attribute for CompositeCelltype
3260 #attribute:: [Decl]
3261 def new_attribute( attribute )
3262 attribute.each { |a|
3263 a.set_owner self # Decl (CompositeCelltype)
3264 # V1.1.0.10 composite の attr の size_is は可となった
3265 # if a.get_size_is then
3266 # cdl_error( "S1070 $1: size_is pointer cannot be exposed for composite attribute" , a.get_name )
3267 # end
3268 @name_list.add_item( a )
3269 if a.get_initializer then
3270 a.get_type.check_init( @locale, a.get_identifier, a.get_initializer, :ATTRIBUTE )
3271 end
3272 }
3273 end
3274
3275 #=== CompositeCelltype# 逆require の結合を生成する
3276 def create_reverse_require_join cell
3277 @name_list.get_items.each{ |n|
3278 if n.instance_of? Port then
3279 n.create_reverse_require_join cell
3280 end
3281 }
3282 end
3283
3284 # false : if not in celltype definition, nil : if not found in celltype
3285 def self.find( name )
3286 if @@current_object == nil then
3287 return false
3288 end
3289 @@current_object.find name
3290 end
3291
3292 def find name
3293 dbgPrint "CompositeCelltype: find in composite: #{name}\n"
3294 cell = @cell_list.get_item( name )
3295 return cell if cell
3296
3297 dbgPrint "CompositeCelltype: #{name}, #{@name_list.get_item( name )}\n"
3298 return @name_list.get_item( name )
3299
3300 # 従来仕様
3301# cj = @export_name_list.get_item( name )
3302#p "#{name}, #{cj.get_port_decl}"
3303# if cj then
3304# return cj.get_port_decl
3305# else
3306# return nil
3307# end
3308 end
3309
3310 #=== CompositeCelltype# export する CompositeCelltypeJoin を得る
3311 #name:: string:
3312 # attribute の場合、同じ名前に対し複数存在する可能性があるが、最初のものしか返さない
3313 def find_export name
3314 return @export_name_list.get_item( name )
3315 end
3316
3317 #=== CompositeCelltype# composite celltype の cell を展開
3318 #name:: string: Composite cell の名前
3319 #global_name:: string: Composite cell の global name (C 言語名)
3320 #join_list:: NamedList : Composite cell に対する Join の NamedList
3321 #RETURN:
3322 # [ { name => cell }, [ cell, ... ] ]
3323 # 戻り値 前は 名前⇒cloneされた内部セル、後ろは composite の出現順のリスト
3324 def expand( name, global_name, namespacePath, join_list, region, plugin, locale )
3325
3326 # debug
3327 dbgPrint "expand composite: #{@name} name: #{name} global_name: #{global_name}\njoin_list:\n"
3328 join_list.get_items.each{ |j|
3329 dbgPrint " #{j.get_name} #{j}\n"
3330 }
3331
3332 # 展開で clone されたセルのリスト、右辺は Cell (composite の場合 composite な cell の clone)
3333 clone_cell_list = {}
3334 clone_cell_list2 = []
3335
3336 # composite 内部のすべての cell について
3337 @cell_list.get_items.each { |c|
3338
3339 # debug
3340 dbgPrint "expand : cell #{c.get_name}\n"
3341
3342 # Join の配列
3343 ja = []
3344
3345 # CompositeCelltype が export する呼び口、受け口、属性のリストについて
3346 # @export_name_list.get_items.each{ |cj| # cj: CompositeCelltypeJoin
3347 # 新仕様では、@export_name_list に入っていない attr がありうる
3348 (@port_list+@attr_list).each{ |cj| # cj: CompositeCelltypeJoin
3349
3350 # debug
3351 dbgPrint " cj : #{cj.get_name}\n"
3352
3353 # CompositeCelltypeJoin (export) の対象セルか?
3354 if cj.match?( c ) then
3355
3356 # 対象セル内の CompositeCelltype の export する Join (attribute または call port)
3357 j = join_list.get_item( cj.get_name )
3358
3359 # debug
3360 if j then
3361 dbgPrint "expand : parent cell: #{name} child cell: #{c.get_name}: parent's export port: #{cj.get_name} join: #{j.get_name} #{j}\n"
3362 else
3363 dbgPrint "expand : parent cell: #{name} child cell: #{c.get_name}: parent's export port: #{cj.get_name} join: nil\n"
3364 end
3365
3366 if j then
3367 # 呼び口、属性の場合
3368 # ComositeCell 用のもの(j) を対象セル用に clone (@through_list もコピーされる)
3369 # p "expand: cloning Join #{j.get_name} #{@name} #{name}"
3370 jc = j.clone_for_composite( @name, name, locale )
3371 # celltype_name, cell_name
3372
3373 # debug
3374 # p "cn #{jc.get_name} #{cj.get_cell_elem_name}"
3375
3376 # 対象セルの呼び口または属性の名前に変更
3377 jc.change_name( cj.get_cell_elem_name )
3378
3379 # 対象セルに対する Join の配列
3380 ja << jc
3381 end
3382
3383 # debug
3384 dbgPrint "\n"
3385 end
3386 }
3387
3388 # debug
3389 dbgPrint "expand : clone #{name}_#{c.get_name}\n"
3390
3391 # セルの clone を生成
3392# clone_cell_list[ "#{name}_#{c.get_name}" ] = c.clone_for_composite( name, global_name, ja )
3393 c2 = c.clone_for_composite( name, global_name, namespacePath, ja, @name, region, plugin, locale )
3394 clone_cell_list[ "#{c.get_local_name}" ] = c2
3395 clone_cell_list2 << c2
3396
3397 }
3398
3399 clone_cell_list.each { |nm,c|
3400 dbgPrint " cloned: #{nm} = #{c.get_global_name}\n"
3401 # join の owner を clone されたセルに変更する V1.1.0.25
3402 c.get_join_list.get_items.each{ |j|
3403 j.set_cloned( clone_cell_list[ "#{c.get_local_name}" ] )
3404 }
3405 }
3406 return [ clone_cell_list, clone_cell_list2 ]
3407 end
3408
3409 #=== CompositeCelltype 指定子リストの設定
3410 def set_specifier_list( spec_list )
3411 return if spec_list == nil
3412
3413 spec_list.each { |s|
3414 case s[0]
3415 when :SINGLETON
3416 @b_singleton = true
3417 when :IDX_IS_ID
3418 cdl_warning( "W1005 $1 : idx_is_id is ineffective for composite celltype" , @name )
3419 when :ACTIVE
3420 @b_active = true
3421 else
3422 cdl_error( "S1071 $1 cannot be specified for composite" , s[0] )
3423 end
3424 }
3425 end
3426
3427 def get_name
3428 @name
3429 end
3430
3431 def get_port_list
3432 @port_list
3433 end
3434
3435 def get_attribute_list
3436 @attr_list
3437 end
3438
3439 def get_var_list
3440 [] # 空の配列を返す
3441 end
3442
3443 def get_internal_allocator_list
3444 @internal_allocator_list
3445 end
3446
3447 #== CompositeCelltype# generate 指定子の情報
3448 # CompositeCelltype には generate が指定できないので nil を返す
3449 # Celltype::@generate を参照のこと
3450 def get_celltype_plugin
3451 nil
3452 end
3453
3454 def is_singleton?
3455 @b_singleton
3456 end
3457
3458 def is_active?
3459 @b_active
3460 end
3461
3462 #=== CompositeCelltype# アクティブではない
3463 # active ではないに加え、全ての内部セルのセルタイプが inactive の場合に inactive
3464 # (内部のセルが active または factory を持っている)
3465 def is_inactive?
3466 if @b_active == false then
3467 @cell_list.get_items.each{ |c|
3468 if c.get_celltype && c.get_celltype.is_inactive? == false then
3469 # c.get_celltype == nil の場合はセルタイプ未定義ですでにエラー
3470 return false
3471 end
3472 }
3473 return true
3474 else
3475 return false
3476 end
3477 end
3478
3479 def get_id_base
3480 raise "get_id_base"
3481 end
3482
3483 def show_tree( indent )
3484 indent.times { print " " }
3485 puts "CompositeCelltype: name: #{@name}"
3486 (indent+1).times { print " " }
3487 puts "active: #{@b_active}, singleton: #{@b_singleton}"
3488 @cell_list.show_tree( indent + 1 )
3489 (indent+1).times { print " " }
3490 puts "name_list"
3491 @name_list.show_tree( indent + 2 )
3492 (indent+1).times { print " " }
3493 puts "export_name_list"
3494 @export_name_list.show_tree( indent + 2 )
3495 if @internal_allocator_list.length > 0 then
3496 (indent+1).times { print " " }
3497 puts "internal_allocator_list:"
3498 @internal_allocator_list.each{ |a|
3499 (indent+1).times { print " " }
3500 puts " #{a[0].get_name} #{a[1]} #{a[2]} #{a[3]} #{a[4]}"
3501 }
3502 end
3503 end
3504
3505end
3506
3507
3508
3509#== 構文要素:口を表すクラス(セルタイプの呼び口、受け口)
3510class Port < BDNode
3511# @name:: str
3512# @signature:: Signature
3513# @port_type:: :CALL, :ENTRY
3514# @array_size:: nil: not array, "[]": sizeless, Integer: sized array
3515# @reverse_require_cell_path:: NamespacePath : 逆require呼び元セル mikan namespace (呼び口のみ指定可能)
3516# @reverse_require_callport_name:: Symbol: 逆require呼び元セルの呼び口名
3517#
3518# set_allocator_port によって設定される.設定された場合、このポートはアロケータポートである。
3519# @allocator_port:: Port : この呼び口ができる元となった呼び口または受け口
3520# @allocator_func_decl:: Decl : この呼び口ができる元となった呼び口または受け口の関数
3521# @allocator_param_decl:: ParamDecl : この呼び口ができる元となった呼び口または受け口のパラメータ
3522#
3523# set_specifier によって設定される(
3524# @allocator_instance:: Hash : {"func_param" => [ :RELAY_ALLOC, func_name, param_name, rhs_cp_name, rhs_func_name, rhs_param_name ]}
3525# [:INTERNAL_ALLOC, func_name, param_name, rhs_ep_name ]
3526# @allocator_instance_tmp:: Hash : {"func_param" => [:INTERNAL_ALLOC|:RELAY_ALLOC, IDENTIFIER, IDENTIFIER, expression ],..}
3527# function parameter rhs
3528#
3529# @b_require:: bool : require により生成された call port の場合 true
3530# @b_has_name:: bool : require : 名前ありのリクワイア呼び口
3531# @b_inline:: bool : entry port のみ
3532# @b_omit:: bool : omit 指定子が指定された (call port のみ)
3533# @b_optional:: bool : call port のみ
3534# @b_ref_des:: bool : ref_desc キーワードが指定された
3535# @b_dynamic:: bool : dynamic キーワードが指定された (呼び口のみ)
3536#
3537# optimize::
3538# @celltype:: 属するセルタイプ
3539#
3540# :CALL の場合の最適化
3541# @b_VMT_useless:: bool # VMT 関数テーブルを使用しない
3542# @b_skelton_useless:: bool # スケルトン関数不要 (true の時、受け口関数を呼出す)
3543# @b_cell_unique:: bool # 呼び先は唯一のセル
3544# @only_callee_port:: Port # 唯一の呼び先ポート
3545# @only_callee_cell:: Cell # 唯一の呼び先セル (@b_PEPDES_in_CB_useless = true の時有効)
3546#
3547# :ENTRY の場合の最適化(呼び口最適化と同じ変数名を使用)
3548# @b_VMT_useless:: bool # VMT 関数テーブルが不要
3549# @b_skelton_useless:: bool # スケルトン関数不要
3550
3551 def initialize( name, sig_path, port_type, array_size = nil, reverse_require_cell_path = nil, reverse_require_entry_port_name = nil )
3552 super()
3553 @name = name
3554 @port_type = port_type
3555
3556 if array_size == "[]" then
3557# if port_type == :ENTRY then
3558# cdl_error( "S1072 $1: entry port: sizeless array not supported in current version" , name )
3559# end
3560 @array_size = array_size
3561 elsif array_size then
3562 if array_size.kind_of? Expression then
3563 @array_size = array_size.eval_const(nil)
3564 else
3565 @array_size = array_size # これはアロケータ呼び口の場合(元の呼び口で既に評価済み)
3566 end
3567 if @array_size == nil then
3568 cdl_error( "S1073 Not constant expression $1" , array_size.to_s )
3569 end
3570
3571 #if Integer( @array_size ) != @array_size || @array_size <= 0 then
3572 if ! @array_size.kind_of? Integer then
3573 cdl_error( "S1074 Not Integer $1" , array_size.to_s )
3574 end
3575
3576 end
3577
3578 object = Namespace.find( sig_path ) #1
3579 if object == nil then
3580 # mikan signature の名前が不完全
3581 cdl_error( "S1075 \'$1\' signature not found" , sig_path )
3582 elsif ! object.instance_of?( Signature ) then
3583 # mikan signature の名前が不完全
3584 cdl_error( "S1076 \'$1\' not signature" , sig_path )
3585 else
3586 @signature = object
3587
3588 end
3589
3590 # 逆require
3591 @reverse_require_cell_path = nil
3592 @reverse_require_entry_port_name = nil
3593 if reverse_require_cell_path then
3594 if port_type == :CALL then
3595 cdl_error( "S1152 $1 call port cannot have fixed join", @name )
3596 else
3597 @reverse_require_cell_path = reverse_require_cell_path
3598 @reverse_require_entry_port_name = reverse_require_entry_port_name
3599
3600 # 受け口配列か?
3601 if array_size then
3602 cdl_error( "S1153 $1: cannot be entry port array for fixed join port", @name )
3603 end
3604
3605 # 呼び口のセルタイプを探す
3606 ct_or_cell = Namespace.find( @reverse_require_cell_path ) #1
3607 if ct_or_cell.instance_of? Cell then
3608 ct = ct_or_cell.get_celltype
3609 elsif ct_or_cell.instance_of? Celltype then
3610 ct = ct_or_cell
3611 if ! ct.is_singleton? then
3612 cdl_error( "S1154 $1: must be singleton celltype for fixed join", @reverse_require_cell_path.to_s )
3613 end
3614 else
3615 ct = nil
3616 cdl_error( "S1155 $1: not celltype or not found", @reverse_require_cell_path.get_path_str)
3617 end
3618
3619 if ct == nil then
3620 return # 既にエラー
3621 end
3622
3623 # 添え字なしの呼び口配列か?
3624 port = ct.find( @reverse_require_entry_port_name )
3625 if port == nil || port.get_port_type != :CALL
3626 cdl_error( "S1156 $1: not call port or not found", @reverse_require_entry_port_name )
3627 else
3628 if port.get_array_size != "[]" then
3629 cdl_error( "S1157 $1: sized array or not array", @reverse_require_entry_port_name )
3630 end
3631 end
3632
3633 end
3634 end
3635
3636 @b_require = false
3637 @b_has_name = false
3638 @b_inline = false
3639 @b_optional = false
3640 @b_ref_desc = false
3641 @b_dynamic = false
3642 reset_optimize
3643 end
3644
3645 #=== Port#最適化に関する変数をリセットする
3646 # Region ごとに最適化のやりなおしをするため、リセットする
3647 def reset_optimize
3648 if @port_type == :CALL then
3649 # call port optimize
3650 @b_VMT_useless = false # VMT 不要 (true の時 VMT を介することなく呼出す)
3651 @b_skelton_useless = false # スケルトン関数不要 (true の時、受け口関数を呼出す)
3652 @b_cell_unique = false # 唯一の呼び先セル
3653 @only_callee_port = nil # 唯一の呼び先ポート
3654 @only_callee_cell = nil # 唯一の呼び先セル
3655 else
3656 # entry port optimize
3657 if $unopt then
3658 # 最適化なし
3659 @b_VMT_useless = false # VMT 不要 (true の時 VMT を介することなく呼出す)
3660 @b_skelton_useless = false # スケルトン関数不要 (true の時、受け口関数を呼出す)
3661 else
3662 # 最適化あり
3663 @b_VMT_useless = true # VMT 不要 (true の時 VMT を介することなく呼出す)
3664 @b_skelton_useless = true # スケルトン関数不要 (true の時、受け口関数を呼出す)
3665 end
3666 end
3667end
3668
3669 def set_celltype celltype
3670 @celltype = celltype
3671 end
3672
3673 def get_name
3674 @name
3675 end
3676
3677 def get_port_type
3678 @port_type
3679 end
3680
3681 def get_signature
3682 @signature
3683 end
3684
3685 def get_array_size
3686 @array_size
3687 end
3688
3689 def get_celltype
3690 @celltype
3691 end
3692
3693 #=== Port# アロケータポートの設定
3694 #port:: Port : send/receive のあった呼び口または受け口
3695 #fd:: Decl : 関数の declarator
3696 #par:: ParamDecl : send/receive のあった引数
3697 # この呼び口が生成されるもとになった呼び口または受け口の情報を設定
3698 def set_allocator_port( port, fd, par )
3699 @allocator_port = port
3700 @allocator_func_decl = fd
3701 @allocator_param_decl = par
3702 end
3703
3704 def is_allocator_port?
3705 @allocator_port != nil
3706 end
3707
3708 def get_allocator_port
3709 @allocator_port
3710 end
3711
3712 def get_allocator_func_decl
3713 @allocator_func_decl
3714 end
3715
3716 def get_allocator_param_decl
3717 @allocator_param_decl
3718 end
3719
3720 def set_require( b_has_name )
3721 @b_require = true
3722 @b_has_name = b_has_name
3723 end
3724
3725 def is_require?
3726 @b_require
3727 end
3728
3729 #=== Port# require 呼び口が名前を持つ?
3730 # require 限定
3731 def has_name?
3732 @b_has_name
3733 end
3734
3735 def is_optional?
3736 @b_optional
3737 end
3738
3739 def set_optional
3740 @b_optional = true
3741 end
3742
3743 #=== Port# omit 指定されている?
3744 def is_omit?
3745 @b_omit || ( @signature && @signature.is_empty? )
3746 end
3747
3748 def set_omit
3749 @b_omit = true
3750 end
3751
3752 def set_VMT_useless # VMT 関数テーブルを使用しない
3753 @b_VMT_useless = true
3754 end
3755
3756 def set_skelton_useless # スケルトン関数不要 (true の時、受け口関数を呼出す)
3757 @b_skelton_useless = true
3758 end
3759
3760 def set_cell_unique # 呼び先セルは一つだけ
3761 @b_cell_unique = true
3762 end
3763
3764 #=== Port# 呼び口/受け口の指定子の設定
3765 # inline, allocator の指定
3766 def set_specifier spec_list
3767 spec_list.each { |s|
3768 case s[0]
3769 when :INLINE
3770 if @port_type == :CALL then
3771 cdl_error( "S1077 inline: cannot be specified for call port" )
3772 next
3773 end
3774 @b_inline = true
3775 when :OMIT
3776 if @port_type == :ENTRY then
3777 cdl_error( "S9999 omit: cannot be specified for entry port" )
3778 next
3779 end
3780 @b_omit = true
3781 when :OPTIONAL
3782 if @port_type == :ENTRY then
3783 cdl_error( "S1078 optional: cannot be specified for entry port" )
3784 next
3785 end
3786 @b_optional = true
3787 when :REF_DESC
3788 @b_ref_desc = true
3789 when :DYNAMIC
3790 if @port_type == :ENTRY then
3791 cdl_error( "S9999 dynamic: cannnot be specified for entry port" )
3792 next
3793 end
3794 @b_dynamic = true
3795 when :ALLOCATOR
3796 if @port_type == :CALL then
3797 cdl_error( "S1079 allocator: cannot be specified for call port" )
3798 end
3799 if @allocator_instance_tmp then
3800 cdl_error( "S1080 duplicate allocator specifier" )
3801 next
3802 end
3803 @allocator_instance_tmp = s[1]
3804 else
3805 raise "unknown specifier #{s[0]}"
3806 end
3807 }
3808 end
3809
3810 #=== Port# リレーアロケータ、内部アロケータのインスタンスを設定
3811 # 呼び口の前方参照可能なように、セルタイプの解釈の最後で行う
3812 def set_allocator_instance
3813 if @allocator_instance_tmp == nil then
3814 return
3815 end
3816
3817 @allocator_instance = {}
3818 @allocator_instance_tmp.each { |ai|
3819 direction = nil
3820 alloc_type = ai[0]
3821 # ai = [ :INTERNAL_ALLOC|:RELAY_ALLOC, func_name, param_name, rhs ]
3822 case alloc_type
3823 when :INTERNAL_ALLOC
3824 if ! @owner.instance_of? CompositeCelltype then # ミスを防ぐために composite でなければとした
3825 cdl_error( "S1081 self allocator not supported yet" ) # mikan これはサポートされているはず。要調査 12/1/15
3826 next
3827 end
3828 # OK
3829 when :RELAY_ALLOC
3830 # OK
3831 when :NORMAL_ALLOC
3832 # ここへ来るのは composite の受け口で右辺が "eEnt.func.param" 形式で指定されていた場合
3833 cdl_error( "S1174 $1 not suitable for lhs, suitable lhs: 'func.param'", "#{ai[1]}.#{ai[3]}.#{ai[4]}" )
3834 next
3835 else
3836 raise "Unknown allocator type #{ai[1]}"
3837 end
3838
3839 # '=' 左辺(func_name,param_name)は実在するか?
3840 if @signature then # signature = nil なら既にエラー
3841 fh = @signature.get_function_head( ai[1] )
3842 if fh == nil then
3843 cdl_error( "S1082 function \'$1\' not found in signature" , ai[1] )
3844 next
3845 end
3846 decl = fh.get_declarator
3847 if ! decl.is_function? then
3848 next # 既にエラー
3849 end
3850 paramdecl = decl.get_type.get_paramlist.find( ai[2] )
3851 if paramdecl == nil then
3852 cdl_error( "S1083 \'$1\' not found in function \'$2\'" , ai[2], ai[1] )
3853 next
3854 end
3855 case paramdecl.get_direction
3856 when :SEND, :RECEIVE
3857 # OK
3858 direction = paramdecl.get_direction
3859 else
3860 cdl_error( "S1084 \'$1\' in function \'$2\' is not send or receive" , ai[2], ai[1] )
3861 next
3862 end
3863 end
3864
3865 # 重複指定がないか?
3866 if @allocator_instance[ "#{@name}_#{ai[1]}_#{ai[2]}" ] then
3867 cdl_error( "S1085 duplicate allocator specifier for \'$1_$2\'" , ai[1], ai[2] )
3868 end
3869
3870 # 右辺のチェック
3871 case alloc_type
3872 when :INTERNAL_ALLOC
3873
3874 ele = ai[3].get_elements
3875 if( ele[0] != :IDENTIFIER )then
3876 cdl_error( "S1086 $1: rhs not in 'allocator_entry_port' form", ai[3].to_s )
3877 next
3878 end
3879
3880 ep_name = ele[1] # アロケータ受け口名
3881 ep = @owner.find ep_name.get_path[0] # mikan "a::b"
3882 if ep == nil || ! ep.instance_of?( Port ) || ep.get_port_type != :ENTRY || ! ep.get_signature.is_allocator? then
3883 cdl_error( "S1175 $1 not found or not allocator entry port for $2" , ep_name, ai[1] )
3884 end
3885 # 右辺チェック終わり
3886 # ai2 = [ :INTERNAL_ALLOC, func_name, param_name, rhs_ep_name ]
3887 ai2 = [ ai[0], ai[1], ai[2], ep_name ]
3888
3889 when :RELAY_ALLOC
3890 ele = ai[3].get_elements
3891 if( ele[0] != :OP_DOT ||
3892 ele[1][0] != :OP_DOT || ele[1][1][0] != :IDENTIFIER || ! ele[1][1][1].is_name_only? ||
3893 ! ele[1][2].instance_of?( Token ) || ! ele[2].instance_of?( Token ) )then #1
3894 # [ :OP_DOT, [ :OP_DOT, [ :IDENTIFIER, name_space_path ], Token(1) ], Token(2) ]
3895 # ele[0] ele[1][0] ele[1][1][0] ele[1][1][1] ele[1][2] ele[2]
3896 # name_space_path.Token(1).Token(2) === call_port.func.param
3897 # mikan Expression#analyze_cell_join_expression の変種を作成して置き換えるべき
3898
3899 cdl_error( "S1176 rhs not in 'call_port.func.param' form for for $1_$2" , ai[1], ai[2] ) # S1086
3900 next
3901 end
3902 func_name = ele[1][2]; cp_name = ele[1][1][1].get_name; param_name = ele[2].to_sym
3903 cp = @owner.find cp_name # リレーする先の呼び口
3904 if cp then
3905# mikan cp が呼び口であることのチェック(属性の場合もある)
3906# mikan 受け口から受け口へのリレーへの対応 (呼び口から呼び口へのリレーはありえない) <=== 文法にかかわる事項(呼び口側でアロケータが決定される)
3907 sig = cp.get_signature
3908 if sig && @signature then
3909 fh = @signature.get_function_head( func_name )
3910 if fh == nil then
3911 cdl_error( "S1087 function \'$1\' not found in signature \'$2\'" , func_name, sig.get_name )
3912 next
3913 end
3914 decl = fh.get_declarator
3915 if ! decl.is_function? then
3916 next # 既にエラー
3917 end
3918 paramdecl = decl.get_type.get_paramlist.find( param_name )
3919 if paramdecl == nil then
3920 cdl_error( "S1088 \'$1\' not found in function \'$2\'" , param_name, func_name )
3921 next
3922 end
3923 case paramdecl.get_direction
3924 when :SEND, :RECEIVE
3925 # OK
3926 if alloc_type == :RELAY_ALLOC && direction != paramdecl.get_direction then
3927 cdl_error( "S1089 relay allocator send/receive mismatch between $1.$2 and $3_$4.$5" , ai[1], ai[2], cp_name, func_name, param_name )
3928 end
3929 else
3930 cdl_error( "S1090 \'$1\' in function \'$2\' is not send or receive" , param_name, func_name )
3931 next
3932 end
3933
3934 # else
3935 # sig == nil ならば既にエラー
3936 end
3937 else
3938 if @celltype then
3939 ct_name = @celltype.get_name
3940 else
3941 ct_name = "(None)"
3942 end
3943 cdl_error( "S1091 call port \'$1\' not found in celltype $2" , cp_name, ct_name )
3944 next
3945 end
3946 # 右辺チェック終わり
3947 # ai2 = [ :RELAY_ALLOC, func_name, param_name, rhs_cp_name, rhs_func_name, rhs_param_name ]
3948 ai2 = [ ai[0], ai[1], ai[2], cp_name, func_name, param_name ]
3949 end # case alloc_type
3950
3951 @allocator_instance[ "#{@name}_#{ai[1]}_#{ai[2]}" ] = ai2
3952 }
3953 end
3954
3955 def is_inline?
3956 @b_inline
3957 end
3958
3959 def is_VMT_useless? # VMT 関数テーブルを使用しない
3960 @b_VMT_useless
3961 end
3962
3963 def is_skelton_useless? # スケルトン関数不要 (true の時、受け口関数を呼出す)
3964 @b_skelton_useless
3965 end
3966
3967 def is_cell_unique? # 呼び先のセルは一つ?
3968 @b_cell_unique
3969 end
3970
3971 #=== Port# 受け口最適化の設定
3972 # この受け口を参照する呼び口が VMT, skelton を必要としているかどうかを設定
3973 # 一つでも呼び口が必要としている(すなわち b_*_useless が false)場合は、
3974 # この受け口の最適化を false とする
3975 def set_entry_VMT_skelton_useless( b_VMT_useless, b_skelton_useless )
3976 if ! b_VMT_useless then
3977 @b_VMT_useless = false
3978 end
3979 if ! b_skelton_useless then
3980 @b_skelton_useless = false
3981 end
3982 end
3983
3984 #=== Port# 唯一の結合先を設定
3985 # 最適化で使用
3986 # b_VMT_useless == true || b_skelton_useless == true の時に設定される
3987 # optional の場合 callee_cell, callee_port が nil となる
3988 def set_only_callee( callee_port, callee_cell )
3989 @only_callee_port = callee_port
3990 @only_callee_cell = callee_cell
3991 end
3992
3993 #=== Port# 唯一の結合先ポートを返す(compositeの場合実セル)
3994 # optional 呼び口で未結合の場合 nil を返す
3995 def get_real_callee_port
3996 if @only_callee_cell then
3997 return @only_callee_cell.get_real_port( @only_callee_port.get_name )
3998 end
3999 end
4000
4001 #=== Port# 唯一の結合先セルを返す(compositeの場合実セル)
4002 # optional 呼び口で未結合の場合 nil を返す
4003 def get_real_callee_cell
4004 if @only_callee_cell then
4005 return @only_callee_cell.get_real_cell( @only_callee_port.get_name )
4006 end
4007 end
4008
4009 def get_allocator_instance
4010 return @allocator_instance
4011 end
4012
4013 def get_allocator_instance_tmp
4014 return @allocator_instance_tmp
4015 end
4016
4017 #=== Port# 逆require の結合を生成する
4018 # STAGE: S
4019 def create_reverse_require_join cell
4020 if @reverse_require_cell_path == nil then
4021 return
4022 end
4023
4024 # 呼び元セルを探す
4025 ct_or_cell = Namespace.find( @reverse_require_cell_path ) # mikan namespace #1
4026 if ct_or_cell.instance_of? Cell then
4027 cell2 = ct_or_cell
4028 ct = cell2.get_celltype
4029 if ct == nil then
4030 return # 既にエラー
4031 end
4032 elsif ct_or_cell.instance_of? Celltype then
4033 cell2 = ct_or_cell.get_singleton_cell( cell.get_region )
4034 if cell2 == nil then
4035 cdl_error( "S1158 $1: singleton cell not found for fixed join", ct_or_cell.get_name )
4036 return
4037 end
4038 ct = ct_or_cell
4039 else
4040 # 既にエラー:無視
4041 return
4042 end
4043
4044 # 結合を生成する
4045 dbgPrint "create_reverse_require_join #{cell2.get_name}.#{@reverse_require_entry_port_name}[] = #{cell.get_name}.#{@name}"
4046 nsp = NamespacePath.new( cell.get_name, false, cell.get_namespace )
4047# rhs = Expression.new( [ :OP_DOT, [ :IDENTIFIER, Token.new( cell.get_name, nil, nil, nil ) ],
4048 rhs = Expression.new( [ :OP_DOT, [ :IDENTIFIER, nsp ],
4049 Token.new( @name, nil, nil, nil ) ], cell.get_locale ) #1
4050 join = Join.new( @reverse_require_entry_port_name, -1, rhs, cell.get_locale )
4051 cell2.new_join( join )
4052 join.set_definition( ct.find(join.get_name) )
4053
4054 end
4055
4056 #=== Port# signature のすべての関数のすべてのパラメータをたどる
4057 #block:: ブロックを引数として取る(ruby の文法で書かない)
4058 # ブロックは3つの引数を受け取る(Port, Decl, ParamDecl) Decl: 関数ヘッダ
4059 # Signature クラスにも each_param がある(同じ働き)
4060 def each_param # ブロック引数{ |port, func_decl, param_decl| }
4061 return if @signature == nil # signature 未定義(既にエラー)
4062 fha = @signature.get_function_head_array # 呼び口または受け口のシグニチャの関数配列
4063 return if fha == nil # nil なら文法エラーで有効値が設定されなかった
4064
4065 pr = Proc.new # このメソッドのブロック引数を pr に代入
4066 port = self
4067 fha.each{ |fh| # fh: FuncHead # 関数配列中の各関数頭部
4068 fd = fh.get_declarator # fd: Decl (関数頭部からDeclarotorを得る)
4069 if fd.is_function? then # fd が関数でなければ、すでにエラー
4070 fd.get_type.get_paramlist.get_items.each{ |par| # すべてのパラメータについて
4071 pr.call( port, fd, par )
4072 }
4073 end
4074 }
4075 end
4076
4077 #=== Port# 逆require指定されている?
4078 def is_reverse_required?
4079 @reverse_require_cell_path != nil
4080 end
4081
4082 def show_tree( indent )
4083 indent.times { print " " }
4084 puts "Port: name:#{@name} port_type:#{@port_type} require:#{@b_require} inline:#{@b_inline} omit:#{@b_omit} optional:#{@b_optional} ref_desc:#{@b_ref_desc} dynamic:#{@b_dynamic}"
4085 (indent+1).times { print " " }
4086 if @signature then
4087 puts "signature: #{@signature.get_name} #{@signature}"
4088 else
4089 puts "signature: NOT defined"
4090 end
4091 if @array_size == "[]" then
4092 (indent+1).times { print " " }
4093 puts "array_size: not specified"
4094 elsif @array_size then
4095 (indent+1).times { print " " }
4096 puts "array_size: #{@array_size}"
4097 end
4098 if @allocator_instance then
4099 (indent+1).times { print " " }
4100 puts "allocator instance:"
4101 @allocator_instance.each { |b,a|
4102 (indent+2).times { print " " }
4103 puts "#{a[0]} #{a[1]} #{b} "
4104 # a[3].show_tree( indent+3 )
4105 }
4106 end
4107 (indent+1).times { print " " }
4108 if @port_type == :CALL then
4109 puts "VMT_useless : #{@b_VMT_useless} skelton_useless : #{@b_skelton_useless} cell_unique : #{@b_cell_unique}"
4110 else
4111 puts "VMT_useless : #{@b_VMT_useless} skelton_useless : #{@b_skelton_useless}"
4112 end
4113 end
4114
4115end
4116
4117#== Namespace
4118#
4119# root namespace だけ、Region クラスのインスタンスとして生成される
4120# root namespace は、root region を兼ねるため
4121#
4122# @cell_list は Region の場合にのみ持つ (mikan @cell_list 関連は Region に移すべき)
4123#
4124class Namespace < NSBDNode
4125# @name:: Symbol # root の場合 "::" (String)
4126# @global_name:: str
4127# @name_list:: NamedList Signature,Celltype,CompositeCelltype,Cell,Typedef,Namespace
4128# @struct_tag_list:: NamedList : StructType
4129# @namespace_list:: Namespace[] : Region は Namespace の子クラスであり、含まれる
4130# @signature_list:: Sginature[]
4131# @celltype_list:: Celltype[]
4132# @compositecelltype_list:: CompositeCelltype[]
4133# @cell_list:: Cell[]
4134# @typedef_list:: Typedef[]
4135# @decl_list:: ( Typedef | StructType | EnumType )[] 依存関係がある場合に備えて、順番どおりに配列に格納 mikan enum
4136# @const_decl_list:: Decl[]
4137# @cache_n_cells:: Integer : get_n_cells の結果をキャッシュする
4138# @cache_generating_region:: Region : get_n_cells の結果をキャッシュするしているリージョン
4139
4140 # mikan namespace の push, pop
4141
4142 # namespace 階層用のスタック
4143 @@namespace_stack = [] # @@namespace_stack[0] = "::" (generator.rb)
4144 @@namespace_sp = -1
4145
4146 # Generator ネスト用のスタック (namespace 階層用のスタックを対比する)
4147 @@nest_stack_index = -1
4148 @@nest_stack = []
4149
4150 @@root_namespace = nil
4151
4152 # Generator ネスト用スタックの push, pop (クラスメソッド)
4153 def self.push
4154 dbgPrint "push Namespace\n"
4155 @@nest_stack_index += 1
4156 @@nest_stack[ @@nest_stack_index ] = [ @@namespace_stack, @@namespace_sp ]
4157 if @@root_namespace then
4158 @@namespace_sp = 0
4159 @@namespace_stack[ @@namespace_sp ] = @@root_namespace
4160 end
4161 end
4162
4163 def self.pop
4164 dbgPrint "pop Namespace\n"
4165 @@namespace_stack, @@namespace_sp = @@nest_stack[ @@nest_stack_index ]
4166 @@nest_stack_index -= 1
4167 if @@nest_stack_index < -1 then
4168 raise "TooManyRestore"
4169 end
4170 end
4171
4172 # namespace 階層用スタックの push, pop (インスタンスメソッド)
4173 def push ns
4174 @@namespace_sp += 1
4175 @@namespace_stack[ @@namespace_sp ] = self
4176 dbgPrint "Namespace.PUSH #{@@namespace_sp} #{@name}\n"
4177 end
4178
4179 def pop
4180 dbgPrint "Namespace.POP #{@@namespace_sp} #{@name}\n"
4181 @@namespace_sp -= 1
4182 if @@namespace_sp < 0 then
4183 raise "StackUnderflow"
4184 end
4185 end
4186
4187 def initialize( name )
4188
4189 super()
4190 @name = name
4191
4192 if( name == "::" )then
4193 if( @@root_namespace != nil )then
4194 # root は一回のみ生成できる
4195 raise "try to re-create root namespace"
4196 end
4197 @@root_namespace = self
4198 @NamespacePath = NamespacePath.new( name, true )
4199 else
4200 ns = @@namespace_stack[ @@namespace_sp ].find( name )
4201 if ns.kind_of? Namespace then
4202 dbgPrint "namespace: re-appear #{@name}\n"
4203 # 登録済み namespace の再登録
4204 ns.push ns
4205 return
4206 elsif ns then
4207 cdl_error( "S1151 $1: not namespace", @name )
4208 prev_locale = ns.get_locale
4209 puts "previous: #{prev_locale[0]}: line #{prev_locale[1]} \'#{name}\' defined here"
4210 end
4211 dbgPrint "namespace: 1st-appear #{@name}\n"
4212 end
4213
4214 if @@namespace_sp >= 0 then # root は除外
4215 @@namespace_stack[@@namespace_sp].new_namespace( self )
4216 end
4217 push self
4218
4219 @global_name = Namespace.get_global_name # stack 登録後取る
4220 @name_list = NamedList.new( nil, "symbol in namespace '#{@name}'" )
4221 @struct_tag_list = NamedList.new( nil, "struct tag" )
4222
4223 @namespace_list = []
4224 @signature_list = []
4225 @celltype_list = []
4226 @compositecelltype_list = []
4227 @cell_list = []
4228 @typedef_list = []
4229 @decl_list = []
4230 @const_decl_list = []
4231 @cache_n_cells = nil
4232 @cache_generating_region = nil
4233 if @NamespacePath == nil then
4234 # root namespace の場合は設定済 (親 namespace が見つからず例外になる)
4235 set_namespace_path # @NamespacePath の設定
4236 end
4237 end
4238
4239 def end_of_parse
4240 pop
4241 end
4242
4243 def get_name
4244 @name
4245 end
4246
4247 #=== Namespace:: global_name を得る
4248 # parse 中のみこのメソッドは使える
4249 # STAGE: P
4250 def self.get_global_name # parse 中有効
4251 if @@namespace_sp <= 0 then
4252 return ""
4253 end
4254
4255 path = @@namespace_stack[1].get_name.to_s
4256 i = 2
4257 while i <= @@namespace_sp
4258 path = path+"_"+@@namespace_stack[i].get_name.to_s
4259 i += 1
4260 end
4261
4262 path
4263 end
4264
4265 def get_global_name
4266 @global_name
4267 end
4268
4269 #=== Namespace#セルの個数を得る
4270 # 子 region が linkunit, node 指定されていれば、含めない(別のリンク単位)
4271 # プロトタイプ宣言のもののみの個数を含めない
4272 # mikan namespace 下に cell を置けない仕様になると、このメソッドは Region のものでよい
4273 # mikan 上記の場合 instance_of? Namespace の条件判定は不要となる
4274 def get_n_cells
4275 if @cache_generating_region == $generating_region then
4276 # このメソッドは繰り返し呼び出されるため、結果をキャッシュする
4277 return @cache_n_cells
4278 end
4279
4280 count = 0
4281 @cell_list.each{ |c|
4282 # 定義かプロトタイプ宣言だけかは、new_cell の段階で判断できないため、カウントしなおす
4283 if c.get_f_def == true then
4284 # print "get_n_cells: cell: #{c.get_name}\n"
4285 count += 1
4286 end
4287 }
4288
4289 @namespace_list.each{ |ns|
4290 if ns.instance_of? Namespace then
4291 count += ns.get_n_cells
4292 else
4293 # ns は Region である
4294 rt = ns.get_region_type
4295 # print "get_n_cells: region: #{ns.get_name}: #{rt}\n"
4296 if rt == :NODE || rt == :LINKUNIT then
4297 # 別の linkunit なので加算しない
4298 else
4299 count += ns.get_n_cells
4300 end
4301 end
4302 }
4303
4304 @cache_generating_region = $generating_region
4305 @cache_n_cells = count
4306 return count
4307 end
4308
4309 #=== Namespace.find : in_path で示されるオブジェクトを探す
4310 #in_path:: NamespacePath
4311 #in_path:: Array : 古い形式
4312 # path [ "::", "ns1", "ns2" ] absolute
4313 # path [ "ns1", "ns2" ] relative
4314 def self.find( in_path )
4315
4316 if in_path.instance_of? Array then
4317 # raise "Namespace.find: old fashion"
4318
4319 path = in_path
4320 length = path.length
4321 return self.find_one( path[0] ) if length == 1
4322
4323 name = path[0]
4324 if name == "::" then
4325 i = 1
4326 name = path[i] # 構文的に必ず存在
4327 object = @@root_namespace.find( name ) # root
4328 else
4329 # 相対パス
4330 i = 0
4331 object = @@namespace_stack[@@namespace_sp].find_one( name ) # crrent
4332 end
4333
4334 elsif in_path.instance_of? NamespacePath then
4335 path = in_path.get_path
4336 length = path.length
4337
4338 if length == 0 then
4339 if in_path.is_absolute? then
4340 return @@root_namespace
4341 else
4342 raise "path length 0, not absolute"
4343 end
4344 end
4345
4346 i = 0
4347 name = path[0]
4348 if in_path.is_absolute? then
4349 object = @@root_namespace.find( name ) # root
4350 else
4351 bns = in_path.get_base_namespace
4352 object = bns.find_one( name ) # crrent
4353 end
4354 else
4355 raise "unexpected path"
4356 end
4357
4358 i += 1
4359 while i < length
4360
4361 unless object.kind_of?( Namespace ) then
4362 # クラスメソッド内で cdl_error を呼び出すことはできない
4363 # また、前方参照対応後、正確な行番号が出ない問題も生じる
4364 # cdl_error( "S1092 \'$1\' not namespace" , name )
4365 # このメソッドから nil が帰った場合 "not found" が出るので、ここでは出さない
4366 return nil
4367 end
4368
4369 object = object.find( path[i] )
4370 i += 1
4371 end
4372
4373 return object
4374 end
4375
4376
4377 def find( name )
4378 @name_list.get_item(name)
4379 end
4380
4381 #=== Namespace# namespace から探す。見つからなければ親 namespace から探す
4382 def self.find_one( name )
4383 return @@namespace_stack[@@namespace_sp].find_one( name )
4384 end
4385
4386 def find_one( name )
4387
4388 object = find( name )
4389 # これは出すぎ
4390 # dbgPrint "in '#{@name}' find '#{name}' object #{object ? object.class : "Not found"}\n"
4391
4392 if object != nil then
4393 return object
4394 elsif @name != "::" then
4395 return @owner.find_one( name )
4396 else
4397 return nil
4398 end
4399 end
4400
4401 def self.get_current
4402 @@namespace_stack[@@namespace_sp]
4403 end
4404
4405 def self.find_tag( name )
4406 # mikan tag : namespace の path に対応しない
4407 # namespace の中にあっても、root namespace にあるものと見なされる
4408 # よって カレント namespace から根に向かって探す
4409 i = @@namespace_sp
4410 while i >= 0
4411 res = @@namespace_stack[i].find_tag( name )
4412 if res then
4413 return res
4414 end
4415 i -= 1
4416 end
4417 end
4418
4419 def find_tag( name )
4420 @struct_tag_list.get_item( name )
4421 end
4422
4423 ### namespace
4424 def self.new_namespace( namespace )
4425 @@namespace_stack[@@namespace_sp].new_namespace( namespace )
4426 end
4427
4428 def new_namespace( namespace )
4429 dbgPrint "new_namespace: #{@name}:#{self} #{namespace.get_name}:#{namespace} \n"
4430 namespace.set_owner self # Namespace (Namespace)
4431
4432 @name_list.add_item( namespace )
4433 @namespace_list << namespace
4434 end
4435
4436 ### signature
4437 def self.new_signature( signature )
4438 @@namespace_stack[@@namespace_sp].new_signature( signature )
4439 end
4440
4441 def new_signature( signature )
4442 signature.set_owner self # Signature (Namespace)
4443 @name_list.add_item( signature )
4444 @signature_list << signature
4445 end
4446
4447 ### celltype
4448 def self.new_celltype( celltype )
4449 @@namespace_stack[@@namespace_sp].new_celltype( celltype )
4450 end
4451
4452 def new_celltype( celltype )
4453 celltype.set_owner self # Celltype (Namespace)
4454 @name_list.add_item( celltype )
4455 @celltype_list << celltype
4456 end
4457
4458 ### compositecelltype
4459 def self.new_compositecelltype( compositecelltype )
4460 @@namespace_stack[@@namespace_sp].new_compositecelltype( compositecelltype )
4461 end
4462
4463 def new_compositecelltype( compositecelltype )
4464 compositecelltype.set_owner self # CompositeCelltype (Namespace)
4465 @name_list.add_item( compositecelltype )
4466 @compositecelltype_list << compositecelltype
4467 end
4468
4469 ### cell (Namespace)
4470 def self.new_cell( cell )
4471 @@namespace_stack[@@namespace_sp].new_cell( cell )
4472 end
4473
4474 def new_cell( cell )
4475 dbgPrint "Namespace.new_cell: #{@NamespacePath.get_path_str}::#{cell.get_name}\n"
4476 if ! is_root? && ! ( instance_of? Region ) then
4477 cdl_error( "S9999 '$1' cell cannot be placed under namespace", cell.get_name )
4478 end
4479 cell.set_owner self # Cell (Namespace)
4480 @name_list.add_item( cell )
4481 @cell_list << cell
4482 end
4483
4484 #=== Namespace# 参照されているが、未定義のセルを探す
4485 # プロトタイプ宣言だけで定義されていないケースをエラーとする
4486 # 受動の未結合セルについて警告する
4487 def check_ref_but_undef
4488 @cell_list.each { |c|
4489 if ! c.get_f_def then # Namespace の @cell_list にはプロトタイプが含まれるケースあり
4490 if c.get_f_ref then
4491 cdl_error( "S1093 $1 : undefined cell" , c.get_namespace_path.get_path_str )
4492 elsif $verbose then
4493 cdl_warning( "W1006 $1 : only prototype, unused and undefined cell" , c.get_namespace_path.get_path_str )
4494 end
4495 else
4496 dbgPrint "check_ref_but_undef: #{c.get_global_name}\n"
4497 ct = c.get_celltype
4498 # if c.get_f_ref == false && c.is_generate? && ct && ct.is_inactive? then
4499 if c.get_f_ref == false && ct && ct.is_inactive? then
4500 cdl_warning( "W1007 $1 : non-active cell has no entry join and no factory" , c.get_namespace_path.get_path_str )
4501 end
4502 end
4503 }
4504 @namespace_list.each { |n|
4505 n.check_ref_but_undef
4506 }
4507 end
4508
4509 #=== Namespace# セルの受け口の参照カウントを設定する
4510 def set_port_reference_count
4511 @cell_list.each { |c|
4512 c.set_port_reference_count
4513 }
4514 @namespace_list.each { |n|
4515 n.set_port_reference_count
4516 }
4517 end
4518
4519 ### struct
4520 def self.new_structtype( struct )
4521 @@namespace_stack[@@namespace_sp].new_structtype( struct )
4522 end
4523
4524 def new_structtype( struct )
4525 # struct.set_owner self # StructType (Namespace) # StructType は BDNode ではない
4526 dup = @struct_tag_list.get_item(struct.get_name)
4527 if dup != nil then
4528 if struct.same? dup then
4529 # 同じものが typedef された
4530 # p "#{struct.get_name}"
4531 return
4532 end
4533 end
4534
4535 @struct_tag_list.add_item( struct )
4536 @decl_list << struct
4537 end
4538
4539 ### typedef
4540 def self.new_typedef( typedef )
4541 @@namespace_stack[@@namespace_sp].new_typedef( typedef )
4542 end
4543
4544 def new_typedef( typedef )
4545 typedef.set_owner self # TypeDef (Namespace)
4546 dup = @name_list.get_item(typedef.get_name)
4547 if dup != nil then
4548 typedef_type = typedef.get_declarator.get_type.get_original_type
4549 dup_type = dup.get_declarator.get_type.get_original_type
4550 # print "typedef: #{typedef.get_name} = #{typedef_type.get_type_str} #{typedef_type.get_type_str_post}\n"
4551 if typedef_type.get_type_str == dup_type.get_type_str &&
4552 typedef_type.get_type_str_post == dup_type.get_type_str_post then
4553 # 同じものが typedef された
4554 # ここへ来るのは C で関数ポインタを typedef しているケース
4555 # 以下のように二重に定義されている場合は type_specifier_qualifier_list として扱われる
4556 # typedef long LONG;
4557 # typedef long LONG;
4558 # bnf.y.rb では declarator に TYPE_NAME を許さないので、ここへ来ることはない
4559 # p "#{typedef.get_declarator.get_type.get_type_str} #{typedef.get_name} #{typedef.get_declarator.get_type.get_type_str_post}"
4560 return
4561 end
4562 # p "prev: #{dup.get_declarator.get_type.get_type_str}#{dup.get_declarator.get_type.get_type_str_post} current:#{typedef.get_declarator.get_type.get_type_str} #{typedef.get_declarator.get_type.get_type_str_post}"
4563 end
4564
4565 # p "typedef: #{typedef.get_name} #{typedef.get_declarator.get_type.get_original_type.get_type_str}#{typedef.get_declarator.get_type.get_original_type.get_type_str_post}"
4566 # typedef.show_tree 0
4567
4568 @name_list.add_item( typedef )
4569 @typedef_list << typedef
4570 @decl_list << typedef
4571 end
4572
4573 def self.is_typename?( str )
4574 i = @@namespace_sp
4575 while i >= 0
4576 if @@namespace_stack[i].is_typename?( str ) then
4577 return true
4578 end
4579 i -= 1
4580 end
4581 false
4582 end
4583
4584 def is_typename?( str )
4585 if @name_list.get_item( str ).instance_of?( Typedef ) then
4586 true
4587 else
4588 false
4589 end
4590 end
4591
4592 ### const_decl
4593 def self.new_const_decl( decl )
4594 @@namespace_stack[@@namespace_sp].new_const_decl( decl )
4595 end
4596
4597 def new_const_decl( decl )
4598 decl.set_owner self # Decl (Namespace:const)
4599 if ! decl.is_const? then # const 修飾さていること
4600 if decl.is_type?( PtrType ) then
4601 cdl_error( "S1094 $1: pointer is not constant. check \'const\'" , decl.get_name )
4602 else
4603 cdl_error( "S1095 $1: not constant" , decl.get_name )
4604 end
4605 elsif ! decl.is_type?( IntType ) && ! decl.is_type?( FloatType ) &&
4606 ! decl.is_type?( BoolType ) && ! decl.is_type?( PtrType ) then
4607 # IntType, FloatType であること
4608 cdl_error( "S1096 $1: should be int, float, bool or pointer type" , decl.get_name )
4609 elsif decl.get_initializer == nil then # 初期値を持つこと
4610 cdl_error( "S1097 $1: has no initializer" , decl.get_name )
4611# elsif decl.get_initializer.eval_const(nil) == nil then #eval_const は check_init で呼出されるので二重チェック
4612# # mikan 初期値が型に対し適切であること
4613# cdl_error( "S1098 $1: has unsuitable initializer" , decl.get_name )
4614 else
4615 decl.get_type.check_init( @locale, decl.get_name, decl.get_initializer, :CONSTANT )
4616 @name_list.add_item( decl )
4617 @const_decl_list << decl
4618 end
4619
4620 end
4621
4622 ### region
4623 # def self.new_region( region )
4624 # @@namespace_stack[@@namespace_sp].new_region( region )
4625 # end
4626#
4627 # def new_region( region )
4628 # region.set_owner self # Rgion (Namespace)
4629 # @name_list.add_item( region )
4630 # end
4631
4632 ###
4633
4634 #=== Namespace# すべてのセルの require ポートを設定
4635 # STAGE: S
4636 def set_require_join
4637 @celltype_list.each{ |ct|
4638 ct.set_require_join
4639 }
4640 # すべての namespace について require ポートをセット
4641 @namespace_list.each{ |ns|
4642 ns.set_require_join
4643 }
4644 end
4645
4646 #=== Namespace# Join への definition の設定とチェック
4647 # セルタイプに属するすべてのセルに対して実施
4648 def set_definition_join
4649 # celltype のコードを生成
4650 @cell_list.each { |c|
4651 dbgPrint "set_definition_join #{c.get_name}\n"
4652 c.set_definition_join
4653 }
4654 @namespace_list.each{ |ns|
4655 ns.set_definition_join
4656 }
4657 end
4658
4659 #=== Namespace# セルの結合をチェックする
4660 def check_join
4661 @cell_list.each { |c|
4662 dbgPrint "check_join #{c.get_name}\n"
4663 c.check_join
4664 c.check_reverse_require
4665 }
4666 @namespace_list.each{ |ns|
4667 ns.check_join
4668 }
4669 end
4670
4671 #== Namespace# ルートか?
4672 # ルートネームスペース と ルートリージョンは同じ
4673 def is_root?
4674 @name == "::"
4675 end
4676
4677 #== Namespace# ルートを得る
4678 # ルートリージョンとルートネームスペースは同じオブジェクト
4679 def self.get_root
4680 @@root_namespace
4681 end
4682
4683 def show_tree( indent )
4684 indent.times { print " " }
4685 puts "#{self.class}: name: #{@name} path: #{get_namespace_path.get_path_str}"
4686 @struct_tag_list.show_tree( indent + 1 )
4687 @name_list.show_tree( indent + 1 )
4688 end
4689
4690end
4691
4692
4693class Join < BDNode
4694# @name:: string
4695# @subscript:: nil: not array, -1: subscript not specified, >=0: array_subscript
4696# @rhs:: Expression | initializer ( array of Expression | initializer (Expression | C_EXP) )
4697# @definition:: Port, Decl(attribute or var)
4698#
4699# available if definition is Port
4700# @cell_name:: string : 右辺のセルの名前
4701# @cell:: Cell : 右辺のセル
4702# @celltype:: Celltype : 右辺のセルタイプ
4703# @port_name:: string : 右辺の受け口名
4704# @port:: Port : 右辺の受け口
4705# @array_member:: rhs array : available only for first appear in the same name
4706# @array_member2:: Join array : available only for first appear in the same name
4707# @rhs_subscript:: nil : not array, >=0: 右辺の添数
4708#
4709
4710# @through_list:: @cp_through_list + @region_through_list
4711# 以下の構造を持つ(@cp_through_list の構造は共通)
4712# @cp_through_list:: 呼び口に指定された through
4713# [ [plugin_name, cell_name, plugin_arg], [plugin_name2, cell_name2, plugin_arg], ... ]
4714# @region_through_list:: region に指定された through
4715# [ [plugin_name, cell_name, plugin_arg, region], [plugin_name2, cell_name2, plugin_arg, region2], ... ]
4716#
4717# @through_generated_list:: [Plugin_class object, ...]: @through_list に対応
4718# @region_through_generated_list:: [Plugin_class object, ...]: @region_through_list に対応
4719#
4720
4721 include PluginModule
4722
4723 #=== Join# 初期化
4724 #name:: string: 名前(属性名、呼び口名)
4725 #subscript:: Nil=非配列, -1="[]", N="[N]"
4726 #rhs:: Expression: 右辺の式
4727 def initialize( name, subscript, rhs, locale = nil )
4728 # dbgPrint "Join#new: #{name}, #{subscript} #{rhs.eval_const(nil)}\n"
4729 dbgPrint "Join#new: #{name}, #{subscript}\n"
4730
4731 super()
4732 if locale then
4733 @locale = locale
4734 end
4735
4736 @name = name
4737 if subscript.instance_of?( Expression ) then
4738 #mikan 配列添数が整数であることを未チェック
4739 @subscript = subscript.eval_const(nil)
4740 if @subscript == nil then
4741 cdl_error( "S1099 array subscript not constant" )
4742 end
4743 else
4744 @subscript = subscript
4745 end
4746
4747 @rhs = rhs
4748 @definition = nil
4749
4750 # 配列要素を設定
4751 # 本当は、初出の要素のみ設定するのが適当
4752 # new_join で add_array_member の中で初出要素の array_member に対し設定する
4753 if @subscript == -1 then
4754 @array_member = [self]
4755 @array_member2 = [self]
4756 elsif @subscript != nil then
4757 @array_member = []
4758 @array_member2 = []
4759 @array_member[@subscript] = self
4760 @array_member2[@subscript] = self
4761 end
4762
4763 @through_list = []
4764 @cp_through_list = []
4765 @region_through_list = []
4766 @through_generated_list = []
4767 @region_through_generated_list = []
4768 end
4769
4770 #=== Join# 左辺に対応する celltype の定義を設定するとともにチェックする
4771 # STAGE: S
4772 #
4773 # 代入可能かチェックする
4774 #definition:: Decl (attribute,varの時) または Port (callの時) または nil (definition が見つからなかった時)
4775
4776 def set_definition( definition )
4777
4778 dbgPrint "set_definition: #{@owner.get_name}.#{@name} = #{definition.class}\n"
4779
4780 # 二重チェックの防止
4781 if @definition then
4782 # set_definition を個別に行うケースで、二重に行われる可能性がある(異常ではない)
4783 # 二重に set_definition が実行されると through が二重に適用されてしまう
4784 # cdl_warning( "W9999 $1, internal error: set_definition duplicate", @name )
4785 return
4786 end
4787
4788 @definition = definition
4789
4790 # mikan 左辺値、右辺値の型チェックなど
4791 if @definition.instance_of?( Decl ) then
4792 check_var_init
4793 elsif @definition.instance_of?( Port ) then
4794 check_call_port_init
4795 if @definition.get_port_type == :CALL then # :ENTRY ならエラー。無視しない
4796 check_and_gen_through
4797 create_allocator_join # through プラグイン生成した後でないと、挿入前のセルのアロケータを結合してしまう
4798 end
4799 elsif @definition == nil then
4800 cdl_error( "S1117 \'$1\' not in celltype", @name )
4801 else
4802 raise "UnknownToken"
4803 end
4804 end
4805
4806 #=== Join# 変数の初期化チェック
4807 def check_var_init
4808 # attribute, var の場合
4809 if @definition.get_kind == :ATTRIBUTE then
4810# check_cell_cb_init( definition.get_type, @rhs )
4811 # 右辺で初期化可能かチェック
4812 @definition.get_type.check_init( @locale, @definition.get_identifier, @rhs, :ATTRIBUTE )
4813 elsif @definition.get_kind == :VAR then
4814 # var は初期化できない
4815 cdl_error( "S1100 $1: cannot initialize var" , @name )
4816 else
4817 # Bug trap
4818 raise "UnknownDeclKind"
4819 end
4820 end
4821
4822 #=== Join# 呼び口の初期化チェック
4823 def check_call_port_init
4824 ### Port
4825
4826 # 左辺は受け口か(受け口を初期化しようとしている)?
4827 if @definition.get_port_type == :ENTRY then
4828 cdl_error( "S1101 \'$1\' cannot initialize entry port" , @name )
4829 return
4830 end
4831
4832# # 配列添数の整合性チェック
4833# # 呼び口の定義で、非配列なら添数なし、添数なし配列なら添数なし、添数あり配列なら添数あり
4834 as = @definition.get_array_size
4835 if ( @subscript == nil && as != nil ) then
4836 cdl_error( "S1102 $1: must specify array subscript here" , @name )
4837 elsif ( @subscript != nil && as == nil ) then
4838 cdl_error( "S1103 $1: cannot specify array subscript here" , @name )
4839 end
4840# if @subscript == nil then
4841# if as != nil then
4842# cdl_error( "S1103 $1: need array subscript" , @name )
4843# end
4844# elsif @subscript == -1 then
4845# if as != "[]" then
4846# cdl_error( "S1104 $1: need array subscript number. ex. \'[0]\'" , @name )
4847# end
4848# else # @subscript >0
4849# if as == nil then
4850# cdl_error( "S1105 $1: cannot specify array subscript here" , @name )
4851# elsif as == "[]" then
4852# cdl_error( "S1106 $1: cannot specify array subscript number. use \'[]\'" , @name )
4853# end
4854# end
4855
4856 # mikan Expression の get_type で型導出させる方がスマート
4857 # mikan '=' の左辺が配列かどうか未チェック
4858 #(1) '=' の右辺は "Cell.ePort" の形式か?
4859 # 演算子は "." かつ "." の左辺が :IDENTIFIER
4860 # "." の右辺はチェック不要 (synatax 的に :IDENTIFIER)
4861 #(2) "Cell" は存在するか?(名前が一致するものはあるか)
4862 #(3) "Cell" は cell か?
4863 #(4) "Cell" の celltype は有効か? (無効なら既にエラー)
4864 #(5) "ePort" は "Cell" の celltype 内に存在するか?
4865 #(6) "ePort" は entry port か?
4866 #(7) signature は一致するか
4867
4868 # 右辺がない(以前の段階でエラー)
4869 return unless @rhs
4870
4871 # cCall = composite.cCall; のチェック.この形式は属性用
4872 # 呼び口を export するには cCall => composite.cCall; の形式を用いる
4873 if @rhs.instance_of?( Array ) == true && @rhs[0] == :COMPOSITE then
4874 cdl_error( "S1107 to export port, use \'cCall => composite.cCall\'" )
4875 return
4876 elsif ! @rhs.instance_of?( Expression ) then
4877 raise "Unknown bug. specify -t to find problem in source"
4878 end
4879
4880 # 右辺の Expression の要素を取り出す
4881 ret = @rhs.analyze_cell_join_expression
4882 if ret == nil then #1
4883 cdl_error( "S1108 $1: rhs not \'Cell.ePort\' form" , @name )
4884 return
4885 end
4886
4887 nsp, @rhs_subscript, @port_name = ret[0], ret[1], ret[2]
4888 @cell_name = nsp.get_name # mikan ns::cellname の形式の考慮
4889
4890 # composite の定義の中なら object は結合先 cell か、見つからなければ nil が返る
4891 # composite の定義外なら false が返る
4892 object = CompositeCelltype.find( @cell_name )
4893 if object == false then
4894# mikan 左辺が namespace に対応していないため。 path にして find
4895 # p nsp.get_path_str, nsp.get_path
4896 object = Namespace.find( nsp ) #1
4897 in_composite = false
4898 else
4899 if nsp.get_path.length != 1 then
4900 cdl_error( "$1 cannot have path", nsp.get_path_str )
4901 end
4902 in_composite = true
4903 end
4904
4905 if object == nil then # (2)
4906 cdl_error( "S1109 \'$1\' not found" , @cell_name )
4907 elsif ! object.instance_of?( Cell ) then # (3)
4908 cdl_error( "S1110 \'$1\' not cell" , @cell_name )
4909 else
4910 dbgPrint "set_definition: set_f_ref #{@owner.get_name}.#{@name} => #{object.get_name}\n"
4911 object.set_f_ref
4912
4913 # 右辺のセルのセルタイプ
4914 celltype = object.get_celltype
4915
4916 if celltype then # (4)
4917 object2 = celltype.find( @port_name )
4918 if object2 == nil then # (5)
4919 cdl_error( "S1111 \'$1\' not found" , @port_name )
4920 elsif ! object2.instance_of? Port \
4921 || object2.get_port_type != :ENTRY then # (6)
4922 cdl_error( "S1112 \'$1\' not entry port" , @port_name )
4923 elsif @definition.get_signature != object2.get_signature then # (7)
4924 cdl_error( "S1113 \'$1\' signature mismatch" , @port_name )
4925 elsif object2.get_array_size then
4926 # 受け口配列
4927
4928 unless @rhs_subscript then
4929 # 右辺に添数指定がなかった
4930 cdl_error( "S1114 \'$1\' should be array" , @port_name )
4931 else
4932
4933 as = object2.get_array_size
4934 if( as.kind_of?( Integer ) && as <= @rhs_subscript )then
4935 # 受け口配列の大きさに対し、右辺の添数が同じか大きい
4936 cdl_error( "S1115 $1[$2]: subscript out of range (< $3)" , @port_name, @rhs_subscript, as )
4937 else
4938 dbgPrint "Join OK #{@owner.get_name}.#{@name}[#{@rhs_subscript}] = #{object.get_name}.#{@port_name} #{self}\n"
4939 @cell = object
4940 @celltype = celltype
4941 @port = object2
4942 # 右辺のセルの受け口 object2 を参照済みにする
4943 # object2: Port, @definition: Port
4944 @cell.set_entry_port_max_subscript( @port, @rhs_subscript )
4945 end
4946
4947 # debug
4948 dbgPrint "Join set_definition: rhs: #{@cell} #{@cell.get_name if @cell}\n"
4949
4950 end
4951 elsif @rhs_subscript then
4952 # 受け口配列でないのに右辺で添数指定されている
4953 cdl_error( "S1116 \'$1\' entry port is not array" , @port_name )
4954 else
4955 dbgPrint "Join OK #{@owner.get_name}.#{@name} = #{object.get_name}.#{@port_name} #{self}\n"
4956 @cell = object
4957 @port = object2
4958 @celltype = celltype
4959
4960 # 右辺のセル object の受け口 object2 を参照済みにする
4961 # object2: Port, @definition: Port
4962
4963 # debug
4964 # p "rhs: #{@cell} #{@cell.get_name}"
4965 end # end of port (object2) チェック
4966
4967 #else
4968 # celltype == nil (すでにエラー)
4969 end # end of celltyep チェック
4970
4971
4972 check_region( object )
4973
4974 end # end of cell (object) チェック
4975
4976 end
4977
4978 #=== Join# アロケータの結合を生成
4979 # STAGE: S
4980 #cell:: 呼び口の結合先のセル
4981 #
4982 # ここでは呼び口側に生成されるアロケータ呼び口の結合を生成
4983 # 受け口側は Cell の set_specifier_list で生成
4984 # a[*] の内容は Cell の set_specifier_list を参照
4985 def create_allocator_join
4986
4987 cell = get_rhs_cell2 # 右辺のセルを得る
4988 port = get_rhs_port2
4989
4990 if( cell && cell.get_allocator_list ) then # cell == nil なら既にエラー
4991
4992 dbgPrint "create_allocator_join: #{@owner.get_name}.#{@name}=>#{cell ? cell.get_name : "nil"}\n"
4993
4994 cell.get_allocator_list.each { |a|
4995
4996 if( a[0+1] == port && a[1+1] == @rhs_subscript )then
4997 # 名前の一致するものの結合を生成する
4998 # 過不足は、別途チェックされる
4999 cp_name = :"#{@name}_#{a[2+1]}_#{a[3+1]}"
5000 # p "creating allocator join #{cp_name} #{@subscript} #{a[1+1]}"
5001 join = Join.new( cp_name, @subscript, a[4+1], @locale )
5002
5003 #debug
5004 dbgPrint "create_allocator_join: #{@owner.get_name}.#{cp_name} [#{@subscript}] #{@name}\n"
5005 @owner.new_join join
5006 else
5007 dbgPrint "create_allocator_join:3 not #{@owner.get_name}.#{a[0+1]} #{@name}\n"
5008 end
5009 }
5010 end
5011 end
5012
5013 #=== Join# リージョン間の結合をチェック
5014 # リージョン間の through による @region_through_list の作成
5015 # 実際の生成は check_and_gen_through で行う
5016 # mikan Cell#distance とRegion へたどり着くまでための処理に共通部分が多い
5017 def check_region( object )
5018
5019 #debug
5020 dbgPrint "check_region #{@owner.get_name}.#{@name} => #{object.get_name}\n"
5021 # print "DOMAIN: check_region #{@owner.get_name}.#{@name} => #{object.get_name}\n"
5022
5023 # プラグインで生成されたなかでは生成しない
5024 # さもないとプラグイン生成されたものとの間で、無限に生成される
5025## if Generator.get_nest >= 1 then
5026## if Generator.get_plugin then # mikan これは必要? (意味解析段階での実行になるので不適切)
5027 if @owner.get_plugin.kind_of?( ThroughPlugin ) then
5028 # プラグイン生成されたセルの場合、結合チェックのみ
5029 return
5030 end
5031
5032 # region のチェック
5033 r1 = @owner.get_region # 呼び口セルの region
5034 r2 = object.get_region # 受け口セルの region
5035
5036 if ! r1.equal? r2 then # 同一 region なら呼出し可能
5037
5038 f1 = r1.get_family_line
5039 len1 = f1.length
5040 f2 = r2.get_family_line
5041 len2 = f2.length
5042
5043 # 不一致になるところ(兄弟)を探す
5044 i = 1 # i = 0 は :RootRegion なので必ず一致
5045 while( i < len1 && i < len2 )
5046 if( f1[i] != f2[i] )then
5047 break
5048 end
5049 i += 1
5050 end
5051
5052 sibling_level = i # 兄弟となるレベル、もしくはどちらか一方が終わったレベル
5053
5054 dbgPrint "sibling_level: #{i}\n"
5055 dbgPrint "from: #{f1[i].get_name}\n" if f1[i]
5056 dbgPrint "to: #{f2[i].get_name}\n" if f2[i]
5057
5058 if f1[sibling_level] && f2[sibling_level] then
5059 b_to_through = true
5060 else
5061 b_to_through = false
5062 end
5063
5064
5065 # 呼び側について呼び元のレベルから兄弟レベルまで(out_through をチェックおよび挿入)
5066 i = len1 -1
5067 if b_to_through then
5068 end_level = sibling_level
5069 else
5070 end_level = sibling_level - 1
5071 end
5072 while i > end_level
5073 # while i > sibling_level
5074 # while i >= sibling_level
5075 dbgPrint "going out from #{f1[i].get_name} level=#{i}\n"
5076 region_count = f1[i].next_out_through_count
5077 out_through_list = f1[i].get_out_through_list # [ plugin_name, plugin_arg ]
5078 domain = f1[i].get_domain_type
5079 if domain then
5080 domain_through = f1[i].get_domain_type.add_through_plugin( self, f1[i], f1[i-1], :OUT_THROUGH )
5081 if domain_through == nil then
5082 cdl_error( "S9999 $1: going out from regin '$2' not permitted by domain '$3'" , @name, f1[i].get_name, f1[i].get_domain_type.get_name )
5083 end
5084 elsif out_through_list.length == 0 then
5085 cdl_error( "S1118 $1: going out from region \'$2\' not permitted" , @name, f1[i].get_name )
5086 end
5087
5088 out_through_list.each { |ol|
5089 if ol[0] then # plugin_name が指定されていなければ登録しない
5090 plugin_arg = CDLString.remove_dquote ol[1]
5091 through = [ ol[0], :"Join_out_through_", plugin_arg, f1[i], f1[i-1], :OUT_THROUGH, region_count]
5092 @region_through_list << through
5093 end
5094 }
5095 if domain_through && domain_through.length > 0 then
5096 through = [ domain_through[0], :"Join_domain_out_through_", domain_through[1], f1[i], f1[i-1], :OUT_THROUGH, region_count ]
5097 @region_through_list << through
5098 end
5099 i -= 1
5100 end
5101
5102 # 兄弟レベルにおいて(to_through をチェックおよび挿入)
5103 if f1[sibling_level] && f2[sibling_level] then
5104 dbgPrint "going from #{f1[sibling_level].get_name} to #{f2[sibling_level].get_name}\n"
5105 found = 0
5106 region_count = f1[i].next_to_through_count( f2[sibling_level].get_name ) # to_through の region カウント
5107 f1[sibling_level].get_to_through_list.each { |t|
5108 if t[0][0] == f2[sibling_level].get_name then # region 名が一致するか ?
5109 if t[1] then # plugin_name が指定されていなければ登録しない
5110 plugin_arg = CDLString.remove_dquote t[2]
5111 through = [ t[1], :"Join_to_through__", plugin_arg, f1[sibling_level], f2[sibling_level], :TO_THROUGH, region_count ]
5112 @region_through_list << through
5113 end
5114 found = 1
5115 end
5116 }
5117 domain = f1[sibling_level].get_domain_type
5118 if domain then
5119 domain_through = f1[sibling_level].get_domain_type.add_through_plugin( self, f1[sibling_level], f2[sibling_level], :TO_THROUGH )
5120 if domain_through == nil then
5121 cdl_error( "S9999 $1: going from regin '$2' not permitted by domain'$3'" , @name, f1[sibling_level].get_name, f2[sibling_level].get_domain_type.get_name )
5122 end
5123 if domain_through && domain_through.length > 0 then
5124 through = [ domain_through[0], :"Join_domain_to_through_", domain_through[1], f1[sibling_level], f2[sibling_level], :TO_THROUGH, region_count ]
5125 @region_through_list << through
5126 end
5127 elsif found == 0 then
5128 cdl_error( "S1119 $1: going from region \'$2\' to \'$3\' not permitted" , @name, f1[sibling_level].get_name, f2[sibling_level].get_name )
5129 end
5130 end
5131
5132 # 受け側について兄弟レベルから受け側のレベルまで(in_through をチェックおよび挿入)
5133 if b_to_through then
5134 i = sibling_level + 1 # to_through を経た場合、最初の in_through は適用しない
5135 else
5136 i = sibling_level
5137 end
5138 while i < len2
5139 dbgPrint "going in to #{f2[i].get_name} level=#{i}\n"
5140 region_count = f2[i].next_in_through_count
5141 in_through_list = f2[i].get_in_through_list # [ plugin_name, plugin_arg ]
5142 domain = f2[i].get_domain_type
5143 if domain then
5144 domain_through = f2[i].get_domain_type.add_through_plugin( self, f2[i-1], f2[i], :IN_THROUGH )
5145 if domain_through == nil then
5146 cdl_error( "S9999 $1: going in from regin '$2' to '$3' not permitted by domain '$4'",
5147 @name, f2[i-1].get_name, f2[i].get_name, f2[i].get_domain_type.get_name )
5148 end
5149 if domain_through && domain_through.length > 0 then
5150 through = [ domain_through[0], :"Join_domain_in_through_", domain_through[1], f2[i-1], f2[i], :IN_THROUGH, region_count ]
5151 @region_through_list << through
5152 end
5153 elsif in_through_list.length == 0 then
5154 cdl_error( "S1120 $1: going in to region \'$2\' not permitted" , @name, f2[i].get_name )
5155 end
5156 in_through_list.each { |il|
5157 if il[0] then # plugin_name が指定されていなければ登録しない
5158 plugin_arg = CDLString.remove_dquote il[1]
5159 through = [ il[0], :"Join_in_through_", plugin_arg, f2[i-1], f2[i],:IN_THROUGH, region_count ]
5160 @region_through_list << through
5161 end
5162 }
5163 i += 1
5164 end
5165
5166 end
5167 end
5168
5169
5170 #=== Join# 生成しないリージョンへの結合かチェック
5171 # 右辺のセルが、生成されないリージョンにあればエラー
5172 # 右辺は、プラグイン生成されたセルがあれば、それを対象とする
5173 def check_region2
5174 lhs_cell = @owner
5175
5176 # 生成しないリージョンのセルへの結合か?
5177 # if join.get_cell && ! join.get_cell.is_generate? then
5178 # if get_rhs_cell && ! get_rhs_cell.is_generate? then # composite セルがプロタイプ宣言の場合例外
5179 # print "Link root: (caller #{@owner.get_name}) '#{@owner.get_region.get_link_root.get_name}'"
5180 # print " #{@owner.get_region.get_link_root == get_rhs_region.get_link_root ? "==" : "!="} "
5181 # print "'#{get_rhs_region.get_link_root.get_name}' (callee #{@cell_name})\n"
5182
5183 if get_rhs_region then
5184 dbgPrint "check_region2 #{lhs_cell.get_name} => #{get_rhs_region.get_path_string}#{@rhs.to_s}\n"
5185
5186 # if get_rhs_region.is_generate? != true then #3
5187 if @owner.get_region.get_link_root != get_rhs_region.get_link_root then
5188 cdl_error( "S1121 \'$1\' in region \'$2\' cannot be directly joined $3 in $4" , lhs_cell.get_name, lhs_cell.get_region.get_namespace_path.get_path_str, @rhs.to_s, get_rhs_region.get_namespace_path.get_path_str )
5189 end
5190 else
5191 # rhs のセルが存在しなかった (既にエラー)
5192 end
5193 end
5194
5195 def get_definition
5196 @definition
5197 end
5198
5199 #=== Join# specifier を設定
5200 # STAGE: B
5201 # set_specifier_list は、join の解析の最後で呼び出される
5202 # through 指定子を設定
5203 # check_and_gen_through を呼出して、through 生成
5204 def set_specifier_list( specifier_list )
5205
5206 specifier_list.each { |s|
5207 case s[0]
5208 when :THROUGH
5209 # set plugin_name
5210 plugin_name = s[1].to_s
5211 plugin_name[0] = "#{plugin_name[/^./].upcase}" # 先頭文字を大文字に : ruby のクラス名の制約
5212
5213 # set cell_name
5214 cell_name = :"#{s[1].to_s}_"
5215
5216 # set plugin_arg
5217 plugin_arg = CDLString.remove_dquote s[2].to_s
5218 # plugin_arg = s[2].to_s.gsub( /\A"(.*)/, '\1' ) # 前後の "" を取り除く
5219 # plugin_arg.sub!( /(.*)"\z/, '\1' )
5220
5221 @cp_through_list << [ plugin_name, cell_name, plugin_arg ]
5222 end
5223 }
5224
5225 end
5226
5227 #=== Join# through のチェックと生成
5228 # new_join の中の check_region で region 間の through が @region_through に設定される
5229 # set_specifier で呼び口の結合で指定された through が @cp_through 設定される
5230 # その後、このメソッドが呼ばれる
5231 def check_and_gen_through
5232
5233 dbgPrint "check_and_gen_through #{@owner.get_name}.#{@name}\n"
5234
5235 if ! @definition.instance_of? Port then
5236 cdl_error( "S1123 $1 : not port: \'through\' can be specified only for port" , @name )
5237 return
5238 end
5239 if @cp_through_list.length > 0 then
5240 # is_empty? must check before is_omit?
5241 if @definition.get_signature && @definition.get_signature.is_empty? then
5242 cdl_warning( "W9999 'through' is specified for empty signature, ignored" )
5243 return
5244 elsif @definition.is_omit? then
5245 cdl_warning( "W9999 'through' is specified for omitted port, ignored" )
5246 return
5247 end
5248 end
5249
5250 @through_list = @cp_through_list + @region_through_list
5251 # 後から @cp_through_list と @region_through_list に分けたため、このような実装になった
5252
5253 if @through_list then # nil when the join is not Port
5254 len = @through_list.length # through が連接している数
5255 else
5256 len = 0
5257 end
5258 cp_len = @cp_through_list.length
5259
5260 if @owner.is_in_composite? && len > 0 then
5261 cdl_error( "S1177 cannot specify 'through' in composite in current version" )
5262 return
5263 end
5264
5265 # 連続した through について、受け口側から順にセルを生成し解釈する
5266 i = len - 1
5267 while i >= 0
5268
5269 through = @through_list[ i ]
5270 plugin_name = through[ 0 ]
5271 generating_cell_name = through[ 1 ]
5272 plugin_arg = through[ 2 ]
5273
5274 if i != len - 1 then
5275
5276 begin
5277 next_cell_nsp = @through_generated_list[ i + 1 ].get_cell_namespace_path
5278 next_port_name = @through_generated_list[ i + 1 ].get_through_entry_port_name
5279 rescue Exception => evar
5280 cdl_error( "S1124 $1: plugin function failed: \'get_through_entry_port_name\'" , plugin_name )
5281 print_exception( evar )
5282 i -= 1
5283 next
5284 end
5285
5286 next_cell = Namespace.find( next_cell_nsp ) #1
5287 if next_cell == nil then
5288 # p "next_cell_path: #{next_cell_nsp.get_path_str}"
5289 cdl_error( "S1125 $1: not generated cell \'$2\'" , @through_generated_list[ i + 1 ].class, next_cell_nsp.get_path_str )
5290 return
5291 end
5292
5293 else
5294 # 最後のセルの場合、次のセルの名前、ポート名
5295 next_cell = @cell
5296 next_port_name = @port_name
5297
5298 if next_cell == nil then
5299 # 結合先がない
5300 return
5301 end
5302 end
5303
5304 if i >= cp_len then
5305 # region_through_list 部分
5306 # region から @cell_name.@port_name への through がないか探す
5307 # rp = @through_list[i][3].find_cell_port_through_plugin( @cell_name, @port_name ) #762
5308 rp = @through_list[i][3].find_cell_port_through_plugin( @cell.get_global_name, @port_name )
5309 # @through_list[i] と @region_through_list[i-cp_len] は同じ
5310 # 共用しないようにするには、見つからなかったことにすればよい
5311 # rp = nil
5312 else
5313 # region 以外のものは共有しない
5314 # 呼び口側に指定されているし、plugin_arg が異なるかもしれない
5315 rp = nil
5316 end
5317
5318 if rp == nil then
5319 if( load_plugin( plugin_name, ThroughPlugin ) ) then
5320 gen_through_cell_code_and_parse( plugin_name, i, next_cell, next_port_name )
5321 end
5322 else
5323 # 見つかったものを共用する
5324 @through_generated_list[ i ] = rp
5325 end
5326
5327 if i >= cp_len then
5328 # @through_generated_list のうち @region_through_listに対応する部分
5329 @region_through_generated_list[ i - cp_len ] = @through_generated_list[ i ]
5330 if rp == nil then
5331 # 生成したものを region(@through_list[i][3]) のリストに追加
5332 # @through_list[i][3].add_cell_port_through_plugin( @cell_name, @port_name, @through_generated_list[i] ) #762
5333 @through_list[i][3].add_cell_port_through_plugin( @cell.get_global_name, @port_name, @through_generated_list[i] )
5334 end
5335 end
5336
5337 if i == 0 then
5338 # 最も呼び口側のセルは、CDL 上の結合がないため、参照されたことにならない
5339 # mikan namespace 対応
5340 # cell = Namespace.find( [ @through_generated_list[0].get_cell_name] ) #1
5341 if @through_generated_list[0] == nil then
5342 return # plugin_object の生成に失敗している
5343 end
5344 cell = Namespace.find( @through_generated_list[0].get_cell_namespace_path ) #1
5345 if cell.instance_of? Cell then
5346 cell.set_f_ref
5347 end
5348 end
5349
5350 i -= 1
5351 end
5352
5353 end
5354
5355 @@through_count = { }
5356 def get_through_count name
5357 sym = name.to_sym
5358 if @@through_count[ sym ] then
5359 @@through_count[ sym ] += 1
5360 else
5361 @@through_count[ sym ] = 0
5362 end
5363 return @@through_count[ sym ]
5364 end
5365
5366 #=== Join# through プラグインを呼び出して CDL 生成させるとともに、import する
5367 def gen_through_cell_code_and_parse( plugin_name, i, next_cell, next_port_name )
5368
5369 through = @through_list[ i ]
5370 plugin_name = through[ 0 ]
5371 generating_cell_name = :"#{through[ 1 ]}_#{get_through_count through[ 1 ]}"
5372 plugin_arg = through[ 2 ]
5373 if through[ 3 ] then
5374 # region 間の through の場合
5375 @@start_region = through[ 3 ]
5376 if next_cell.get_region.equal? @@start_region then
5377 @@end_region = @@start_region
5378 else
5379 @@end_region = through[ 4 ]
5380 end
5381 @@through_type = through[ 5 ]
5382 @@region_count = through[ 6 ]
5383 else
5384 # 呼び口の through の場合
5385 @@start_region = @owner.get_region # 呼び口側セルの region
5386 @@end_region = next_cell.get_region # 次のセルの region
5387 @@through_type = :THROUGH # 呼び口の through 指定
5388 @@region_count = 0
5389 end
5390 @@plugin_creating_join = self
5391
5392 caller_cell = @owner
5393
5394 plugin_object = nil
5395 eval_str = "plugin_object = #{plugin_name}.new( '#{generating_cell_name}'.to_sym, plugin_arg.to_s, next_cell, '#{next_port_name}'.to_sym, @definition.get_signature, @celltype, caller_cell )"
5396 if $verbose then
5397 print "new through: #{eval_str}\n"
5398 end
5399
5400 begin
5401 eval( eval_str ) # plugin を生成
5402 plugin_object.set_locale @locale
5403 rescue Exception => evar
5404 cdl_error( "S1126 $1: fail to new" , plugin_name )
5405 if @celltype && @definition.get_signature && caller_cell && next_cell then
5406 print "signature: #{@definition.get_signature.get_name} from: #{caller_cell.get_name} to: #{next_cell.get_name} of celltype: #{@celltype.get_name}\n"
5407 end
5408 print "eval( #{eval_str} )\n"
5409
5410 print_exception( evar )
5411 return
5412 end
5413
5414 @through_generated_list[ i ] = plugin_object
5415
5416 # Region に関する情報を設定
5417 # 後から追加したので、new の引数外で設定
5418 # plugin_object.set_through_info( start_region, end_region, through_type )
5419
5420 generate_and_parse plugin_object
5421 end
5422
5423 #プラグインへの引数で渡さないものを、一時的に記憶しておく
5424 # プラグインの initialize の中でコールバックして設定する
5425 @@plugin_creating_join = nil
5426 @@start_region = nil
5427 @@end_region = nil
5428 @@through_type = nil
5429 @@region_count = nil
5430
5431 #=== Join# ThroughPlugin の追加情報を設定する
5432 # このメソッドは ThroughPlugin#initialize から呼び出される
5433 # plugin_object を生成する際の引数では不足する情報を追加する
5434 def self.set_through_info plugin_object
5435 plugin_object.set_through_info( @@start_region, @@end_region, @@through_type,
5436 @@plugin_creating_join,
5437 @@plugin_creating_join.get_cell,
5438 @@region_count )
5439 end
5440
5441 def get_name
5442 @name
5443 end
5444
5445 #=== Join#配列添数を得る
5446 # @subscript の説明を参照のこと
5447 def get_subscript
5448 @subscript
5449 end
5450
5451 def get_cell_name # 受け口セル名
5452 @cell_name
5453 end
5454
5455 def get_celltype
5456 @celltype
5457 end
5458
5459 def get_cell
5460 @cell
5461 end
5462
5463 #=== Join# 右辺の実セルを得る
5464 # 実セルとは through で挿入されたもの、composite の内部など実際に結合される先
5465 # このメソッドは get_rhs_port と対になっている
5466 # このメソッドは、意味解析段階では呼び出してはならない (対象セルの意味解析が済む前には正しい結果を返さない)
5467 def get_rhs_cell
5468 # through 指定あり?
5469 if @through_list[0] then
5470 # mikan through で生成したものが root namespace 限定
5471 if @through_generated_list[0] then
5472 # cell = Namespace.find( [ "::", @through_generated_list[0].get_cell_name.to_sym ] ) #1
5473 cell = Namespace.find( @through_generated_list[0].get_cell_namespace_path ) #1
5474 # cell が nil になるのはプラグインの get_cell_namespace_path が正しくないか、
5475 # プラグイン生成コードがエラーになっている。
5476 # できの悪いプラグインが多ければ、cell == nil をはじいた方がよい。
5477 return cell.get_real_cell( @through_generated_list[0].get_through_entry_port_name )
5478 else
5479 return nil # generate に失敗している
5480 end
5481 elsif @cell then
5482 return @cell.get_real_cell( @port_name )
5483 else
5484 # 右辺が未定義の場合 @cell は nil (既にエラー)
5485 return nil
5486 end
5487 end
5488
5489 #=== Join# 右辺のセルを得る
5490 # 右辺のセルを得る。ただし、composite 展開されていない
5491 # composite 展開されたものを得るには get_rhs_cell を使う
5492 # プロトタイプ宣言しかされていない場合には、こちらしか使えない
5493 # このメソッドは get_rhs_port2 と対になっている
5494 def get_rhs_cell2
5495 # through 指定あり?
5496 if @through_list[0] then
5497 # mikan through で生成したものが root namespace 限定
5498 # cell = Namespace.find( [ "::", @through_generated_list[0].get_cell_name ] )
5499 if @through_generated_list[0] then
5500 # cell = Namespace.find( [ @through_generated_list[0].get_cell_name ] ) #1
5501 cell = Namespace.find( @through_generated_list[0].get_cell_namespace_path ) #1
5502 else
5503 cell = @cell # generate に失敗している
5504 end
5505 else
5506 cell = @cell
5507 end
5508
5509 return cell
5510 end
5511
5512 #=== Join# 右辺のセルを得る
5513 # through は適用しないが、composite は展開した後のセル
5514 # (意味解析が終わっていないと、composite 展開が終わっていない)
5515 # このメソッドは get_rhs_port3 と対になっている
5516 def get_rhs_cell3
5517 if @cell then
5518 return @cell.get_real_cell( @port_name )
5519 end
5520 end
5521
5522 #=== Join# 右辺のセルのリージョンを得る
5523 # 右辺が未定義の場合、nil を返す
5524 # composite の場合、実セルではなく composite cell の region を返す(composite はすべて同じ region に属する)
5525 # composite の cell がプロトタイプ宣言されているとき get_rhs_cell/get_real_cell は ruby の例外となる
5526 def get_rhs_region
5527 # through 指定あり?
5528 if @through_list[0] then
5529 if @through_generated_list[0] then
5530 # mikan through で生成したものが root namespace 限定
5531 # cell = Namespace.find( [ "::", @through_generated_list[0].get_cell_name.to_sym ] ) #1
5532 cell = Namespace.find( @through_generated_list[0].get_cell_namespace_path ) #1
5533 if cell then
5534 return cell.get_region
5535 end
5536 else
5537 return nil # generate に失敗している
5538 end
5539 elsif @cell then
5540 return @cell.get_region
5541 end
5542 # 右辺が未定義の場合 @cell は nil (既にエラー)
5543 return nil
5544 end
5545
5546 def get_cell_global_name # 受け口セル名(コンポジットなら展開した内側のセル)
5547
5548 # debug
5549 dbgPrint "cell get_cell_global_name: #{@cell_name}\n"
5550 # @cell.show_tree( 1 )
5551
5552 if @cell then
5553 return @cell.get_real_global_name( @port_name )
5554 else
5555 return "NonDefinedCell?"
5556 end
5557
5558 end
5559
5560 #=== Join# 結合の右辺の受け口の名前
5561 # namespace 名 + '_' + セル名 + '_' + 受け口名 (このセルが composite ならば展開後のセル名、受け口名)
5562 #subscript:: Integer 呼び口配列の時添数 または nil 呼び口配列でない時
5563 def get_port_global_name( subscript = nil ) # 受け口名(コンポジットなら展開した内側のセル)
5564
5565 # debug
5566 dbgPrint "Cell get_port_global_name: #{@cell_name}\n"
5567
5568 # through 指定あり?
5569 if @through_list[0] then
5570
5571 # mikan through で生成したものが root namespace 限定
5572 # cell = Namespace.find( [ "::", @through_generated_list[0].get_cell_name.to_sym ] ) #1
5573 cell = Namespace.find( @through_generated_list[0].get_cell_namespace_path ) #1
5574
5575 # through で挿入されたセルで、実際に接続されるセル(compositeの場合内部の)の受け口の C 言語名前
5576 return cell.get_real_global_port_name( @through_generated_list[0].get_through_entry_port_name )
5577 else
5578
5579 # 実際に接続されるセルの受け口の C 言語名前
5580 if @cell then
5581 return @cell.get_real_global_port_name( @port_name )
5582 else
5583 return "UndefinedCellsPort?"
5584 end
5585
5586 end
5587
5588 end
5589
5590 def get_port_name
5591 @port_name
5592 end
5593
5594 def get_rhs
5595 @rhs
5596 end
5597
5598 def get_rhs_subscript
5599 @rhs_subscript
5600 end
5601
5602 #=== Join# 右辺のポートを得る
5603 # 右辺が composite の場合は、内部の繋がるセルのポート, through の場合は挿入されたセルのポート
5604 # このメソッドは get_rhs_cell と対になっている
5605 def get_rhs_port
5606 # through 指定あり?
5607 if @through_list[0] then
5608 # mikan through で生成したものが root namespace 限定
5609 # through で生成されたセルを探す
5610# cell = Namespace.find( [ "::", @through_generated_list[0].get_cell_name.to_sym ] ) #1
5611 cell = Namespace.find( @through_generated_list[0].get_cell_namespace_path ) #1
5612 # cell のプラグインで生成されたポート名のポートを探す (composite なら内部の繋がるポート)
5613 return cell.get_real_port( @through_generated_list[0].get_through_entry_port_name )
5614 else
5615 # ポートを返す(composite なら内部の繋がるポートを返す)
5616 return @cell.get_real_port( @port_name )
5617 end
5618 end
5619
5620 #=== Join# 右辺のポートを得る
5621 # 右辺のポートを得る。
5622 # これはプロトタイプ宣言しかされていない場合には、こちらしか使えない
5623 def get_rhs_port2
5624 # through 指定あり?
5625 if @through_list[0] then
5626 if @through_generated_list[0] then
5627 port = @through_generated_list[0].get_through_entry_port_name.to_sym
5628 else
5629 port = @port_name # generate に失敗している
5630 end
5631 else
5632 port = @port_name
5633 end
5634
5635 return port
5636 end
5637
5638 #=== Join# 右辺のポートを得る
5639 # through は適用しないが、composite は展開した後のセルの対応するポート
5640 def get_rhs_port3
5641 if @cell then
5642 return @cell.get_real_port( @port_name )
5643 end
5644 end
5645
5646 #=== Join# 呼び口配列の2番目以降の要素を追加する
5647 # 一番最初に定義された配列要素が全要素の初期値の配列を持つ
5648 # このメソッドは非配列の場合も呼出される(join 重複エラーの場合)
5649 #join2:: Join 呼び口配列要素の Join
5650 def add_array_member join2
5651
5652 # subscript2: join2 の左辺添数
5653 subscript2 = join2.get_subscript
5654
5655 if @subscript == nil then # not array : initialize duplicate
5656 # 非配列の場合、join が重複している
5657 cdl_error( "S1127 \'$1\' duplicate", @name )
5658 # print "add_array_member2: #{@owner.get_name}\n"
5659
5660 elsif @subscript >= 0 then
5661 # 添数指定ありの場合
5662 if( subscript2 == nil || subscript2 < 0 ) then
5663 # join2 左辺は非配列または添数なし
5664 # 配列が不一致
5665 cdl_error( "S1128 \'$1\' inconsistent array definition", @name )
5666 elsif @array_member[subscript2] != nil then
5667 # 同じ添数が既に定義済み
5668 cdl_error( "S1129 \'$1\' redefinition of subscript $2" ,@name, subscript2 )
5669 else
5670 # 添数の位置に要素を追加
5671 @array_member[subscript2] = join2.get_rhs
5672 @array_member2[subscript2] = join2
5673# p "0:#{join2.get_rhs}"
5674 end
5675
5676 else
5677 # 添数指定なしの場合
5678 if( subscript2 == nil || subscript2 >= 0 ) then
5679 # join2 左辺は非配列または添数有
5680 # 配列が不一致
5681 cdl_error( "S1130 \'R1\' inconsistent array definition", @name )
5682 end
5683
5684 # 添数なし配列の場合、配列要素を追加
5685 @array_member << join2.get_rhs
5686 @array_member2 << join2
5687 end
5688 end
5689
5690 def get_array_member
5691 @array_member
5692 end
5693
5694 def get_array_member2
5695 @array_member2
5696 end
5697
5698 def change_name name
5699 # debug
5700 dbgPrint "change_name: #{@name} to #{name}\n"
5701
5702 @name = name
5703
5704 if @array_member2 then
5705 i = 0
5706 while i < @array_member2.length
5707 if @array_member2[i] != self && @array_member[i] != nil then
5708 # @array_member2[i] が nil になるのは optional の時と、
5709 # Join の initialize で無駄に @array_member2 が設定されている場合
5710 # 無駄に設定されているものについては、再帰的に呼び出す必要はない(clone_for_composite では対策している)
5711 @array_member2[i].change_name( name )
5712 end
5713 i += 1
5714 end
5715 end
5716 end
5717
5718 # composite cell を展開したセルの結合を clone したセルの名前に変更
5719 def change_rhs_port( clone_cell_list, celltype )
5720
5721 # debug
5722 if $debug then
5723 dbgPrint "change_rhs name: #{@name} cell_name: #{@cell_name} #{@cell} #{self}\n"
5724
5725 clone_cell_list.each{ |cell, ce|
5726 dbgPrint "change_rhs: #{cell.get_name}=#{cell} : #{ce.get_name}\n"
5727 }
5728 end
5729
5730 c = clone_cell_list[@cell]
5731 return if c == nil
5732
5733 # debug
5734 dbgPrint " cell_name: #{@cell_name} => #{c.get_global_name}, #{c.get_name}\n"
5735
5736 # @rhs の内容を調整しておく(この内容は、subscript を除いて、後から使われていない)
5737 elements = @rhs.get_elements
5738 if elements[0] == :OP_SUBSC then # 右辺:受け口配列?
5739 elements = elements[1]
5740 end
5741
5742 # 右辺が cell.ePort の形式でない
5743 if elements[0] != :OP_DOT || elements[1][0] != :IDENTIFIER then #1
5744 return
5745 else
5746 # セル名を composite 内部の名前から、外部の名前に入れ替える
5747 # elements[1][1] = Token.new( c.get_name, nil, nil, nil )
5748 elements[1][1] = NamespacePath.new( c.get_name, false, c.get_namespace )
5749 end
5750
5751 @cell_name = c.get_name
5752 @cell = c
5753 # @definition = nil # @definition が有効: チェック済み(とは、しない)
5754
5755 if @array_member2 then
5756
5757 # debug
5758 # p "array_member2.len : #{@array_member.length}"
5759
5760 i = 0
5761 while i < @array_member2.length
5762 # @array_member2[i] が nil になるのは optional の時と、
5763 # Join の initialize で無駄に @array_member2 が設定されている場合
5764 # 無駄に設定されているものについては、再帰的に呼び出す必要はない(clone_for_composite では対策している)
5765 if @array_member2[i] != self && @array_member[i] != nil then
5766 @array_member2[i].change_rhs_port( clone_cell_list, celltype )
5767 end
5768 i += 1
5769 end
5770 end
5771
5772 end
5773
5774 #=== Join# composite セル用にクローン
5775 #cell_global_name:: string : 親セルのグローバル名
5776 # 右辺の C_EXP に含まれる $id$, $cell$, $ct$ を置換
5777 # ここで置換するのは composite の attribute の C_EXP を composite セルタイプおよびセル名に置換するため
5778 # (内部セルの C_EXP もここで置換される)
5779 # @through_list などもコピーされるので、これが呼び出される前に確定する必要がある
5780 def clone_for_composite( ct_name, cell_name, locale, b_need_recursive = true )
5781
5782 # debug
5783 dbgPrint "join.clone_for_composite : #{@name} #{@cell_name} #{self}\n"
5784 cl = self.clone
5785
5786 if @array_member2 && b_need_recursive then
5787 cl.clone_array_member( @array_member, @array_member2, ct_name, cell_name, self, locale )
5788 end
5789
5790 rhs = CDLInitializer.clone_for_composite( @rhs, ct_name, cell_name, locale )
5791 cl.change_rhs rhs
5792
5793 # debug
5794 dbgPrint "join cloned : #{cl}\n"
5795 return cl
5796 end
5797
5798 def clone_array_member( array_member, array_member2, ct_name, cell_name, prev, locale )
5799 # 配列のコピーを作る
5800 am = array_member.clone
5801 am2 = array_member2.clone
5802
5803 # 配列要素のコピーを作る
5804 i = 0
5805 while i < am2.length
5806 if array_member2[i] == prev then
5807 # 自分自身である(ので、呼出すと無限再帰呼出しとなる)
5808 am2[i] = self
5809 elsif array_member2[i] then
5810 am2[i] = array_member2[i].clone_for_composite( ct_name, cell_name, locale, false )
5811 else
5812 # 以前のエラーで array_member2[i] は nil になっている
5813 end
5814
5815 # debug
5816 dbgPrint "clone_array_member: #{@name} #{am2[i]} #{array_member2[i]}\n"
5817
5818 i += 1
5819 end
5820
5821 # i = 0 は、ここで自分自身を設定
5822 # am2[0] = self
5823
5824 @array_member = am
5825 @array_member2 = am2
5826
5827 end
5828
5829 #=== Join# rhs を入れ換える
5830 #rhs:: Expression | initializer
5831 # 右辺を入れ換える.
5832 # このメソッドは、composite で cell の属性の初期値を attribute の値で置き換えるのに使われる
5833 # このメソッドは composite 内の cell の属性の初期値が定数ではなく式になった場合、不要になる
5834 def change_rhs rhs
5835 @rhs = rhs
5836 end
5837
5838 #=== Join# clone された join の owner を変更
5839 def set_cloned( owner )
5840 dbgPrint "Join#set_cloned: #{@name} prev owner: #{@owner.get_name} new owner: #{owner.get_name}\n"
5841 @owner = owner
5842 end
5843
5844 def show_tree( indent )
5845 indent.times { print " " }
5846 puts "Join: name: #{@name} owner: #{@owner.get_name} id: #{self}"
5847 if @subscript == nil then
5848 elsif @subscript >= 0 then
5849 (indent+1).times { print " " }
5850 puts "subscript: #{@subscript}"
5851 else
5852 (indent+1).times { print " " }
5853 puts "subscript: not specified"
5854 end
5855 (indent+1).times { print " " }
5856 puts "rhs: "
5857 if @rhs.instance_of?( Array )then
5858 @rhs.each{ |i|
5859 if i.instance_of?( Array )then
5860 i.each{ |j|
5861 j.show_tree( indent + 3 )
5862 }
5863 elsif i.instance_of? Symbol then
5864 (indent+2).times { print " " }
5865 print i
5866 print "\n"
5867 else
5868 i.show_tree( indent + 2 )
5869 end
5870 }
5871 else
5872 @rhs.show_tree( indent + 2 )
5873 (indent+1).times { print " " }
5874 if @definition then
5875 puts "definition:"
5876 @definition.show_tree( indent + 2 )
5877 else
5878 puts "definition: not found"
5879 end
5880 end
5881 if @definition.instance_of?( Port ) then
5882 (indent+2).times { print " " }
5883 if @cell then
5884 puts "cell: #{@cell_name} #{@cell} port: #{@port_name} cell_global_name: #{@cell.get_global_name}"
5885 else
5886 puts "cell: #{@cell_name} port: #{@port_name} (cell not found)"
5887 end
5888 end
5889 if @through_list then
5890 i = 0
5891 @through_list.each { |t|
5892 (indent+2).times { print " " }
5893 puts "through: plugin name : '#{t[0]}' arg : '#{t[2]}'"
5894 if @through_generated_list[i] then
5895 @through_generated_list[i].show_tree( indent+3 )
5896 end
5897 i += 1
5898 }
5899 end
5900 if @array_member2 then
5901 (indent+1).times { print " " }
5902 puts "array member:"
5903 i = 0
5904 @array_member2.each { |j|
5905 if j then
5906 (indent+2).times { print " " }
5907 puts "[#{i}]: #{j.get_name} id: #{j}"
5908 j.get_rhs.show_tree(indent+3)
5909 (indent+3).times { print " " }
5910 puts "cell global name: #{j.get_cell_global_name}"
5911 (indent+3).times { print " " }
5912 puts "port global name: #{j.get_port_global_name}"
5913 else
5914 (indent+2).times { print " " }
5915 puts "[#{i}]: [optional] id: #{j}"
5916 end
5917 i += 1
5918 }
5919 end
5920 end
5921
5922end
5923
5924#== 逆結合
5925class ReverseJoin < BDNode
5926#@ep_name:: Symbol
5927#@ep_subscript:: Expression or nil
5928#@cell_nsp: NamespacePath
5929#@cp_name:: Symbol
5930#@cp_subscript:: Expression or nil
5931 def initialize( ep_name, ep_subscript, cell_nsp, cp_name, cp_subscript = nil )
5932 super()
5933 @ep_name = ep_name
5934 @ep_subscript = ep_subscript
5935 @cell_nsp = cell_nsp
5936 @cp_name = cp_name
5937 @cp_subscript = cp_subscript
5938 end
5939
5940 def get_name
5941 @ep_name
5942 end
5943
5944 def get_rhs_cell_and_port
5945 [ @ep_subscript, @cell_nsp, @cp_name, @cp_subscript ]
5946 end
5947end
5948
5949# CLASS: CompositeCelltype 用の Join
5950# REM: CompositeCelltype が export するもの
5951class CompositeCelltypeJoin < BDNode
5952# @export_name:: string : CompositeCelltype が export する名前(呼び口、受け口、属性)
5953# @internal_cell_name:: string : CompositeCelltype 内部のセルの名前
5954# @internal_cell_elem_name:: string : CompositeCelltype 内部のセルの呼び口、受け口、属性の名前
5955# @cell : Cell : Cell:: internal cell : CompositeCelltyep 内部のセル(in_compositeセル)
5956# @port_decl:: Port | Decl
5957# @b_pseudo: bool :
5958
5959 def initialize( export_name, internal_cell_name,
5960 internal_cell_elem_name, cell, port_decl )
5961 super()
5962 @export_name = export_name
5963 @internal_cell_name = internal_cell_name
5964 @internal_cell_elem_name = internal_cell_elem_name
5965 @cell = cell
5966 @port_decl = port_decl
5967
5968 end
5969
5970 #=== CompositeCelltypeJoin# CompositeCelltypeJoin の対象セルか?
5971 #cell:: Cell 対象かどうかチェックするセル
5972 #
5973 # CompositeCelltypeJoin と cell の名前が一致するかチェックする
5974 # port_decl が指定された場合は、現状使われていない
5975 def match?( cell, port_decl = nil )
5976
5977 #debug
5978 if port_decl
5979 dbgPrint( "match?" )
5980 dbgPrintf( " @cell: %-20s %08x\n", @cell.get_name, @cell.object_id )
5981 dbgPrintf( " @port_decl: %-20s %08x\n", @port_decl.get_name, @port_decl.object_id )
5982 dbgPrintf( " cell: %-20s %08x\n", cell.get_name, cell.object_id )
5983 dbgPrintf( " port_decl: %-20s %08x\n", port_decl.get_name, port_decl.object_id )
5984 dbgPrint( " cell_name: #{cell.get_name.class}=#{cell.get_name} cell_elem_name: #{port_decl.get_name.class}=#{port_decl.get_name}\n" )
5985 dbgPrint( " @cell_name: #{@cell.get_name.class}=#{@cell.get_name} cell_elem_name: #{@port_decl.get_name.class}=#{@port_decl.get_name}\n" )
5986
5987 end
5988
5989# if @cell.equal?( cell ) && ( port_decl == nil || @port_decl.equal?( port_decl ) ) then
5990 # なぜ port_decl が一致しなければならなかったか忘れた。
5991 # recursive_composite で名前の一致に変更 060917
5992 if((@cell.get_name == cell.get_name) && (port_decl == nil || @port_decl.get_name == port_decl.get_name))then
5993 true
5994 else
5995 false
5996 end
5997 end
5998
5999 def check_dup_init
6000 return if get_port_type != :CALL
6001
6002 if @cell.get_join_list.get_item @internal_cell_elem_name then
6003 cdl_error( "S1131 \'$1.$2\' has duplicate initializer" , @internal_cell_name, @internal_cell_elem_name )
6004 end
6005 end
6006
6007 def get_name
6008 @export_name
6009 end
6010
6011 def get_cell_name
6012 @internal_cell_name
6013 end
6014
6015 def get_cell
6016 @cell
6017 end
6018
6019 def get_cell_elem_name
6020 @internal_cell_elem_name
6021 end
6022
6023 # @port_decl が Port の場合のみ呼び出してよい
6024 def get_port_type
6025 if @port_decl then
6026 @port_decl.get_port_type
6027 end
6028 end
6029
6030 def get_port_decl
6031 @port_decl
6032 end
6033
6034 #=== CompositeCelltypeJoin#get_allocator_instance
6035 def get_allocator_instance
6036 if @port_decl.instance_of? Port then
6037 return @port_decl.get_allocator_instance
6038 elsif @port_decl
6039 raise "CompositeCelltypeJoin#get_allocator_instance: not port"
6040 else
6041 return nil
6042 end
6043 end
6044
6045 # @port_decl が Port の場合のみ呼び出してよい
6046 def is_require?
6047 if @port_decl then
6048 @port_decl.is_require?
6049 end
6050 end
6051
6052 # @port_decl が Port の場合のみ呼び出してよい
6053 def is_allocator_port?
6054 if @port_decl then
6055 @port_decl.is_allocator_port?
6056 end
6057 end
6058
6059 # @port_decl が Port の場合のみ呼び出してよい
6060 def is_optional?
6061 if @port_decl then
6062 @port_decl.is_optional?
6063 end
6064 end
6065
6066 #=== CompositeCelltypeJoin# 右辺が Decl ならば初期化子(式)を返す
6067 # このメソッドは Cell の check_join から初期値チェックのために呼び出される
6068 def get_initializer
6069 if @port_decl.instance_of? Decl then
6070 @port_decl.get_initializer
6071 end
6072 end
6073
6074 def get_size_is
6075 if @port_decl.instance_of? Decl then
6076 @port_decl.get_size_is
6077 end
6078 end
6079
6080 #=== CompositeCelltypeJoin# 配列サイズを得る
6081 #RETURN:: nil: not array, "[]": 大きさ指定なし, Integer: 大きさ指定あり
6082 def get_array_size
6083 @port_decl.get_array_size
6084 end
6085
6086 #=== CompositeCelltypeJoin# signature を得る
6087 # @port_decl が Port の時のみ呼び出してもよい
6088 def get_signature
6089 @port_decl.get_signature
6090 end
6091
6092 #=== CompositeCelltypeJoin# get_type
6093 def get_type
6094 if @port_decl.instance_of? Decl
6095 @port_decl.get_type
6096 end
6097 end
6098
6099 #=== CompositeCelltypeJoin# get_initializer
6100 def get_initializer
6101 if @port_decl.instance_of? Decl
6102 @port_decl.get_initializer
6103 end
6104 end
6105
6106 #=== CompositeCelltypeJoin# get_choice_list
6107 def get_choice_list
6108 if @port_decl.instance_of? Decl
6109 @port_decl.get_choice_list
6110 end
6111 end
6112
6113 def show_tree( indent )
6114 indent.times { print " " }
6115 puts "CompositeCelltypeJoin: export_name: #{@export_name} #{self}"
6116 (indent+1).times { print " " }
6117 puts "internal_cell_name: #{@internal_cell_name}"
6118 (indent+1).times { print " " }
6119 puts "internal_cell_elem_name: #{@internal_cell_elem_name}"
6120 if @port_decl then
6121 @port_decl.show_tree( indent + 1 )
6122 end
6123 end
6124end
6125
6126class Factory < BDNode
6127# @name:: string
6128# @file_name:: string
6129# @format:: string
6130# @arg_list:: Expression の elements と同じ形式 [ [:IDENTIFIER, String], ... ]
6131# @f_celltype:: bool : true: celltype factory, false: cell factory
6132
6133 @@f_celltype = false
6134
6135 def initialize( name, file_name, format, arg_list )
6136 super()
6137 @f_celltype = @@f_celltype
6138
6139 case name
6140 when :write
6141 # write 関数
6142 @name = name
6143
6144 # write 関数の第一引数:出力先ファイル名
6145 # 式を評価する(通常単一の文字列であるから、単一の文字列が返される)
6146 @file_name = file_name.eval_const(nil).val # file_name : Expression
6147 if ! @file_name.instance_of?( String ) then
6148 # 文字列定数ではなかった
6149 cdl_error( "S1132 $1: 1st parameter is not string(file name)" , @name )
6150 @file_name = nil
6151 end
6152
6153 # write 関数の第二引数:フォーマット文字列
6154 @format = format.eval_const(nil).val # format : Expression
6155 # 式を評価する(通常単一の文字列であるから、単一の文字列が返される)
6156 if ! @format.instance_of?( String ) then
6157 # 文字列定数ではなかった
6158 cdl_error( "S1133 $1: 2nd parameter is not string(fromat)" , @name )
6159 @format = nil
6160 end
6161
6162 # 第三引数以降を引数リストとする mikan 引数のチェック
6163 @arg_list = arg_list
6164
6165 else
6166 cdl_error( "S1134 $1: unknown factory function" , name )
6167 end
6168 Celltype.new_factory( self )
6169 end
6170
6171 def check_arg( celltype )
6172 if ! @arg_list then
6173 return
6174 end
6175
6176 if @f_celltype then
6177 cdl_error( "S1135 celltype factory can\'t have parameter(s)" )
6178 return
6179 end
6180
6181 @arg_list.each{ |elements|
6182
6183 case elements[0]
6184 when :IDENTIFIER #1
6185 obj = celltype.find( elements[1] )
6186 if obj == nil then
6187 cdl_error( "S1136 \'$1\': not found" , elements[1] )
6188 elsif ! obj.instance_of?( Decl ) || obj.get_kind != :ATTRIBUTE then
6189 cdl_error( "S1137 \'$1\': not attribute" , elements[1] )
6190 end
6191 when :STRING_LITERAL
6192 else
6193 cdl_error( "S1138 internal error Factory.check_arg()" )
6194 end
6195
6196 }
6197 end
6198
6199 def self.set_f_celltype( f_celltype )
6200 @@f_celltype = f_celltype
6201 end
6202
6203 def get_f_celltype
6204 @f_celltype
6205 end
6206
6207 def get_name
6208 @name
6209 end
6210
6211 def get_file_name
6212 @file_name
6213 end
6214
6215 def get_format
6216 @format
6217 end
6218
6219 def get_arg_list
6220 @arg_list
6221 end
6222
6223 def show_tree( indent )
6224 indent.times { print " " }
6225 puts "Factory: name: #{@name}"
6226 if @arg_list then
6227 (indent+1).times { print " " }
6228 puts "argument(s):"
6229 @arg_list.each { |l|
6230 (indent+2).times { print " " }
6231 print "\"#{l}\"\n"
6232 }
6233 end
6234 end
6235end
6236
6237#== Domain
6238#
6239# region の domain を記憶するクラス
6240class DomainType < Node
6241#@name::Symbol : ドメインタイプの名前 ex) HRP2
6242#@region::Region
6243#@plugin_name::Symbol : ex) HRP2Plugin
6244#@option::String : ex) "trusted", "nontrusted"
6245#@plugin::DomainPlugin の子クラス
6246
6247 include PluginModule
6248
6249 # ドメインに属する region の Hash
6250 # domain 指定が一度も行われない場合、このリストは空である
6251 # ルートリージョンは option = "OutOfDomain" で登録される (domain 指定が無ければ登録されない)
6252 @@domain_regions = { } # { :domain_type => [ region, ... ] }
6253
6254 def initialize( region, name, option )
6255 super()
6256 @name = name
6257 @plugin_name = (name.to_s + "Plugin").to_sym
6258 load_plugin( @plugin_name, DomainPlugin )
6259 @region = region
6260 @option = option
6261
6262 if @@domain_regions[ name ] then
6263 if ! @@domain_regions[ name ].include?( region ) then
6264 @@domain_regions[ name ] << region
6265 end
6266 else
6267 @@domain_regions[ name ] = [ region ]
6268 end
6269 end
6270
6271 def create_domain_plugin
6272 if ! @plugin then
6273 pluginClass = Object.const_get @plugin_name
6274 @plugin = pluginClass.new( @region, @name, @option )
6275 end
6276 end
6277
6278 def add_through_plugin( join, from_region, to_region, through_type )
6279 # print( "DOMAIN: add_through_plugin: from=#{from_region.get_name}#{join.get_owner.get_name}.#{join.get_name} to=#{to_region}#{join.get_cell.get_name}.#{join.get_port_name} through_type=#{through_type}\n" )
6280 return @plugin.add_through_plugin( join, from_region, to_region, through_type )
6281 end
6282
6283 def joinable?( from_region, to_region, through_type )
6284 # print( "DOMAIN: joinable? from_region=#{from_region.get_name} to_region=#{to_region} through_type=#{through_type}\n" )
6285 return @plugin.joinable?( from_region, to_region, through_type )
6286 end
6287
6288 def get_name
6289 @name
6290 end
6291
6292 #== Domain リージョンの Hash を得る
6293 # @@domain_regions の説明参照
6294 def self.get_domain_regions
6295 return @@domain_regions
6296 end
6297
6298 def get_regions
6299 return @@domain_regions[ @name ]
6300 end
6301
6302 def get_option
6303 @option
6304 end
6305
6306 def show_tree( indent )
6307 (indent+1).times { print( " " ) }
6308 puts "domain: name=#{@name} plugin=#{@plugin_name} option=#{@option}"
6309 end
6310end
6311
6312#== Region クラス
6313#
6314# Region は Namespace を継承している
6315# root region は特殊で、root namespace と同じである
6316#
6317# cell は region に属する
6318# region に属する cell のリストは Namespace クラスのインスタンス変数として記憶される
6319#
6320class Region < Namespace
6321# @name:: string
6322# @in_through_list:: [ [ plugin_name, plugin_arg ], ... ] : plungin_name = nil の時 in 禁止
6323# @out_through_list:: [ [ plugin_name, plugin_arg ], ... ] : plungin_name = nil の時 out 禁止
6324# @to_through_list:: [ [ dst_region, plugin_name, plugin_arg ], ... ]
6325# @cell_port_throug_plugin_list:: { "#{cell_name}.#{port_name}" => through_generated_list の要素 }
6326# この region から cell_name.port_name への through プラグインで生成されたオブジェクト
6327# @region_type::Symbol : :NODE, :LINKUNIT, :DOMAIN, :CLASS
6328# @region_type_param::Symbol : domain, class の名前. node, linkunit では nil
6329# @link_root:: Region : linkUnit の根っことなる region (node, linkunit が指定された region)
6330# @family_line:: [ @region_root, ...,@region_me ] 家系
6331# @in_through_count:: Integer : n 番目の in_through 結合 (n>=0)
6332# @out_through_count:: Integer : n 番目の out_through 結合 (n>=0)
6333# @to_through_count:: { :RegionName => Integer }: RegionName への n 番目の to_through 結合 (n>=0)
6334# @domain_type::DomainType : domain 指定されていない場合、nil
6335# @domain_root::Region : domain 指定されていなる Region (root の場合 nil)
6336
6337 @@in_through_list = []
6338 @@out_through_list = []
6339 @@to_through_list = []
6340 @@region_type = nil
6341 @@region_type_param = nil
6342 @@domain_name = nil
6343 @@domain_option = nil # Token が入る
6344
6345 @@link_roots = []
6346
6347 def initialize( name )
6348 # mikan name の Namespace 修飾
6349 # object = Namespace.find( [ name ] ) # 親まで捜しにいく
6350 if name != "::" then
6351 object = Namespace.get_current.find( name ) #1
6352 else
6353 # root リージョン
6354 object = nil
6355 @@region_type = :NODE
6356 end
6357
6358 @in_through_list = @@in_through_list
6359 @out_through_list = @@out_through_list
6360 @to_through_list = @@to_through_list
6361 @region_type = @@region_type
6362 @region_type_param = @@region_type_param
6363
6364 if @@domain_name then
6365 domain_option = CDLString.remove_dquote @@domain_option.to_s
6366 @domain_type = DomainType.new( self, @@domain_name, domain_option )
6367 @@domain_name = nil
6368 @@domain_option = nil
6369 else
6370 @domain_type = nil
6371 end
6372
6373 @@in_through_list = []
6374 @@out_through_list = []
6375 @@to_through_list = []
6376 @@region_type = nil
6377 @@region_type_param = nil
6378
6379 @in_through_count = -1
6380 @out_through_count = -1
6381 @to_through_count = {}
6382
6383 super( name )
6384 if object then
6385
6386 if object.instance_of?( Region ) then
6387 dbgPrint "Region.new: re-appear #{@name}\n"
6388
6389 # # Region path が前回出現と一致するか?
6390 # if @@region_stack[ @@region_stack_sp - 1 ] then
6391 # my_path = @@region_stack[ @@region_stack_sp - 1 ].get_path_string.to_s + "." + @name.to_s
6392 # else
6393 # my_path = @name.to_s
6394 # end
6395 # if my_path != object.get_path_string then
6396 # cdl_error( "S1139 $1: region path mismatch. previous path: $2" , my_path, object.get_path_string )
6397 # end
6398
6399 # 再出現
6400 # @@region_stack[@@region_stack_sp] = object
6401
6402 # 再出現時に specifier が指定されているか?
6403 if( @in_through_list.length != 0 || @out_through_list.length != 0 || @to_through_list.length != 0 || @region_type != nil )then
6404 cdl_error( "S1140 $1: region specifier must place at first appearence" , name )
6405 end
6406 return
6407
6408 else
6409 # エラー用ダミー定義
6410
6411 # 異なる同名のオブジェクトが定義済み
6412 cdl_error( "S1141 $1 duplication, previous one : $2" , name, object.class )
6413 # @@region_stack[@@region_stack_sp] = self # エラー時暫定 region
6414 end
6415 else
6416 # 初出現
6417 dbgPrint "Region.new: #{@name}\n"
6418 set_region_family_line
6419
6420 if @region_type == :NODE || @region_type == :LINKUNIT then
6421 dbgPrint "new LinkRoot: #{@name}\n"
6422 @@link_roots << self
6423 end
6424 end
6425
6426 @cell_port_throug_plugin_list = {}
6427
6428# p @name
6429# p @in_through_list
6430# p @out_through_list
6431# p @to_through_list
6432
6433 end
6434
6435 def self.end_of_parse
6436 Namespace.get_current.create_domain_plugin
6437 Namespace.get_current.end_of_parse
6438 end
6439
6440 def self.new_in_through( plugin_name = nil, plugin_arg = nil )
6441 @@in_through_list << [ plugin_name, plugin_arg ]
6442 end
6443
6444 def self.new_out_through( plugin_name = nil, plugin_arg = nil )
6445 @@out_through_list << [ plugin_name, plugin_arg ]
6446 end
6447
6448 def self.new_to_through( dst_region, plugin_name, plugin_arg )
6449 # p "New to_through #{dst_region}"
6450 @@to_through_list << [ dst_region, plugin_name, plugin_arg ]
6451 end
6452
6453 def self.set_type( type, param = nil )
6454 if @@region_type then
6455 Generator.error( "S1178 $1 region type specifier duplicate, previous $2", type, @@region_type )
6456 end
6457 @@region_type = type
6458 @@region_type_param = param
6459 end
6460
6461 def self.set_domain( name, option )
6462 if @@domain_name then
6463 Generator.error( "S9999 $1 domain specifier duplicate, previous $2", type, @@region_type )
6464 end
6465 @@domain_name = name
6466 @@domain_option = option
6467 end
6468
6469 #== Region ルートリージョンを得る
6470 # ルートリージョンは、ルートネームスペースと同じである
6471 def self.get_root
6472 Namespace.get_root
6473 end
6474
6475 def set_region_family_line
6476
6477 dbgPrint "set_region_family_line: Region: #{@name} \n"
6478 # root namespace (root region) の region type は :NODE
6479 if @name == "::" then
6480 @region_type = :NODE
6481 end
6482
6483 if @region_type == :NODE || @region_type == :LINKUNIT then
6484 @link_root = self
6485 else
6486 @link_root = @owner.get_link_root
6487 end
6488
6489 if @domain_type != nil || @owner == nil then
6490 @domain_root = self
6491 else
6492 @domain_root = @owner.get_domain_root
6493 end
6494
6495 if @domain_type then
6496 # ルートリージョンが最初から @domain_type 設定されることはないの
6497 # で @owner == nil を調べる必要はない
6498 @owner.set_domain_type @domain_type
6499 end
6500
6501 if @owner then
6502 @family_line = ( @owner.get_family_line.dup ) << self
6503 else
6504 @family_line = [ self ] # root region
6505 end
6506
6507=begin
6508 @family_line = []
6509 @link_root = nil
6510
6511 # @family_line を作成する
6512 # @link_root もみつける
6513 # (上位にたどっていって Region で node または linkunit のいずれか先に見つかったものが @link_root となる)
6514 # root namespace は Region かつ node なので必ず @link_root は見つかる
6515 # mikan: self が node, linkUnit の場合、ここで期待したとおりに設定されないため、Region#initialize で再設定
6516 obj = self
6517 while 1
6518 if obj.instance_of? Region then
6519 @family_line << obj
6520 if @link_root == nil then
6521 if obj.get_region_type == :NODE || obj.get_region_type == :LINKUNIT then
6522 @link_root = obj
6523 end
6524 end
6525 else
6526 # さもなければ Namespace
6527 # namespace の下に region がある場合
6528 end
6529
6530 # root namespace にたどり着けば終り
6531 break if obj.get_name == "::"
6532
6533 obj = obj.get_owner
6534 end
6535 # print "#{@name}: linkRoot: #{@link_root.get_name} (this can be wrong if #{@name} is node or linkunit, and corret later\n"
6536 @family_line.reverse!
6537=end
6538
6539 end
6540
6541 #== Region#ドメインを設定する
6542 def set_domain_type domain_type
6543 if @region_type == :NODE then
6544 if @domain_type then
6545 if @domain_type.get_name != domain_type.get_name then
6546 cdl_error( "S9999 '$1' node root cannot belong to both $2 and $3", @name, @domain_type.get_name, domain_type.get_name )
6547 end
6548 else
6549 @domain_type = DomainType.new( self, domain_type.get_name, "OutOfDomain" )
6550 @domain_type.create_domain_plugin
6551 end
6552 elsif @domain_type == nil then
6553 @owner.set_domain_type domain_type
6554 end
6555 end
6556
6557 def self.get_link_roots
6558 @@link_roots
6559 end
6560
6561 def get_family_line
6562 @family_line
6563 end
6564
6565 def get_in_through_list
6566 @in_through_list
6567 end
6568
6569 def get_out_through_list
6570 @out_through_list
6571 end
6572
6573 def get_to_through_list
6574 @to_through_list
6575 end
6576
6577 def get_link_root
6578 @link_root
6579 end
6580
6581 def get_domain_type
6582 @domain_type
6583 end
6584
6585 #== Region# domain の根っことなる region を得る
6586 # Region のインスタンスを返す
6587 # domain 指定子があれば、そのリージョンがドメインルートである
6588 # なければ、親リージョンのドメインルートとする
6589 def get_domain_root
6590 @domain_root
6591 end
6592
6593 def get_path_string
6594 pstring = ""
6595 delim = ""
6596 @family_line.each{ |p|
6597 pstring = "#{pstring}#{delim}#{p.get_name}"
6598 delim = "."
6599 }
6600 dbgPrint "get_path_string: #{pstring}\n"
6601 pstring
6602 end
6603
6604 def get_region_type
6605 @region_type
6606 end
6607
6608 def get_name
6609 @name
6610 end
6611
6612 def next_in_through_count
6613 @in_through_count += 1
6614 end
6615
6616 def next_out_through_count
6617 @out_through_count += 1
6618 end
6619
6620 def next_to_through_count( symRegionName )
6621 if @to_through_count[ symRegionName ] == nil then
6622 @to_through_count[ symRegionName ] = 0
6623 else
6624 @to_through_count[ symRegionName ] += 1
6625 end
6626 end
6627
6628 #=== Region# 構文解析中の region を得る
6629 # 構文解析中 Namespace (あるいは子クラスの Region) の上位をたどって Region を見つける
6630 # cell が namespace 下におくことができなければ、ループをまわす必要はない
6631 def self.get_current
6632 # @@region_stack[@@region_stack_sp]
6633 region = Namespace.get_current
6634 while 1
6635 if region.instance_of? Region
6636 break
6637 end
6638 region = region.get_owner
6639 end
6640 return region
6641 end
6642
6643 #=== Region# through プラグインで、この region から cell_name.port_name へのプラグインオブジェクトを登録
6644 # mikan namesppace 対応 (cell_name)
6645 def add_cell_port_through_plugin( cell_name, port_name, through_plugin_object )
6646 @cell_port_throug_plugin_list[ "#{cell_name}.#{port_name}" ] = through_plugin_object
6647 end
6648
6649 def find_cell_port_through_plugin( cell_name, port_name )
6650 return @cell_port_throug_plugin_list[ "#{cell_name}.#{port_name}" ]
6651 end
6652
6653 def create_domain_plugin
6654 if @domain_type then
6655 @domain_type.create_domain_plugin
6656 end
6657 end
6658
6659 #=== Region# to_region への距離(unreachable な場合 nil)
6660 # mikan Cell#check_region とRegion へたどり着くまでための処理に共通性が高い
6661 # region#distance は require で用いられる
6662 def distance( to_region )
6663
6664 r1 = self # 出発 region
6665 r2 = to_region # 目的 region
6666 dist = 0
6667
6668 if ! r1.equal? r2 then # 同一 region なら呼出し可能
6669
6670 # mikan namespace 対応
6671 f1 = r1.get_family_line
6672 len1 = f1.length
6673 f2 = r2.get_family_line
6674 len2 = f2.length
6675
6676 # 不一致になるところ(兄弟)を探す
6677 i = 1 # i = 0 は :RootRegion なので必ず一致
6678 while( i < len1 && i < len2 )
6679 if( f1[i] != f2[i] )then
6680 break
6681 end
6682 i += 1
6683 end
6684
6685 sibling_level = i # 兄弟となるレベル、もしくはどちらか一方が終わったレベル
6686
6687 # p "sibling_level: #{i}"
6688 # p "from: #{f1[i].get_name}" if f1[i]
6689 # p "to: #{f2[i].get_name}" if f2[i]
6690
6691 # 呼び側について呼び元のレベルから兄弟レベルまで(out_through をチェックおよび挿入)
6692 i = len1 -1
6693 while i >= sibling_level
6694 dbgPrint "going out from #{f1[i].get_name} level=#{i}\n"
6695 # print "DOMAIN: going out from #{f1[i].get_name} level=#{i}\n"
6696 domain = f1[i].get_domain_type
6697 domain_ok = false
6698 if domain then
6699 if ! f1[i].get_domain_type.joinable?( f1[i], f1[i-1], :OUT_THROUGH ) then
6700 return nil
6701 end
6702 domain_ok = true
6703 end
6704 if ! domain_ok then
6705 out_through_list = f1[i].get_out_through_list # [ plugin_name, plugin_arg ]
6706 if out_through_list.length == 0 then
6707 return nil
6708 end
6709 end
6710 i -= 1
6711 dist += 1
6712 end
6713
6714 # 兄弟レベルにおいて(to_through をチェックおよび挿入)
6715 if f1[sibling_level] && f2[sibling_level] then
6716 dbgPrint "going from #{f1[sibling_level].get_name} to #{f2[sibling_level].get_name}\n"
6717 # print "DOMAIN: going from #{f1[sibling_level].get_name} to #{f2[sibling_level].get_name}\n"
6718 domain = f1[sibling_level].get_domain_type
6719 domain_ok = false
6720 if domain then
6721 if ! f1[i].get_domain_type.joinable?( f1[i], f1[i-1], :TO_THROUGH ) then
6722 return nil
6723 end
6724 domain_ok = true
6725 end
6726 if ! domain_ok then
6727 found = 0
6728 f1[sibling_level].get_to_through_list.each { |t|
6729 if t[0][0] == f2[sibling_level].get_name then # region 名が一致するか ?
6730 found = 1
6731 end
6732 }
6733 if found == 0 then
6734 return nil
6735 end
6736 end
6737 dist += 1
6738 end
6739
6740 # 受け側について兄弟レベルから受け側のレベルまで(in_through をチェックおよび挿入)
6741 i = sibling_level
6742 while i < len2
6743 dbgPrint "going in to #{f2[i].get_name} level=#{i}\n"
6744 # print "DOMAIN: going in to #{f2[i].get_name} level=#{i}\n"
6745 domain = f2[i].get_domain_type
6746 domain_ok = false
6747 if domain then
6748 if ! f2[i].get_domain_type.joinable?( f2[i-1], f2[i], :IN_THROUGH ) then
6749 return nil
6750 end
6751 domain_ok = true
6752 end
6753 if ! domain_ok then
6754 in_through_list = f2[i].get_in_through_list # [ plugin_name, plugin_arg ]
6755 if in_through_list.length == 0 then
6756 return nil
6757 end
6758 end
6759 i += 1
6760 dist += 1
6761 end
6762 end
6763
6764 dbgPrint "dsitance=#{dist} from #{r1.get_name} to #{r2.get_name}\n"
6765
6766 return dist
6767 end
6768
6769 def show_tree( indent )
6770 super
6771 (indent+1).times { print( " " ) }
6772 puts "path: #{get_path_string}"
6773 (indent+1).times { print( " " ) }
6774 puts "namespace: #{@namespace ? @namespace.get_name : "nil"} owner: #{@owner.class}.#{@owner ? @owner.get_name : "nil"}"
6775 if @domain
6776 @domain.show_tree( indent+1 )
6777 end
6778 end
6779end
6780
6781class Import_C < Node
6782
6783 # ヘッダの名前文字列のリスト
6784 @@header_list = {}
6785 @@header_list2 = []
6786 @@define_list = {}
6787
6788 #=== Import_C# import_C の生成(ヘッダファイルを取込む)
6789 #header:: Token : import_C の第一引数文字列リテラルトークン
6790 #define:: Token : import_C の第二引数文字列リテラルトークン
6791 def initialize( header, define = nil )
6792 super()
6793 # ヘッダファイル名文字列から前後の "" を取り除く
6794 # header = header.to_s.gsub( /\A"(.*)"\z/, '\1' )
6795 header = CDLString.remove_dquote header.to_s
6796
6797 if define then
6798 # 前後の "" を取り除く
6799 # def_opt = define.to_s.gsub( /\A"(.*)/, '\1' )
6800 # def_opt.sub!( /(.*)"\z/, '\1' )
6801 def_opt = CDLString.remove_dquote define.to_s
6802
6803 # "," を -D に置き換え
6804 def_opt = def_opt.gsub( /,/, " -D " )
6805
6806 # 先頭に -D を挿入 # mikan 不適切な define 入力があった場合、CPP 時にエラー
6807 def_opt = def_opt.gsub( /^/, "-D " )
6808
6809 end
6810
6811 # コマンドライン指定された DEFINE
6812 $define.each{ |define|
6813 if $IN_EXERB then
6814 q = ""
6815 else
6816 if define =~ /'/ then
6817 q = '"'
6818 else
6819 q = "'"
6820 end
6821 end
6822 def_opt = "#{def_opt} -D #{q}#{define}#{q}"
6823 }
6824
6825 include_opt = ""
6826 found = false
6827 header_path = ""
6828 $import_path.each{ |path|
6829 include_opt = "#{include_opt} -I #{path}"
6830 if found == false then
6831 begin
6832 # ファイルの stat を取ってみる(なければ例外発生)
6833 File.stat( "#{path}/#{header}" )
6834
6835 # cdl を見つかったファイルパスに再設定
6836 header_path = "#{path}/#{header}"
6837 found = true
6838 rescue => evar
6839 found = false
6840 # print_exception( evar )
6841 end
6842 end
6843 }
6844
6845 if found == false then
6846 cdl_error( "S1142 $1 not found in search path" , header )
6847 return
6848 end
6849
6850 # 読込み済み?
6851 if( @@header_list[ header ] ) then
6852 # 第二引数 define が以前と異なる
6853 if @@define_list[ header ].to_s != define.to_s then
6854 cdl_error( "S1143 import_C: arg2: mismatch with previous one" )
6855 end
6856 # いずれにせよ読み込まない
6857 return
6858 end
6859
6860 # ヘッダのリストを記録
6861 @@header_list[ header ] = header_path
6862 @@header_list2 << header
6863 @@define_list[ header ] = define
6864
6865 begin
6866 tmp_C = "#{$gen}/tmp_C_src.c"
6867 file = File.open( tmp_C, "w" )
6868 rescue => evar
6869 cdl_error( "S1144 $1: temporary C source: open error" , tmp_C )
6870 print_exception( evar )
6871 end
6872
6873 begin
6874 print_defines file
6875
6876 file.print( "#include \"#{header}\"\n" )
6877 rescue => evar
6878 cdl_error( "S1145 $1: temporary C source: writing error" , tmp_C )
6879 print_exception( evar )
6880 ensure
6881 file.close
6882 end
6883
6884 # CPP 出力用 tmp ファイル名
6885 tmp_header = header.gsub( /\//, "_" )
6886 tmp_header = "#{$gen}/tmp_#{tmp_header}"
6887
6888 # CPP コマンドラインを作成
6889 cmd = "#{$cpp} #{def_opt} #{include_opt} #{tmp_C}"
6890
6891 begin
6892 if( $verbose )then
6893 puts "CPP: #{cmd}"
6894 end
6895
6896 # プリプロセッサコマンドを pipe として開く
6897 # cmd は cygwin/Linux では bash(sh) 経由で実行される
6898 # Exerb 版では cmd.exe 経由で実行される
6899 # この差は引き数の (), $, % などシェルの特別な文字の評価に現れるので注意
6900 cpp = IO.popen( cmd, "r:ASCII-8BIT" )
6901 begin
6902 tmp_file = nil
6903 tmp_file = File.open( tmp_header, "w:ASCII-8BIT" )
6904 cpp.each { |line|
6905 line = line.gsub( /^#(.*)$/, '/* \1 */' )
6906 tmp_file.puts( line )
6907 }
6908 rescue => evar
6909 cdl_error( "S1146 $1: error occured while CPP" , header )
6910 print_exception( evar )
6911 ensure
6912 tmp_file.close if tmp_file # mikan File.open に失敗した時 tmp_file == nil は保証されている ?
6913 cpp.close
6914 end
6915 rescue => evar
6916 cdl_error( "S1147 $1: popen for CPP failed" , header )
6917 print_exception( evar )
6918 end
6919
6920 # C 言語のパーサインスタンスを生成
6921 c_parser = C_parser.new
6922
6923 # tmp_header をパース
6924 c_parser.parse( [tmp_header] )
6925
6926 # 終期化 パーサスタックを戻す
6927 c_parser.finalize
6928
6929 end
6930
6931 def print_defines file
6932 if ! $b_no_gcc_extension_support then
6933
6934 file.print <<EOT
6935
6936#ifndef TECS_NO_GCC_EXTENSION_SUPPORT
6937
6938/*
6939 * these extension can be eliminated also by spefcifying option
6940 * --no-gcc-extension-support for tecsgen.
6941 */
6942#ifndef __attribute__
6943#define __attribute__(x)
6944#endif
6945
6946#ifndef __extension__
6947#define __extension__
6948#endif
6949
6950#ifndef __builtin_va_list
6951#define __builtin_va_list va_list
6952#endif
6953
6954#ifndef __asm__
6955#define __asm__(x)
6956#endif
6957
6958#endif /* TECS_NO_GCC_EXTENSION_SUPPORT */
6959EOT
6960 end
6961
6962 file.print <<EOT
6963
6964/* va_list is not supported in C_parser.y.rb */
6965typedef struct { int dummy; } va_list;
6966
6967EOT
6968 end
6969
6970 def self.get_header_list
6971 @@header_list
6972 end
6973 def self.get_header_list2
6974 @@header_list2
6975 end
6976
6977end
6978
6979class Import < Node
6980# @b_reuse::bool: 再利用.セルタイプの template 生成不要
6981# @b_reuse_real::bool: 実際に再利用
6982# @cdl:: string: import する CDL
6983# @cdl_path:: string: CDL のパス
6984# @b_imported:: bool: import された(コマンドライン指定されていない)
6985
6986 # ヘッダの名前文字列のリスト 添字:expand したパス、値:Import
6987 @@import_list = {}
6988
6989 @@nest_stack_index = -1
6990 @@nest_stack = []
6991 @@current_object = nil
6992
6993 def self.push object
6994 @@nest_stack_index += 1
6995 @@nest_stack[ @@nest_stack_index ] = @@current_object
6996 @@current_object = object
6997 end
6998
6999 def self.pop
7000 @@current_object = @@nest_stack[ @@nest_stack_index ]
7001 @@nest_stack_index -= 1
7002 if @@nest_stack_index < -1 then
7003 raise "TooManyRestore"
7004 end
7005 end
7006
7007 #=== Import# import を行う
7008 #cdl:: string cdl へのパス."" で囲まれていることを仮定
7009 #b_reuse:: bool true: template を生成しない
7010 def initialize( cdl, b_reuse = false, b_imported = true )
7011 Import.push self
7012 @b_imported = b_imported
7013 super()
7014 @@current_import = self
7015 # ヘッダファイル名文字列から前後の "", <> を取り除くn
7016 @cdl = cdl.to_s.gsub( /\A["<](.*)[">]\z/, '\1' )
7017
7018 # サーチパスから探す
7019 found = false
7020 @cdl_path = ""
7021
7022 @b_reuse = b_reuse
7023 @b_reuse_real = @b_reuse || Generator.is_reuse?
7024
7025 if Generator.get_plugin then
7026 # plugin から import されている場合 gen をサーチパスの先頭に加える
7027 search_path = [ $gen ] + $import_path
7028 else
7029 search_path = $import_path
7030 end
7031
7032 search_path.each{ |path|
7033 dbgPrint "import: searching #{path}/#{@cdl}"
7034 begin
7035 if path == "."
7036 cdl_path = @cdl
7037 else
7038 cdl_path = "#{path}/#{@cdl}"
7039 end
7040
7041 # ファイルの stat を取ってみる(なければ例外発生)
7042 File.stat( cdl_path )
7043
7044 # cdl を見つかったファイルパスに再設定
7045 @cdl_path = cdl_path
7046 found = true
7047 dbgPrint ": found\n"
7048 break
7049 rescue => evar
7050 found = false
7051 dbgPrint ": not found\n"
7052 # print_exception( evar )
7053 end
7054 }
7055
7056 if found == false then
7057 cdl_error( "S1148 $1 not found in search path" , @cdl )
7058 return
7059 end
7060
7061 # 読込み済みなら、読込まない
7062 prev = @@import_list[ File.expand_path( @cdl_path ) ]
7063 if( prev ) then
7064 if prev.is_reuse_real? != @b_reuse_real then
7065 cdl_warning( "W1008 $1: reuse designation mismatch with previous import" , @cdl )
7066 end
7067 return
7068 end
7069
7070 # import リストを記録
7071 @@import_list[ File.expand_path( @cdl_path ) ] = self
7072
7073 # plugin から import されている場合
7074 plugin = Generator.get_plugin
7075
7076 # パーサインスタンスを生成(別パーサで読み込む)
7077 parser = Generator.new
7078
7079 # plugin から import されている場合の plugin 設定
7080 parser.set_plugin plugin
7081
7082 # reuse フラグを設定
7083 parser.set_reuse @b_reuse_real
7084
7085 # cdl をパース
7086 parser.parse( [@cdl_path] )
7087
7088 # 終期化 パーサスタックを戻す
7089 parser.finalize
7090 Import.pop
7091 end
7092
7093 def self.get_list
7094 @@import_list
7095 end
7096
7097 def get_cdl_path
7098 @cdl_path
7099 end
7100
7101 def is_reuse_real?
7102 @b_reuse_real
7103 end
7104
7105 def self.get_current
7106 @@current_object
7107 end
7108
7109 def is_imported?
7110 @b_imported
7111 end
7112
7113 #=== cdl の名前を返す
7114 # 引数で指定されている cdl 名。一部パスを含む可能性がある
7115 def get_cdl_name
7116 @cdl
7117 end
7118end
7119
7120#== generate: signature プラグインのロードと実行
7121class Generate < Node
7122#@plugin_name:: Symbol
7123#@signature_nsp:: NamespacePath
7124#@option:: String '"', '"' で囲まれている
7125
7126 include PluginModule
7127
7128 def initialize( plugin_name, signature_nsp, option )
7129 super()
7130 @plugin_name = plugin_name
7131 @signature_nsp = signature_nsp
7132 option = option.to_s # option は Token
7133 @option = option
7134
7135 signature = Namespace.find( signature_nsp ) #mikan Namespace #1
7136 if ! signature.instance_of? Signature then
7137 cdl_error( "S1149 $1 not signature" , signature_nsp )
7138 return
7139 elsif signature.is_empty? then
7140 cdl_warning( "S9999 $1 is empty. cannot apply signature plugin. ignored" , signature_nsp )
7141 return
7142 end
7143
7144 load_plugin( plugin_name, SignaturePlugin )
7145
7146 plugin_object = nil
7147 eval_str = "plugin_object = #{plugin_name}.new( signature, option )"
7148 if $verbose then
7149 print "new through: #{eval_str}\n"
7150 end
7151
7152 begin
7153 eval( eval_str ) # plugin を生成
7154 plugin_object.set_locale @locale
7155 rescue Exception => evar
7156 cdl_error( "S1150 $1: fail to new" , plugin_name )
7157 print "eval( #{eval_str} )\n"
7158
7159 print_exception( evar )
7160 end
7161 generate_and_parse plugin_object
7162 end
7163end
7164
7165#== 名前空間パス
7166class NamespacePath < Node
7167#@b_absolute::Bool
7168#@path::[ Symbol,... ]
7169#@namespace::Namespace: @b_absolute == false のとき、基点となる namespace
7170
7171 #=== NamespacePath# initialize
7172 #ident::Symbol 最初の名前, ただし "::" のみの場合は String
7173 #b_absolute:Bool "::" で始まっている場合 true
7174 #namespace::Namespace b_absolute = false かつ、構文解釈段階以外で呼び出す場合は、必ず指定すること
7175 def initialize( ident, b_absolute, namespace = nil )
7176 super()
7177
7178 if ident == "::" then # RootNamespace
7179 @path = []
7180 @b_absolute = true
7181 else
7182 @path = [ ident ]
7183 @b_absolute = b_absolute
7184 end
7185
7186 if namespace then
7187 @namespace = namespace
7188 if b_absolute == true then
7189 raise "NamespacePath#initialize: naamespace specified for absolute path"
7190 end
7191 else
7192 if b_absolute == false then
7193 @namespace = Namespace.get_current
7194 else
7195 @namespace = nil
7196 end
7197 end
7198 end
7199
7200 #=== NamespacePath# append する
7201 #RETURN self
7202 # このメソッドは、元の NamespacePath オブジェクトを変形して返す
7203 def append!( ident )
7204 @path << ident
7205 return self
7206 end
7207 #=== NamespacePath# append する
7208 # このメソッドは、元の NamespacePath オブジェクトを変形しない
7209 #RETURN:: 複製した NamespacePath
7210 def append( ident )
7211 cl = self.clone
7212 cl.set_clone
7213 cl.append!( ident )
7214 return cl
7215 end
7216
7217 def set_clone
7218 @path = @path.clone
7219 end
7220
7221 def get_name
7222 @path[ @path.length - 1 ]
7223 end
7224
7225 #=== NamespacePath#クローンを作成して名前を変更する
7226 def change_name name
7227 cl = self.clone
7228 cl.set_clone
7229 cl.change_name_no_clone name
7230 return cl
7231 end
7232 alias :change_name_clone :change_name
7233
7234 #=== NamespacePath#名前を変更する
7235 # このインスタンスを参照するすべてに影響を与えることに注意
7236 def change_name_no_clone name
7237 @path[ @path.length - 1 ] = name
7238 nil
7239 end
7240
7241 #=== NamespacePath:: path 文字列を得る
7242 # CDL 用の path 文字列を生成
7243 def to_s
7244 get_path_str
7245 end
7246 def get_path_str
7247 first = true
7248 if @b_absolute then
7249 path = "::"
7250 else
7251 path = ""
7252 end
7253 @path.each{ |n|
7254 if first then
7255 path = "#{path}#{n}"
7256 first = false
7257 else
7258 path += "::#{n}"
7259 end
7260 }
7261 return path
7262 end
7263
7264 def is_absolute?
7265 @b_absolute
7266 end
7267 def is_name_only?
7268 @path.length == 1 && @b_absolute == false
7269 end
7270
7271 #=== NamespacePath:: パスの配列を返す
7272 # is_absolute? true の場合、ルートからのパス
7273 # false の場合、base_namespace からの相対
7274 # ルート namespace の場合、長さ0の配列を返す
7275 #
7276 def get_path
7277 @path
7278 end
7279
7280 #=== NamespacePath#フルパスの配列を返す
7281 # 返された配列を書き換えてはならない
7282 def get_full_path
7283 if @b_absolute then
7284 return @path
7285 else
7286 return @namespace.get_namespace_path.get_full_path.clone + @path
7287 end
7288 end
7289
7290 #=== NamespacePath:: 相対パスのベースとなる namespace
7291 # is_absolute? == false の時のみ有効な値を返す (true なら nil)
7292 def get_base_namespace
7293 @namespace
7294 end
7295
7296 #=== NamespacePath:: C 言語グローバル名を得る
7297 def get_global_name
7298 if @b_absolute then
7299 global_name = ""
7300 else
7301 global_name = @namespace.get_global_name
7302 end
7303
7304 @path.each{ |n|
7305 if global_name != "" then
7306 global_name = "#{global_name}_#{n}"
7307 else
7308 global_name = n.to_s
7309 end
7310 }
7311 global_name
7312 end
7313
7314 #=== NamespacePath:: 分解して NamespacePath インスタンスを生成する
7315 #path_str:: String : namespace または region のパス ex) "::path::A" , "::", "ident"
7316 #b_force_absolute:: Bool : "::" で始まっていない場合でも絶対パスに扱う
7317 #
7318 # NamespacePath は通常構文解析されて作成される
7319 # このメソッドは、オプションなどで指定される文字列を分解して NamespacePath を生成するのに用いる
7320 # チェックはゆるい。不適切なパス指定は、不適切な NamespacePath が生成される
7321 def self.analyze( path_str, b_force_absolute = false )
7322
7323 if path_str == "::" then
7324 return self.new( "::", true )
7325 end
7326
7327 pa = path_str.split( "::" )
7328 if pa[0] == "" then
7329 pa.shift
7330 b_absolute = true
7331 else
7332 if b_force_absolute then
7333 b_absolute = true
7334 else
7335 b_absolute = false
7336 end
7337 end
7338
7339 if pa[0] then
7340 nsp = self.new( pa[0].to_sym, b_absolute )
7341 else
7342 nsp = self.new( "::", b_absolute )
7343 end
7344 pa.shift
7345
7346 pa.each{ |a|
7347 if a then
7348 nsp.append! a.to_sym
7349 else
7350 nsp.append! "::"
7351 end
7352 }
7353
7354 return nsp
7355 end
7356
7357end
7358
7359# 以下単体テストコード
7360if $unit_test then
7361 root_namespace = Namespace.new("::")
7362
7363 puts( "===== Unit Test: NamespacePath ===== (componentobj.rb)")
7364 a = NamespacePath.new( :"ABC", true )
7365 printf( "Path: %-10s global_name: %s\n", a.get_path_str, a.get_global_name )
7366
7367 a.append( :"DEF" )
7368 printf( "Path: %-10s global_name: %s\n", a.get_path_str, a.get_global_name )
7369
7370 a = NamespacePath.new( :"abc", false )
7371 printf( "Path: %-10s global_name: %s\n", a.get_path_str, a.get_global_name )
7372
7373 a.append( :"def" )
7374 printf( "Path: %-10s global_name: %s\n", a.get_path_str, a.get_global_name )
7375
7376 puts ""
7377end
Note: See TracBrowser for help on using the repository browser.