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

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

mruby版ECNLプロトタイピング・ツールを追加

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