1 | # -*- coding: utf-8 -*-
|
---|
2 | #
|
---|
3 | # TECS Generator
|
---|
4 | # Generator for TOPPERS Embedded Component System
|
---|
5 | #
|
---|
6 | # Copyright (C) 2008-2016 by TOPPERS Project
|
---|
7 | #--
|
---|
8 | # 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
|
---|
9 | # ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
|
---|
10 | # 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
|
---|
11 | # (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
|
---|
12 | # 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
|
---|
13 | # スコード中に含まれていること.
|
---|
14 | # (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
|
---|
15 | # 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
|
---|
16 | # 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
|
---|
17 | # の無保証規定を掲載すること.
|
---|
18 | # (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
|
---|
19 | # 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
|
---|
20 | # と.
|
---|
21 | # (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
|
---|
22 | # 作権表示,この利用条件および下記の無保証規定を掲載すること.
|
---|
23 | # (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
|
---|
24 | # 報告すること.
|
---|
25 | # (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
|
---|
26 | # 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
|
---|
27 | # また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
|
---|
28 | # 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
|
---|
29 | # 免責すること.
|
---|
30 | #
|
---|
31 | # 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
|
---|
32 | # よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
|
---|
33 | # に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
|
---|
34 | # アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
|
---|
35 | # の責任を負わない.
|
---|
36 | #
|
---|
37 | # $Id$
|
---|
38 | #++
|
---|
39 |
|
---|
40 | # STAGE:
|
---|
41 | # このメンテナンス状況はよろしくない
|
---|
42 | # B bnf.y.rb から呼出される
|
---|
43 | # P parse 段階で呼出される(bnf.y.rb から直接呼出されるわけではないが、構文木生成を行う)
|
---|
44 | # S P の中から呼出されるが、構文木生成するわけではなく意味チェックする
|
---|
45 | # G コード生成(この段階で、構文木は完全である.不完全ならエラーで打ちきられている)
|
---|
46 | # factory の第一引数 "format" の後ろの引数
|
---|
47 |
|
---|
48 | # mikan 以下は ruby の mix in で実現できるかもしれない
|
---|
49 | # Nestable を継承した場合、クラス変数は Nestable のものが共有される(別にしたかった)
|
---|
50 | # class Nestable
|
---|
51 | # @@nest_stack_index = -1
|
---|
52 | # @@nest_stack = []
|
---|
53 | # @@current_object = nil
|
---|
54 | #
|
---|
55 | # def self.push
|
---|
56 | # @@nest_stack_index += 1
|
---|
57 | # @@nest_stack[ @nest_stack_index ] = @@current_object
|
---|
58 | # @@current_object = nil
|
---|
59 | # end
|
---|
60 | #
|
---|
61 | # def pop
|
---|
62 | # @@current_object = @@nest_stack[ @@nest_stack_index ]
|
---|
63 | # @nest_stack_index -= 1
|
---|
64 | # if @@nest_stack_index < -1 then
|
---|
65 | # raise TooManyRestore
|
---|
66 | # end
|
---|
67 | # end
|
---|
68 | # end
|
---|
69 | #
|
---|
70 |
|
---|
71 | class Signature < NSBDNode # < Nestable
|
---|
72 | # @name:: Symbol
|
---|
73 | # @global_name:: Symbol
|
---|
74 | # @function_head_list:: NamedList : FuncHead のインスタンスが要素
|
---|
75 | # @func_name_to_id:: {String} : 関数名を添字とする配列で id を記憶する.id は signature の出現順番 (1から始まる)
|
---|
76 | # @context:: string : コンテキスト名
|
---|
77 | # @b_callback:: bool: callback : コールバック用のシグニチャ
|
---|
78 | # @b_deviate:: bool: deviate : 逸脱(pointer level mismatch を出さない)
|
---|
79 | # @b_checked_as_allocator_signature:: bool: アロケータシグニチャとしてチェック済み
|
---|
80 | # @b_empty:: Bool: 空(関数が一つもない状態)
|
---|
81 |
|
---|
82 | @@nest_stack_index = -1
|
---|
83 | @@nest_stack = []
|
---|
84 | @@current_object = nil
|
---|
85 |
|
---|
86 | def self.push
|
---|
87 | @@nest_stack_index += 1
|
---|
88 | @@nest_stack[ @@nest_stack_index ] = @@current_object
|
---|
89 | @@current_object = nil
|
---|
90 | end
|
---|
91 |
|
---|
92 | def self.pop
|
---|
93 | @@current_object = @@nest_stack[ @@nest_stack_index ]
|
---|
94 | @@nest_stack_index -= 1
|
---|
95 | if @@nest_stack_index < -1 then
|
---|
96 | raise "TooManyRestore"
|
---|
97 | end
|
---|
98 | end
|
---|
99 |
|
---|
100 | # STAGE: P
|
---|
101 | # このメソッドは parse 中のみ呼び出される
|
---|
102 | def self.get_current
|
---|
103 | @@current_object
|
---|
104 | end
|
---|
105 |
|
---|
106 | #
|
---|
107 | # STAGE: B
|
---|
108 | def initialize( name )
|
---|
109 | super()
|
---|
110 | @name = name
|
---|
111 | Namespace.new_signature( self )
|
---|
112 | set_namespace_path # @NamespacePath の設定
|
---|
113 | if "#{Namespace.get_global_name}" == "" then
|
---|
114 | @global_name = @name
|
---|
115 | else
|
---|
116 | @global_name = :"#{Namespace.get_global_name}_#{@name}"
|
---|
117 | end
|
---|
118 |
|
---|
119 | @func_name_to_id = {}
|
---|
120 | @context = nil
|
---|
121 | @b_callback = false
|
---|
122 | @b_deviate = false
|
---|
123 | @b_empty = false
|
---|
124 | @b_checked_as_allocator_signature = false
|
---|
125 | @@current_object = self
|
---|
126 | set_specifier_list( Generator.get_statement_specifier )
|
---|
127 | end
|
---|
128 |
|
---|
129 | #
|
---|
130 | # STAGE: B
|
---|
131 | def end_of_parse( function_head_list )
|
---|
132 | @function_head_list = function_head_list
|
---|
133 |
|
---|
134 | # id を割付ける
|
---|
135 | id = 1
|
---|
136 | function_head_list.get_items.each{ |f|
|
---|
137 | @func_name_to_id[ f.get_name ] = id
|
---|
138 | id += 1
|
---|
139 | }
|
---|
140 | if id == 1 then
|
---|
141 | @b_empty = true
|
---|
142 | end
|
---|
143 |
|
---|
144 | @@current_object = nil
|
---|
145 | return self
|
---|
146 | end
|
---|
147 |
|
---|
148 | #=== Signature# signature の指定子を設定
|
---|
149 | # STAGE: B
|
---|
150 | #spec_list:: [ [ :CONTEXT, String ], ... ]
|
---|
151 | # s[0] s[1]
|
---|
152 | def set_specifier_list( spec_list )
|
---|
153 | return if spec_list == nil # 空ならば何もしない
|
---|
154 |
|
---|
155 | spec_list.each { |s|
|
---|
156 | case s[0] # statement_specifier
|
---|
157 | when :CALLBACK
|
---|
158 | @b_callback = true
|
---|
159 | when :CONTEXT # [context("non-task")] etc
|
---|
160 | if @context then
|
---|
161 | cdl_error( "S1001 context specifier duplicate" )
|
---|
162 | end
|
---|
163 | # @context = s[1].gsub( /\A\"(.*)\"$/, "\\1" )
|
---|
164 | @context = CDLString.remove_dquote s[1]
|
---|
165 | case @context
|
---|
166 | when "non-task", "task", "any"
|
---|
167 | else
|
---|
168 | cdl_warning( "W1001 \'$1\': unknown context type. usually specifiy task, non-task or any" , @context )
|
---|
169 | end
|
---|
170 | when :DEVIATE
|
---|
171 | @b_deviate = true
|
---|
172 | else
|
---|
173 | cdl_error( "S1002 \'$1\': unknown specifier for signature" , s[0] )
|
---|
174 | end
|
---|
175 | }
|
---|
176 | end
|
---|
177 |
|
---|
178 | def get_name
|
---|
179 | @name
|
---|
180 | end
|
---|
181 |
|
---|
182 | def get_global_name
|
---|
183 | @global_name
|
---|
184 | end
|
---|
185 |
|
---|
186 | def get_function_head_array
|
---|
187 | if @function_head_list then
|
---|
188 | return @function_head_list.get_items
|
---|
189 | else
|
---|
190 | return nil
|
---|
191 | end
|
---|
192 | end
|
---|
193 |
|
---|
194 | def get_function_head( func_name )
|
---|
195 | return @function_head_list.get_item( func_name.to_sym )
|
---|
196 | end
|
---|
197 |
|
---|
198 | #=== Signature# 関数名から signature 内の id を得る
|
---|
199 | def get_id_from_func_name func_name
|
---|
200 | @func_name_to_id[ func_name ]
|
---|
201 | end
|
---|
202 |
|
---|
203 | #=== Signature# context を得る
|
---|
204 | # context 文字列を返す "task", "non-task", "any"
|
---|
205 | # 未指定時のデフォルトとして task を返す
|
---|
206 | def get_context
|
---|
207 | if @context then
|
---|
208 | return @context
|
---|
209 | else
|
---|
210 | return "task"
|
---|
211 | end
|
---|
212 | end
|
---|
213 |
|
---|
214 | #=== Signature# signaure のすべての関数のすべてのパラメータをたどる
|
---|
215 | #block:: ブロックを引数に取る
|
---|
216 | # ブロックは2つの引数を受け取る Decl, ParamDecl ( Decl: 関数ヘッダ )
|
---|
217 | # Port クラスにも each_param がある(同じ働き)
|
---|
218 | def each_param # ブロック引数 { |func_decl, param_decl| }
|
---|
219 | fha = get_function_head_array # 呼び口または受け口のシグニチャの関数配列
|
---|
220 | return if fha == nil # nil なら文法エラーで有効値が設定されなかった
|
---|
221 |
|
---|
222 | pr = Proc.new # このメソッドのブロック引数を pr に代入
|
---|
223 | fha.each{ |fh| # fh: FuncHead # 関数配列中の各関数頭部
|
---|
224 | fd = fh.get_declarator # fd: Decl (関数頭部からDeclarotorを得る)
|
---|
225 | if fd.is_function? then # fd が関数でなければ、すでにエラー
|
---|
226 | fd.get_type.get_paramlist.get_items.each{ |par| # すべてのパラメータについて
|
---|
227 | pr.call( fd, par )
|
---|
228 | }
|
---|
229 | end
|
---|
230 | }
|
---|
231 | end
|
---|
232 |
|
---|
233 | #=== Signature# 正当なアロケータ シグニチャかテストする
|
---|
234 | # alloc, dealloc 関数を持つかどうか、第一引き数がそれぞれ、整数、ポインタ、第二引き数が、ポインタへのポインタ、なし
|
---|
235 | def is_allocator?
|
---|
236 |
|
---|
237 | # 一回だけチェックする
|
---|
238 | if @b_checked_as_allocator_signature == true then
|
---|
239 | return true
|
---|
240 | end
|
---|
241 | @b_checked_as_allocator_signature = true
|
---|
242 |
|
---|
243 | fha = get_function_head_array # 呼び口または受け口のシグニチャの関数配列
|
---|
244 | if fha == nil then # nil なら文法エラーで有効値が設定されなかった
|
---|
245 | return false
|
---|
246 | end
|
---|
247 |
|
---|
248 | found_alloc = false; found_dealloc = false
|
---|
249 | fha.each{ |fh| # fh: FuncHead # 関数配列中の各関数頭部
|
---|
250 | fd = fh.get_declarator # fd: Decl (関数頭部からDeclarotorを得る)
|
---|
251 | if fd.is_function? then # fd が関数でなければ、すでにエラー
|
---|
252 | func_name = fd.get_name.to_sym
|
---|
253 | if func_name == :alloc then
|
---|
254 | found_alloc = true
|
---|
255 | params = fd.get_type.get_paramlist.get_items
|
---|
256 | if params then
|
---|
257 | if ! params[0].instance_of?( ParamDecl ) ||
|
---|
258 | ! params[0].get_type.get_original_type.kind_of?( IntType ) ||
|
---|
259 | params[0].get_direction != :IN then
|
---|
260 | # 第一引数が int 型でない
|
---|
261 | if ! params[0].instance_of?( ParamDecl ) ||
|
---|
262 | ! params[0].get_type.kind_of?( PtrType ) ||
|
---|
263 | ! params[0].get_type.get_type.kind_of?( PtrType ) ||
|
---|
264 | params[0].get_type.get_type.get_type.kind_of?( PtrType ) ||
|
---|
265 | params[0].get_direction != :OUT then
|
---|
266 | # 第一引数がポインタ型でもない
|
---|
267 | cdl_error3( @locale, "S1003 $1: \'alloc\' 1st parameter neither [in] integer type nor [out] double pointer type", @name )
|
---|
268 | end
|
---|
269 | elsif ! params[1].instance_of?( ParamDecl ) ||
|
---|
270 | ! params[1].get_type.kind_of?( PtrType ) ||
|
---|
271 | ! params[1].get_type.get_type.kind_of?( PtrType ) ||
|
---|
272 | params[1].get_type.get_type.get_type.kind_of?( PtrType ) ||
|
---|
273 | params[0].get_direction != :IN then
|
---|
274 | # (第一引数が整数で) 第二引数がポインタでない
|
---|
275 | cdl_error3( @locale, "S1004 $1: \'alloc\' 2nd parameter not [in] double pointer" , @name )
|
---|
276 | end
|
---|
277 | else
|
---|
278 | cdl_error3( @locale, "S1005 $1: \'alloc\' has no parameter, unsuitable for allocator signature" , @name )
|
---|
279 | end
|
---|
280 | elsif func_name == :dealloc then
|
---|
281 | found_dealloc = true
|
---|
282 | params = fd.get_type.get_paramlist.get_items
|
---|
283 | if params then
|
---|
284 | if ! params[0].instance_of?( ParamDecl ) ||
|
---|
285 | ! params[0].get_type.kind_of?( PtrType ) ||
|
---|
286 | params[0].get_type.get_type.kind_of?( PtrType ) ||
|
---|
287 | params[0].get_direction != :IN then
|
---|
288 | cdl_error3( @locale, "S1006 $1: \'dealloc\' 1st parameter not [in] pointer type" , @name )
|
---|
289 | # elsif params[1] != nil then # 第二引き数はチェックしない
|
---|
290 | # cdl_error3( @locale, "S1007 Error message is changed to empty" )
|
---|
291 | # cdl_error3( @locale, "S1007 $1: \'dealloc\' cannot has 2nd parameter" , @name )
|
---|
292 | end
|
---|
293 | else
|
---|
294 | cdl_error3( @locale, "S1008 $1: \'dealloc\' has no parameter, unsuitable for allocator signature" , @name )
|
---|
295 | end
|
---|
296 | end
|
---|
297 | if found_alloc && found_dealloc then
|
---|
298 | return true
|
---|
299 | end
|
---|
300 | end
|
---|
301 | }
|
---|
302 | if ! found_alloc then
|
---|
303 | cdl_error3( @locale, "S1009 $1: \'alloc\' function not found, unsuitable for allocator signature" , @name )
|
---|
304 | end
|
---|
305 | if ! found_dealloc then
|
---|
306 | cdl_error3( @locale, "S1010 $1: \'dealloc\' function not found, unsuitable for allocator signature" , @name )
|
---|
307 | end
|
---|
308 | return false
|
---|
309 | end
|
---|
310 |
|
---|
311 | #== Signature# 引数で参照されている Descriptor 型のリストを作成する
|
---|
312 | #RETURN:: Hash { Signature => ParamDecl }: 複数の ParamDecl から参照されている場合、最後のものしか返さない
|
---|
313 | def get_descriptor_list
|
---|
314 | desc_list = { }
|
---|
315 | # p "has_desc #{@name}"
|
---|
316 | fha = get_function_head_array # 呼び口または受け口のシグニチャの関数配列
|
---|
317 | if fha == nil then # nil の場合、自己参照によるケースと仮定
|
---|
318 | return desc_list
|
---|
319 | end
|
---|
320 | fha.each{ |fh|
|
---|
321 | fd = fh.get_declarator # fd: Decl (関数頭部からDeclarotorを得る)
|
---|
322 | if fd.is_function? then # fd が関数でなければ、すでにエラー
|
---|
323 | params = fd.get_type.get_paramlist.get_items
|
---|
324 | if params then
|
---|
325 | params.each{ |param|
|
---|
326 | t = param.get_type.get_original_type
|
---|
327 | while( t.kind_of? PtrType )
|
---|
328 | t = t.get_referto
|
---|
329 | end
|
---|
330 | # p "has_desc #{param.get_name} #{t}"
|
---|
331 | if t.kind_of? DescriptorType then
|
---|
332 | desc_list[t] = param
|
---|
333 | end
|
---|
334 | }
|
---|
335 | end
|
---|
336 | end
|
---|
337 | }
|
---|
338 | return desc_list
|
---|
339 | end
|
---|
340 |
|
---|
341 | #=== Signature# 引数に Descriptor があるか?
|
---|
342 | def has_descriptor?
|
---|
343 | # p "has_desc #{@name}"
|
---|
344 | fha = get_function_head_array # 呼び口または受け口のシグニチャの関数配列
|
---|
345 | if fha == nil then # nil の場合、自己参照によるケースと仮定
|
---|
346 | return true
|
---|
347 | end
|
---|
348 | fha.each{ |fh|
|
---|
349 | fd = fh.get_declarator # fd: Decl (関数頭部からDeclarotorを得る)
|
---|
350 | if fd.is_function? then # fd が関数でなければ、すでにエラー
|
---|
351 | params = fd.get_type.get_paramlist.get_items
|
---|
352 | if params then
|
---|
353 | params.each{ |param|
|
---|
354 | t = param.get_type.get_original_type
|
---|
355 | while( t.kind_of? PtrType )
|
---|
356 | t = t.get_referto
|
---|
357 | end
|
---|
358 | # p "has_desc #{param.get_name} #{t}"
|
---|
359 | if t.kind_of? DescriptorType then
|
---|
360 | return true
|
---|
361 | end
|
---|
362 | }
|
---|
363 | end
|
---|
364 | end
|
---|
365 | }
|
---|
366 | return false
|
---|
367 | end
|
---|
368 |
|
---|
369 | #=== Signature# コールバックか?
|
---|
370 | # 指定子 callback が指定されていれば true
|
---|
371 | def is_callback?
|
---|
372 | @b_callback
|
---|
373 | end
|
---|
374 |
|
---|
375 | #=== Signature# 逸脱か?
|
---|
376 | # 指定子 deviate が指定されていれば true
|
---|
377 | def is_deviate?
|
---|
378 | @b_deviate
|
---|
379 | end
|
---|
380 |
|
---|
381 | #=== Signature# 空か?
|
---|
382 | def is_empty?
|
---|
383 | @b_empty
|
---|
384 | end
|
---|
385 |
|
---|
386 | #=== Signature# Push Pop Allocator が必要か?
|
---|
387 | # Transparent RPC の場合 oneway かつ in の配列(size_is, count_is, string のいずれかで修飾)がある
|
---|
388 | def need_PPAllocator?( b_opaque = false )
|
---|
389 | fha = get_function_head_array # 呼び口または受け口のシグニチャの関数配列
|
---|
390 | fha.each{ |fh|
|
---|
391 | fd = fh.get_declarator
|
---|
392 | if fd.get_type.need_PPAllocator?( b_opaque ) then
|
---|
393 | # p "#{fd.get_name} need_PPAllocator: true"
|
---|
394 | @b_need_PPAllocator = true
|
---|
395 | return true
|
---|
396 | end
|
---|
397 | # p "#{fd.get_name} need_PPAllocator: false"
|
---|
398 | }
|
---|
399 | return false
|
---|
400 | end
|
---|
401 |
|
---|
402 | def show_tree( indent )
|
---|
403 | indent.times { print " " }
|
---|
404 | puts "Signature: name: #{@name} context: #{@context} deviate : #{@b_deviate} PPAllocator: #{@b_PPAllocator} #{self}"
|
---|
405 | (indent+1).times { print " " }
|
---|
406 | puts "namespace_path: #{@NamespacePath}"
|
---|
407 | (indent+1).times { print " " }
|
---|
408 | puts "function head list:"
|
---|
409 | @function_head_list.show_tree( indent + 2 )
|
---|
410 | end
|
---|
411 |
|
---|
412 | end
|
---|
413 |
|
---|
414 | class Celltype < NSBDNode # < Nestable
|
---|
415 | # @name:: Symbol
|
---|
416 | # @global_name:: Symbol
|
---|
417 | # @name_list:: NamedList item: Decl (attribute, var), Port
|
---|
418 | # @port:: Port[]
|
---|
419 | # @attribute:: Decl[]
|
---|
420 | # @var:: Decl[]
|
---|
421 | # @require:: [[cp_name,Celltype|Cell,Port],...]
|
---|
422 | # @factory_list:: Factory[]
|
---|
423 | # @ct_factory_list:: Factory[] : celltype factory
|
---|
424 | # @cell_list:: Cell[] : 定義のみ (V1.0.0.2 以降)
|
---|
425 | # @singleton:: bool
|
---|
426 | # @idx_is_id:: bool
|
---|
427 | # @idx_is_id_act:: bool: actual value
|
---|
428 | # @active:: bool
|
---|
429 | # @b_reuse:: bool : reuse 指定されて import された(template 不要)
|
---|
430 | # @generate:: [ Symbol, String, Plugin ] = [ PluginName, option, Plugin ] Plugin は生成後に追加される
|
---|
431 | #
|
---|
432 | # @n_attribute_ro:: int >= 0 none specified
|
---|
433 | # @n_attribute_rw:: int >= 0 # of [rw] specified attributes (obsolete)
|
---|
434 | # @n_attribute_omit : int >= 0 # of [omit] specified attributes
|
---|
435 | # @n_var:: int >= 0
|
---|
436 | # @n_var_size_is:: int >= 0 # of [size_is] specified vars # mikan count_is
|
---|
437 | # @n_var_omit:: int >= 0 # of [omit] specified vars # mikan var の omit は有?
|
---|
438 | # @n_var_init:: int >= 0 # of vars with initializer
|
---|
439 | # @n_call_port:: int >= 0
|
---|
440 | # @n_call_port_array:: int >= 0
|
---|
441 | # @n_call_port_omitted_in_CB:: int >= 0 最適化で省略される呼び口
|
---|
442 | # @n_entry_port:: int >= 0
|
---|
443 | # @n_entry_port_array:: int >= 0
|
---|
444 | # @n_entry_port_inline:: int >= 0
|
---|
445 | # @n_cell_gen:: int >= 0 生成するセルの数.コード生成の頭で算出する.意味解析段階では参照不可
|
---|
446 | # @id_base:: Integer : cell の ID の最小値(最大値は @id_base + @n_cell)
|
---|
447 | #
|
---|
448 | # @b_cp_optimized:: bool : 呼び口最適化実施
|
---|
449 | # @plugin:: PluginObject このセルタイプがプラグインにより生成された CDL から生成された場合に有効。
|
---|
450 | # generate の指定は @generate にプラグインが保持される
|
---|
451 | #
|
---|
452 | # @included_header:: Hash : include されたヘッダファイル
|
---|
453 | # @domain_roots::Hash { DomainTypeName(Symbol) => [ Region ] } ドメインタイプ名と Region の配列 (optimize.rb で設定)
|
---|
454 | # ルートリージョンはドメイン名が nil
|
---|
455 |
|
---|
456 | include PluginModule
|
---|
457 |
|
---|
458 | @@nest_stack_index = -1
|
---|
459 | @@nest_stack = []
|
---|
460 | @@current_object = nil
|
---|
461 | @@celltype_list = []
|
---|
462 |
|
---|
463 | def self.push
|
---|
464 | @@nest_stack_index += 1
|
---|
465 | @@nest_stack[ @@nest_stack_index ] = @@current_object
|
---|
466 | @@current_object = nil
|
---|
467 | end
|
---|
468 |
|
---|
469 | def self.pop
|
---|
470 | @@current_object = @@nest_stack[ @@nest_stack_index ]
|
---|
471 | @@nest_stack_index -= 1
|
---|
472 | if @@nest_stack_index < -1 then
|
---|
473 | raise "TooManyRestore"
|
---|
474 | end
|
---|
475 | end
|
---|
476 |
|
---|
477 | def initialize( name )
|
---|
478 | super()
|
---|
479 | @@current_object = self
|
---|
480 | @name = name
|
---|
481 | if "#{Namespace.get_global_name}" != "" then
|
---|
482 | @global_name = :"#{Namespace.get_global_name}_#{@name}"
|
---|
483 | else
|
---|
484 | @global_name = name
|
---|
485 | end
|
---|
486 |
|
---|
487 | @name_list = NamedList.new( nil, "symbol in celltype #{name}" )
|
---|
488 | @port = []
|
---|
489 | @attribute = []
|
---|
490 | @var = []
|
---|
491 | @require = []
|
---|
492 | @factory_list = []
|
---|
493 | @ct_factory_list = []
|
---|
494 | @cell_list = []
|
---|
495 | @singleton = false
|
---|
496 | @active = false
|
---|
497 | @generate = nil
|
---|
498 |
|
---|
499 | @n_attribute_ro = 0
|
---|
500 | @n_attribute_rw = 0
|
---|
501 | @n_attribute_omit = 0
|
---|
502 | @n_var = 0
|
---|
503 | @n_var_omit = 0
|
---|
504 | @n_var_size_is = 0
|
---|
505 | @n_var_init = 0
|
---|
506 | @n_call_port = 0
|
---|
507 | @n_call_port_array = 0
|
---|
508 | @n_call_port_omitted_in_CB = 0
|
---|
509 | @n_entry_port = 0
|
---|
510 | @n_entry_port_array = 0
|
---|
511 | @n_entry_port_array_ns = 0
|
---|
512 | @n_entry_port_inline = 0
|
---|
513 | @n_cell_gen = 0
|
---|
514 |
|
---|
515 | @b_cp_optimized = false
|
---|
516 |
|
---|
517 | @plugin = Generator.get_plugin
|
---|
518 | # plugin の場合 PluginObject が返される
|
---|
519 | # 元の Generator から呼出された Generator の中でパースおよび意味チェックされている
|
---|
520 |
|
---|
521 | # if @plugin then
|
---|
522 | # # plugin 生成されるセルタイプは再利用ではない #833 不具合修正
|
---|
523 | # @b_reuse = false
|
---|
524 | # else
|
---|
525 | @b_reuse = Generator.is_reuse?
|
---|
526 | # end
|
---|
527 |
|
---|
528 | if $idx_is_id then
|
---|
529 | @idx_is_id = true
|
---|
530 | else
|
---|
531 | @idx_is_id = false
|
---|
532 | end
|
---|
533 | @idx_is_id_act = @idx_is_id
|
---|
534 |
|
---|
535 | Namespace.new_celltype( self )
|
---|
536 | set_namespace_path # @NamespacePath の設定
|
---|
537 | set_specifier_list( Generator.get_statement_specifier )
|
---|
538 |
|
---|
539 | if @singleton then
|
---|
540 | @idx_is_id_act = false
|
---|
541 | end
|
---|
542 |
|
---|
543 | @included_header = {}
|
---|
544 | @domain_roots = {}
|
---|
545 | @@celltype_list << self
|
---|
546 | end
|
---|
547 |
|
---|
548 | def get_name
|
---|
549 | @name
|
---|
550 | end
|
---|
551 |
|
---|
552 | #== Celltype#ドメインルートを返す
|
---|
553 | # @domain_roots の説明を参照
|
---|
554 | def get_domain_roots
|
---|
555 | @domain_roots
|
---|
556 | end
|
---|
557 |
|
---|
558 | # Celltype# end_of_parse
|
---|
559 | def end_of_parse
|
---|
560 | # 属性・変数のチェック
|
---|
561 | check_attribute
|
---|
562 |
|
---|
563 | # アロケータ呼び口を内部生成
|
---|
564 | generate_allocator_port
|
---|
565 |
|
---|
566 | # リレーアロケータ、内部アロケータの設定
|
---|
567 | @port.each { |p|
|
---|
568 | p.set_allocator_instance
|
---|
569 | }
|
---|
570 |
|
---|
571 | if @n_entry_port == 0 && @active == false && @factory_list.length == 0 &&
|
---|
572 | ( @singleton && @ct_factory_list.length == 0 || ! @singleton )then
|
---|
573 | cdl_warning( "W1002 $1: non-active celltype has no entry port & factory" , @name )
|
---|
574 | end
|
---|
575 |
|
---|
576 | if @generate then
|
---|
577 | celltype_plugin
|
---|
578 | end
|
---|
579 |
|
---|
580 | @@current_object = nil
|
---|
581 | end
|
---|
582 |
|
---|
583 | def self.new_port( port )
|
---|
584 | @@current_object.new_port( port )
|
---|
585 | end
|
---|
586 |
|
---|
587 | def new_port( port )
|
---|
588 | port.set_owner self
|
---|
589 | @port << port
|
---|
590 | @name_list.add_item( port )
|
---|
591 | if port.get_port_type == :CALL then
|
---|
592 | @n_call_port += 1
|
---|
593 | @n_call_port_array += 1 if port.get_array_size != nil
|
---|
594 | else
|
---|
595 | @n_entry_port += 1
|
---|
596 | @n_entry_port_array += 1 if port.get_array_size != nil
|
---|
597 | @n_entry_port_array_ns += 1 if port.get_array_size == "[]"
|
---|
598 | @n_entry_port_inline += 1 if port.is_inline?
|
---|
599 | end
|
---|
600 | port.set_celltype self
|
---|
601 | end
|
---|
602 |
|
---|
603 | def get_port_list
|
---|
604 | @port
|
---|
605 | end
|
---|
606 |
|
---|
607 | def self.new_attribute( attribute )
|
---|
608 | @@current_object.new_attribute( attribute )
|
---|
609 | end
|
---|
610 |
|
---|
611 | #=== Celltype# new_attribute for Celltype
|
---|
612 | #attribute:: [Decl]
|
---|
613 | def new_attribute( attribute )
|
---|
614 | @attribute += attribute
|
---|
615 | attribute.each { |a|
|
---|
616 | a.set_owner self
|
---|
617 | @name_list.add_item( a )
|
---|
618 | if( a.is_omit? )then
|
---|
619 | @n_attribute_omit += 1
|
---|
620 | elsif( a.is_rw? )then
|
---|
621 | @n_attribute_rw += 1
|
---|
622 | else
|
---|
623 | @n_attribute_ro += 1
|
---|
624 | end
|
---|
625 | if a.get_initializer then
|
---|
626 | # 登録後にチェックしても問題ない(attr を参照できないので、自己参照しない)
|
---|
627 | a.get_type.check_init( @locale, a.get_identifier, a.get_initializer, :ATTRIBUTE )
|
---|
628 | end
|
---|
629 | }
|
---|
630 | end
|
---|
631 |
|
---|
632 | #=== Celltype# celltype の attribute/var のチェック
|
---|
633 | # STAGE: S
|
---|
634 | #
|
---|
635 | # このメソッドは celltype のパースが完了した時点で呼出される.
|
---|
636 | def check_attribute
|
---|
637 | # attribute の size_is 指定が妥当かチェック
|
---|
638 | (@attribute+@var).each{ |a|
|
---|
639 | if a.get_size_is then
|
---|
640 | if ! a.get_type.kind_of?( PtrType ) then
|
---|
641 | # size_is がポインタ型以外に指定された
|
---|
642 | cdl_error( "S1011 $1: size_is specified for non-pointer type" , a.get_identifier )
|
---|
643 | else
|
---|
644 |
|
---|
645 | # 参照する変数が存在し、計算可能な型かチェックする
|
---|
646 | size = a.get_size_is.eval_const( @name_list ) # C_EXP の可能性あり
|
---|
647 | init = a.get_initializer
|
---|
648 | if init then
|
---|
649 | if ! init.instance_of?( Array ) then
|
---|
650 | # 初期化子が配列ではない
|
---|
651 | cdl_error( "S1012 $1: unsuitable initializer, need array initializer" , a.get_identifier )
|
---|
652 | elsif size.kind_of?( Integer ) && size < init.length then
|
---|
653 | # size_is 指定された個数よりも初期化子の配列要素が多い
|
---|
654 | cdl_error( "S1013 $1: too many initializer, $2 for $3" , a.get_identifier, init.length, size )
|
---|
655 | # elsif a.get_size_is.eval_const( nil ) == nil # C_EXP の可能性あり
|
---|
656 | end
|
---|
657 |
|
---|
658 | end
|
---|
659 | end
|
---|
660 | else
|
---|
661 | if a.get_type.kind_of?( PtrType ) then
|
---|
662 | if a.get_initializer.instance_of?( Array ) ||
|
---|
663 | ( a.get_initializer.instance_of?( Expression ) &&
|
---|
664 | a.get_initializer.eval_const2(@name_list).instance_of?( Array ) ) then
|
---|
665 | # size_is 指定されていないポインタが Array で初期化されていたら、エラー
|
---|
666 | cdl_error( "S1159 $1: non-size_is pointer cannot be initialized with array initializer" , a.get_identifier )
|
---|
667 | end
|
---|
668 | end
|
---|
669 | end
|
---|
670 | }
|
---|
671 | end
|
---|
672 |
|
---|
673 | def get_attribute_list
|
---|
674 | @attribute
|
---|
675 | end
|
---|
676 |
|
---|
677 | #=== Celltype# アロケータ呼び口を生成
|
---|
678 | # send, receive 引数のアロケータを呼出すための呼び口を生成
|
---|
679 | def generate_allocator_port
|
---|
680 | @port.each { |port|
|
---|
681 | # ポートのすべてのパラメータを辿る
|
---|
682 | port.each_param { |port, fd, par|
|
---|
683 | case par.get_direction # 引数の方向指定子 (in, out, inout, send, receive )
|
---|
684 | when :SEND, :RECEIVE
|
---|
685 | if par.get_allocator then
|
---|
686 | cp_name = :"#{port.get_name}_#{fd.get_name}_#{par.get_name}" # アロケータ呼び口の名前
|
---|
687 | # ポート名 関数名 パラメータ名
|
---|
688 | # alloc_sig_path = [ par.get_allocator.get_name ] # mikan Namespace アロケータ呼び口のシグニチャ #1
|
---|
689 | alloc_sig_path = par.get_allocator.get_namespace_path
|
---|
690 | array_size = port.get_array_size # 呼び口または受け口配列のサイズ
|
---|
691 | created_port = Port.new( cp_name, alloc_sig_path, :CALL, array_size ) # 呼び口を生成
|
---|
692 | created_port.set_allocator_port( port, fd, par )
|
---|
693 | if port.is_optional? then
|
---|
694 | created_port.set_optional
|
---|
695 | end
|
---|
696 | if port.is_omit? then
|
---|
697 | created_port.set_omit
|
---|
698 | end
|
---|
699 | new_port( created_port ) # セルタイプに新しい呼び口を追加
|
---|
700 | # else
|
---|
701 | # already error "not found or not signature" in class ParamDecl
|
---|
702 | end
|
---|
703 | end
|
---|
704 | }
|
---|
705 | }
|
---|
706 | end
|
---|
707 |
|
---|
708 | def get_name_list
|
---|
709 | @name_list
|
---|
710 | end
|
---|
711 |
|
---|
712 | def self.new_var( var )
|
---|
713 | @@current_object.new_var( var )
|
---|
714 | end
|
---|
715 |
|
---|
716 | #=== Celltype# 新しい内部変数
|
---|
717 | #var:: [Decl]
|
---|
718 | def new_var( var )
|
---|
719 | @var += var
|
---|
720 | var.each { |i| # i: Decl
|
---|
721 | i.set_owner self
|
---|
722 | if i.is_omit? then
|
---|
723 | @n_var_omit += 1
|
---|
724 | else
|
---|
725 | @n_var += 1
|
---|
726 | end
|
---|
727 | @name_list.add_item( i )
|
---|
728 |
|
---|
729 | # size_is 指定された配列? mikan count_is
|
---|
730 | if i.get_size_is then
|
---|
731 | @n_var_size_is += 1
|
---|
732 | end
|
---|
733 |
|
---|
734 | if i.get_initializer then
|
---|
735 | i.get_type.check_init( @locale, i.get_identifier, i.get_initializer, :VAR, @name_list )
|
---|
736 | @n_var_init += 1
|
---|
737 | end
|
---|
738 | }
|
---|
739 | end
|
---|
740 |
|
---|
741 | def get_var_list
|
---|
742 | @var
|
---|
743 | end
|
---|
744 |
|
---|
745 | #=== Celltype# celltype の指定子を設定
|
---|
746 | def set_specifier_list( spec_list )
|
---|
747 | return if spec_list == nil
|
---|
748 |
|
---|
749 | spec_list.each { |s|
|
---|
750 | case s[0]
|
---|
751 | when :SINGLETON
|
---|
752 | @singleton = true
|
---|
753 | when :IDX_IS_ID
|
---|
754 | @idx_is_id = true
|
---|
755 | when :ACTIVE
|
---|
756 | @active = true
|
---|
757 | when :GENERATE
|
---|
758 | if @generate then
|
---|
759 | cdl_error( "S1014 generate specifier duplicate" )
|
---|
760 | end
|
---|
761 | @generate = [ s[1], s[2] ] # [ PluginName, "option" ]
|
---|
762 | else
|
---|
763 | cdl_error( "S1015 $1 cannot be specified for composite" , s[0] )
|
---|
764 | end
|
---|
765 | }
|
---|
766 | end
|
---|
767 |
|
---|
768 | #
|
---|
769 | def self.new_require( ct_or_cell_nsp, ep_name, cp_name = nil )
|
---|
770 | @@current_object.new_require( ct_or_cell_nsp, ep_name.to_sym, cp_name )
|
---|
771 | end
|
---|
772 |
|
---|
773 | def new_require( ct_or_cell_nsp, ep_name, cp_name )
|
---|
774 | # Require: set_owner するものがない
|
---|
775 | obj = Namespace.find( ct_or_cell_nsp ) #1
|
---|
776 | if obj.instance_of? Celltype then
|
---|
777 | # Celltype 名で指定
|
---|
778 | ct = obj
|
---|
779 | elsif obj.instance_of? Cell then
|
---|
780 | # Cell 名で指定
|
---|
781 | ct = obj.get_celltype
|
---|
782 | elsif obj == nil then
|
---|
783 | cdl_error( "S1016 $1 not found" , ct_or_cell_nsp.get_path_str )
|
---|
784 | return
|
---|
785 | else
|
---|
786 | cdl_error( "S1017 $1 : neither celltype nor cell" , ct_or_cell_nsp.get_path_str )
|
---|
787 | return
|
---|
788 | end
|
---|
789 |
|
---|
790 | if( ! ct.is_singleton? ) then
|
---|
791 | # シングルトンではない
|
---|
792 | cdl_error( "S1018 $1 : not singleton cell" , obj.get_name )
|
---|
793 | end
|
---|
794 |
|
---|
795 | # 受け口を探す
|
---|
796 | obj2 = ct.find( ep_name )
|
---|
797 | if( ( ! obj2.instance_of? Port ) || obj2.get_port_type != :ENTRY ) then
|
---|
798 | cdl_error( "S1019 \'$1\' : not entry port" , ep_name )
|
---|
799 | return
|
---|
800 | elsif obj2.get_array_size then
|
---|
801 | cdl_error( "S1020 \'$1\' : required port cannot be array" , ep_name )
|
---|
802 | return
|
---|
803 | end
|
---|
804 |
|
---|
805 | if obj2.get_signature == nil then
|
---|
806 | # signature が未定義:既にエラー
|
---|
807 | return
|
---|
808 | end
|
---|
809 |
|
---|
810 | require_call_port_prefix = :_require_call_port
|
---|
811 | if cp_name == nil then
|
---|
812 | # 関数名重複チェック
|
---|
813 | @require.each{ |req|
|
---|
814 | unless req[0].to_s =~ /^#{require_call_port_prefix}/ then
|
---|
815 | next # 名前ありの require は関数名重複チェックしない
|
---|
816 | end
|
---|
817 | port = req[2]
|
---|
818 | if port.get_signature == obj2.get_signature then
|
---|
819 | # 同じ signature (すべて同じ関数名を持つ)個別に出すのではなく、まとめてエラーとする
|
---|
820 | cdl_error( "S1021 $1 : require cannot have same signature with \'$2\'" , obj2.get_name, port.get_name )
|
---|
821 | next
|
---|
822 | end
|
---|
823 | port.get_signature.get_function_head_array.each{ |f|
|
---|
824 | # mikan ここは、namedList からの検索にならないの?(効率が悪い)
|
---|
825 | obj2.get_signature.get_function_head_array.each{ |f2|
|
---|
826 | if( f.get_name == f2.get_name ) then
|
---|
827 | cdl_error( "S1022 $1.$2 : \'$3\' conflict function name in $4.$5" , obj.get_name, obj2.get_name, f.get_name, req[1].get_name, req[2].get_name )
|
---|
828 | end
|
---|
829 | }
|
---|
830 | }
|
---|
831 | }
|
---|
832 | end
|
---|
833 |
|
---|
834 | if cp_name == nil then
|
---|
835 | b_has_name = false
|
---|
836 | cp_name = :"#{require_call_port_prefix}_#{ct.get_name}_#{obj2.get_name}"
|
---|
837 | else
|
---|
838 | b_has_name = true
|
---|
839 | end
|
---|
840 | # require を追加
|
---|
841 | @require << [ cp_name, obj, obj2 ] # [ lhs:cp_name, rhs:Celltype, rhs:Port ]
|
---|
842 |
|
---|
843 | # require port を追加 (呼び口として追加する。ただし require をセットしておく)
|
---|
844 | port = Port.new( cp_name, obj2.get_signature.get_namespace_path, :CALL )
|
---|
845 | port.set_require( b_has_name )
|
---|
846 | self.new_port port
|
---|
847 | end
|
---|
848 |
|
---|
849 | def self.new_factory( factory )
|
---|
850 | @@current_object.new_factory( factory )
|
---|
851 | end
|
---|
852 |
|
---|
853 | def new_factory( factory )
|
---|
854 | factory.set_owner self
|
---|
855 | if factory.get_f_celltype then
|
---|
856 | @ct_factory_list << factory
|
---|
857 | else
|
---|
858 | @factory_list << factory
|
---|
859 | end
|
---|
860 |
|
---|
861 | factory.check_arg( self )
|
---|
862 |
|
---|
863 | end
|
---|
864 |
|
---|
865 | #=== Celltype# セルタイププラグイン (generate 指定子)
|
---|
866 | def celltype_plugin
|
---|
867 |
|
---|
868 | load_plugin( @generate[0], CelltypePlugin )
|
---|
869 |
|
---|
870 | plugin_name = @generate[0]
|
---|
871 | option = @generate[1]
|
---|
872 | plugin_object = nil
|
---|
873 | eval_str = "plugin_object = #{plugin_name}.new( self, option )"
|
---|
874 | if $verbose then
|
---|
875 | print "new celltype : #{eval_str}\n"
|
---|
876 | end
|
---|
877 |
|
---|
878 | begin
|
---|
879 | eval( eval_str ) # plugin を生成
|
---|
880 | plugin_object.set_locale @locale
|
---|
881 | @generate[ 2 ] = plugin_object
|
---|
882 | generate_and_parse plugin_object
|
---|
883 | rescue Exception => evar
|
---|
884 | cdl_error( "S1023 $1: fail to new" , plugin_name )
|
---|
885 | print "eval( #{eval_str} )\n"
|
---|
886 |
|
---|
887 | print_exception( evar )
|
---|
888 | end
|
---|
889 | end
|
---|
890 |
|
---|
891 | #=== Celltype# celltype に新しい cell を追加
|
---|
892 | #cell:: Cell
|
---|
893 | # 新しいセルをセルタイプに追加.
|
---|
894 | # セルの構文解釈の最後でこのメソドを呼出される.
|
---|
895 | # シングルトンセルが同じ linkunit に複数ないかチェック
|
---|
896 | def new_cell( cell )
|
---|
897 | # Celltype では Cell の set_owner しない
|
---|
898 | # シングルトンで、プロトタイプ宣言でない場合、コード生成対象リージョンの場合
|
---|
899 | if @singleton then
|
---|
900 | @cell_list.each{ |c|
|
---|
901 | if c.get_region.get_link_root == cell.get_region.get_link_root then
|
---|
902 | cdl_error( "S1024 $1: multiple cell for singleton celltype" , @name )
|
---|
903 | end
|
---|
904 | }
|
---|
905 | end
|
---|
906 | @cell_list << cell
|
---|
907 | if @plugin then
|
---|
908 | @plugin.new_cell cell
|
---|
909 | end
|
---|
910 | end
|
---|
911 |
|
---|
912 | #=== Celltype# セルタイプは INIB を持つか?
|
---|
913 | # セルタイプが INIB を持つかどうかを判定する
|
---|
914 | # $rom == false のとき: INIB を持たない. (すべては CB に置かれる)
|
---|
915 | # $rom == true のとき、INIB に置かれるものが一つでも存在すれば INIB を持つ
|
---|
916 | # INIB に置かれるものは
|
---|
917 | # attribute (omit のものは除く.現仕様では rw のものはない)
|
---|
918 | # size_is を伴う var
|
---|
919 | # 呼び口(ただし、最適化で不要となるものは除く)
|
---|
920 | def has_INIB?
|
---|
921 | # print "name=#{@name} @n_attribute_ro=#{@n_attribute_ro} @n_var_size_is=#{@n_var_size_is} @n_call_port=#{@n_call_port} @n_call_port_omitted_in_CB=#{@n_call_port_omitted_in_CB} @n_entry_port_array_ns=#{@n_entry_port_array_ns}\n"
|
---|
922 | return $rom && (@n_attribute_ro > 0 || @n_var_size_is > 0 || ( @n_call_port - @n_call_port_omitted_in_CB ) > 0 || @n_entry_port_array_ns > 0)
|
---|
923 | # return $rom && (@n_attribute_ro > 0 || ( @n_call_port - @n_call_port_omitted_in_CB ) > 0)
|
---|
924 | end
|
---|
925 |
|
---|
926 | #=== Celltype# セルタイプは CB を持つか?
|
---|
927 | # $rom == true のとき、いかのものが置かれる.それらの一つでも存在すれば CB を持つ
|
---|
928 | # size_is が指定されていない var
|
---|
929 | # rw 指定された attribute (現仕様では存在しない)
|
---|
930 | # $rom == false のとき、いかのものが置かれる.それらの一つでも存在すれば CB を持つ
|
---|
931 | # attribute
|
---|
932 | # var
|
---|
933 | # 呼び口(ただし、最適化で不要となるものは除く)
|
---|
934 | def has_CB?
|
---|
935 | if $rom then
|
---|
936 | return @n_attribute_rw > 0 || (@n_var-@n_var_size_is) > 0
|
---|
937 | # return @n_attribute_rw > 0 || @n_var > 0
|
---|
938 | else
|
---|
939 | return @n_attribute_rw > 0 || @n_attribute_ro > 0 || @n_var > 0 || (@n_call_port-@n_call_port_omitted_in_CB) > 0 || @n_entry_port_array_ns > 0
|
---|
940 | end
|
---|
941 | end
|
---|
942 |
|
---|
943 | #=== Celltype# SET_CB_INIB_POINTER, INITIALIZE_CB が必要か
|
---|
944 | def need_CB_initializer?
|
---|
945 | @n_var_init > 0 || has_CB?
|
---|
946 | end
|
---|
947 |
|
---|
948 | #=== Celltype# 逆require の結合を生成する
|
---|
949 | def create_reverse_require_join cell
|
---|
950 | @port.each{ |p|
|
---|
951 | p.create_reverse_require_join cell
|
---|
952 | }
|
---|
953 | end
|
---|
954 |
|
---|
955 | #=== Celltype# singleton セルを得る
|
---|
956 | #region:: Region : singleton を探す Region
|
---|
957 | # 距離が最も近いものを返す
|
---|
958 | # mikan 本当は region の範囲の singleton を探す必要がある
|
---|
959 | def get_singleton_cell region
|
---|
960 | cell = nil
|
---|
961 | dist = 999999999 # mikan 制限値(これは十分すぎるほどデカイが)
|
---|
962 | # require: celltype で指定
|
---|
963 | @cell_list.each{ |c|
|
---|
964 | # 到達可能で最も近いセルを探す(複数の singleton があるかもしれない)
|
---|
965 | d = region.distance( c.get_region )
|
---|
966 | #debug
|
---|
967 | dbgPrint "distance #{d} from #{region.get_name} to #{c.get_name} in #{c.get_region.get_name}\n"
|
---|
968 | # print "DOMAIN: distance #{d} from #{region.get_name} to #{c.get_name} in #{c.get_region.get_name}\n"
|
---|
969 | if d != nil then
|
---|
970 | if d < dist then
|
---|
971 | cell = c
|
---|
972 | dist = d
|
---|
973 | end
|
---|
974 | end
|
---|
975 | }
|
---|
976 | return cell
|
---|
977 | end
|
---|
978 |
|
---|
979 | def find( name )
|
---|
980 | @name_list.get_item( name )
|
---|
981 | end
|
---|
982 |
|
---|
983 | #=== Celltype# セルタイププラグインを得る
|
---|
984 | def get_celltype_plugin
|
---|
985 | if @generate then
|
---|
986 | return @generate[2]
|
---|
987 | end
|
---|
988 | end
|
---|
989 |
|
---|
990 | def get_global_name
|
---|
991 | @global_name
|
---|
992 | end
|
---|
993 |
|
---|
994 | def is_singleton?
|
---|
995 | @singleton
|
---|
996 | end
|
---|
997 |
|
---|
998 | def is_active?
|
---|
999 | @active
|
---|
1000 | end
|
---|
1001 |
|
---|
1002 | #=== Celltype# アクティブではないか
|
---|
1003 | # このメソッドでは active の他に factory (singleton においては FACTORYを含む)がなければ inactive とする
|
---|
1004 | def is_inactive?
|
---|
1005 | if @active == false && @factory_list.length == 0 &&
|
---|
1006 | ( @singleton && @ct_factory_list.length == 0 || ! @singleton )then
|
---|
1007 | return true
|
---|
1008 | end
|
---|
1009 | return false
|
---|
1010 | end
|
---|
1011 |
|
---|
1012 | def get_id_base
|
---|
1013 | @id_base
|
---|
1014 | end
|
---|
1015 |
|
---|
1016 | def get_plugin
|
---|
1017 | @plugin
|
---|
1018 | end
|
---|
1019 |
|
---|
1020 | def get_require
|
---|
1021 | @require
|
---|
1022 | end
|
---|
1023 |
|
---|
1024 | #=== Celltype# コード生成する必要があるか判定
|
---|
1025 | # セルの個数が 0 ならセルタイプコードは生成不要
|
---|
1026 | def need_generate?
|
---|
1027 | @n_cell_gen > 0
|
---|
1028 | end
|
---|
1029 |
|
---|
1030 | #=== Celltype# require 呼び口の結合を行う
|
---|
1031 | # STAGE: S
|
---|
1032 | # セルタイプの require 呼び口について、結合を行う
|
---|
1033 | # セルが生成されないかチェックを行う
|
---|
1034 | def set_require_join
|
---|
1035 | @require.each{ |req|
|
---|
1036 | cp_name = req[0]
|
---|
1037 | cell_or_ct = req[1]
|
---|
1038 | port = req[2]
|
---|
1039 | @cell_list.each{ |c|
|
---|
1040 | c.set_require_join( cp_name, cell_or_ct, port )
|
---|
1041 | }
|
---|
1042 | }
|
---|
1043 | end
|
---|
1044 |
|
---|
1045 | def get_cell_list
|
---|
1046 | @cell_list
|
---|
1047 | end
|
---|
1048 |
|
---|
1049 | #=== Celltype# inline 受け口しかないか?
|
---|
1050 | # 受け口が無い場合、すべての受け口が inline とはしない
|
---|
1051 | def is_all_entry_inline?
|
---|
1052 | @n_entry_port == @n_entry_port_inline && @n_entry_port > 0
|
---|
1053 | end
|
---|
1054 |
|
---|
1055 | #=== Celltype.get_celltype_list
|
---|
1056 | def self.get_celltype_list
|
---|
1057 | @@celltype_list
|
---|
1058 | end
|
---|
1059 |
|
---|
1060 | def show_tree( indent )
|
---|
1061 | indent.times { print " " }
|
---|
1062 | puts "Celltype: name=#{@name} global_name=#{@global_name}"
|
---|
1063 | (indent+1).times { print " " }
|
---|
1064 | puts "active=#{@active}, singleton=#{@singleton}, idx_is_id=#{@idx_is_id} plugin=#{@plugin.class} reuse=#{@b_reuse}"
|
---|
1065 | (indent+1).times { print " " }
|
---|
1066 | puts "namespace_path: #{@NamespacePath}"
|
---|
1067 | (indent+1).times { print " " }
|
---|
1068 | puts "port:"
|
---|
1069 | @port.each { |i| i.show_tree( indent + 2 ) }
|
---|
1070 | (indent+1).times { print " " }
|
---|
1071 | puts "attribute:"
|
---|
1072 | @attribute.each { |i| i.show_tree( indent + 2 ) }
|
---|
1073 | (indent+1).times { print " " }
|
---|
1074 | puts "var:"
|
---|
1075 | @var.each { |i| i.show_tree( indent + 2 ) }
|
---|
1076 | # (indent+1).times { print " " }
|
---|
1077 | # puts "require:" mikan
|
---|
1078 | # @require.each { |i| i.show_tree( indent + 2 ) }
|
---|
1079 | (indent+1).times { print " " }
|
---|
1080 | puts "factory:"
|
---|
1081 | @factory_list.each { |i| i.show_tree( indent + 2 ) }
|
---|
1082 | (indent+1).times { print " " }
|
---|
1083 | puts "@n_attribute_ro #{@n_attribute_ro}"
|
---|
1084 | (indent+1).times { print " " }
|
---|
1085 | puts "@n_attribute_rw #{@n_attribute_rw}"
|
---|
1086 | # @n_attribute_omit : int >= 0 # of [omit] specified cells
|
---|
1087 | # @n_var:: int >= 0
|
---|
1088 | # @n_var_size_is:: int >= 0 # of [size_is] specified cells # mikan count_is
|
---|
1089 | # @n_var_omit:: int >= 0 # of [omit] specified cells # mikan var の omit は有?
|
---|
1090 | # @n_call_port:: int >= 0
|
---|
1091 | # @n_call_port_array:: int >= 0
|
---|
1092 | # @n_call_port_omitted_in_CB:: int >= 0 最適化で省略される呼び口
|
---|
1093 | # @n_entry_port:: int >= 0
|
---|
1094 | # @n_entry_port_array:: int >= 0
|
---|
1095 | (indent+1).times { print " " }
|
---|
1096 | puts "@n_entry_port_inline #{@n_entry_port_inline}"
|
---|
1097 | # @n_cell:: int >= 0 コード生成の頭で算出する.意味解析段階では参照不可
|
---|
1098 | # @id_base:: Integer : cell の ID の最小値(最大値は @id_base + @n_cell)
|
---|
1099 |
|
---|
1100 | end
|
---|
1101 | end
|
---|
1102 |
|
---|
1103 | class Cell < NSBDNode # < Nestable
|
---|
1104 | # @name:: Symbol : composite celltype の内側のインスタンスでは外のセル
|
---|
1105 | # @global_name:: Symbol : C で使える名前(namespace を含む)
|
---|
1106 | # @local_name:: str : cell celltype name { ... } の name
|
---|
1107 | # @celltype:: Celltype | CompositeCelltype
|
---|
1108 | # @join_list:: NamedList
|
---|
1109 | # @reverse_join_list:: NamedList
|
---|
1110 | # @b_defined:: definition flag (false if only prototype )
|
---|
1111 | # @b_prototype:: bool: prototype specified in current parsing cell. (@b_defined is used to determine whether definition done)
|
---|
1112 | # @b_duplicate:: bool: definition duplicate
|
---|
1113 | # @b_checked:: bool: set_definition_join が済んでいる場合 true
|
---|
1114 | # @require_joined_list:: {cp_name=>true}: set_require_join が済んでいる呼び口は true
|
---|
1115 | # @f_ref:: refercenced from others
|
---|
1116 | # @entry_array_max_subscript:: { @port=>Integer } : 受け口配列の配列添数の最大値(添数無し受け口配列対応)
|
---|
1117 | # @plugin:: Plugin: avialble if cell is generated by plugin generated cdl code.
|
---|
1118 | # @referenced_port_list:: { Port => Integer } : 受け口の参照数
|
---|
1119 | # すべての意味解析(through, composite展開)が終わった後に設定する
|
---|
1120 | # 逆require ポートに対して複数の結合がないかチェックする
|
---|
1121 | # @generate:: [ Symbol, String, Plugin ] = [ PluginName, option, Plugin ] Plugin は生成後に追加される
|
---|
1122 | #
|
---|
1123 | # composite のためインスタンス変数
|
---|
1124 | # @in_composite:: bool : true if in composite celltype
|
---|
1125 | # @compositecelltypejoin_list:: NamedList : item= CompositeCelltypeJoin ( if @in_composite )
|
---|
1126 | # @f_cloned:: bool : true if cloned (instantiate of composite consist cell)
|
---|
1127 | # @my_clone:: Cell : Composite cell で in_composite = true の場合のみ有効(直前の clone を一時記憶)
|
---|
1128 | # @cell_list:: Cell[local_name] : Composite cell で clone した後のリスト cell_list
|
---|
1129 | # @cell_list2:: [ Cell ] : Composite cell で clone した後のリスト cell_list
|
---|
1130 | # @cell_list2 は composite 内での出現順
|
---|
1131 | #
|
---|
1132 | # region のためのインスタンス変数
|
---|
1133 | # @region:: Region (属するregion)
|
---|
1134 | #
|
---|
1135 | # allocator のためのインスタンス変数
|
---|
1136 | # @alloc_list:: [ [ NORMAL_ALLOC, ep_name, func_name, param_name, expr ], ... ]
|
---|
1137 | # 受け口側のアロケータへの結合を記憶。以下のメソッドで追加される
|
---|
1138 | # set_specifier … cell 定義時にアロケータ指定されている場合
|
---|
1139 | # create_relay_allocator_join … リレーアロケータの場合
|
---|
1140 | #
|
---|
1141 | # ID のためのインスタンス変数(optimize.rb にて設定)
|
---|
1142 | # @id:: Integer : コード生成直前に設定 (プロトタイプ宣言の場合は -1 のまま放置)
|
---|
1143 | # @id_specified::Integer : 指定された id
|
---|
1144 | # @restrict_list::{ entry_name => { func_name, [ region_name, ... ] } }
|
---|
1145 |
|
---|
1146 | =begin
|
---|
1147 | # Cell クラスは、以下のものを扱う
|
---|
1148 | # 1)普通のセル
|
---|
1149 | # 2)composite セルタイプのセル
|
---|
1150 | # 3)composite セルタイプの内側のセル (@in_composite) # composite の内側の composite セルタイプのセルもある
|
---|
1151 | #
|
---|
1152 | # 2) は CellOfComposite クラスとして分けたほうがよいかもしれない
|
---|
1153 | # expand (composite セルの展開) は CellOfComposite にのみ必要なメソッドである
|
---|
1154 | # get_real_cell, get_real_port など @celltype.instance_of?( CompositeCelltype ) の判定がなくすっきりする
|
---|
1155 | # ただ、分離しても、メンテナンスすべき範囲が切り離されてしまい、忘れやすくなる問題とのトレードオフかも
|
---|
1156 | #
|
---|
1157 | # 3) は CellInCompoiste クラスとして分けたほうがよいかもしれない
|
---|
1158 | # @in_composite で判定している処理を切り離せる (上記 2) よりも分離は容易ではない)
|
---|
1159 | # clone_for_composite は CellInCompoiste にのみ必要なメソッドである
|
---|
1160 | # ただし、clone 後に Cell, CellOfComposite に変化する必要があるので、clone ではなく new する実装に変更する必要がある
|
---|
1161 | #
|
---|
1162 | =end
|
---|
1163 |
|
---|
1164 | include PluginModule
|
---|
1165 |
|
---|
1166 | @@nest_stack_index = -1
|
---|
1167 | @@nest_stack = []
|
---|
1168 | @@current_object = nil
|
---|
1169 |
|
---|
1170 | # 定義されたすべてのセル(出現順. namespace に影響されない)
|
---|
1171 | @@cell_list = [] # composite の内部のセルを含まない
|
---|
1172 | @@cell_list2 = [] # composite の内部のセルを含む (元のセルを含む)
|
---|
1173 | # 意味解析後 make_cell_list2 にて設定される
|
---|
1174 |
|
---|
1175 | def self.push
|
---|
1176 | @@nest_stack_index += 1
|
---|
1177 | @@nest_stack[ @@nest_stack_index ] = @@current_object
|
---|
1178 | @@current_object = nil
|
---|
1179 | end
|
---|
1180 |
|
---|
1181 | def self.pop
|
---|
1182 | @@current_object = @@nest_stack[ @@nest_stack_index ]
|
---|
1183 | @@nest_stack_index -= 1
|
---|
1184 | if @@nest_stack_index < -1 then
|
---|
1185 | raise "TooManyRestore"
|
---|
1186 | end
|
---|
1187 | end
|
---|
1188 |
|
---|
1189 |
|
---|
1190 | # composite で clone されたもの(子孫まで含む)
|
---|
1191 | # Join.change_rhs_port にて CompoisteCelltype 内の Join の結合先を変更する際に使用
|
---|
1192 | @@cloned_cell_list = {}
|
---|
1193 | ### mikan BUG @@cloned_cell_list は composite の階層ごとに記憶していないため、同じ名前が内部に現れると、うまく動作しない
|
---|
1194 | # change_rhs_port の実装は、こんな回りくどいことをする必要はなかった。右辺に現れるセル名には、composite のセル名を前につなげるだけでよかった
|
---|
1195 |
|
---|
1196 | def initialize( ct_path, in_composite = false )
|
---|
1197 | super()
|
---|
1198 | @region = Region.get_current
|
---|
1199 |
|
---|
1200 | # celltype のplugin/存在をチェック
|
---|
1201 | object = Namespace.find( ct_path ) #1
|
---|
1202 | if object == nil then
|
---|
1203 | # mikan celltype の名前が不完全 "::ct1ct2" になる
|
---|
1204 | cdl_error( "S1027 \'$1\' celltype not found" , ct_path.get_path_str )
|
---|
1205 | elsif ! object.instance_of?( Celltype ) && ! object.instance_of?( CompositeCelltype ) then
|
---|
1206 | # mikan celltype の名前が不完全
|
---|
1207 | cdl_error( "S1028 \'$1\' not celltype" , ct_path.get_path_str )
|
---|
1208 | else
|
---|
1209 | @celltype = object
|
---|
1210 | end
|
---|
1211 |
|
---|
1212 | @in_composite = in_composite
|
---|
1213 | if @in_composite then
|
---|
1214 | @compositecelltypejoin_list = NamedList.new( nil, "in cell '#{@name}'" )
|
---|
1215 | @plugin = nil
|
---|
1216 | else
|
---|
1217 | @compositecelltypejoin_list = nil
|
---|
1218 | @plugin = Generator.get_plugin
|
---|
1219 | end
|
---|
1220 |
|
---|
1221 | @@current_object = self
|
---|
1222 | @b_defined = false
|
---|
1223 | @b_prototype = false
|
---|
1224 | @f_ref = false
|
---|
1225 | @f_cloned = false
|
---|
1226 | @alloc_list = []
|
---|
1227 | @id = -1
|
---|
1228 | @id_specified = nil
|
---|
1229 | @b_duplicate = false
|
---|
1230 | @b_checked = false
|
---|
1231 | @require_joined_list = {}
|
---|
1232 | @entry_array_max_subscript = {}
|
---|
1233 | @referenced_port_list = {}
|
---|
1234 | @restrict_list = {}
|
---|
1235 |
|
---|
1236 | @cell_list = {}
|
---|
1237 | @cell_list2 = []
|
---|
1238 | end
|
---|
1239 |
|
---|
1240 | def self.set_name( name )
|
---|
1241 | @@current_object.set_name( name )
|
---|
1242 | end
|
---|
1243 |
|
---|
1244 | def set_name( name )
|
---|
1245 |
|
---|
1246 | @name = name
|
---|
1247 | @local_name = name
|
---|
1248 | if "#{Namespace.get_global_name}" != "" then
|
---|
1249 | @global_name = :"#{Namespace.get_global_name}_#{name}"
|
---|
1250 | else
|
---|
1251 | @global_name = name
|
---|
1252 | end
|
---|
1253 |
|
---|
1254 | # この時点ではプロトタイプか、定義か分らないが、自己参照のために登録
|
---|
1255 | # set_f_def で再度登録しなおす
|
---|
1256 | # Celltype への登録は、end_of_parse で行う
|
---|
1257 | if @in_composite then
|
---|
1258 | cell_prev = CompositeCelltype.find( name )
|
---|
1259 | if cell_prev == nil then
|
---|
1260 | CompositeCelltype.new_cell( self )
|
---|
1261 | end
|
---|
1262 | else
|
---|
1263 | # cell_prev = Namespace.find( [ name ] ) # 親まで捜しにいく
|
---|
1264 | cell_prev = Namespace.get_current.find( name )
|
---|
1265 | if cell_prev == nil then
|
---|
1266 | Namespace.new_cell( self )
|
---|
1267 | set_namespace_path # @NamespacePath の設定
|
---|
1268 | end
|
---|
1269 | end
|
---|
1270 |
|
---|
1271 | if cell_prev then
|
---|
1272 | if ! cell_prev.instance_of?( Cell ) then
|
---|
1273 | cdl_error( "S1029 $1 mismatch with previous one" , name )
|
---|
1274 | # celltype が一致しているか ?
|
---|
1275 | elsif get_celltype != cell_prev.get_celltype then
|
---|
1276 | cdl_error( "S1030 $1: celltype mismatch with previous one" , name )
|
---|
1277 | else
|
---|
1278 | # region が一致しているか?
|
---|
1279 | if ! cell_prev.get_region.equal? get_region then
|
---|
1280 | cdl_error( "S1031 $1 region \'$2\' mismatch with previous one \'$3\'" , name, @region.get_name, cell_prev.get_region.get_name )
|
---|
1281 | end
|
---|
1282 |
|
---|
1283 | @@current_object = cell_prev
|
---|
1284 | # この時点では、まだプロトタイプ宣言か定義か分らない
|
---|
1285 | # 以前が定義であって、今回も定義の場合、重複エラーである
|
---|
1286 | end
|
---|
1287 | end
|
---|
1288 |
|
---|
1289 | @join_list = NamedList.new( nil, "in cell '#{@name}'" )
|
---|
1290 | @reverse_join_list = nil
|
---|
1291 |
|
---|
1292 | # debug
|
---|
1293 | dbgPrint "Cell new_cell: #{@global_name} #{@in_composite} #{self}\n"
|
---|
1294 |
|
---|
1295 | # 内部アロケータを @alloc_list に追加
|
---|
1296 | if @celltype.instance_of? CompositeCelltype then
|
---|
1297 | @celltype.get_internal_allocator_list.each{ |cell, cp_internal_name, port_name, fd_name, par_name, ext_alloc_ent|
|
---|
1298 | nsp = NamespacePath.new( @name, false )
|
---|
1299 | rhs = Expression.new( [:OP_DOT, [:IDENTIFIER, nsp], Token.new( ext_alloc_ent.to_s.to_sym, nil, nil, nil ) ] ) #1 構文解析段階なので locale 不要
|
---|
1300 |
|
---|
1301 | @alloc_list << [:NORMAL_ALLOC,port_name,nil,fd_name,par_name,rhs]
|
---|
1302 | # print "add alloc_list: #{port_name}.#{fd_name}.#{par_name}=#{rhs.to_s}\n"
|
---|
1303 | }
|
---|
1304 | end
|
---|
1305 | end
|
---|
1306 |
|
---|
1307 | #=== Cell# cell の定義
|
---|
1308 | # 本体(join)の定義の直前に呼び出される
|
---|
1309 | def self.new_def
|
---|
1310 | @@current_object.new_def
|
---|
1311 | end
|
---|
1312 |
|
---|
1313 | #=== Cell# cell の定義
|
---|
1314 | # 本体(join)の定義の直前に呼び出される
|
---|
1315 | # このメソッドは cell tCelltype Cell { }; '{', '}' の部分がある場合に呼出される
|
---|
1316 | def new_def
|
---|
1317 | set_specifier_list( Generator.get_statement_specifier )
|
---|
1318 |
|
---|
1319 | # prototype 指定子ないか
|
---|
1320 | if ! @b_prototype then
|
---|
1321 | # 二重定義のチェック
|
---|
1322 | if @b_defined == true then
|
---|
1323 | cdl_error( "S1032 $1: duplicate cell" , @name )
|
---|
1324 | dbgPrint "previous: #{@prev_locale[0]}: line #{@prev_locale[1]} '#{@name}' defined here\n"
|
---|
1325 |
|
---|
1326 | # セルの重複定義エラーの処置
|
---|
1327 | # 前の定義は捨てる
|
---|
1328 | @join_list = NamedList.new( nil, "in cell '#{@name}'" )
|
---|
1329 | end
|
---|
1330 |
|
---|
1331 | @b_defined = true
|
---|
1332 | @prev_locale = @locale
|
---|
1333 | end
|
---|
1334 | end
|
---|
1335 |
|
---|
1336 | def self.new_join( join, b_regular = false )
|
---|
1337 | @@current_object.new_join( join, b_regular )
|
---|
1338 | end
|
---|
1339 |
|
---|
1340 | #=== Cell# 新しい結合をチェック
|
---|
1341 | # STAGE: P
|
---|
1342 | #
|
---|
1343 | #join:: Join : 新しい結合
|
---|
1344 | #b_regular:: bool : 通常の場所 (bnf.y.rb)からならば true, それ以外(allocator, require) では false
|
---|
1345 | def new_join( join, b_regular = false )
|
---|
1346 | join.set_owner self
|
---|
1347 |
|
---|
1348 | # composite の新文法対応.
|
---|
1349 | # composite の中のセルで、attribute の定義である場合
|
---|
1350 | # cell 内の attr_ext = composite.attr; 構文を処理
|
---|
1351 | if @in_composite then
|
---|
1352 | if @celltype then
|
---|
1353 | if @celltype.find(join.get_name).instance_of?( Decl ) then # mikan a::b で指定されていたものがエラーにならないかも
|
---|
1354 | rhs = join.get_rhs
|
---|
1355 | if rhs.instance_of? Expression then
|
---|
1356 | ele = rhs.get_elements
|
---|
1357 | if( ele[0]==:IDENTIFIER )then # attr = attr_ext (右辺単項)か? #1
|
---|
1358 | if( CompositeCelltype.has_attribute?(ele[1].get_name ) )then # mikan a::b.ePort がエラーにならないかも
|
---|
1359 | ident = ele[1].get_name # 右辺は attribute.
|
---|
1360 | else
|
---|
1361 | # 右辺は attribute にないのであれば、定数のはず
|
---|
1362 | # 定数は下へ渡す (cell の join にする)
|
---|
1363 | ident = nil
|
---|
1364 | end
|
---|
1365 | else
|
---|
1366 | if join.get_rhs.eval_const2(nil) == nil then # 定数式ではないか?
|
---|
1367 | # 右辺が、単一のシンボルでない場合、現状は扱えない
|
---|
1368 | cdl_error( "S1033 rhs expression is not supported. Only attribute is permitted on current version." )
|
---|
1369 | return
|
---|
1370 | else
|
---|
1371 | # 定数は下へ渡す (cell の join にする)
|
---|
1372 | ident = nil
|
---|
1373 | end
|
---|
1374 | end
|
---|
1375 |
|
---|
1376 | if ident then
|
---|
1377 | # attr = attr; のような参照はエラー (a = composite.a とする必要がある)
|
---|
1378 | if @celltype.find( ident ) then
|
---|
1379 | cdl_error( "S1034 $1 : cannot refer to $2\'s attribute here. Use \'composite.$3\' to refer to composite celltype\'s" , ident, @celltype.get_name, ident )
|
---|
1380 | end
|
---|
1381 | end
|
---|
1382 | elsif rhs.instance_of? Array then
|
---|
1383 | if rhs[0] == :COMPOSITE then # 右辺は composite.attr の形式
|
---|
1384 | ident = rhs[1].to_sym
|
---|
1385 | else
|
---|
1386 | ident = nil # 右辺は { 10, -10 } の形式
|
---|
1387 | end
|
---|
1388 | else
|
---|
1389 | ident = nil # 右辺は C_EXP の形式
|
---|
1390 | end
|
---|
1391 |
|
---|
1392 | # ident が見つかった(右辺は単一の ident)
|
---|
1393 | if ident then
|
---|
1394 | # composite の旧文法の構文処理へ渡す.セル外の attr_ext = Cell.attr; 構文の処理に渡す
|
---|
1395 | # export_name, internal_cell_name, internal_cell_elem_name
|
---|
1396 | decl = CompositeCelltype.new_join( ident, @name, join.get_name, :ATTRIBUTE ) # mikan a::b.ePort がエラーにならないかも
|
---|
1397 | if ! decl.instance_of? Decl then
|
---|
1398 | return
|
---|
1399 | end
|
---|
1400 | ini = decl.get_initializer
|
---|
1401 | if ini == nil then
|
---|
1402 | return
|
---|
1403 | end
|
---|
1404 | # 以下の旧文法実装に渡す.
|
---|
1405 | # 旧文法では cell に初期値を与えることで、composite で属性の初期値を指定することができた
|
---|
1406 | # attribute で指定された初期値を cell の属性として処理させる
|
---|
1407 | join.change_rhs( ini )
|
---|
1408 | else
|
---|
1409 | # ident がない.定数式
|
---|
1410 | end
|
---|
1411 | else
|
---|
1412 | # celltype の属性として、この join の名前がない
|
---|
1413 | # 以下の join.set_definition の中でエラーとなる
|
---|
1414 | end
|
---|
1415 | else
|
---|
1416 | return # celltype がない.すでにエラー
|
---|
1417 | end
|
---|
1418 | elsif join.get_rhs.instance_of? Array then
|
---|
1419 | rhs = join.get_rhs
|
---|
1420 | if rhs[0] == :COMPOSITE then
|
---|
1421 | # composite の中でないのに attr = composite.attr が使われた
|
---|
1422 | cdl_error( "S1035 composite : cannot specify out of composite celltype definition" )
|
---|
1423 | return
|
---|
1424 | end
|
---|
1425 | end
|
---|
1426 |
|
---|
1427 | # 以下 composite 文法変更前からある処理
|
---|
1428 |
|
---|
1429 | # 既に左辺が同じ名前の初期化が存在するか?
|
---|
1430 | j = @join_list.get_item( join.get_name ) # mikan NamespacePath がパスを持っている
|
---|
1431 | if j.instance_of? Join then # mikan ここでは j が Join or Nil 以外は、ないはず
|
---|
1432 |
|
---|
1433 | # debug
|
---|
1434 | dbgPrint "add_array_member: #{@name} port: #{j.get_port_name} rhs: #{j.get_rhs}, #{join.get_port_name} #{join.get_rhs}\n"
|
---|
1435 | # 呼び口配列(であると仮定して)要素を追加
|
---|
1436 | j.add_array_member join
|
---|
1437 |
|
---|
1438 | else
|
---|
1439 | # join
|
---|
1440 | @join_list.add_item( join )
|
---|
1441 | end
|
---|
1442 |
|
---|
1443 | # if get_owner then # error S1030 発生時 get_owner が見つからなくて例外になる
|
---|
1444 | # dbgPrint "Cell#new_join: #{get_owner.get_name}.#{@name}\n"
|
---|
1445 | # else
|
---|
1446 | # dbgPrint "Cell#new_join: \"owner not fund\".#{@name}\n"
|
---|
1447 | # end
|
---|
1448 | if ! @in_composite then
|
---|
1449 | if join.get_cell
|
---|
1450 | dbgPrint "new_join: #{@name} #{@region.get_name} => #{join.get_cell.get_name} #{join.get_cell.get_region.get_path_string}\n"
|
---|
1451 | end
|
---|
1452 | # p "region: generate? #{@region.is_generate?}"
|
---|
1453 | end
|
---|
1454 |
|
---|
1455 | end
|
---|
1456 |
|
---|
1457 | #=== Cell.新しい逆結合
|
---|
1458 | def self.new_reverse_join( reverse_join )
|
---|
1459 | @@current_object.new_reverse_join( reverse_join )
|
---|
1460 | end
|
---|
1461 |
|
---|
1462 | #=== Cell#新しい逆結合
|
---|
1463 | def new_reverse_join( reverse_join )
|
---|
1464 | dbgPrint( "new_reverse_join name=#{reverse_join.get_name}\n")
|
---|
1465 | b_cb = false
|
---|
1466 | if @celltype then
|
---|
1467 | ep_name = reverse_join.get_name
|
---|
1468 | port = @celltype.find ep_name
|
---|
1469 | if port && port.get_signature
|
---|
1470 | if port.get_signature.is_callback? then
|
---|
1471 | b_cb = true
|
---|
1472 | end
|
---|
1473 | end
|
---|
1474 | end
|
---|
1475 | if ! @b_prototype && ! b_cb then
|
---|
1476 | cdl_error( "S9999 '$1': reverse join can be used in prototype cell, or with callback signature", @name )
|
---|
1477 | end
|
---|
1478 | if @reverse_join_list == nil then
|
---|
1479 | # @reverse_join_list = NamedList.new( reverse_join, "in cell '#{@name}'" )
|
---|
1480 | @reverse_join_list = [ reverse_join ]
|
---|
1481 | else
|
---|
1482 | # @reverse_join_list.add_item( reverse_join )
|
---|
1483 | @reverse_join_list << reverse_join
|
---|
1484 | end
|
---|
1485 | end
|
---|
1486 |
|
---|
1487 | #=== Cell#逆結合から結合を生成
|
---|
1488 | # STAGE: S
|
---|
1489 | def create_reverse_join
|
---|
1490 | if @b_checked then
|
---|
1491 | return
|
---|
1492 | end
|
---|
1493 |
|
---|
1494 | if @reverse_join_list then
|
---|
1495 | # @reverse_join_list.get_items.each{ |rj|
|
---|
1496 | @reverse_join_list.each{ |rj|
|
---|
1497 | # 逆結合の情報を得る
|
---|
1498 | ep_name = rj.get_name
|
---|
1499 | ep_subscript, cp_cell_nsp, cp_name, cp_subscript = rj.get_rhs_cell_and_port
|
---|
1500 |
|
---|
1501 | # 呼び口側のセルと、そのセルタイプ
|
---|
1502 | cell = Namespace.find cp_cell_nsp
|
---|
1503 | if ! cell.instance_of? Cell then
|
---|
1504 | cdl_error( "S9999 '$1': not cell for reverse join", cp_cell_nsp.get_path_str )
|
---|
1505 | next
|
---|
1506 | end
|
---|
1507 | ct = cell.get_celltype
|
---|
1508 | if ct == nil then
|
---|
1509 | next
|
---|
1510 | end
|
---|
1511 |
|
---|
1512 | ep_cell_nsp = get_namespace_path
|
---|
1513 | ep_subscript_val = ep_subscript ? ep_subscript.eval_const( nil ) : nil
|
---|
1514 | rhs = Expression.create_cell_join_expression( ep_cell_nsp, ep_subscript_val, ep_name, rj.get_locale )
|
---|
1515 | join = Join.new( cp_name, cp_subscript, rhs, rj.get_locale )
|
---|
1516 | cell.new_join( join )
|
---|
1517 | # join.set_definition( ct.find(join.get_name) )
|
---|
1518 | if cp_subscript then
|
---|
1519 | ss_str = "[#{cp_subscript}]"
|
---|
1520 | else
|
---|
1521 | ss_str = ""
|
---|
1522 | end
|
---|
1523 | dbgPrint "create_reverse_join: #{cell.get_name}.#{cp_name}#{ss_str} => #{ep_cell_nsp.get_path_str}.ep_name\n"
|
---|
1524 | }
|
---|
1525 | end
|
---|
1526 | end
|
---|
1527 |
|
---|
1528 | def self.external_join( internal_cell_elem_name, export_name, b_composite )
|
---|
1529 | @@current_object.external_join( internal_cell_elem_name, export_name, b_composite )
|
---|
1530 | end
|
---|
1531 |
|
---|
1532 | #=== Cell# cell 内に記述する呼び口の外部結合
|
---|
1533 | # internal_cell_elem_name:: string : 呼び口名
|
---|
1534 | # export_name:: string: composite の外部に公開する呼び口名
|
---|
1535 | # 呼び口を外部結合する.
|
---|
1536 | # このメソッドは、composite の中の cell でしか呼ばれない.
|
---|
1537 | def external_join( internal_cell_elem_name, export_name, b_composite )
|
---|
1538 |
|
---|
1539 | # cCall => composite.cCall; ではないか?
|
---|
1540 | if( b_composite == false )then
|
---|
1541 | # cCall => cCall; のような場合
|
---|
1542 | if @celltype.find( export_name ) then
|
---|
1543 | cdl_error( "S1036 $1 : cannot refer to $2\'s here. Use \'composite.$3\' to refer to composite celltype\'s" , export_name, @celltype.get_name, export_name )
|
---|
1544 | end
|
---|
1545 | end
|
---|
1546 | # composite の旧文法における、cell 外の cCall = Cell.cCall; の構文処理に渡す
|
---|
1547 | CompositeCelltype.new_join( export_name, @name, internal_cell_elem_name, :CALL )
|
---|
1548 | end
|
---|
1549 |
|
---|
1550 | def self.end_of_parse f_def
|
---|
1551 | cell = @@current_object
|
---|
1552 | cell.end_of_parse f_def
|
---|
1553 | @@current_object = nil
|
---|
1554 | return cell
|
---|
1555 | end
|
---|
1556 |
|
---|
1557 | def end_of_parse f_def
|
---|
1558 | if @b_prototype then # prototype 指定子あったか?
|
---|
1559 | f_def = false # プロトタイプ宣言とする
|
---|
1560 | @b_prototype = false
|
---|
1561 | end
|
---|
1562 | if f_def == false then
|
---|
1563 | # cell tCelltype Cell; の形式の場合
|
---|
1564 | # f_def == true の場合 new_def で、呼出される
|
---|
1565 | set_specifier_list( Generator.get_statement_specifier )
|
---|
1566 | end
|
---|
1567 | set_f_def f_def
|
---|
1568 |
|
---|
1569 | if @generate then
|
---|
1570 | cell_plugin
|
---|
1571 | end
|
---|
1572 | end
|
---|
1573 |
|
---|
1574 | #=== Cell# プロトタイプ宣言(false)か定義(true)かを設定
|
---|
1575 | # このメソッドは構文解釈の最後に呼出される
|
---|
1576 | #f_def:: bool false if prototype, true if definition
|
---|
1577 | def set_f_def f_def
|
---|
1578 | if ! f_def then
|
---|
1579 | return
|
---|
1580 | end
|
---|
1581 |
|
---|
1582 | if ! @in_composite then
|
---|
1583 | if @celltype.instance_of? Celltype then
|
---|
1584 | @celltype.new_cell self
|
---|
1585 | end
|
---|
1586 | @@cell_list << self
|
---|
1587 | end
|
---|
1588 | end
|
---|
1589 |
|
---|
1590 | def set_f_ref
|
---|
1591 | dbgPrint "set_f_ref: #{@global_name}\n"
|
---|
1592 | @f_ref = true
|
---|
1593 |
|
---|
1594 | # composite の内部セルを参照されたことにする
|
---|
1595 | # 今のところ問題ないが、未参照であるべきものまで参照されたことになる
|
---|
1596 | if @cell_list then
|
---|
1597 | @cell_list.each{ |cn,cell|
|
---|
1598 | cell.set_f_ref
|
---|
1599 | }
|
---|
1600 | end
|
---|
1601 | end
|
---|
1602 |
|
---|
1603 | #=== Cell# cell の指定子を設定
|
---|
1604 | # STAGE: B
|
---|
1605 | #
|
---|
1606 | # bnf.y.rb の statement_specifiler_list
|
---|
1607 | #spec_list:: [ :ALLOCATOR, [ [ :NORMAL_ALLOC, ep_name, subscript, func_name, param_name, expr ], ... ] ]
|
---|
1608 | # s[0] s[1] a[0] a[1] a[2] a[3] a[4] a[5]
|
---|
1609 | # セルに指定されたアロケータ指定子
|
---|
1610 | # a[1] の subscript はこのメソッドの中で Expression から Integer に評価される
|
---|
1611 | # 受け口側に生成されるアロケータ呼び口の結合を内部生成する
|
---|
1612 | # 呼び口側は Port の create_allocator_join にて生成
|
---|
1613 | # リレーアロケータの場合 create_relay_allocator_join にて生成す
|
---|
1614 | def set_specifier_list( spec_list )
|
---|
1615 | return if spec_list == nil # 空ならば何もしない
|
---|
1616 |
|
---|
1617 | dbgPrint( "set_spec_list: #{@name}\n" )
|
---|
1618 | b_generate = false # generate が指定された
|
---|
1619 |
|
---|
1620 | spec_list.each{ |s|
|
---|
1621 | case s[0] # statement_specifier
|
---|
1622 | when :ALLOCATOR # [allocator(ePort.func.param=allocCell.eA,ePort.func2.param=allocCell.eA)]
|
---|
1623 | s[1].each { |a| # alloc_list : allocator の内部の ',' で区切られた部分の配列
|
---|
1624 | cp_name = :"#{a[0+1]}_#{a[2+1]}_#{a[3+1]}" # アロケータ呼び口の名前:'=' の左辺を '.' に変えて '_' で連結
|
---|
1625 | # p "#{a[0]} #{a[0+1]} #{a[2+1]} #{a[3+1]} #{cp_name}"
|
---|
1626 | if a[1+1] then
|
---|
1627 | subscript = a[1+1].eval_const nil
|
---|
1628 | a[1+1] = subscript
|
---|
1629 | else
|
---|
1630 | subscript = nil
|
---|
1631 | end
|
---|
1632 | # アロケータ呼び口の結合を生成
|
---|
1633 | join = Join.new( cp_name, subscript, a[4+1] ) # 構文解析段階なので locale 不要
|
---|
1634 | dbgPrint( "new allocator join #{cp_name} #{subscript} #{a[4+1]}\n" )
|
---|
1635 | Cell.new_join( join )
|
---|
1636 | @alloc_list << a
|
---|
1637 | }
|
---|
1638 | when :ID # [id(0)]
|
---|
1639 | if ! s[1].instance_of? Expression then
|
---|
1640 | cdl_error( "S1160 $1 must be constant for id", s[1].to_s )
|
---|
1641 | else
|
---|
1642 | id = s[1].eval_const nil
|
---|
1643 | if id == nil || Integer(id) != id then
|
---|
1644 | cdl_error( "S1161 $1 must be constant for id", s[1].to_s )
|
---|
1645 | elsif id == 0 then
|
---|
1646 | cdl_error( "S1162 $1: id cannot be 0", s[1].to_s )
|
---|
1647 | else
|
---|
1648 | @id_specified = id
|
---|
1649 | end
|
---|
1650 | end
|
---|
1651 | when :GENERATE # [generate(CellPlugin,"option")]
|
---|
1652 | if @generate then
|
---|
1653 | cdl_error( "S1163 generate specifier duplicate" )
|
---|
1654 | end
|
---|
1655 | @generate = [ s[1], s[2] ] # [ PluginName, "option" ]
|
---|
1656 | b_generate = true
|
---|
1657 | when :PROTOTYPE # [prototype]
|
---|
1658 | @b_prototype = true
|
---|
1659 | when :RESTRICT # [restrict]
|
---|
1660 | s[1].each{ |re|
|
---|
1661 | add_restrict re[0], re[1], re[2]
|
---|
1662 | }
|
---|
1663 | else
|
---|
1664 | cdl_error( "S1039 \'$1\': unknown specifier for cell" , s[0] )
|
---|
1665 | end
|
---|
1666 | }
|
---|
1667 | if @b_prototype then
|
---|
1668 | if b_generate then
|
---|
1669 | cdl_error( "S9999 '$1': generate and prototype specified simultaneously" , @name )
|
---|
1670 | end
|
---|
1671 | if @b_defined then
|
---|
1672 | cdl_error( "S9999 '$1': prototype specified after definition" , @name )
|
---|
1673 | end
|
---|
1674 | end
|
---|
1675 | end
|
---|
1676 |
|
---|
1677 | def get_allocator_list
|
---|
1678 |
|
---|
1679 | # 意味チェック(set_definition)されていない?
|
---|
1680 | # relay アロケータの場合、セルの意味チェックが行われていないと、@alloc_list が完成しない
|
---|
1681 | if @b_checked == false then
|
---|
1682 | set_definition_join
|
---|
1683 | end
|
---|
1684 | @alloc_list
|
---|
1685 | end
|
---|
1686 |
|
---|
1687 | def get_specified_id
|
---|
1688 | @id_specified
|
---|
1689 | end
|
---|
1690 |
|
---|
1691 | #=== id 指定子の値を設定
|
---|
1692 | # このメソッドは、プラグインで cell の生成順序を制御したい場合のために設けた
|
---|
1693 | # 通常の id 指定子では使っていない
|
---|
1694 | def set_specified_id id
|
---|
1695 | if Integer( id ) != id || id <= 0 then
|
---|
1696 | cdl_error( "S1164 '$1' set_specified_id: id not positive integer '$2'", @name, id )
|
---|
1697 | elsif @id_specified then
|
---|
1698 | cdl_error( "S1165 '$1' set_specified_id: id duplicate", @name )
|
---|
1699 | else
|
---|
1700 | @id_specified = id
|
---|
1701 | end
|
---|
1702 | end
|
---|
1703 |
|
---|
1704 | #=== Cell# セルタイププラグイン (generate 指定子)
|
---|
1705 | def cell_plugin
|
---|
1706 |
|
---|
1707 | load_plugin( @generate[0], CellPlugin )
|
---|
1708 |
|
---|
1709 | plugin_name = @generate[0]
|
---|
1710 | option = @generate[1]
|
---|
1711 | plugin_object = nil
|
---|
1712 | eval_str = "plugin_object = #{plugin_name}.new( self, option )"
|
---|
1713 | if $verbose then
|
---|
1714 | print "new cell : #{eval_str}\n"
|
---|
1715 | end
|
---|
1716 |
|
---|
1717 | begin
|
---|
1718 | eval( eval_str ) # plugin を生成
|
---|
1719 | plugin_object.set_locale @locale
|
---|
1720 | @generate[ 2 ] = plugin_object
|
---|
1721 | generate_and_parse plugin_object
|
---|
1722 | rescue Exception => evar
|
---|
1723 | cdl_error( "S1166 $1: fail to new", plugin_name )
|
---|
1724 | print "eval( #{eval_str} )\n"
|
---|
1725 |
|
---|
1726 | print_exception( evar )
|
---|
1727 | end
|
---|
1728 | end
|
---|
1729 |
|
---|
1730 | def add_compositecelltypejoin join
|
---|
1731 | @compositecelltypejoin_list.add_item join
|
---|
1732 | end
|
---|
1733 |
|
---|
1734 | #=== Cell# cell を composite セルタイプのセル用に clone する
|
---|
1735 | #name:: string : 親 cell の名前 (cell tComposite cell1 での cell1)
|
---|
1736 | #global_name:: string : 親 cell の global_name
|
---|
1737 | #join_array:: Join[] : composite の cell の join で、この cell に対応するもの
|
---|
1738 | #ct_name:: string : 親セルのセルタイプ名
|
---|
1739 | #region:: Region : 元のセルが属する region
|
---|
1740 | #このメソッドは CompositeCelltype の expand から呼出される
|
---|
1741 | def clone_for_composite( name, global_name, namespacePath, join_array, ct_name, region, plugin, locale )
|
---|
1742 |
|
---|
1743 | # debug
|
---|
1744 | dbgPrint "Cell#clone_for_composite : cloning: #{@name} #{global_name} b_defined=#{@b_defined}\n"
|
---|
1745 |
|
---|
1746 | @my_clone = self.clone
|
---|
1747 | @@cloned_cell_list[ self ] = @my_clone
|
---|
1748 |
|
---|
1749 | # clone したセルの内部に持つ名前情報を調整する
|
---|
1750 |
|
---|
1751 | @my_clone.set_cloned( name, global_name, namespacePath, join_array, ct_name, region, plugin, locale )
|
---|
1752 |
|
---|
1753 | # @celltype == nil は以前にセルタイプ未定義エラー
|
---|
1754 | if @b_defined == true && @celltype != nil then
|
---|
1755 | if @celltype.instance_of?( Celltype ) then
|
---|
1756 | # celltype に登録(コード生成の対象となる)
|
---|
1757 | @celltype.new_cell( @my_clone )
|
---|
1758 | end
|
---|
1759 | end
|
---|
1760 |
|
---|
1761 | return @my_clone
|
---|
1762 | end
|
---|
1763 |
|
---|
1764 | #=== Cell# clone されたセルの内部に持つ名前情報を調整する
|
---|
1765 | #name:: string : 親 cell の名前 (cell tComposite cell1 での cell1)
|
---|
1766 | #global_name:: string : 親 cell の global_name
|
---|
1767 | #join_array:: Join[] : composite の cell の join で、この cell に対応するもの
|
---|
1768 | #parent_ct_name:: string : 親セルのセルタイプ名(composite セルタイプ)
|
---|
1769 | # このメソッドはすぐ上の clone_for_composite から呼出され、clone されたセルを整える
|
---|
1770 | def set_cloned( name, global_name, namespacePath, join_array, parent_ct_name, region, plugin, locale )
|
---|
1771 |
|
---|
1772 | # debug
|
---|
1773 | dbgPrint "cell.set_cloned : global_name: #{global_name} name: #{name} @name: #{@name}\n"
|
---|
1774 |
|
---|
1775 | @global_name = :"#{global_name}_#{@name}"
|
---|
1776 | @name = :"#{name}_#{@name}"
|
---|
1777 | @NamespacePath = namespacePath.change_name @name
|
---|
1778 | @region = region
|
---|
1779 | @plugin = plugin
|
---|
1780 | @locale = locale
|
---|
1781 |
|
---|
1782 | @in_composite = false
|
---|
1783 | @b_checked = false
|
---|
1784 | @f_cloned = true
|
---|
1785 |
|
---|
1786 | # Namespace.new_cell( self ) # mikan namespace 対応
|
---|
1787 | region.new_cell( self ) # mikan namespace に cell を置けないことを仮定
|
---|
1788 |
|
---|
1789 | # join_list : NamedList の clone を作る
|
---|
1790 | if @celltype then
|
---|
1791 | dbgPrint "set_cloned: #{@celltype.get_name} #{@name} #{region.get_name}\n"
|
---|
1792 | end
|
---|
1793 | @join_list = @join_list.clone_for_composite( parent_ct_name, name, locale )
|
---|
1794 | @referenced_port_list = {}
|
---|
1795 |
|
---|
1796 | @alloc_list = []
|
---|
1797 | @require_joined_list = {}
|
---|
1798 | @entry_array_max_subscript = {}
|
---|
1799 | @cell_list = {}
|
---|
1800 | @cell_list2 = []
|
---|
1801 |
|
---|
1802 | # このセルのグローバル名を与える
|
---|
1803 | # C_EXP の$id$ 置換はこのセルの名前になる
|
---|
1804 | join_array.each { |j|
|
---|
1805 | @join_list.change_item j
|
---|
1806 | }
|
---|
1807 |
|
---|
1808 | # clone しようとするセルが composit セルタイプ?
|
---|
1809 | if @celltype.instance_of?( CompositeCelltype ) then
|
---|
1810 | # composite cell を再帰的に展開
|
---|
1811 | @cell_list, @cell_list2 = @celltype.expand( @name, @global_name, @NamespacePath, @join_list, @region, @plugin, @locale )
|
---|
1812 | end
|
---|
1813 |
|
---|
1814 | end
|
---|
1815 |
|
---|
1816 | #=== Cell# clone された cell の join_list の右辺の変更
|
---|
1817 | # 呼び口の右辺の cell を他の clone された cell に置換え
|
---|
1818 | def change_rhs_port
|
---|
1819 |
|
---|
1820 | # debug
|
---|
1821 | dbgPrint "Cell change_rhs_port: global_name: #{@global_name}\n"
|
---|
1822 |
|
---|
1823 | @join_list.get_items.each { |j|
|
---|
1824 | j.change_rhs_port( @@cloned_cell_list, @celltype )
|
---|
1825 | }
|
---|
1826 |
|
---|
1827 | if @celltype.instance_of?( CompositeCelltype ) then
|
---|
1828 |
|
---|
1829 | # 入れ子のセルについても変更
|
---|
1830 | @cell_list.each{ |name,c|
|
---|
1831 | c.change_rhs_port
|
---|
1832 | }
|
---|
1833 | end
|
---|
1834 | end
|
---|
1835 |
|
---|
1836 | def get_f_def
|
---|
1837 | @b_defined
|
---|
1838 | end
|
---|
1839 |
|
---|
1840 | def get_f_ref
|
---|
1841 | if @f_ref then
|
---|
1842 | return true
|
---|
1843 | else
|
---|
1844 | return false
|
---|
1845 | end
|
---|
1846 | end
|
---|
1847 |
|
---|
1848 | def get_name
|
---|
1849 | @name
|
---|
1850 | end
|
---|
1851 |
|
---|
1852 | def get_local_name
|
---|
1853 | @local_name
|
---|
1854 | end
|
---|
1855 |
|
---|
1856 | def get_global_name
|
---|
1857 | @global_name
|
---|
1858 | end
|
---|
1859 |
|
---|
1860 | def get_region
|
---|
1861 | @region
|
---|
1862 | end
|
---|
1863 |
|
---|
1864 | def self.get_current
|
---|
1865 | @@current_object
|
---|
1866 | end
|
---|
1867 |
|
---|
1868 | #=== Cell# 生成されるセルか?
|
---|
1869 | # 最適化、コード生成中に、対象となる region に属する場合 true を返す
|
---|
1870 | def is_generate?
|
---|
1871 | if $generating_region == nil then
|
---|
1872 | # 構文解釈、意味解析段階で呼ばれると例外発生
|
---|
1873 | raise "is_generate? called before optimizing"
|
---|
1874 | end
|
---|
1875 |
|
---|
1876 | # print "Cell#is_generate?: #{@name} #{@region.get_name} #{$generating_region.get_name}\n"
|
---|
1877 | if $generating_region == @region.get_link_root then
|
---|
1878 | return true
|
---|
1879 | else
|
---|
1880 | return false
|
---|
1881 | end
|
---|
1882 | end
|
---|
1883 |
|
---|
1884 | #=== Cell# composite 内部の複製されたセルか?
|
---|
1885 | # composite 定義の内部のセル (@in_composite = true) ではない
|
---|
1886 | def is_cloned?
|
---|
1887 | @f_cloned
|
---|
1888 | end
|
---|
1889 |
|
---|
1890 | #=== Cell# composite 内部のセルか?
|
---|
1891 | def is_in_composite?
|
---|
1892 | @in_composite
|
---|
1893 | end
|
---|
1894 |
|
---|
1895 | # composite cell の port に対応する内部の cell の port の名前(リンク時に必要な名前)
|
---|
1896 | def get_real_global_name port_name
|
---|
1897 | if @celltype.instance_of?( CompositeCelltype ) then
|
---|
1898 |
|
---|
1899 | # debug
|
---|
1900 | dbgPrint "get_real_global_name: cell name: #{@name} #{@local_name} #{@global_name} #{port_name}\n"
|
---|
1901 | @cell_list.each{ |n,c|
|
---|
1902 | dbgPrint " name: #{n}\n"
|
---|
1903 | dbgPrint " get_name: #{c.get_name} local_name: #{c.get_local_name}\n" if c
|
---|
1904 | dbgPrint "\n\n"
|
---|
1905 | }
|
---|
1906 |
|
---|
1907 | cj = @celltype.find_export( port_name )
|
---|
1908 |
|
---|
1909 | # debug
|
---|
1910 | dbgPrint " composite join name: #{cj.get_name} cell: #{cj.get_cell_name} cell elem: #{cj.get_cell_elem_name}\n"
|
---|
1911 |
|
---|
1912 | name = @cell_list[ "#{cj.get_cell_name}" ].get_real_global_name( cj.get_cell_elem_name )
|
---|
1913 | return name
|
---|
1914 |
|
---|
1915 | else
|
---|
1916 | # debug
|
---|
1917 | dbgPrint " get_real_global_name: cell name: #{@global_name}\n"
|
---|
1918 |
|
---|
1919 | return @global_name
|
---|
1920 | end
|
---|
1921 | end
|
---|
1922 |
|
---|
1923 | #=== Cell# セルの受け口 port_name に対する実際のセル名、受け口名を '_' で連結
|
---|
1924 | # namespace 名 + '_' + セル名 + '_' + 受け口名 (このセルが composite ならば展開後のセル名、受け口名)
|
---|
1925 | def get_real_global_port_name port_name
|
---|
1926 |
|
---|
1927 | # composite か?
|
---|
1928 | if @celltype.instance_of?( CompositeCelltype ) then
|
---|
1929 |
|
---|
1930 | # debug
|
---|
1931 | dbgPrint "get_real_global_port_name: cell name: #{@name} #{@local_name} #{@global_name} #{port_name}\n"
|
---|
1932 | @cell_list.each{ |n,c|
|
---|
1933 | dbgPrint " name: #{n}\n"
|
---|
1934 | dbgPrint " get_name: #{c.get_name} local_name: #{c.get_local_name}\n" if c
|
---|
1935 | dbgPrint "\n"
|
---|
1936 | }
|
---|
1937 |
|
---|
1938 | # セルタイプ内で port_name の CompositeCelltypeJoin を探す(コード生成段階では必ず見つかる)
|
---|
1939 | cj = @celltype.find_export( port_name )
|
---|
1940 |
|
---|
1941 | # debug
|
---|
1942 | dbgPrint " composite join name: #{cj.get_name} cell: #{cj.get_cell_name} cell elem: #{cj.get_cell_elem_name}\n"
|
---|
1943 |
|
---|
1944 | # composite の内部のセルに対し再帰的に get_real_global_port_name を適用
|
---|
1945 | name = @cell_list[ "#{cj.get_cell_name}" ].get_real_global_port_name( cj.get_cell_elem_name )
|
---|
1946 | return name
|
---|
1947 |
|
---|
1948 | else
|
---|
1949 | # debug
|
---|
1950 | dbgPrint "get_real_global_port_name: cell name: #{@global_name}\n"
|
---|
1951 |
|
---|
1952 | return "#{@global_name}_#{port_name}"
|
---|
1953 | end
|
---|
1954 | end
|
---|
1955 |
|
---|
1956 | #=== Cell# PORT (celltype の定義) を得る
|
---|
1957 | def get_real_port( port_name )
|
---|
1958 |
|
---|
1959 | # composite か?
|
---|
1960 | if @celltype.instance_of?( CompositeCelltype ) then
|
---|
1961 |
|
---|
1962 | # セルタイプ内で port_name の CompositeCelltypeJoin を探す(コード生成段階では必ず見つかる)
|
---|
1963 | cj = @celltype.find_export( port_name )
|
---|
1964 |
|
---|
1965 | # composite の内部のセルに対し再帰的に get_real_port を適用
|
---|
1966 | port = @cell_list[ "#{cj.get_cell_name}" ].get_real_port( cj.get_cell_elem_name )
|
---|
1967 | return port
|
---|
1968 | else
|
---|
1969 |
|
---|
1970 | return @celltype.find( port_name )
|
---|
1971 | end
|
---|
1972 | end
|
---|
1973 |
|
---|
1974 | #=== Cell# cell を得る
|
---|
1975 | # composite でなければ自分自身を返す
|
---|
1976 | def get_real_cell( port_name )
|
---|
1977 |
|
---|
1978 | # composite か?
|
---|
1979 | if @celltype.instance_of?( CompositeCelltype ) then
|
---|
1980 |
|
---|
1981 | # セルタイプ内で port_name の CompositeCelltypeJoin を探す(コード生成段階では必ず見つかる)
|
---|
1982 | cj = @celltype.find_export( port_name )
|
---|
1983 |
|
---|
1984 | # composite の内部のセルに対し再帰的に get_real_port を適用
|
---|
1985 | cell = @cell_list[ "#{cj.get_cell_name}" ].get_real_cell( cj.get_cell_elem_name )
|
---|
1986 | return cell
|
---|
1987 | else
|
---|
1988 |
|
---|
1989 | return self
|
---|
1990 | end
|
---|
1991 | end
|
---|
1992 |
|
---|
1993 |
|
---|
1994 | #=== Cell# 受け口のport の参照カウントをアップする
|
---|
1995 | #port_name:: Symbol : ポート名
|
---|
1996 | def port_referenced port
|
---|
1997 | if @referenced_port_list[ port ] then
|
---|
1998 | @referenced_port_list[ port ] += 1
|
---|
1999 | else
|
---|
2000 | @referenced_port_list[ port ] = 1
|
---|
2001 | end
|
---|
2002 |
|
---|
2003 | # composite か?
|
---|
2004 | if @celltype.instance_of?( CompositeCelltype ) then
|
---|
2005 |
|
---|
2006 | # セルタイプ内で port_name の CompositeCelltypeJoin を探す(コード生成段階では必ず見つかる)
|
---|
2007 | cj = @celltype.find_export( port.get_name )
|
---|
2008 |
|
---|
2009 | dbgPrint " port_referenced: #{@celltype.get_name} #{@name} cj=#{cj&&(cj.get_name)||"nil"}\n"
|
---|
2010 |
|
---|
2011 | if cj then # 既にエラー
|
---|
2012 | # composite の内部のセルに対し再帰的に get_real_port を適用
|
---|
2013 | cell = @cell_list[ "#{cj.get_cell_name}" ]
|
---|
2014 | if cell && cell.get_celltype then
|
---|
2015 | cell.port_referenced( cell.get_celltype.find( cj.get_cell_elem_name ) )
|
---|
2016 | end
|
---|
2017 | end
|
---|
2018 | end
|
---|
2019 | end
|
---|
2020 |
|
---|
2021 | def get_internal_port_name port_name
|
---|
2022 | if @celltype.instance_of?( CompositeCelltype ) then
|
---|
2023 | cj = @celltype.find_export( port_name )
|
---|
2024 | # return "#{@name}_#{cj.get_cell.get_internal_port_name cj.get_cell_elem_name}"
|
---|
2025 | return cj.get_cell.get_internal_port_name( cj.get_cell_elem_name )
|
---|
2026 | else
|
---|
2027 |
|
---|
2028 | # debug
|
---|
2029 | dbgPrint " get_global_port_name: cell port: #{@global_name}_#{port_name}\n"
|
---|
2030 |
|
---|
2031 | return "#{@global_name}_#{port_name}"
|
---|
2032 | end
|
---|
2033 | end
|
---|
2034 |
|
---|
2035 | def get_celltype
|
---|
2036 | @celltype
|
---|
2037 | end
|
---|
2038 |
|
---|
2039 | def get_join_list
|
---|
2040 | @join_list
|
---|
2041 | end
|
---|
2042 |
|
---|
2043 | def set_id id
|
---|
2044 | @id = id
|
---|
2045 | end
|
---|
2046 |
|
---|
2047 | def get_id
|
---|
2048 | @id
|
---|
2049 | end
|
---|
2050 |
|
---|
2051 | def get_plugin
|
---|
2052 | @plugin
|
---|
2053 | end
|
---|
2054 |
|
---|
2055 | def get_cell_list2
|
---|
2056 | list = []
|
---|
2057 | @cell_list2.each{ |cell|
|
---|
2058 | list << cell
|
---|
2059 | list += cell.get_cell_list2
|
---|
2060 | }
|
---|
2061 | return list
|
---|
2062 | end
|
---|
2063 |
|
---|
2064 | #=== Cell# 受け口配列の添数の最大値を設定
|
---|
2065 | def set_entry_port_max_subscript( port, num )
|
---|
2066 | dbgPrint( "set_entry_port_max_subscript: #{@name}.#{port.get_name}: #{num}\n" )
|
---|
2067 | subscript = @entry_array_max_subscript[port]
|
---|
2068 |
|
---|
2069 | if subscript == nil || num > subscript then
|
---|
2070 | @entry_array_max_subscript[port] = num
|
---|
2071 | set_entry_inner_port_max_subscript( port, num )
|
---|
2072 | end
|
---|
2073 | end
|
---|
2074 |
|
---|
2075 | #=== Cell# composite の内側セルの受け口配列の添数の最大値を設定
|
---|
2076 | def set_entry_inner_port_max_subscript( port, num )
|
---|
2077 | if @cell_list == nil then # mikan これって問題ない?
|
---|
2078 | return # プロトタイプ宣言しかされていなくて、内側セルが展開されていない
|
---|
2079 | end
|
---|
2080 |
|
---|
2081 | # composite の内側のセルに伝播
|
---|
2082 | if @celltype.instance_of? CompositeCelltype then
|
---|
2083 | cj = @celltype.find_export port.get_name
|
---|
2084 | if cj && @cell_list[ cj.get_cell_name.to_s ] then
|
---|
2085 | inner_cell = @cell_list[ cj.get_cell_name.to_s ]
|
---|
2086 | ct = inner_cell.get_celltype
|
---|
2087 | if ct then
|
---|
2088 | inner_port = ct.find( cj.get_cell_elem_name )
|
---|
2089 | inner_cell.set_entry_port_max_subscript( inner_port, num )
|
---|
2090 | end
|
---|
2091 | end
|
---|
2092 | end
|
---|
2093 | end
|
---|
2094 |
|
---|
2095 | #=== Cell# 受け口配列の添数の最大値を返す
|
---|
2096 | # 長さは +1 する
|
---|
2097 | # 1つもない場合は -1 を返す
|
---|
2098 | def get_entry_port_max_subscript( port )
|
---|
2099 | subscript = @entry_array_max_subscript[port]
|
---|
2100 | if subscript == nil then
|
---|
2101 | subscript = -1
|
---|
2102 | end
|
---|
2103 | return subscript
|
---|
2104 | end
|
---|
2105 |
|
---|
2106 | #=== Cell# リレーアロケータの結合を生成
|
---|
2107 | # STAGE: S
|
---|
2108 | # 呼び口側の結合を元に受け口側の結合を生成
|
---|
2109 | def create_relay_allocator_join
|
---|
2110 |
|
---|
2111 | # celltype がなければチェックしない(既にエラー)
|
---|
2112 | return if @celltype == nil
|
---|
2113 |
|
---|
2114 | # relay allocator を生成
|
---|
2115 | @celltype.get_port_list.each { |p|
|
---|
2116 | ail = p.get_allocator_instance
|
---|
2117 | if ail then
|
---|
2118 | dbgPrint "create_relay_allocator_join: #{@name}, #{p.get_name}\n"
|
---|
2119 | if p.get_array_size then
|
---|
2120 | # mikan relay allocator が array に対応できてもよいのでは?
|
---|
2121 | cdl_error( "S1040 array not supported for relay allocator" )
|
---|
2122 | next
|
---|
2123 | end
|
---|
2124 | ail.each{ |name,ai2|
|
---|
2125 | # ai2 = [ :INTERNAL_ALLOC|:RELAY_ALLOC, func_name, param_name, rhs_cp_name, rhs_func_name, rhs_param_name ]
|
---|
2126 | if ai2[0] == :RELAY_ALLOC then
|
---|
2127 | dbgPrint "create_relay_allocator_join: #{@name}, #{name}\n"
|
---|
2128 | # 呼び口側の結合を取り出す
|
---|
2129 | ja = @join_list.get_item( :"#{ai2[3]}_#{ai2[4]}_#{ai2[5]}" )
|
---|
2130 | if ja == nil then
|
---|
2131 | # 見つからない場合
|
---|
2132 | found = false
|
---|
2133 |
|
---|
2134 | # composite 内で外部に結合されているか
|
---|
2135 | if @in_composite then
|
---|
2136 | @compositecelltypejoin_list.get_items.each { |cj|
|
---|
2137 | dbgPrint( "create relay_allocator in_composite\n" )
|
---|
2138 | dbgPrint(" #{cj.get_cell_name} #{@name} #{cj.get_cell_elem_name} #{ai2[3]}_#{ai2[4]}_#{ai2[5]}\n")
|
---|
2139 | if cj.get_cell_name == @name &&
|
---|
2140 | cj.get_cell_elem_name == :"#{ai2[3]}_#{ai2[4]}_#{ai2[5]}" then
|
---|
2141 | found = true
|
---|
2142 | dbgPrint "create_relay_allocator: found #{cj.get_cell_elem_name}\n"
|
---|
2143 | break
|
---|
2144 | end
|
---|
2145 | }
|
---|
2146 | end
|
---|
2147 |
|
---|
2148 | if found == false then
|
---|
2149 | cdl_error( "S1041 \'$1_$2_$3\': not joined. cannot create internal join for relay allocator" , ai2[3], ai2[4], ai2[5] )
|
---|
2150 | print( " In cell #{get_name}\n" )
|
---|
2151 | # join が未結合であることのエラーは二度でる (S1043)
|
---|
2152 | end
|
---|
2153 | next # 打ち切る
|
---|
2154 | end
|
---|
2155 |
|
---|
2156 | b_export = false
|
---|
2157 | # composite 内のセルでエクスポートされているかチェック
|
---|
2158 | # mikan エクスポート側と、こちら側で、リレー先が一致するかチェックが必要
|
---|
2159 | if @compositecelltypejoin_list then
|
---|
2160 | # export されているか調べる
|
---|
2161 | @compositecelltypejoin_list.get_items.each{ |cj|
|
---|
2162 | # 属性名と composite の export する名前は一致するか
|
---|
2163 | if p.get_name == cj.get_cell_elem_name then
|
---|
2164 | print "export : #{p.get_name}\n"
|
---|
2165 | b_export = true # 属性は export されているので、とりあえず未初期化とはしない
|
---|
2166 | break
|
---|
2167 | end
|
---|
2168 | }
|
---|
2169 | #
|
---|
2170 | end
|
---|
2171 |
|
---|
2172 | # mikan 配列
|
---|
2173 | am = nil
|
---|
2174 | if am then
|
---|
2175 | am.each{ |ja2|
|
---|
2176 | rhs = ja2.get_rhs
|
---|
2177 | subscript = ja2.get_subscript
|
---|
2178 | if b_export == false then
|
---|
2179 | # CompositeCelltype の場合、内側のセルで生成させる
|
---|
2180 | join = Join.new( :"#{p.get_name}_#{ai2[1]}_#{ai2[2]}", subscript, rhs, @loacle )
|
---|
2181 | # p ( "#{p.get_name}_#{ai2[1]}_#{ai2[2]}", subscript, rhs )
|
---|
2182 | new_join( join )
|
---|
2183 | join.set_definition( @celltype.find(join.get_name) )
|
---|
2184 | # mikan relay mismatch チェックができていない(下方を参照)
|
---|
2185 | end
|
---|
2186 | @alloc_list << [ :NORMAL_ALLOC, p.get_name, subscript, ai2[1], ai2[2], rhs ]
|
---|
2187 | }
|
---|
2188 | else
|
---|
2189 | if b_export == false then
|
---|
2190 | # CompositeCelltype の場合、内側のセルで生成させる
|
---|
2191 | join = Join.new( :"#{p.get_name}_#{ai2[1]}_#{ai2[2]}", nil, ja.get_rhs, @locale )
|
---|
2192 | new_join( join )
|
---|
2193 | join.set_definition( @celltype.find(join.get_name) )
|
---|
2194 | if @celltype.instance_of? CompositeCelltype then
|
---|
2195 | jr = @join_list.get_item( :"#{ai2[3]}_#{ai2[4]}_#{ai2[5]}" )
|
---|
2196 | if jr.get_rhs_cell2 != join.get_rhs_cell2 || jr.get_rhs_port2 != join.get_rhs_port2 then
|
---|
2197 | cdl_error( "S1167 \'$1\': relay mismatch \'$2\'",
|
---|
2198 | "#{p.get_name}_#{ai2[1]}_#{ai2[2]}",
|
---|
2199 | "#{ai2[3]}_#{ai2[4]}_#{ai2[5]}" )
|
---|
2200 | # 本当は composite の呼び口と受け口の間で行うべきだが、内部で多段接続されている場合
|
---|
2201 | else
|
---|
2202 | dbgPrint "relay success: #{p.get_name}_#{ai2[1]}_#{ai2[2]}=>#{ai2[3]}_#{ai2[4]}_#{ai2[5]} #{jr.get_rhs_cell2.get_name}.#{jr.get_rhs_port2} \n"
|
---|
2203 | end
|
---|
2204 | end
|
---|
2205 | end
|
---|
2206 | @alloc_list << [ :NORMAL_ALLOC, p.get_name, nil, ai2[1], ai2[2], ja.get_rhs ]
|
---|
2207 | end
|
---|
2208 | dbgPrint "create_relay_allocator_join: #{p.get_name}_#{ai2[1]}_#{ai2[2]} #{ai2[3]}_#{ai2[4]}_#{ai2[5]}\n"
|
---|
2209 | end
|
---|
2210 | }
|
---|
2211 | end
|
---|
2212 | }
|
---|
2213 | end
|
---|
2214 |
|
---|
2215 | #=== Cell# @@cell_list2 を作る
|
---|
2216 | # @@cell_list2 は、出現順に composite 内を含むセルのリスト
|
---|
2217 | def self.make_cell_list2
|
---|
2218 | @@cell_list.each{ |c|
|
---|
2219 | @@cell_list2 << c
|
---|
2220 | @@cell_list2 += c.get_cell_list2
|
---|
2221 | }
|
---|
2222 | end
|
---|
2223 |
|
---|
2224 | #=== Cell# @@cell_list2 を得る
|
---|
2225 | # composite 内を含む (compositeも含む)
|
---|
2226 | # 意味解析後に作成される
|
---|
2227 | def self.get_cell_list2
|
---|
2228 | @@cell_list2
|
---|
2229 | end
|
---|
2230 |
|
---|
2231 | #=== Cell# @@cell_list を得る
|
---|
2232 | #composite の中を含まない
|
---|
2233 | def self.get_cell_list
|
---|
2234 | @@cell_list
|
---|
2235 | end
|
---|
2236 |
|
---|
2237 | #=== Cell# reverse_join を生成する
|
---|
2238 | def self.create_reverse_join
|
---|
2239 | @@cell_list.each{ |c|
|
---|
2240 | ct = c.get_celltype
|
---|
2241 | # if c.is_generate? then
|
---|
2242 | if ct then
|
---|
2243 | c.create_reverse_join
|
---|
2244 | end
|
---|
2245 | # end
|
---|
2246 | }
|
---|
2247 | end
|
---|
2248 |
|
---|
2249 | #=== Cell# reverse_require_join を生成する
|
---|
2250 | def self.create_reverse_require_join
|
---|
2251 | @@cell_list2.each{ |c|
|
---|
2252 | ct = c.get_celltype
|
---|
2253 | # if c.is_generate? then
|
---|
2254 | if ct then
|
---|
2255 | # self への呼び口側の結合を生成
|
---|
2256 | ct.create_reverse_require_join c
|
---|
2257 | end
|
---|
2258 | # end
|
---|
2259 | }
|
---|
2260 | end
|
---|
2261 |
|
---|
2262 | #=== Cell# 受け口のport の参照カウントを設定する
|
---|
2263 | # self は呼び元のセル
|
---|
2264 | # 呼び先セルの受け口の参照カウントをアップする
|
---|
2265 | def set_port_reference_count
|
---|
2266 | @join_list.get_items.each { |j|
|
---|
2267 | if j.get_definition.instance_of? Port then
|
---|
2268 | am = j.get_array_member2
|
---|
2269 | if am then # 呼び口配列
|
---|
2270 | am.each { |j2|
|
---|
2271 | next if j2 == nil # optional で一部が欠落しているケース
|
---|
2272 | cell = j2.get_rhs_cell2
|
---|
2273 | next if cell == nil # 右辺が見つからなかった.既にエラー
|
---|
2274 | port = cell.get_celltype.find( j2.get_rhs_port2 )
|
---|
2275 | dbgPrint( "set_port_reference_count: #{@name}.#{j2.get_name} => #{cell.get_name}.#{port.get_name}\n")
|
---|
2276 | cell.port_referenced port
|
---|
2277 | }
|
---|
2278 | else
|
---|
2279 | cell = j.get_rhs_cell2
|
---|
2280 | next if cell == nil # 右辺が見つからなかった.既にエラー
|
---|
2281 | port = cell.get_celltype.find( j.get_rhs_port2 )
|
---|
2282 | dbgPrint( "set_port_reference_count: #{@name}.#{j.get_name} => #{cell.get_name}.#{port.get_name}\n")
|
---|
2283 | cell.port_referenced port
|
---|
2284 | end
|
---|
2285 | end
|
---|
2286 | }
|
---|
2287 | end
|
---|
2288 |
|
---|
2289 | #=== Cell# 結合(Join)のチェック
|
---|
2290 | # Join は呼び口の結合または attribute の初期化
|
---|
2291 | #
|
---|
2292 | # mikan このメソッドは、以下の4つのチェックからなるが、分割したほうがより適切な長さのメソッドになる
|
---|
2293 | # ・リレーアロケータの生成 => create_relay_allocator_join
|
---|
2294 | # ・未結合の呼び口のチェック
|
---|
2295 | # ・ポインタ型が配列で初期化される場合のチェック
|
---|
2296 | # ・未初期化の属性のチェック
|
---|
2297 | def check_join
|
---|
2298 |
|
---|
2299 | # celltype がなければチェックしない(既にエラー)
|
---|
2300 | return if @celltype == nil
|
---|
2301 | return if @b_defined == false
|
---|
2302 | return if @f_cloned == true # 内部セルについては、composite の定義時にチェックされている
|
---|
2303 |
|
---|
2304 | # debug
|
---|
2305 | # if @compositecelltypejoin_list then
|
---|
2306 | # p "check_join"
|
---|
2307 | # @compositecelltypejoin_list.get_items.each { |cj| p "#{cj.get_name} #{cj.get_name.object_id}" }
|
---|
2308 | # end
|
---|
2309 |
|
---|
2310 | # 未結合の呼び口のチェック
|
---|
2311 | @celltype.get_port_list.each { |p|
|
---|
2312 |
|
---|
2313 | # 呼び口でなければ、チェックしない
|
---|
2314 | next if p.get_port_type != :CALL
|
---|
2315 |
|
---|
2316 | # debug
|
---|
2317 | dbgPrint "check_join: #{@name} #{get_celltype.get_name} #{p.get_name}\n"
|
---|
2318 |
|
---|
2319 | # 結合リストの中から呼び口名に一致するものを取りだす
|
---|
2320 | j = @join_list.get_item( p.get_name )
|
---|
2321 |
|
---|
2322 | if j == nil then
|
---|
2323 | # 未結合の呼び口
|
---|
2324 |
|
---|
2325 | # composite celltype の内部の場合、composite celltype が export する呼び口に結合されているか探す
|
---|
2326 | found = false
|
---|
2327 | if @in_composite then
|
---|
2328 | # composite celltype の export するものすべてから探す
|
---|
2329 | # (export するものの右辺値から探すために get_item ではダメ)
|
---|
2330 | @compositecelltypejoin_list.get_items.each{ |cj|
|
---|
2331 | # 呼び口名と composite の export する名前は一致するか
|
---|
2332 | if p.get_name == cj.get_cell_elem_name then
|
---|
2333 | found = true
|
---|
2334 | end
|
---|
2335 | }
|
---|
2336 | end
|
---|
2337 |
|
---|
2338 | # 呼び口配列の場合 optional で全ての要素が初期化されない場合に、ここへ来る
|
---|
2339 | if ! found && ! p.is_require? && ! p.is_optional? then
|
---|
2340 | if ! p.is_allocator_port? then
|
---|
2341 | cdl_error( "S1042 call port \'$1\' not initialized in cell \'$2\'" , p.get_name, @name )
|
---|
2342 | else
|
---|
2343 | cdl_error( "S1043 call port \'$1\' not initialized in cell \'$2\'. this call port is created by tecsgen. check allocator specifier" , p.get_name, @name )
|
---|
2344 | end
|
---|
2345 | end
|
---|
2346 | elsif p.get_array_size.kind_of? Integer then
|
---|
2347 | # 添数あり呼び口配列の場合、すべての添数要素が初期化されているかチェックする
|
---|
2348 |
|
---|
2349 | am = j.get_array_member2
|
---|
2350 | if( am )then
|
---|
2351 | # join は配列
|
---|
2352 |
|
---|
2353 | # 呼び口配列定義での配列の大きさ
|
---|
2354 | length = p.get_array_size
|
---|
2355 |
|
---|
2356 | # 配列の大きさが呼び口配列定義と結合定義で一致するか?
|
---|
2357 | if am.length != length then
|
---|
2358 | if ! p.is_optional? || am.length >= length then
|
---|
2359 | # optional の場合、要素数が少なすぎるのは OK
|
---|
2360 | cdl_error( "S1044 $1: array initializer too many or few, $2 for $3" , p.get_name, am.length, length )
|
---|
2361 | end
|
---|
2362 |
|
---|
2363 | # am の要素に nil を追加しておく (#_CPA_# のコード生成時、この配列要素数分生成)
|
---|
2364 | i = am.length
|
---|
2365 | while i < length
|
---|
2366 | am << nil
|
---|
2367 | i += 1
|
---|
2368 | end
|
---|
2369 | end
|
---|
2370 |
|
---|
2371 | # # 配列要素の抜けがないかチェック
|
---|
2372 | # if am.length < length then # 満たない場合既にエラーだが要素のある範囲でチェック
|
---|
2373 | # length = am.length
|
---|
2374 | # end
|
---|
2375 | i = 0
|
---|
2376 | while( i < length )
|
---|
2377 | if am[i] == nil then
|
---|
2378 | if ! p.is_optional? then
|
---|
2379 | cdl_error( "S1045 $1[$2]: not initialized" , p.get_name, i )
|
---|
2380 | end
|
---|
2381 | else
|
---|
2382 | # 生成されないリージョンへの結合かチェック
|
---|
2383 | if ! @in_composite then
|
---|
2384 | am[i].check_region2
|
---|
2385 | end
|
---|
2386 | end
|
---|
2387 | i += 1
|
---|
2388 | end
|
---|
2389 |
|
---|
2390 | # else
|
---|
2391 | # join が非配列であれば、既にエラー
|
---|
2392 | end
|
---|
2393 | elsif j.get_array_member then
|
---|
2394 | # 添数なし呼び口配列の場合
|
---|
2395 | am = j.get_array_member2
|
---|
2396 | length = am.length
|
---|
2397 | i = 0
|
---|
2398 | while i < length
|
---|
2399 | if am[i] == nil then
|
---|
2400 | if ! p.is_optional? then
|
---|
2401 | cdl_error( "S1046 $1[$2]: not initialized" , p.get_name, i )
|
---|
2402 | end
|
---|
2403 | end
|
---|
2404 | i += 1
|
---|
2405 | end
|
---|
2406 |
|
---|
2407 | # 生成されないリージョンへの結合かチェック
|
---|
2408 | if ! @in_composite then
|
---|
2409 | am.each { |join|
|
---|
2410 | if join then
|
---|
2411 | join.check_region2
|
---|
2412 | end
|
---|
2413 | }
|
---|
2414 | end
|
---|
2415 | else
|
---|
2416 | # 呼び口[配列」でない場合
|
---|
2417 |
|
---|
2418 | # 生成されないリージョンへの結合かチェック
|
---|
2419 | if ! @in_composite then
|
---|
2420 | j.check_region2
|
---|
2421 | end
|
---|
2422 |
|
---|
2423 | end # j != nil
|
---|
2424 | }
|
---|
2425 |
|
---|
2426 | # ポインタ型が配列で初期化される場合のチェック
|
---|
2427 | (@celltype.get_attribute_list+@celltype.get_var_list).each { |a|
|
---|
2428 | if a.get_size_is then
|
---|
2429 |
|
---|
2430 | if a.instance_of? CompositeCelltypeJoin then
|
---|
2431 | # 既にエラーになっている
|
---|
2432 | # cdl_error( "S1047 size_is pointer cannot be exposed for composite attribute" )
|
---|
2433 | next
|
---|
2434 | end
|
---|
2435 |
|
---|
2436 | if( ! a.get_type.kind_of?( PtrType ) ) then
|
---|
2437 | cdl_error( "S1048 $1: size_is specified for non-pointer type" , a.get_name )
|
---|
2438 | else
|
---|
2439 | size = a.get_size_is.eval_const( @join_list, @celltype.get_name_list )
|
---|
2440 | a.get_type.set_scs( a.get_size_is, nil, nil, nil, false )
|
---|
2441 | if( ! size.kind_of? Integer )then # C_EXP の可能性あり
|
---|
2442 | # mikan 多分ここでのエラー発生は不要、eval_const の中で変数が存在しない、型が不適切などのエラーになるはず
|
---|
2443 | cdl_error( "S1049 $1: size_is arg not constant" , a.get_name )
|
---|
2444 | else
|
---|
2445 | j = @join_list.get_item( a.get_identifier )
|
---|
2446 | if j then
|
---|
2447 | ini = j.get_rhs
|
---|
2448 | if ini then
|
---|
2449 | if ! ini.instance_of?( Array ) then
|
---|
2450 | cdl_error( "S1050 unsuitable initializer, need array initializer" )
|
---|
2451 | elsif size < ini.length then
|
---|
2452 | cdl_error( "S1051 too many initializer for array, $1 for $2" , ini.length, size )
|
---|
2453 | else
|
---|
2454 | # a.get_type.set_scs( a.get_size_is, nil, nil )
|
---|
2455 | end
|
---|
2456 | end
|
---|
2457 | else
|
---|
2458 | # size_is 引数がセルで指定されていて、初期化子がセルタイプで指定されているケースのチェック
|
---|
2459 | ini = a.get_initializer
|
---|
2460 | if ini.instance_of? Expression
|
---|
2461 | ini = ini.eval_const( @celltype.get_name_list )
|
---|
2462 | end
|
---|
2463 | if ini.instance_of? Array then
|
---|
2464 | if( ini.length > size )then
|
---|
2465 | cdl_error( "S1168 too many initializer for array, $1 for $2", ini.length, size )
|
---|
2466 | end
|
---|
2467 | end
|
---|
2468 | end
|
---|
2469 | end
|
---|
2470 | end
|
---|
2471 | else
|
---|
2472 | if ! a.instance_of? CompositeCelltypeJoin then
|
---|
2473 | # composite は size_is 指定できない
|
---|
2474 | if a.get_type.kind_of?( PtrType ) then
|
---|
2475 | j = @join_list.get_item( a.get_identifier )
|
---|
2476 | if j && j.get_rhs.instance_of?( Array ) then
|
---|
2477 | ## size_is 指定されていないポインタが Array で初期化されていたら、エラーとする
|
---|
2478 | cdl_error( "S1169 $1: non-size_is pointer cannot be initialized with array initializer" , a.get_identifier )
|
---|
2479 | end
|
---|
2480 | end
|
---|
2481 | end
|
---|
2482 | end
|
---|
2483 | }
|
---|
2484 |
|
---|
2485 | # 未初期化の属性をチェック
|
---|
2486 | @celltype.get_attribute_list.each { |a|
|
---|
2487 | b_init = false
|
---|
2488 | # self.show_tree 1
|
---|
2489 | if a.get_initializer then # セルタイプで初期化されている
|
---|
2490 | b_init = true
|
---|
2491 | # @in_composite で export されている場合には、この初期値は使われない
|
---|
2492 | # export されている、いないに関わらず、初期化されていることが保証される
|
---|
2493 | elsif @join_list.get_item( a.get_name ) then # セルで初期化されている
|
---|
2494 | b_init = true
|
---|
2495 | elsif @in_composite && @compositecelltypejoin_list then
|
---|
2496 | # 属性が export されているか調べる。export されていれば未初期化とはしない
|
---|
2497 | # mikan リニアサーチ
|
---|
2498 | @compositecelltypejoin_list.get_items.each{ |cj|
|
---|
2499 | # 属性名と composite の export する名前は一致するか
|
---|
2500 | if a.get_name.to_sym == cj.get_cell_elem_name.to_sym then
|
---|
2501 | b_init = true # 属性は export されているので、とりあえず未初期化とはしない
|
---|
2502 | end
|
---|
2503 | }
|
---|
2504 | if b_init then
|
---|
2505 | # size_is の引数がマッチするかチェックする
|
---|
2506 | # 内部セルの size_is をエクスポートする size_is とマッチするかチェックする
|
---|
2507 | # 内部セルとエクスポートで名前を変えている可能性があるので、内部セルの size_is の名前を変換した上でチェックする
|
---|
2508 | if a.get_size_is then
|
---|
2509 | ### p "attr: get_size_is"
|
---|
2510 | cj = @compositecelltypejoin_list.get_item a.get_name.to_sym
|
---|
2511 | if cj.get_port_decl.instance_of? Decl then
|
---|
2512 | ### p "attr: get_size_is 2"
|
---|
2513 | # cj_size_is は、外部公開される attr の size_is
|
---|
2514 | cj_size_is = cj.get_port_decl.get_size_is
|
---|
2515 | if cj_size_is == nil then
|
---|
2516 | cdl_error( "S1170 \'$1\' has size_is but export attr \'$2\' doesn't have", a.get_name, cj.get_name )
|
---|
2517 | end
|
---|
2518 | exprs = a.get_size_is.to_s
|
---|
2519 | ### p "exprs : ", exprs
|
---|
2520 | remain = exprs
|
---|
2521 | inner_to_export = {}
|
---|
2522 | ### exprs に含まれる識別子を抜き出し、対応する export される名前を探す
|
---|
2523 | while remain != "" && remain != nil
|
---|
2524 | ### p "remain ", remain
|
---|
2525 | remain =~ /([^\w]*)([_A-Za-z][\w\d]*)/ # 変数名文字列を取り出す
|
---|
2526 | if $2 == nil then
|
---|
2527 | break
|
---|
2528 | end
|
---|
2529 | arg_name = $2.to_sym
|
---|
2530 | remain = $'
|
---|
2531 | ### p exprs, $1, $2, $'
|
---|
2532 | # size_is に含まれる変数は、composite で export されているか
|
---|
2533 | cj2 = nil
|
---|
2534 | @compositecelltypejoin_list.get_items.each{ |cj2t|
|
---|
2535 | if cj2t.get_cell_elem_name == arg_name then
|
---|
2536 | cj2 = cj2t
|
---|
2537 | end
|
---|
2538 | }
|
---|
2539 | if cj2 == nil then
|
---|
2540 | cdl_error( "S1171 \'$1\' size_is argument of \'$2\' not exported", a.get_name, cj.get_name )
|
---|
2541 | next
|
---|
2542 | end
|
---|
2543 | if cj2.get_port_decl.instance_of? Decl then
|
---|
2544 | decl2 = cj2.get_port_decl
|
---|
2545 | # 内部の名前と外部の名前の対応関係を記憶
|
---|
2546 | inner_to_export[arg_name] = decl2.get_name
|
---|
2547 | # else cj2 は Port (既にエラー)
|
---|
2548 | end
|
---|
2549 | end
|
---|
2550 | # 内部の名前を外部の名前で置換
|
---|
2551 | inner_to_export.each{ |arg_name, exp_name|
|
---|
2552 | ### p "changing #{arg_name}=>#{exp_name}"
|
---|
2553 | # exprs.gsub!( Regexp.new("#{arg_name}[^0-9A-Za-z_]"), exp_name.to_s )
|
---|
2554 | exprs.gsub!( Regexp.new("#{arg_name}(\\W)"), exp_name.to_s+"\\1" ) # 文字列末尾にないケース
|
---|
2555 | exprs.gsub!( Regexp.new("#{arg_name}\\Z"), exp_name.to_s ) # 文字列末尾にあるケース
|
---|
2556 | }
|
---|
2557 | ### p "changed: #{exprs} #{cj_size_is.to_s}"
|
---|
2558 | if exprs != cj_size_is.to_s then
|
---|
2559 | cdl_error( "S1172 \'$1\' size_is argument mismatch with exporting one \'$2\'", a.get_name, cj.get_name )
|
---|
2560 | end
|
---|
2561 | # else cj は Port (既にエラー)
|
---|
2562 | end
|
---|
2563 | end
|
---|
2564 | end
|
---|
2565 | end
|
---|
2566 |
|
---|
2567 | if b_init == false then
|
---|
2568 | cdl_error( "S1052 attribute \'$1\' not initialized in cell \'$2\'" , a.get_name, @name )
|
---|
2569 | end
|
---|
2570 |
|
---|
2571 | }
|
---|
2572 | end
|
---|
2573 |
|
---|
2574 | #=== Cell# 逆 require をチェックする
|
---|
2575 | # 逆 require 指定された受け口に複数の結合がないかチェックする
|
---|
2576 | # composite の内部セル (f_cloned=true) もチェックする
|
---|
2577 | def check_reverse_require
|
---|
2578 | # celltype がなければチェックしない(既にエラー)
|
---|
2579 | return if @celltype == nil
|
---|
2580 | return if @b_defined == false
|
---|
2581 |
|
---|
2582 | # p "check reverse require #{@name}"
|
---|
2583 | # 逆require 指定された受け口に複数の結合がないかチェック
|
---|
2584 | @referenced_port_list.each{ |port,count|
|
---|
2585 | # p port.class, count
|
---|
2586 | # p port.get_name, port.get_port_type, port.get_signature.get_name
|
---|
2587 | if port.is_reverse_required? && count > 1 then
|
---|
2588 | cdl_warning( "W1009 $1: fixed join entry port has multi join", port.get_name )
|
---|
2589 | end
|
---|
2590 | }
|
---|
2591 | end
|
---|
2592 |
|
---|
2593 | #=== Cell# require 呼び口の結合を行う
|
---|
2594 | # STAGE: S
|
---|
2595 | #cp_name:: Symbol : 呼び口名
|
---|
2596 | #cell_or_t:: Celltype|Cell : celltype の require の右辺で指定されたセルタイプまたはセル
|
---|
2597 | #port:: Port : celltype の Port オブジェクト
|
---|
2598 | def set_require_join( cp_name, cell_or_ct, port )
|
---|
2599 |
|
---|
2600 | # set_require_join は2度呼び出される
|
---|
2601 | # 2度目は post コードを生成した後 ##### いったん見合わせ(重複エラーを見逃す)
|
---|
2602 | # if @require_joined_list[ cp_name ] then
|
---|
2603 | # return
|
---|
2604 | # else
|
---|
2605 | # @require_joined_list[ cp_name ] = true
|
---|
2606 | # end
|
---|
2607 |
|
---|
2608 | dbgPrint "set_require_join: #{@name}.#{cp_name} = #{cell_or_ct.get_name}.#{port.get_name}\n"
|
---|
2609 |
|
---|
2610 | if cell_or_ct.instance_of? Celltype then
|
---|
2611 | # print "DOMAIN: not considered\n"
|
---|
2612 | cell = cell_or_ct.get_singleton_cell @region
|
---|
2613 | if cell == nil then
|
---|
2614 | cdl_error( "S1025 not found reachable cell for require \'$1\' in celltype \'$2\'" , port.get_name, cell_or_ct.get_name )
|
---|
2615 | return
|
---|
2616 | end
|
---|
2617 | else
|
---|
2618 | # require: cell で指定
|
---|
2619 | cell = cell_or_ct
|
---|
2620 | if @region.distance( cell.get_region ) == nil then
|
---|
2621 | cdl_error( "S1026 required cell \'$1\' not reachable" , cell.get_name )
|
---|
2622 | end
|
---|
2623 | end
|
---|
2624 |
|
---|
2625 | if @join_list.get_item( cp_name ) then
|
---|
2626 | cdl_warning( "W1003 $1 : require call port overridden in $2" , cp_name, @name )
|
---|
2627 | else
|
---|
2628 | # require の join を生成(呼び口の結合)
|
---|
2629 | # rhs = Expression.new( [ :OP_DOT, [ :IDENTIFIER, Token.new( cell.get_name, nil, nil, nil ) ],
|
---|
2630 | nsp = NamespacePath.new( cell.get_name, false, cell.get_namespace )
|
---|
2631 | nsp.set_locale @locale
|
---|
2632 | rhs = Expression.new( [ :OP_DOT, [ :IDENTIFIER, nsp ],
|
---|
2633 | Token.new( port.get_name, nil, nil, nil ) ], @locale ) #1
|
---|
2634 | join = Join.new( cp_name, nil, rhs, @locale )
|
---|
2635 | self.new_join( join )
|
---|
2636 |
|
---|
2637 | join.set_definition( @celltype.find(join.get_name) )
|
---|
2638 | end
|
---|
2639 | end
|
---|
2640 |
|
---|
2641 | #=== Cell# Join の definition の設定とチェック
|
---|
2642 | # STAGE: S
|
---|
2643 | def set_definition_join
|
---|
2644 | return if @celltype == nil # 既にエラー:打ち切る
|
---|
2645 | return if @b_defined == false # プロトタイプ宣言のみ
|
---|
2646 | return if @b_checked == true # 既に設定(チェック)済み
|
---|
2647 |
|
---|
2648 | dbgPrint "set_definition_join in #{@name}\n"
|
---|
2649 |
|
---|
2650 | # relay allocator をたどって再入しないよう、先頭で @b_checked を true にする
|
---|
2651 | @b_checked = true
|
---|
2652 |
|
---|
2653 | if ! @f_cloned then
|
---|
2654 | check_restrict_list
|
---|
2655 |
|
---|
2656 | # compoiste セルのクローンされたものは、set_definition 不要
|
---|
2657 | # 元の join は既に definition されている
|
---|
2658 | # 元のセルにおいて、代入チェックされているので、二重にチェック(through適用)されてしまう
|
---|
2659 | @join_list.get_items.each{ |join|
|
---|
2660 | dbgPrint " set_definition_join: checking #{@name}.#{join.get_name}\n"
|
---|
2661 | if join.get_array_member then
|
---|
2662 | port = @celltype.find(join.get_name)
|
---|
2663 | join.get_array_member2.each { |am|
|
---|
2664 | if am == nil then # 未結合の場合、エラーチェックは check_join
|
---|
2665 | if port && ! port.is_optional? then
|
---|
2666 | # テスト用にエラーメッセージ出力
|
---|
2667 | # cdl_error( "TEMPORAL set_definition_join: uninitialized array member" )
|
---|
2668 | end
|
---|
2669 | next
|
---|
2670 | end
|
---|
2671 | am.set_definition( port )
|
---|
2672 | }
|
---|
2673 | else
|
---|
2674 | join.set_definition( @celltype.find(join.get_name) )
|
---|
2675 | end
|
---|
2676 | }
|
---|
2677 | end
|
---|
2678 |
|
---|
2679 | # リレー join は through プラグイン生成後にしかできない
|
---|
2680 | # through 後に結合先が入れ替えられる
|
---|
2681 | create_relay_allocator_join
|
---|
2682 |
|
---|
2683 | # composite セルの展開
|
---|
2684 | if ! @in_composite && ! @f_cloned && @celltype.instance_of?( CompositeCelltype ) then
|
---|
2685 | # composite セルタイプ内の composite は展開しない
|
---|
2686 | # compoiste セル展開中の composite は展開しない (CompositeCelltype::expand 内で再帰的に expnad)
|
---|
2687 | expand
|
---|
2688 | end
|
---|
2689 |
|
---|
2690 | # celltype に generate が指定されされているか
|
---|
2691 | celltype_plugin = @celltype.get_celltype_plugin
|
---|
2692 | if celltype_plugin then
|
---|
2693 | begin
|
---|
2694 | celltype_plugin.new_cell self
|
---|
2695 | rescue Exception => evar
|
---|
2696 | cdl_error( "S1037 $1: celltype plugin fail to new_cell" , celltype_plugin.class.name )
|
---|
2697 | print_exception( evar )
|
---|
2698 | end
|
---|
2699 | end
|
---|
2700 | end
|
---|
2701 |
|
---|
2702 | #=== Cell# composite セルの展開
|
---|
2703 | # このセルが composite セルタイプ
|
---|
2704 | def expand
|
---|
2705 |
|
---|
2706 | #debug
|
---|
2707 | dbgPrint "expanding #{@name} #{@celltype.get_name}\n"
|
---|
2708 |
|
---|
2709 | # 展開されたセルのリスト
|
---|
2710 | @@cloned_cell_list = {}
|
---|
2711 |
|
---|
2712 | # composite celltype の cell を展開
|
---|
2713 | @cell_list, @cell_list2 = @celltype.expand( @name, @global_name, @NamespacePath, @join_list, @region, @plugin, @locale )
|
---|
2714 |
|
---|
2715 | # プロトタイプが参照されている場合、子も参照されていることにする
|
---|
2716 | if @f_ref then
|
---|
2717 | dbgPrint "expand: set_f_ref\n"
|
---|
2718 | set_f_ref
|
---|
2719 | end
|
---|
2720 |
|
---|
2721 | # 呼び口の右辺のセルを clone したものに変更
|
---|
2722 | self.change_rhs_port
|
---|
2723 |
|
---|
2724 | # プロトタイプ宣言で設定されていたものを反映する
|
---|
2725 | @entry_array_max_subscript.each{ |port,name|
|
---|
2726 | set_entry_inner_port_max_subscript( port, name )
|
---|
2727 | }
|
---|
2728 | end
|
---|
2729 |
|
---|
2730 | #=== Cell#restrict を追加
|
---|
2731 | def add_restrict( entry_name, func_name, region_name_list )
|
---|
2732 | if @restrict_list[ entry_name ] then
|
---|
2733 | if @restrict_list[ entry_name ][ func_name ] then
|
---|
2734 | @restrict_list[ entry_name ][ func_name ].each{ |rn|
|
---|
2735 | if region_name_list.include? rn then
|
---|
2736 | # p func_name
|
---|
2737 | name = func_name ? entry_name : entry_name+"."+func_name
|
---|
2738 | cdl_warning( "W9999 $1 restrict region duplicate $2", name, rn )
|
---|
2739 | end
|
---|
2740 | }
|
---|
2741 | else
|
---|
2742 | @restrict_list[ entry_name ][ func_name ] = region_name_list
|
---|
2743 | end
|
---|
2744 | else
|
---|
2745 | func_list = { }
|
---|
2746 | func_list[ func_name ] = region_name_list
|
---|
2747 | @restrict_list[ entry_name ] = func_list
|
---|
2748 | end
|
---|
2749 | # pp @restrict_list
|
---|
2750 | end
|
---|
2751 |
|
---|
2752 | #=== Cell#check_restrict_list
|
---|
2753 | def check_restrict_list
|
---|
2754 | @restrict_list.each{ |entry_name, func_hash|
|
---|
2755 | func_hash.each{ |func_name, region_list|
|
---|
2756 | region_list.each{ |rn|
|
---|
2757 | obj = Namespace.find [ rn ]
|
---|
2758 | if ( obj.kind_of? Region ) then
|
---|
2759 | if obj.get_domain_root != @region.get_domain_root then
|
---|
2760 | else
|
---|
2761 | cdl_warning( "W9999 $1 in same domain", rn )
|
---|
2762 | end
|
---|
2763 | else
|
---|
2764 | cdl_error( "S9999 $1 not region", region )
|
---|
2765 | end
|
---|
2766 | }
|
---|
2767 | }
|
---|
2768 | }
|
---|
2769 | end
|
---|
2770 |
|
---|
2771 | #=== Cell#callable?
|
---|
2772 | def callable?( callee_cell, entry_name, func_name )
|
---|
2773 | res = callee_cell.callable_from?( entry_name, func_name, self )
|
---|
2774 | dbgPrint "callable? #{callee_cell.get_namespace_path}.#{entry_name}.#{func_name} from #{@NamespacePath} is #{res}\n"
|
---|
2775 | return res
|
---|
2776 | end
|
---|
2777 |
|
---|
2778 | #=== Cell#callable_from? (private)
|
---|
2779 | def callable_from?( entry_name, func_name, caller_cell )
|
---|
2780 | if @restrict_list.length == 0 then
|
---|
2781 | return true
|
---|
2782 | end
|
---|
2783 |
|
---|
2784 | if @restrict_list[entry_name] then
|
---|
2785 | if @restrict_list[entry_name][nil] &&
|
---|
2786 | @restrict_list[entry_name][nil].include?( caller_cell.get_region.get_domain_root.get_name )then
|
---|
2787 | return true
|
---|
2788 | end
|
---|
2789 | if @restrict_list[entry_name][func_name] &&
|
---|
2790 | @restrict_list[entry_name][func_name].include?( caller_cell.get_region.get_domain_root.get_name )then
|
---|
2791 | return true
|
---|
2792 | else
|
---|
2793 | return false
|
---|
2794 | end
|
---|
2795 | else
|
---|
2796 | return true
|
---|
2797 | end
|
---|
2798 | end
|
---|
2799 |
|
---|
2800 | def show_tree( indent )
|
---|
2801 | indent.times { print " " }
|
---|
2802 | puts "Cell: name: #{@name} in_composite: #{@in_composite} def: #{@b_defined} ref: #{@f_ref} cloned: #{@f_cloned}"
|
---|
2803 | (indent+1).times { print " " }
|
---|
2804 | puts "Cell locale: #{@name}@#{@locale[0]}##{@locale[1]}"
|
---|
2805 | (indent+1).times { print " " }
|
---|
2806 | puts "id: #{@id} global_name: #{@global_name} region: #{@region.get_name} plugin: #{@plugin.class.name} #{self}"
|
---|
2807 | (indent+1).times { print " " }
|
---|
2808 | puts "namespace_path: #{@NamespacePath}"
|
---|
2809 |
|
---|
2810 | if @celltype then
|
---|
2811 | (indent+1).times { print " " }
|
---|
2812 | puts "celltype: #{@celltype.get_name}"
|
---|
2813 | end
|
---|
2814 | @join_list.show_tree( indent + 1 )
|
---|
2815 | @entry_array_max_subscript.each{ |port, num|
|
---|
2816 | (indent+1).times { print " " }
|
---|
2817 | puts "entry array #{port.get_name}: max subscript=#{num}"
|
---|
2818 | }
|
---|
2819 | if @cell_list then # ここで @cell_list が nil なのは Bug
|
---|
2820 | (indent+1).times { print " " }
|
---|
2821 | puts "cloned cell list:"
|
---|
2822 | @cell_list.each { |n,c|
|
---|
2823 | (indent+2).times { print " " }
|
---|
2824 | puts "inner cell : #{n} = #{c.get_name}"
|
---|
2825 | }
|
---|
2826 | end
|
---|
2827 | if @compositecelltypejoin_list then
|
---|
2828 | @compositecelltypejoin_list.get_items.each{ |cj|
|
---|
2829 | cj.show_tree( indent+1 )
|
---|
2830 | }
|
---|
2831 | end
|
---|
2832 | if @alloc_list.length > 0 then
|
---|
2833 | (indent+1).times { print " " }
|
---|
2834 | puts "allocator list: "
|
---|
2835 | @alloc_list.each { |a|
|
---|
2836 | cp_name = :"#{a[0+1]}_#{a[2+1]}_#{a[3+1]}"
|
---|
2837 | if a[1+1] then
|
---|
2838 | # subscript = "[#{a[1+1].eval_const nil}]"
|
---|
2839 | subscript = "[#{a[1+1]}]"
|
---|
2840 | else
|
---|
2841 | subscript = ""
|
---|
2842 | end
|
---|
2843 | # アロケータ呼び口の結合を生成
|
---|
2844 | (indent+2).times { print " " }
|
---|
2845 | puts "#{cp_name}#{subscript} = #{a[4+1]}"
|
---|
2846 | }
|
---|
2847 | end
|
---|
2848 | @referenced_port_list.each{ |port,count|
|
---|
2849 | (indent+1).times { print " " }
|
---|
2850 | puts( "#{port.get_name} : #{count} times referenced" )
|
---|
2851 | }
|
---|
2852 | end
|
---|
2853 |
|
---|
2854 | end
|
---|
2855 |
|
---|
2856 | class CompositeCelltype < NSBDNode # < Nestable
|
---|
2857 | # @name:: str
|
---|
2858 | # @global_name:: str
|
---|
2859 | # @cell_list:: NamedList Cell
|
---|
2860 | # @export_name_list:: NamedList : CompositeCelltypeJoin
|
---|
2861 | # @port_list:: CompositeCelltypeJoin[]
|
---|
2862 | # @attr_list:: CompositeCelltypeJoin[]
|
---|
2863 | # @b_singleton:: bool : 'singleton' specified
|
---|
2864 | # @b_active:: bool : 'active' specified
|
---|
2865 | # @real_singleton:: bool : has singleton cell in this composite celltype
|
---|
2866 | # @real_active:: bool : has active cell in this composite celltype
|
---|
2867 | # @name_list:: NamedList item: Decl (attribute), Port エクスポート定義
|
---|
2868 | # @internal_allocator_list:: [ [cell, internal_cp_name, port_name, func_name, param_name, ext_alloc_ent], ... ]
|
---|
2869 |
|
---|
2870 | @@nest_stack_index = -1
|
---|
2871 | @@nest_stack = []
|
---|
2872 | @@current_object = nil
|
---|
2873 |
|
---|
2874 | def self.push
|
---|
2875 | @@nest_stack_index += 1
|
---|
2876 | @@nest_stack[ @@nest_stack_index ] = @@current_object
|
---|
2877 | @@current_object = nil
|
---|
2878 | end
|
---|
2879 |
|
---|
2880 | def self.pop
|
---|
2881 | @@current_object = @@nest_stack[ @@nest_stack_index ]
|
---|
2882 | @@nest_stack_index -= 1
|
---|
2883 | if @@nest_stack_index < -1 then
|
---|
2884 | raise "TooManyRestore"
|
---|
2885 | end
|
---|
2886 | end
|
---|
2887 |
|
---|
2888 | def initialize( name )
|
---|
2889 | super()
|
---|
2890 | @name = name
|
---|
2891 | @cell_list = NamedList.new( nil, "in composite celltype #{name}" )
|
---|
2892 | @export_name_list = NamedList.new( nil, "export in composite celltype #{name}" )
|
---|
2893 | @name_list = NamedList.new( nil, "in composite celltype #{name}" )
|
---|
2894 | @@current_object = self
|
---|
2895 |
|
---|
2896 | @b_singleton = false
|
---|
2897 | @real_singleton = nil
|
---|
2898 | @b_active = false
|
---|
2899 | @real_active = nil
|
---|
2900 | if "#{Namespace.get_global_name}" == "" then
|
---|
2901 | @global_name = @name
|
---|
2902 | else
|
---|
2903 | @global_name = :"#{Namespace.get_global_name}_#{@name}"
|
---|
2904 | end
|
---|
2905 |
|
---|
2906 | Namespace.new_compositecelltype( self )
|
---|
2907 | set_namespace_path # @NamespacePath の設定
|
---|
2908 |
|
---|
2909 | @port_list = []
|
---|
2910 | @attr_list = []
|
---|
2911 | @internal_allocator_list = []
|
---|
2912 | set_specifier_list( Generator.get_statement_specifier )
|
---|
2913 | end
|
---|
2914 |
|
---|
2915 | def self.end_of_parse
|
---|
2916 | @@current_object.end_of_parse
|
---|
2917 | @@current_object = nil
|
---|
2918 | end
|
---|
2919 |
|
---|
2920 | # CompositeCelltype#end_of_parse
|
---|
2921 | def end_of_parse
|
---|
2922 |
|
---|
2923 | # singleton に関するチェック
|
---|
2924 | if @b_singleton && @real_singleton == nil then
|
---|
2925 | cdl_warning( "W1004 $1 : specified singleton but has no singleton in this celltype" , @name )
|
---|
2926 | elsif ! @b_singleton && @real_singleton != nil then
|
---|
2927 | if ! @b_singleton then
|
---|
2928 | cdl_error( "S1053 $1 must be singleton. inner cell \'$2\' is singleton" , @name, @real_singleton.get_name )
|
---|
2929 | end
|
---|
2930 | end
|
---|
2931 |
|
---|
2932 | # active に関するチェック
|
---|
2933 | if @b_active && @real_active == nil then
|
---|
2934 | cdl_error( "S1054 $1 : specified active but has no active in this celltype" , @name )
|
---|
2935 | elsif ! @b_active && @real_active != nil then
|
---|
2936 | cdl_error( "S1055 $1 must be active. inner cell \'$2\' is active" , @name, @real_active.get_name )
|
---|
2937 | end
|
---|
2938 |
|
---|
2939 | # @allocator_instance を設定する
|
---|
2940 | @name_list.get_items.each{ |n|
|
---|
2941 | if n.instance_of? Port then
|
---|
2942 | n.set_allocator_instance
|
---|
2943 | end
|
---|
2944 | }
|
---|
2945 |
|
---|
2946 | # リレーアロケータの entry 側
|
---|
2947 | @port_list.each{ |p|
|
---|
2948 | if p.get_port_type == :ENTRY then
|
---|
2949 | if p.get_allocator_instance == nil then
|
---|
2950 | next
|
---|
2951 | end
|
---|
2952 |
|
---|
2953 | p.get_allocator_instance.each{ |name,ai|
|
---|
2954 | if ai[0] == :RELAY_ALLOC then
|
---|
2955 | self.new_join( :"#{p.get_name}_#{ai[4]}_#{ai[5]}", p.get_cell_name, :"#{p.get_cell_elem_name}_#{ai[4]}_#{ai[5]}", :CALL )
|
---|
2956 | end
|
---|
2957 | }
|
---|
2958 | end
|
---|
2959 | }
|
---|
2960 | # mikan relay が正しく抜けているかチェックされていない
|
---|
2961 |
|
---|
2962 | # 意味解析
|
---|
2963 | @cell_list.get_items.each{ |c|
|
---|
2964 | c.set_definition_join
|
---|
2965 | }
|
---|
2966 |
|
---|
2967 | # cell の未結合の呼び口がないかチェック
|
---|
2968 | @cell_list.get_items.each{ |c|
|
---|
2969 | c.check_join
|
---|
2970 | c.check_reverse_require
|
---|
2971 | }
|
---|
2972 |
|
---|
2973 | # 呼び口の結合について、export と内部結合の両方がないかチェック
|
---|
2974 | # リレーアロケータ、内部アロケータの設定
|
---|
2975 | @port_list.each{ |p|
|
---|
2976 | p.check_dup_init
|
---|
2977 | }
|
---|
2978 |
|
---|
2979 | # すべてのエクスポート定義に対応した呼び口、受け口、属性が存在するかチェック
|
---|
2980 | @name_list.get_items.each{ |n|
|
---|
2981 | if( @export_name_list.get_item( n.get_name ) == nil )then
|
---|
2982 | cdl_error( "S1056 $1 : cannot export, nothing designated" , n.get_name )
|
---|
2983 | end
|
---|
2984 | }
|
---|
2985 |
|
---|
2986 | # 内部アロケータを設定する
|
---|
2987 | @internal_allocator_list.each{ |cell, cp_internal_name, port_name, fd_name, par_name, ext_alloc_ent|
|
---|
2988 | res = ext_alloc_ent.get_allocator_rhs_elements( :INTERNAL_ALLOC )
|
---|
2989 | ep_name = res[0]
|
---|
2990 | cj = @export_name_list.get_item( ep_name )
|
---|
2991 | internal_alloc_name_from_port_def = cj.get_cell_name
|
---|
2992 | internal_alloc_ep_name_from_port_def = cj.get_cell_elem_name
|
---|
2993 |
|
---|
2994 | # puts "internal_allocator #{cell.get_name} #{cp_internal_name} #{port_name}.#{fd_name}.#{par_name}"
|
---|
2995 | cell.get_allocator_list.each{ |a|
|
---|
2996 | # puts "allocator_list of #{cell.get_name} #{a[0]} #{a[1]}.#{a[2]}.#{a[3]}.#{a[4]} #{a[5].to_s}"
|
---|
2997 | if cp_internal_name == :"#{a[1]}_#{a[3]}_#{a[4]}" then
|
---|
2998 | dbgPrint "internal_allocator {cp_internal_name} #{a[1]}_#{a[3]}_#{a[4]}\n"
|
---|
2999 | dbgPrint "internal_allocator: #{a[5]}, #{internal_alloc_name_from_port_def}.#{internal_alloc_ep_name_from_port_def}\n"
|
---|
3000 | if a[5].to_s != "#{internal_alloc_name_from_port_def}.#{internal_alloc_ep_name_from_port_def}" then
|
---|
3001 | cdl_error( "S1173 $1: allocator mismatch from $2's allocator", "#{port_name}.#{fd_name}.#{par_name}", cell.get_name )
|
---|
3002 | end
|
---|
3003 | end
|
---|
3004 | }
|
---|
3005 | }
|
---|
3006 | end
|
---|
3007 |
|
---|
3008 | ### cell (CompositeCelltype)
|
---|
3009 | def self.new_cell( cell )
|
---|
3010 | @@current_object.new_cell( cell )
|
---|
3011 |
|
---|
3012 | end
|
---|
3013 |
|
---|
3014 | def new_cell( cell )
|
---|
3015 | cell.set_owner self # Cell (in_omposite)
|
---|
3016 | @cell_list.add_item( cell )
|
---|
3017 | if cell.get_celltype then # nil ならば、すでにセルタイプなしエラー
|
---|
3018 | if cell.get_celltype.is_singleton? then
|
---|
3019 | @real_singleton = cell
|
---|
3020 | end
|
---|
3021 | if cell.get_celltype.is_active? then
|
---|
3022 | @real_active = cell
|
---|
3023 | end
|
---|
3024 | end
|
---|
3025 | end
|
---|
3026 |
|
---|
3027 | ### join
|
---|
3028 | def self.new_join( export_name, internal_cell_name,
|
---|
3029 | internal_cell_elem_name, type )
|
---|
3030 | @@current_object.new_join( export_name, internal_cell_name,
|
---|
3031 | internal_cell_elem_name, type )
|
---|
3032 |
|
---|
3033 | end
|
---|
3034 |
|
---|
3035 | #=== CompositeCelltype# CompositeCelltypeJoin を作成
|
---|
3036 | # STAGE: B
|
---|
3037 | #export_name:: Symbol : 外部に公開する名前
|
---|
3038 | #internal_cell_name:: Symbol : 内部セル名
|
---|
3039 | #internal_cell_elem_name:: Symbol : 内部セルの要素名(呼び口名、受け口名、属性名のいずれか)
|
---|
3040 | #type:: :CALL, :ENTRY, :ATTRIBUTE のいずれか(構文要素としてあるべきもの)
|
---|
3041 | #RETURN:: Decl | Port : エクスポート定義
|
---|
3042 | # new_join は
|
---|
3043 | # cCall => composite.cCall; (セル内)
|
---|
3044 | # attr = composite.attr; (セル内)
|
---|
3045 | # composite.eEnt => cell2.eEnt; (セル外)
|
---|
3046 | # の構文要素の出現に対して呼び出される
|
---|
3047 | def new_join( export_name, internal_cell_name,
|
---|
3048 | internal_cell_elem_name, type )
|
---|
3049 |
|
---|
3050 | dbgPrint "new_join: #{export_name} #{internal_cell_name} #{internal_cell_elem_name}\n"
|
---|
3051 |
|
---|
3052 | cell = @cell_list.get_item( internal_cell_name )
|
---|
3053 | if cell == nil then
|
---|
3054 | cdl_error( "S1057 $1 not found in $2" , internal_cell_name, @name )
|
---|
3055 | return
|
---|
3056 | end
|
---|
3057 |
|
---|
3058 | celltype = cell.get_celltype
|
---|
3059 | return if celltype == nil # celltype == nil ならすでにエラー
|
---|
3060 |
|
---|
3061 | # 内部セルのセルタイプから対応要素を探す
|
---|
3062 | # このメソッドは、構文上、呼び口、受け口、属性が記述できる箇所から呼出される
|
---|
3063 | # 構文上の呼出し位置(記述位置)と、要素が対応したものかチェック
|
---|
3064 | obj = celltype.find( internal_cell_elem_name )
|
---|
3065 | if obj.instance_of?( Decl ) then
|
---|
3066 | if obj.get_kind == :VAR then
|
---|
3067 | cdl_error( "S1058 \'$1\' : cannot export var" , internal_cell_elem_name )
|
---|
3068 | return
|
---|
3069 | elsif type != :ATTRIBUTE then
|
---|
3070 | cdl_error( "S1059 \'$1\' : exporting attribute. write in cell or use \'=\' to export attribute" , export_name )
|
---|
3071 | # return 次のエラーを避けるために処理続行し、付け加えてみる
|
---|
3072 | end
|
---|
3073 | elsif obj.instance_of?( Port ) then
|
---|
3074 | if obj.get_port_type != type then
|
---|
3075 | cdl_error( "S1060 \'$1\' : port type mismatch. $2 type is allowed here." , export_name, type )
|
---|
3076 | # return 次のエラーを避けるために処理続行し、付け加えてみる
|
---|
3077 | end
|
---|
3078 | else
|
---|
3079 | cdl_error( "S1061 \'$1\' : not defined" , internal_cell_elem_name )
|
---|
3080 | dbgPrint "S1061 CompositeCelltypeJoin#new_join: #{export_name} => #{internal_cell_name}.#{internal_cell_elem_name} #{type}\n"
|
---|
3081 | return
|
---|
3082 | end
|
---|
3083 |
|
---|
3084 | # エクスポート定義と一致するかどうかチェック
|
---|
3085 | obj2 = @name_list.get_item( export_name )
|
---|
3086 | if( obj2 == nil )then
|
---|
3087 | cdl_error( "S1062 $1 has no export definition" , export_name )
|
---|
3088 | elsif obj2.instance_of?( Decl ) then
|
---|
3089 | if( ! obj.instance_of? Decl )then
|
---|
3090 | cdl_error( "S1063 $1 is port but previously defined as an attribute" , export_name )
|
---|
3091 | elsif ! obj.get_type.equal? obj2.get_type then
|
---|
3092 | cdl_error( "S1064 $1 : type \'$2$3\' mismatch with pprevious definition\'$4$5\'" , export_name, obj.get_type.get_type_str, obj.get_type.get_type_str_post, obj2.get_type.get_type_str, obj2.get_type.get_type_str_post )
|
---|
3093 | end
|
---|
3094 | elsif obj2.instance_of?( Port ) then
|
---|
3095 | if( obj.instance_of? Port )then
|
---|
3096 | if( obj.get_port_type != obj2.get_port_type )then
|
---|
3097 | cdl_error( "S1065 $1 : port type $2 mismatch with previous definition $3" , export_name, obj.get_port_type, obj2.get_port_type )
|
---|
3098 | elsif obj.get_signature != obj2.get_signature then
|
---|
3099 | if obj.get_signature != nil && obj2.get_signature != nil then
|
---|
3100 | # nil ならば既にエラーなので報告しない
|
---|
3101 | cdl_error( "S1066 $1 : signature \'$2\' mismatch with previous definition \'$3\'" , export_name, obj.get_signature.get_name, obj2.get_signature.get_name )
|
---|
3102 | end
|
---|
3103 | elsif obj.get_array_size != obj2.get_array_size then
|
---|
3104 | cdl_error( "S1067 $1 : array size mismatch with previous definition" , export_name )
|
---|
3105 | elsif obj.is_optional? != obj2.is_optional? then
|
---|
3106 | cdl_error( "S1068 $1 : optional specifier mismatch with previous definition" , export_name )
|
---|
3107 | elsif obj.is_omit? != obj2.is_omit? then
|
---|
3108 | cdl_error( "S9999 $1 : omit specifier mismatch with previous definition" , export_name )
|
---|
3109 | end
|
---|
3110 | else
|
---|
3111 | cdl_error( "S1069 $1 is an attribute but previously defined as a port" , export_name )
|
---|
3112 | end
|
---|
3113 | end
|
---|
3114 |
|
---|
3115 | join = CompositeCelltypeJoin.new( export_name, internal_cell_name,
|
---|
3116 | internal_cell_elem_name, cell, obj2 )
|
---|
3117 | join.set_owner self # CompositeCelltypeJoin
|
---|
3118 | cell.add_compositecelltypejoin join
|
---|
3119 |
|
---|
3120 | # debug
|
---|
3121 | dbgPrint "compositecelltype join: add #{cell.get_name} #{export_name} = #{internal_cell_name}.#{internal_cell_elem_name}\n"
|
---|
3122 |
|
---|
3123 | if obj.instance_of?( Decl ) then
|
---|
3124 | # attribute
|
---|
3125 | # # 内部から外部へ複数の結合がないかチェック
|
---|
3126 | # found = false
|
---|
3127 | # @attr_list.each{ |a|
|
---|
3128 | # if a.get_name == join.get_name then
|
---|
3129 | # found = true
|
---|
3130 | # break
|
---|
3131 | # end
|
---|
3132 | # }
|
---|
3133 | # if found == false then
|
---|
3134 | @attr_list << join
|
---|
3135 | # end
|
---|
3136 | else
|
---|
3137 | # call/entry port
|
---|
3138 | # # 内部から外部へ複数の結合がないかチェック
|
---|
3139 | # found = false
|
---|
3140 | # @port_list.each{ |port|
|
---|
3141 | # if port.get_name == join.get_name then
|
---|
3142 | # found = true
|
---|
3143 | # break
|
---|
3144 | # end
|
---|
3145 | # }
|
---|
3146 | # if found == false then
|
---|
3147 | @port_list << join
|
---|
3148 | # end
|
---|
3149 | end
|
---|
3150 |
|
---|
3151 | # join を @export_name_list に登録(重複チェックとともに,後で行われる CompositeCelltypeJoin の clone に備える)
|
---|
3152 | if obj.instance_of?( Decl ) && @export_name_list.get_item( export_name ) then
|
---|
3153 | # 既に存在する。追加しない。新仕様では、@export_name_list に同じ名前が含まれることがある。
|
---|
3154 | elsif obj.instance_of?( Port ) && obj.get_port_type == :CALL && @export_name_list.get_item( export_name ) then
|
---|
3155 | # 既に存在する。追加しない。新仕様では、@export_name_list に同じ名前が含まれることがある。
|
---|
3156 | else
|
---|
3157 | @export_name_list.add_item( join )
|
---|
3158 | end
|
---|
3159 |
|
---|
3160 | # export するポートに含まれる send/receive パラメータのアロケータ(allocator)呼び口をセルと結合
|
---|
3161 | if obj2.instance_of? Port then
|
---|
3162 | obj2.each_param{ |port, fd, par|
|
---|
3163 | case par.get_direction # 引数の方向指定子 (in, out, inout, send, receive )
|
---|
3164 | when :SEND, :RECEIVE
|
---|
3165 | cp_name = :"#{port.get_name}_#{fd.get_name}_#{par.get_name}" # アロケータ呼び口の名前
|
---|
3166 | # ポート名 関数名 パラメータ名
|
---|
3167 | cp_internal_name = :"#{internal_cell_elem_name}_#{fd.get_name}_#{par.get_name}"
|
---|
3168 |
|
---|
3169 | # リレーアロケータ or 内部アロケータ指定がなされている場合、アロケータ呼び口を追加しない
|
---|
3170 | # この時点では get_allocator_instance では得られないため tmp を得る
|
---|
3171 | if port.get_allocator_instance_tmp then
|
---|
3172 | found = false
|
---|
3173 | port.get_allocator_instance_tmp.each { |s|
|
---|
3174 | if s[1] == fd.get_name && s[2] == par.get_name then
|
---|
3175 | found = true
|
---|
3176 |
|
---|
3177 | if s[0] == :INTERNAL_ALLOC then
|
---|
3178 | # 内部アロケータの場合 # mikan これは内部のセルに直結する。外部のポートに改めるべき
|
---|
3179 | @internal_allocator_list << [ cell, cp_internal_name, port.get_name, fd.get_name, par.get_name, s[3] ]
|
---|
3180 | end
|
---|
3181 | end
|
---|
3182 | }
|
---|
3183 | if found == true
|
---|
3184 | next
|
---|
3185 | end
|
---|
3186 | end
|
---|
3187 |
|
---|
3188 | # 外部アロケータの場合
|
---|
3189 | new_join( cp_name, internal_cell_name, cp_internal_name, :CALL )
|
---|
3190 | end
|
---|
3191 | }
|
---|
3192 | end
|
---|
3193 |
|
---|
3194 | # エクスポート定義を返す
|
---|
3195 | return obj2
|
---|
3196 | end
|
---|
3197 |
|
---|
3198 | def self.has_attribute? attr
|
---|
3199 | @@current_object.has_attribute? attr
|
---|
3200 | end
|
---|
3201 |
|
---|
3202 | def has_attribute? attr
|
---|
3203 | @name_list.get_item( attr ) != nil
|
---|
3204 | end
|
---|
3205 |
|
---|
3206 | def self.new_port port
|
---|
3207 | @@current_object.new_port port
|
---|
3208 | end
|
---|
3209 |
|
---|
3210 | #=== CompositeCelltype# new_port
|
---|
3211 | def new_port port
|
---|
3212 | port.set_owner self # Port (CompositeCelltype)
|
---|
3213 | dbgPrint "new_port: #{@owner.get_name}.#{port.get_name}\n"
|
---|
3214 | @name_list.add_item port
|
---|
3215 |
|
---|
3216 | # export するポートに含まれる send/receive パラメータのアロケータ呼び口の export を生成してポートに追加
|
---|
3217 | # この時点では内部アロケータかどうか判断できないので、とりあえず生成しておく
|
---|
3218 | port.each_param { |port, fd, par|
|
---|
3219 | case par.get_direction # 引数の方向指定子 (in, out, inout, send, receive )
|
---|
3220 | when :SEND, :RECEIVE
|
---|
3221 | #### リレーアロケータ or 内部アロケータ指定がなされている場合、アロケータ呼び口を追加しない
|
---|
3222 | # 内部アロケータ指定がなされている場合、アロケータ呼び口を追加しない
|
---|
3223 | # この時点では get_allocator_instance では得られないため tmp を得る
|
---|
3224 | if port.get_allocator_instance_tmp then
|
---|
3225 | found = false
|
---|
3226 | port.get_allocator_instance_tmp.each { |s|
|
---|
3227 | if s[0] == :INTERNAL_ALLOC && s[1] == fd.get_name && s[2] == par.get_name then
|
---|
3228 | found = true
|
---|
3229 | break
|
---|
3230 | end
|
---|
3231 | }
|
---|
3232 | if found == true
|
---|
3233 | next
|
---|
3234 | end
|
---|
3235 | end
|
---|
3236 |
|
---|
3237 | if par.get_allocator then
|
---|
3238 | cp_name = :"#{port.get_name}_#{fd.get_name}_#{par.get_name}" # アロケータ呼び口の名前
|
---|
3239 | # ポート名 関数名 パラメータ名
|
---|
3240 | alloc_sig_path = [ par.get_allocator.get_name ] # mikan Namespace アロケータ呼び口のシグニチャ
|
---|
3241 | array_size = port.get_array_size # 呼び口または受け口配列のサイズ
|
---|
3242 | created_port = Port.new( cp_name, alloc_sig_path, :CALL, array_size ) # 呼び口を生成
|
---|
3243 | created_port.set_allocator_port( port, fd, par )
|
---|
3244 | if port.is_omit? then
|
---|
3245 | created_port.set_omit
|
---|
3246 | end
|
---|
3247 | new_port( created_port ) # セルタイプに新しい呼び口を追加
|
---|
3248 | # else
|
---|
3249 | # already error
|
---|
3250 | end
|
---|
3251 | end
|
---|
3252 | }
|
---|
3253 | end
|
---|
3254 |
|
---|
3255 | def self.new_attribute attr
|
---|
3256 | @@current_object.new_attribute attr
|
---|
3257 | end
|
---|
3258 |
|
---|
3259 | #=== CompositeCelltype# new_attribute for CompositeCelltype
|
---|
3260 | #attribute:: [Decl]
|
---|
3261 | def new_attribute( attribute )
|
---|
3262 | attribute.each { |a|
|
---|
3263 | a.set_owner self # Decl (CompositeCelltype)
|
---|
3264 | # V1.1.0.10 composite の attr の size_is は可となった
|
---|
3265 | # if a.get_size_is then
|
---|
3266 | # cdl_error( "S1070 $1: size_is pointer cannot be exposed for composite attribute" , a.get_name )
|
---|
3267 | # end
|
---|
3268 | @name_list.add_item( a )
|
---|
3269 | if a.get_initializer then
|
---|
3270 | a.get_type.check_init( @locale, a.get_identifier, a.get_initializer, :ATTRIBUTE )
|
---|
3271 | end
|
---|
3272 | }
|
---|
3273 | end
|
---|
3274 |
|
---|
3275 | #=== CompositeCelltype# 逆require の結合を生成する
|
---|
3276 | def create_reverse_require_join cell
|
---|
3277 | @name_list.get_items.each{ |n|
|
---|
3278 | if n.instance_of? Port then
|
---|
3279 | n.create_reverse_require_join cell
|
---|
3280 | end
|
---|
3281 | }
|
---|
3282 | end
|
---|
3283 |
|
---|
3284 | # false : if not in celltype definition, nil : if not found in celltype
|
---|
3285 | def self.find( name )
|
---|
3286 | if @@current_object == nil then
|
---|
3287 | return false
|
---|
3288 | end
|
---|
3289 | @@current_object.find name
|
---|
3290 | end
|
---|
3291 |
|
---|
3292 | def find name
|
---|
3293 | dbgPrint "CompositeCelltype: find in composite: #{name}\n"
|
---|
3294 | cell = @cell_list.get_item( name )
|
---|
3295 | return cell if cell
|
---|
3296 |
|
---|
3297 | dbgPrint "CompositeCelltype: #{name}, #{@name_list.get_item( name )}\n"
|
---|
3298 | return @name_list.get_item( name )
|
---|
3299 |
|
---|
3300 | # 従来仕様
|
---|
3301 | # cj = @export_name_list.get_item( name )
|
---|
3302 | #p "#{name}, #{cj.get_port_decl}"
|
---|
3303 | # if cj then
|
---|
3304 | # return cj.get_port_decl
|
---|
3305 | # else
|
---|
3306 | # return nil
|
---|
3307 | # end
|
---|
3308 | end
|
---|
3309 |
|
---|
3310 | #=== CompositeCelltype# export する CompositeCelltypeJoin を得る
|
---|
3311 | #name:: string:
|
---|
3312 | # attribute の場合、同じ名前に対し複数存在する可能性があるが、最初のものしか返さない
|
---|
3313 | def find_export name
|
---|
3314 | return @export_name_list.get_item( name )
|
---|
3315 | end
|
---|
3316 |
|
---|
3317 | #=== CompositeCelltype# composite celltype の cell を展開
|
---|
3318 | #name:: string: Composite cell の名前
|
---|
3319 | #global_name:: string: Composite cell の global name (C 言語名)
|
---|
3320 | #join_list:: NamedList : Composite cell に対する Join の NamedList
|
---|
3321 | #RETURN:
|
---|
3322 | # [ { name => cell }, [ cell, ... ] ]
|
---|
3323 | # 戻り値 前は 名前⇒cloneされた内部セル、後ろは composite の出現順のリスト
|
---|
3324 | def expand( name, global_name, namespacePath, join_list, region, plugin, locale )
|
---|
3325 |
|
---|
3326 | # debug
|
---|
3327 | dbgPrint "expand composite: #{@name} name: #{name} global_name: #{global_name}\njoin_list:\n"
|
---|
3328 | join_list.get_items.each{ |j|
|
---|
3329 | dbgPrint " #{j.get_name} #{j}\n"
|
---|
3330 | }
|
---|
3331 |
|
---|
3332 | # 展開で clone されたセルのリスト、右辺は Cell (composite の場合 composite な cell の clone)
|
---|
3333 | clone_cell_list = {}
|
---|
3334 | clone_cell_list2 = []
|
---|
3335 |
|
---|
3336 | # composite 内部のすべての cell について
|
---|
3337 | @cell_list.get_items.each { |c|
|
---|
3338 |
|
---|
3339 | # debug
|
---|
3340 | dbgPrint "expand : cell #{c.get_name}\n"
|
---|
3341 |
|
---|
3342 | # Join の配列
|
---|
3343 | ja = []
|
---|
3344 |
|
---|
3345 | # CompositeCelltype が export する呼び口、受け口、属性のリストについて
|
---|
3346 | # @export_name_list.get_items.each{ |cj| # cj: CompositeCelltypeJoin
|
---|
3347 | # 新仕様では、@export_name_list に入っていない attr がありうる
|
---|
3348 | (@port_list+@attr_list).each{ |cj| # cj: CompositeCelltypeJoin
|
---|
3349 |
|
---|
3350 | # debug
|
---|
3351 | dbgPrint " cj : #{cj.get_name}\n"
|
---|
3352 |
|
---|
3353 | # CompositeCelltypeJoin (export) の対象セルか?
|
---|
3354 | if cj.match?( c ) then
|
---|
3355 |
|
---|
3356 | # 対象セル内の CompositeCelltype の export する Join (attribute または call port)
|
---|
3357 | j = join_list.get_item( cj.get_name )
|
---|
3358 |
|
---|
3359 | # debug
|
---|
3360 | if j then
|
---|
3361 | dbgPrint "expand : parent cell: #{name} child cell: #{c.get_name}: parent's export port: #{cj.get_name} join: #{j.get_name} #{j}\n"
|
---|
3362 | else
|
---|
3363 | dbgPrint "expand : parent cell: #{name} child cell: #{c.get_name}: parent's export port: #{cj.get_name} join: nil\n"
|
---|
3364 | end
|
---|
3365 |
|
---|
3366 | if j then
|
---|
3367 | # 呼び口、属性の場合
|
---|
3368 | # ComositeCell 用のもの(j) を対象セル用に clone (@through_list もコピーされる)
|
---|
3369 | # p "expand: cloning Join #{j.get_name} #{@name} #{name}"
|
---|
3370 | jc = j.clone_for_composite( @name, name, locale )
|
---|
3371 | # celltype_name, cell_name
|
---|
3372 |
|
---|
3373 | # debug
|
---|
3374 | # p "cn #{jc.get_name} #{cj.get_cell_elem_name}"
|
---|
3375 |
|
---|
3376 | # 対象セルの呼び口または属性の名前に変更
|
---|
3377 | jc.change_name( cj.get_cell_elem_name )
|
---|
3378 |
|
---|
3379 | # 対象セルに対する Join の配列
|
---|
3380 | ja << jc
|
---|
3381 | end
|
---|
3382 |
|
---|
3383 | # debug
|
---|
3384 | dbgPrint "\n"
|
---|
3385 | end
|
---|
3386 | }
|
---|
3387 |
|
---|
3388 | # debug
|
---|
3389 | dbgPrint "expand : clone #{name}_#{c.get_name}\n"
|
---|
3390 |
|
---|
3391 | # セルの clone を生成
|
---|
3392 | # clone_cell_list[ "#{name}_#{c.get_name}" ] = c.clone_for_composite( name, global_name, ja )
|
---|
3393 | c2 = c.clone_for_composite( name, global_name, namespacePath, ja, @name, region, plugin, locale )
|
---|
3394 | clone_cell_list[ "#{c.get_local_name}" ] = c2
|
---|
3395 | clone_cell_list2 << c2
|
---|
3396 |
|
---|
3397 | }
|
---|
3398 |
|
---|
3399 | clone_cell_list.each { |nm,c|
|
---|
3400 | dbgPrint " cloned: #{nm} = #{c.get_global_name}\n"
|
---|
3401 | # join の owner を clone されたセルに変更する V1.1.0.25
|
---|
3402 | c.get_join_list.get_items.each{ |j|
|
---|
3403 | j.set_cloned( clone_cell_list[ "#{c.get_local_name}" ] )
|
---|
3404 | }
|
---|
3405 | }
|
---|
3406 | return [ clone_cell_list, clone_cell_list2 ]
|
---|
3407 | end
|
---|
3408 |
|
---|
3409 | #=== CompositeCelltype 指定子リストの設定
|
---|
3410 | def set_specifier_list( spec_list )
|
---|
3411 | return if spec_list == nil
|
---|
3412 |
|
---|
3413 | spec_list.each { |s|
|
---|
3414 | case s[0]
|
---|
3415 | when :SINGLETON
|
---|
3416 | @b_singleton = true
|
---|
3417 | when :IDX_IS_ID
|
---|
3418 | cdl_warning( "W1005 $1 : idx_is_id is ineffective for composite celltype" , @name )
|
---|
3419 | when :ACTIVE
|
---|
3420 | @b_active = true
|
---|
3421 | else
|
---|
3422 | cdl_error( "S1071 $1 cannot be specified for composite" , s[0] )
|
---|
3423 | end
|
---|
3424 | }
|
---|
3425 | end
|
---|
3426 |
|
---|
3427 | def get_name
|
---|
3428 | @name
|
---|
3429 | end
|
---|
3430 |
|
---|
3431 | def get_port_list
|
---|
3432 | @port_list
|
---|
3433 | end
|
---|
3434 |
|
---|
3435 | def get_attribute_list
|
---|
3436 | @attr_list
|
---|
3437 | end
|
---|
3438 |
|
---|
3439 | def get_var_list
|
---|
3440 | [] # 空の配列を返す
|
---|
3441 | end
|
---|
3442 |
|
---|
3443 | def get_internal_allocator_list
|
---|
3444 | @internal_allocator_list
|
---|
3445 | end
|
---|
3446 |
|
---|
3447 | #== CompositeCelltype# generate 指定子の情報
|
---|
3448 | # CompositeCelltype には generate が指定できないので nil を返す
|
---|
3449 | # Celltype::@generate を参照のこと
|
---|
3450 | def get_celltype_plugin
|
---|
3451 | nil
|
---|
3452 | end
|
---|
3453 |
|
---|
3454 | def is_singleton?
|
---|
3455 | @b_singleton
|
---|
3456 | end
|
---|
3457 |
|
---|
3458 | def is_active?
|
---|
3459 | @b_active
|
---|
3460 | end
|
---|
3461 |
|
---|
3462 | #=== CompositeCelltype# アクティブではない
|
---|
3463 | # active ではないに加え、全ての内部セルのセルタイプが inactive の場合に inactive
|
---|
3464 | # (内部のセルが active または factory を持っている)
|
---|
3465 | def is_inactive?
|
---|
3466 | if @b_active == false then
|
---|
3467 | @cell_list.get_items.each{ |c|
|
---|
3468 | if c.get_celltype && c.get_celltype.is_inactive? == false then
|
---|
3469 | # c.get_celltype == nil の場合はセルタイプ未定義ですでにエラー
|
---|
3470 | return false
|
---|
3471 | end
|
---|
3472 | }
|
---|
3473 | return true
|
---|
3474 | else
|
---|
3475 | return false
|
---|
3476 | end
|
---|
3477 | end
|
---|
3478 |
|
---|
3479 | def get_id_base
|
---|
3480 | raise "get_id_base"
|
---|
3481 | end
|
---|
3482 |
|
---|
3483 | def show_tree( indent )
|
---|
3484 | indent.times { print " " }
|
---|
3485 | puts "CompositeCelltype: name: #{@name}"
|
---|
3486 | (indent+1).times { print " " }
|
---|
3487 | puts "active: #{@b_active}, singleton: #{@b_singleton}"
|
---|
3488 | @cell_list.show_tree( indent + 1 )
|
---|
3489 | (indent+1).times { print " " }
|
---|
3490 | puts "name_list"
|
---|
3491 | @name_list.show_tree( indent + 2 )
|
---|
3492 | (indent+1).times { print " " }
|
---|
3493 | puts "export_name_list"
|
---|
3494 | @export_name_list.show_tree( indent + 2 )
|
---|
3495 | if @internal_allocator_list.length > 0 then
|
---|
3496 | (indent+1).times { print " " }
|
---|
3497 | puts "internal_allocator_list:"
|
---|
3498 | @internal_allocator_list.each{ |a|
|
---|
3499 | (indent+1).times { print " " }
|
---|
3500 | puts " #{a[0].get_name} #{a[1]} #{a[2]} #{a[3]} #{a[4]}"
|
---|
3501 | }
|
---|
3502 | end
|
---|
3503 | end
|
---|
3504 |
|
---|
3505 | end
|
---|
3506 |
|
---|
3507 |
|
---|
3508 |
|
---|
3509 | #== 構文要素:口を表すクラス(セルタイプの呼び口、受け口)
|
---|
3510 | class Port < BDNode
|
---|
3511 | # @name:: str
|
---|
3512 | # @signature:: Signature
|
---|
3513 | # @port_type:: :CALL, :ENTRY
|
---|
3514 | # @array_size:: nil: not array, "[]": sizeless, Integer: sized array
|
---|
3515 | # @reverse_require_cell_path:: NamespacePath : 逆require呼び元セル mikan namespace (呼び口のみ指定可能)
|
---|
3516 | # @reverse_require_callport_name:: Symbol: 逆require呼び元セルの呼び口名
|
---|
3517 | #
|
---|
3518 | # set_allocator_port によって設定される.設定された場合、このポートはアロケータポートである。
|
---|
3519 | # @allocator_port:: Port : この呼び口ができる元となった呼び口または受け口
|
---|
3520 | # @allocator_func_decl:: Decl : この呼び口ができる元となった呼び口または受け口の関数
|
---|
3521 | # @allocator_param_decl:: ParamDecl : この呼び口ができる元となった呼び口または受け口のパラメータ
|
---|
3522 | #
|
---|
3523 | # set_specifier によって設定される(
|
---|
3524 | # @allocator_instance:: Hash : {"func_param" => [ :RELAY_ALLOC, func_name, param_name, rhs_cp_name, rhs_func_name, rhs_param_name ]}
|
---|
3525 | # [:INTERNAL_ALLOC, func_name, param_name, rhs_ep_name ]
|
---|
3526 | # @allocator_instance_tmp:: Hash : {"func_param" => [:INTERNAL_ALLOC|:RELAY_ALLOC, IDENTIFIER, IDENTIFIER, expression ],..}
|
---|
3527 | # function parameter rhs
|
---|
3528 | #
|
---|
3529 | # @b_require:: bool : require により生成された call port の場合 true
|
---|
3530 | # @b_has_name:: bool : require : 名前ありのリクワイア呼び口
|
---|
3531 | # @b_inline:: bool : entry port のみ
|
---|
3532 | # @b_omit:: bool : omit 指定子が指定された (call port のみ)
|
---|
3533 | # @b_optional:: bool : call port のみ
|
---|
3534 | # @b_ref_des:: bool : ref_desc キーワードが指定された
|
---|
3535 | # @b_dynamic:: bool : dynamic キーワードが指定された (呼び口のみ)
|
---|
3536 | #
|
---|
3537 | # optimize::
|
---|
3538 | # @celltype:: 属するセルタイプ
|
---|
3539 | #
|
---|
3540 | # :CALL の場合の最適化
|
---|
3541 | # @b_VMT_useless:: bool # VMT 関数テーブルを使用しない
|
---|
3542 | # @b_skelton_useless:: bool # スケルトン関数不要 (true の時、受け口関数を呼出す)
|
---|
3543 | # @b_cell_unique:: bool # 呼び先は唯一のセル
|
---|
3544 | # @only_callee_port:: Port # 唯一の呼び先ポート
|
---|
3545 | # @only_callee_cell:: Cell # 唯一の呼び先セル (@b_PEPDES_in_CB_useless = true の時有効)
|
---|
3546 | #
|
---|
3547 | # :ENTRY の場合の最適化(呼び口最適化と同じ変数名を使用)
|
---|
3548 | # @b_VMT_useless:: bool # VMT 関数テーブルが不要
|
---|
3549 | # @b_skelton_useless:: bool # スケルトン関数不要
|
---|
3550 |
|
---|
3551 | def initialize( name, sig_path, port_type, array_size = nil, reverse_require_cell_path = nil, reverse_require_entry_port_name = nil )
|
---|
3552 | super()
|
---|
3553 | @name = name
|
---|
3554 | @port_type = port_type
|
---|
3555 |
|
---|
3556 | if array_size == "[]" then
|
---|
3557 | # if port_type == :ENTRY then
|
---|
3558 | # cdl_error( "S1072 $1: entry port: sizeless array not supported in current version" , name )
|
---|
3559 | # end
|
---|
3560 | @array_size = array_size
|
---|
3561 | elsif array_size then
|
---|
3562 | if array_size.kind_of? Expression then
|
---|
3563 | @array_size = array_size.eval_const(nil)
|
---|
3564 | else
|
---|
3565 | @array_size = array_size # これはアロケータ呼び口の場合(元の呼び口で既に評価済み)
|
---|
3566 | end
|
---|
3567 | if @array_size == nil then
|
---|
3568 | cdl_error( "S1073 Not constant expression $1" , array_size.to_s )
|
---|
3569 | end
|
---|
3570 |
|
---|
3571 | #if Integer( @array_size ) != @array_size || @array_size <= 0 then
|
---|
3572 | if ! @array_size.kind_of? Integer then
|
---|
3573 | cdl_error( "S1074 Not Integer $1" , array_size.to_s )
|
---|
3574 | end
|
---|
3575 |
|
---|
3576 | end
|
---|
3577 |
|
---|
3578 | object = Namespace.find( sig_path ) #1
|
---|
3579 | if object == nil then
|
---|
3580 | # mikan signature の名前が不完全
|
---|
3581 | cdl_error( "S1075 \'$1\' signature not found" , sig_path )
|
---|
3582 | elsif ! object.instance_of?( Signature ) then
|
---|
3583 | # mikan signature の名前が不完全
|
---|
3584 | cdl_error( "S1076 \'$1\' not signature" , sig_path )
|
---|
3585 | else
|
---|
3586 | @signature = object
|
---|
3587 |
|
---|
3588 | end
|
---|
3589 |
|
---|
3590 | # 逆require
|
---|
3591 | @reverse_require_cell_path = nil
|
---|
3592 | @reverse_require_entry_port_name = nil
|
---|
3593 | if reverse_require_cell_path then
|
---|
3594 | if port_type == :CALL then
|
---|
3595 | cdl_error( "S1152 $1 call port cannot have fixed join", @name )
|
---|
3596 | else
|
---|
3597 | @reverse_require_cell_path = reverse_require_cell_path
|
---|
3598 | @reverse_require_entry_port_name = reverse_require_entry_port_name
|
---|
3599 |
|
---|
3600 | # 受け口配列か?
|
---|
3601 | if array_size then
|
---|
3602 | cdl_error( "S1153 $1: cannot be entry port array for fixed join port", @name )
|
---|
3603 | end
|
---|
3604 |
|
---|
3605 | # 呼び口のセルタイプを探す
|
---|
3606 | ct_or_cell = Namespace.find( @reverse_require_cell_path ) #1
|
---|
3607 | if ct_or_cell.instance_of? Cell then
|
---|
3608 | ct = ct_or_cell.get_celltype
|
---|
3609 | elsif ct_or_cell.instance_of? Celltype then
|
---|
3610 | ct = ct_or_cell
|
---|
3611 | if ! ct.is_singleton? then
|
---|
3612 | cdl_error( "S1154 $1: must be singleton celltype for fixed join", @reverse_require_cell_path.to_s )
|
---|
3613 | end
|
---|
3614 | else
|
---|
3615 | ct = nil
|
---|
3616 | cdl_error( "S1155 $1: not celltype or not found", @reverse_require_cell_path.get_path_str)
|
---|
3617 | end
|
---|
3618 |
|
---|
3619 | if ct == nil then
|
---|
3620 | return # 既にエラー
|
---|
3621 | end
|
---|
3622 |
|
---|
3623 | # 添え字なしの呼び口配列か?
|
---|
3624 | port = ct.find( @reverse_require_entry_port_name )
|
---|
3625 | if port == nil || port.get_port_type != :CALL
|
---|
3626 | cdl_error( "S1156 $1: not call port or not found", @reverse_require_entry_port_name )
|
---|
3627 | else
|
---|
3628 | if port.get_array_size != "[]" then
|
---|
3629 | cdl_error( "S1157 $1: sized array or not array", @reverse_require_entry_port_name )
|
---|
3630 | end
|
---|
3631 | end
|
---|
3632 |
|
---|
3633 | end
|
---|
3634 | end
|
---|
3635 |
|
---|
3636 | @b_require = false
|
---|
3637 | @b_has_name = false
|
---|
3638 | @b_inline = false
|
---|
3639 | @b_optional = false
|
---|
3640 | @b_ref_desc = false
|
---|
3641 | @b_dynamic = false
|
---|
3642 | reset_optimize
|
---|
3643 | end
|
---|
3644 |
|
---|
3645 | #=== Port#最適化に関する変数をリセットする
|
---|
3646 | # Region ごとに最適化のやりなおしをするため、リセットする
|
---|
3647 | def reset_optimize
|
---|
3648 | if @port_type == :CALL then
|
---|
3649 | # call port optimize
|
---|
3650 | @b_VMT_useless = false # VMT 不要 (true の時 VMT を介することなく呼出す)
|
---|
3651 | @b_skelton_useless = false # スケルトン関数不要 (true の時、受け口関数を呼出す)
|
---|
3652 | @b_cell_unique = false # 唯一の呼び先セル
|
---|
3653 | @only_callee_port = nil # 唯一の呼び先ポート
|
---|
3654 | @only_callee_cell = nil # 唯一の呼び先セル
|
---|
3655 | else
|
---|
3656 | # entry port optimize
|
---|
3657 | if $unopt then
|
---|
3658 | # 最適化なし
|
---|
3659 | @b_VMT_useless = false # VMT 不要 (true の時 VMT を介することなく呼出す)
|
---|
3660 | @b_skelton_useless = false # スケルトン関数不要 (true の時、受け口関数を呼出す)
|
---|
3661 | else
|
---|
3662 | # 最適化あり
|
---|
3663 | @b_VMT_useless = true # VMT 不要 (true の時 VMT を介することなく呼出す)
|
---|
3664 | @b_skelton_useless = true # スケルトン関数不要 (true の時、受け口関数を呼出す)
|
---|
3665 | end
|
---|
3666 | end
|
---|
3667 | end
|
---|
3668 |
|
---|
3669 | def set_celltype celltype
|
---|
3670 | @celltype = celltype
|
---|
3671 | end
|
---|
3672 |
|
---|
3673 | def get_name
|
---|
3674 | @name
|
---|
3675 | end
|
---|
3676 |
|
---|
3677 | def get_port_type
|
---|
3678 | @port_type
|
---|
3679 | end
|
---|
3680 |
|
---|
3681 | def get_signature
|
---|
3682 | @signature
|
---|
3683 | end
|
---|
3684 |
|
---|
3685 | def get_array_size
|
---|
3686 | @array_size
|
---|
3687 | end
|
---|
3688 |
|
---|
3689 | def get_celltype
|
---|
3690 | @celltype
|
---|
3691 | end
|
---|
3692 |
|
---|
3693 | #=== Port# アロケータポートの設定
|
---|
3694 | #port:: Port : send/receive のあった呼び口または受け口
|
---|
3695 | #fd:: Decl : 関数の declarator
|
---|
3696 | #par:: ParamDecl : send/receive のあった引数
|
---|
3697 | # この呼び口が生成されるもとになった呼び口または受け口の情報を設定
|
---|
3698 | def set_allocator_port( port, fd, par )
|
---|
3699 | @allocator_port = port
|
---|
3700 | @allocator_func_decl = fd
|
---|
3701 | @allocator_param_decl = par
|
---|
3702 | end
|
---|
3703 |
|
---|
3704 | def is_allocator_port?
|
---|
3705 | @allocator_port != nil
|
---|
3706 | end
|
---|
3707 |
|
---|
3708 | def get_allocator_port
|
---|
3709 | @allocator_port
|
---|
3710 | end
|
---|
3711 |
|
---|
3712 | def get_allocator_func_decl
|
---|
3713 | @allocator_func_decl
|
---|
3714 | end
|
---|
3715 |
|
---|
3716 | def get_allocator_param_decl
|
---|
3717 | @allocator_param_decl
|
---|
3718 | end
|
---|
3719 |
|
---|
3720 | def set_require( b_has_name )
|
---|
3721 | @b_require = true
|
---|
3722 | @b_has_name = b_has_name
|
---|
3723 | end
|
---|
3724 |
|
---|
3725 | def is_require?
|
---|
3726 | @b_require
|
---|
3727 | end
|
---|
3728 |
|
---|
3729 | #=== Port# require 呼び口が名前を持つ?
|
---|
3730 | # require 限定
|
---|
3731 | def has_name?
|
---|
3732 | @b_has_name
|
---|
3733 | end
|
---|
3734 |
|
---|
3735 | def is_optional?
|
---|
3736 | @b_optional
|
---|
3737 | end
|
---|
3738 |
|
---|
3739 | def set_optional
|
---|
3740 | @b_optional = true
|
---|
3741 | end
|
---|
3742 |
|
---|
3743 | #=== Port# omit 指定されている?
|
---|
3744 | def is_omit?
|
---|
3745 | @b_omit || ( @signature && @signature.is_empty? )
|
---|
3746 | end
|
---|
3747 |
|
---|
3748 | def set_omit
|
---|
3749 | @b_omit = true
|
---|
3750 | end
|
---|
3751 |
|
---|
3752 | def set_VMT_useless # VMT 関数テーブルを使用しない
|
---|
3753 | @b_VMT_useless = true
|
---|
3754 | end
|
---|
3755 |
|
---|
3756 | def set_skelton_useless # スケルトン関数不要 (true の時、受け口関数を呼出す)
|
---|
3757 | @b_skelton_useless = true
|
---|
3758 | end
|
---|
3759 |
|
---|
3760 | def set_cell_unique # 呼び先セルは一つだけ
|
---|
3761 | @b_cell_unique = true
|
---|
3762 | end
|
---|
3763 |
|
---|
3764 | #=== Port# 呼び口/受け口の指定子の設定
|
---|
3765 | # inline, allocator の指定
|
---|
3766 | def set_specifier spec_list
|
---|
3767 | spec_list.each { |s|
|
---|
3768 | case s[0]
|
---|
3769 | when :INLINE
|
---|
3770 | if @port_type == :CALL then
|
---|
3771 | cdl_error( "S1077 inline: cannot be specified for call port" )
|
---|
3772 | next
|
---|
3773 | end
|
---|
3774 | @b_inline = true
|
---|
3775 | when :OMIT
|
---|
3776 | if @port_type == :ENTRY then
|
---|
3777 | cdl_error( "S9999 omit: cannot be specified for entry port" )
|
---|
3778 | next
|
---|
3779 | end
|
---|
3780 | @b_omit = true
|
---|
3781 | when :OPTIONAL
|
---|
3782 | if @port_type == :ENTRY then
|
---|
3783 | cdl_error( "S1078 optional: cannot be specified for entry port" )
|
---|
3784 | next
|
---|
3785 | end
|
---|
3786 | @b_optional = true
|
---|
3787 | when :REF_DESC
|
---|
3788 | @b_ref_desc = true
|
---|
3789 | when :DYNAMIC
|
---|
3790 | if @port_type == :ENTRY then
|
---|
3791 | cdl_error( "S9999 dynamic: cannnot be specified for entry port" )
|
---|
3792 | next
|
---|
3793 | end
|
---|
3794 | @b_dynamic = true
|
---|
3795 | when :ALLOCATOR
|
---|
3796 | if @port_type == :CALL then
|
---|
3797 | cdl_error( "S1079 allocator: cannot be specified for call port" )
|
---|
3798 | end
|
---|
3799 | if @allocator_instance_tmp then
|
---|
3800 | cdl_error( "S1080 duplicate allocator specifier" )
|
---|
3801 | next
|
---|
3802 | end
|
---|
3803 | @allocator_instance_tmp = s[1]
|
---|
3804 | else
|
---|
3805 | raise "unknown specifier #{s[0]}"
|
---|
3806 | end
|
---|
3807 | }
|
---|
3808 | end
|
---|
3809 |
|
---|
3810 | #=== Port# リレーアロケータ、内部アロケータのインスタンスを設定
|
---|
3811 | # 呼び口の前方参照可能なように、セルタイプの解釈の最後で行う
|
---|
3812 | def set_allocator_instance
|
---|
3813 | if @allocator_instance_tmp == nil then
|
---|
3814 | return
|
---|
3815 | end
|
---|
3816 |
|
---|
3817 | @allocator_instance = {}
|
---|
3818 | @allocator_instance_tmp.each { |ai|
|
---|
3819 | direction = nil
|
---|
3820 | alloc_type = ai[0]
|
---|
3821 | # ai = [ :INTERNAL_ALLOC|:RELAY_ALLOC, func_name, param_name, rhs ]
|
---|
3822 | case alloc_type
|
---|
3823 | when :INTERNAL_ALLOC
|
---|
3824 | if ! @owner.instance_of? CompositeCelltype then # ミスを防ぐために composite でなければとした
|
---|
3825 | cdl_error( "S1081 self allocator not supported yet" ) # mikan これはサポートされているはず。要調査 12/1/15
|
---|
3826 | next
|
---|
3827 | end
|
---|
3828 | # OK
|
---|
3829 | when :RELAY_ALLOC
|
---|
3830 | # OK
|
---|
3831 | when :NORMAL_ALLOC
|
---|
3832 | # ここへ来るのは composite の受け口で右辺が "eEnt.func.param" 形式で指定されていた場合
|
---|
3833 | cdl_error( "S1174 $1 not suitable for lhs, suitable lhs: 'func.param'", "#{ai[1]}.#{ai[3]}.#{ai[4]}" )
|
---|
3834 | next
|
---|
3835 | else
|
---|
3836 | raise "Unknown allocator type #{ai[1]}"
|
---|
3837 | end
|
---|
3838 |
|
---|
3839 | # '=' 左辺(func_name,param_name)は実在するか?
|
---|
3840 | if @signature then # signature = nil なら既にエラー
|
---|
3841 | fh = @signature.get_function_head( ai[1] )
|
---|
3842 | if fh == nil then
|
---|
3843 | cdl_error( "S1082 function \'$1\' not found in signature" , ai[1] )
|
---|
3844 | next
|
---|
3845 | end
|
---|
3846 | decl = fh.get_declarator
|
---|
3847 | if ! decl.is_function? then
|
---|
3848 | next # 既にエラー
|
---|
3849 | end
|
---|
3850 | paramdecl = decl.get_type.get_paramlist.find( ai[2] )
|
---|
3851 | if paramdecl == nil then
|
---|
3852 | cdl_error( "S1083 \'$1\' not found in function \'$2\'" , ai[2], ai[1] )
|
---|
3853 | next
|
---|
3854 | end
|
---|
3855 | case paramdecl.get_direction
|
---|
3856 | when :SEND, :RECEIVE
|
---|
3857 | # OK
|
---|
3858 | direction = paramdecl.get_direction
|
---|
3859 | else
|
---|
3860 | cdl_error( "S1084 \'$1\' in function \'$2\' is not send or receive" , ai[2], ai[1] )
|
---|
3861 | next
|
---|
3862 | end
|
---|
3863 | end
|
---|
3864 |
|
---|
3865 | # 重複指定がないか?
|
---|
3866 | if @allocator_instance[ "#{@name}_#{ai[1]}_#{ai[2]}" ] then
|
---|
3867 | cdl_error( "S1085 duplicate allocator specifier for \'$1_$2\'" , ai[1], ai[2] )
|
---|
3868 | end
|
---|
3869 |
|
---|
3870 | # 右辺のチェック
|
---|
3871 | case alloc_type
|
---|
3872 | when :INTERNAL_ALLOC
|
---|
3873 |
|
---|
3874 | ele = ai[3].get_elements
|
---|
3875 | if( ele[0] != :IDENTIFIER )then
|
---|
3876 | cdl_error( "S1086 $1: rhs not in 'allocator_entry_port' form", ai[3].to_s )
|
---|
3877 | next
|
---|
3878 | end
|
---|
3879 |
|
---|
3880 | ep_name = ele[1] # アロケータ受け口名
|
---|
3881 | ep = @owner.find ep_name.get_path[0] # mikan "a::b"
|
---|
3882 | if ep == nil || ! ep.instance_of?( Port ) || ep.get_port_type != :ENTRY || ! ep.get_signature.is_allocator? then
|
---|
3883 | cdl_error( "S1175 $1 not found or not allocator entry port for $2" , ep_name, ai[1] )
|
---|
3884 | end
|
---|
3885 | # 右辺チェック終わり
|
---|
3886 | # ai2 = [ :INTERNAL_ALLOC, func_name, param_name, rhs_ep_name ]
|
---|
3887 | ai2 = [ ai[0], ai[1], ai[2], ep_name ]
|
---|
3888 |
|
---|
3889 | when :RELAY_ALLOC
|
---|
3890 | ele = ai[3].get_elements
|
---|
3891 | if( ele[0] != :OP_DOT ||
|
---|
3892 | ele[1][0] != :OP_DOT || ele[1][1][0] != :IDENTIFIER || ! ele[1][1][1].is_name_only? ||
|
---|
3893 | ! ele[1][2].instance_of?( Token ) || ! ele[2].instance_of?( Token ) )then #1
|
---|
3894 | # [ :OP_DOT, [ :OP_DOT, [ :IDENTIFIER, name_space_path ], Token(1) ], Token(2) ]
|
---|
3895 | # ele[0] ele[1][0] ele[1][1][0] ele[1][1][1] ele[1][2] ele[2]
|
---|
3896 | # name_space_path.Token(1).Token(2) === call_port.func.param
|
---|
3897 | # mikan Expression#analyze_cell_join_expression の変種を作成して置き換えるべき
|
---|
3898 |
|
---|
3899 | cdl_error( "S1176 rhs not in 'call_port.func.param' form for for $1_$2" , ai[1], ai[2] ) # S1086
|
---|
3900 | next
|
---|
3901 | end
|
---|
3902 | func_name = ele[1][2]; cp_name = ele[1][1][1].get_name; param_name = ele[2].to_sym
|
---|
3903 | cp = @owner.find cp_name # リレーする先の呼び口
|
---|
3904 | if cp then
|
---|
3905 | # mikan cp が呼び口であることのチェック(属性の場合もある)
|
---|
3906 | # mikan 受け口から受け口へのリレーへの対応 (呼び口から呼び口へのリレーはありえない) <=== 文法にかかわる事項(呼び口側でアロケータが決定される)
|
---|
3907 | sig = cp.get_signature
|
---|
3908 | if sig && @signature then
|
---|
3909 | fh = @signature.get_function_head( func_name )
|
---|
3910 | if fh == nil then
|
---|
3911 | cdl_error( "S1087 function \'$1\' not found in signature \'$2\'" , func_name, sig.get_name )
|
---|
3912 | next
|
---|
3913 | end
|
---|
3914 | decl = fh.get_declarator
|
---|
3915 | if ! decl.is_function? then
|
---|
3916 | next # 既にエラー
|
---|
3917 | end
|
---|
3918 | paramdecl = decl.get_type.get_paramlist.find( param_name )
|
---|
3919 | if paramdecl == nil then
|
---|
3920 | cdl_error( "S1088 \'$1\' not found in function \'$2\'" , param_name, func_name )
|
---|
3921 | next
|
---|
3922 | end
|
---|
3923 | case paramdecl.get_direction
|
---|
3924 | when :SEND, :RECEIVE
|
---|
3925 | # OK
|
---|
3926 | if alloc_type == :RELAY_ALLOC && direction != paramdecl.get_direction then
|
---|
3927 | cdl_error( "S1089 relay allocator send/receive mismatch between $1.$2 and $3_$4.$5" , ai[1], ai[2], cp_name, func_name, param_name )
|
---|
3928 | end
|
---|
3929 | else
|
---|
3930 | cdl_error( "S1090 \'$1\' in function \'$2\' is not send or receive" , param_name, func_name )
|
---|
3931 | next
|
---|
3932 | end
|
---|
3933 |
|
---|
3934 | # else
|
---|
3935 | # sig == nil ならば既にエラー
|
---|
3936 | end
|
---|
3937 | else
|
---|
3938 | if @celltype then
|
---|
3939 | ct_name = @celltype.get_name
|
---|
3940 | else
|
---|
3941 | ct_name = "(None)"
|
---|
3942 | end
|
---|
3943 | cdl_error( "S1091 call port \'$1\' not found in celltype $2" , cp_name, ct_name )
|
---|
3944 | next
|
---|
3945 | end
|
---|
3946 | # 右辺チェック終わり
|
---|
3947 | # ai2 = [ :RELAY_ALLOC, func_name, param_name, rhs_cp_name, rhs_func_name, rhs_param_name ]
|
---|
3948 | ai2 = [ ai[0], ai[1], ai[2], cp_name, func_name, param_name ]
|
---|
3949 | end # case alloc_type
|
---|
3950 |
|
---|
3951 | @allocator_instance[ "#{@name}_#{ai[1]}_#{ai[2]}" ] = ai2
|
---|
3952 | }
|
---|
3953 | end
|
---|
3954 |
|
---|
3955 | def is_inline?
|
---|
3956 | @b_inline
|
---|
3957 | end
|
---|
3958 |
|
---|
3959 | def is_VMT_useless? # VMT 関数テーブルを使用しない
|
---|
3960 | @b_VMT_useless
|
---|
3961 | end
|
---|
3962 |
|
---|
3963 | def is_skelton_useless? # スケルトン関数不要 (true の時、受け口関数を呼出す)
|
---|
3964 | @b_skelton_useless
|
---|
3965 | end
|
---|
3966 |
|
---|
3967 | def is_cell_unique? # 呼び先のセルは一つ?
|
---|
3968 | @b_cell_unique
|
---|
3969 | end
|
---|
3970 |
|
---|
3971 | #=== Port# 受け口最適化の設定
|
---|
3972 | # この受け口を参照する呼び口が VMT, skelton を必要としているかどうかを設定
|
---|
3973 | # 一つでも呼び口が必要としている(すなわち b_*_useless が false)場合は、
|
---|
3974 | # この受け口の最適化を false とする
|
---|
3975 | def set_entry_VMT_skelton_useless( b_VMT_useless, b_skelton_useless )
|
---|
3976 | if ! b_VMT_useless then
|
---|
3977 | @b_VMT_useless = false
|
---|
3978 | end
|
---|
3979 | if ! b_skelton_useless then
|
---|
3980 | @b_skelton_useless = false
|
---|
3981 | end
|
---|
3982 | end
|
---|
3983 |
|
---|
3984 | #=== Port# 唯一の結合先を設定
|
---|
3985 | # 最適化で使用
|
---|
3986 | # b_VMT_useless == true || b_skelton_useless == true の時に設定される
|
---|
3987 | # optional の場合 callee_cell, callee_port が nil となる
|
---|
3988 | def set_only_callee( callee_port, callee_cell )
|
---|
3989 | @only_callee_port = callee_port
|
---|
3990 | @only_callee_cell = callee_cell
|
---|
3991 | end
|
---|
3992 |
|
---|
3993 | #=== Port# 唯一の結合先ポートを返す(compositeの場合実セル)
|
---|
3994 | # optional 呼び口で未結合の場合 nil を返す
|
---|
3995 | def get_real_callee_port
|
---|
3996 | if @only_callee_cell then
|
---|
3997 | return @only_callee_cell.get_real_port( @only_callee_port.get_name )
|
---|
3998 | end
|
---|
3999 | end
|
---|
4000 |
|
---|
4001 | #=== Port# 唯一の結合先セルを返す(compositeの場合実セル)
|
---|
4002 | # optional 呼び口で未結合の場合 nil を返す
|
---|
4003 | def get_real_callee_cell
|
---|
4004 | if @only_callee_cell then
|
---|
4005 | return @only_callee_cell.get_real_cell( @only_callee_port.get_name )
|
---|
4006 | end
|
---|
4007 | end
|
---|
4008 |
|
---|
4009 | def get_allocator_instance
|
---|
4010 | return @allocator_instance
|
---|
4011 | end
|
---|
4012 |
|
---|
4013 | def get_allocator_instance_tmp
|
---|
4014 | return @allocator_instance_tmp
|
---|
4015 | end
|
---|
4016 |
|
---|
4017 | #=== Port# 逆require の結合を生成する
|
---|
4018 | # STAGE: S
|
---|
4019 | def create_reverse_require_join cell
|
---|
4020 | if @reverse_require_cell_path == nil then
|
---|
4021 | return
|
---|
4022 | end
|
---|
4023 |
|
---|
4024 | # 呼び元セルを探す
|
---|
4025 | ct_or_cell = Namespace.find( @reverse_require_cell_path ) # mikan namespace #1
|
---|
4026 | if ct_or_cell.instance_of? Cell then
|
---|
4027 | cell2 = ct_or_cell
|
---|
4028 | ct = cell2.get_celltype
|
---|
4029 | if ct == nil then
|
---|
4030 | return # 既にエラー
|
---|
4031 | end
|
---|
4032 | elsif ct_or_cell.instance_of? Celltype then
|
---|
4033 | cell2 = ct_or_cell.get_singleton_cell( cell.get_region )
|
---|
4034 | if cell2 == nil then
|
---|
4035 | cdl_error( "S1158 $1: singleton cell not found for fixed join", ct_or_cell.get_name )
|
---|
4036 | return
|
---|
4037 | end
|
---|
4038 | ct = ct_or_cell
|
---|
4039 | else
|
---|
4040 | # 既にエラー:無視
|
---|
4041 | return
|
---|
4042 | end
|
---|
4043 |
|
---|
4044 | # 結合を生成する
|
---|
4045 | dbgPrint "create_reverse_require_join #{cell2.get_name}.#{@reverse_require_entry_port_name}[] = #{cell.get_name}.#{@name}"
|
---|
4046 | nsp = NamespacePath.new( cell.get_name, false, cell.get_namespace )
|
---|
4047 | # rhs = Expression.new( [ :OP_DOT, [ :IDENTIFIER, Token.new( cell.get_name, nil, nil, nil ) ],
|
---|
4048 | rhs = Expression.new( [ :OP_DOT, [ :IDENTIFIER, nsp ],
|
---|
4049 | Token.new( @name, nil, nil, nil ) ], cell.get_locale ) #1
|
---|
4050 | join = Join.new( @reverse_require_entry_port_name, -1, rhs, cell.get_locale )
|
---|
4051 | cell2.new_join( join )
|
---|
4052 | join.set_definition( ct.find(join.get_name) )
|
---|
4053 |
|
---|
4054 | end
|
---|
4055 |
|
---|
4056 | #=== Port# signature のすべての関数のすべてのパラメータをたどる
|
---|
4057 | #block:: ブロックを引数として取る(ruby の文法で書かない)
|
---|
4058 | # ブロックは3つの引数を受け取る(Port, Decl, ParamDecl) Decl: 関数ヘッダ
|
---|
4059 | # Signature クラスにも each_param がある(同じ働き)
|
---|
4060 | def each_param # ブロック引数{ |port, func_decl, param_decl| }
|
---|
4061 | return if @signature == nil # signature 未定義(既にエラー)
|
---|
4062 | fha = @signature.get_function_head_array # 呼び口または受け口のシグニチャの関数配列
|
---|
4063 | return if fha == nil # nil なら文法エラーで有効値が設定されなかった
|
---|
4064 |
|
---|
4065 | pr = Proc.new # このメソッドのブロック引数を pr に代入
|
---|
4066 | port = self
|
---|
4067 | fha.each{ |fh| # fh: FuncHead # 関数配列中の各関数頭部
|
---|
4068 | fd = fh.get_declarator # fd: Decl (関数頭部からDeclarotorを得る)
|
---|
4069 | if fd.is_function? then # fd が関数でなければ、すでにエラー
|
---|
4070 | fd.get_type.get_paramlist.get_items.each{ |par| # すべてのパラメータについて
|
---|
4071 | pr.call( port, fd, par )
|
---|
4072 | }
|
---|
4073 | end
|
---|
4074 | }
|
---|
4075 | end
|
---|
4076 |
|
---|
4077 | #=== Port# 逆require指定されている?
|
---|
4078 | def is_reverse_required?
|
---|
4079 | @reverse_require_cell_path != nil
|
---|
4080 | end
|
---|
4081 |
|
---|
4082 | def show_tree( indent )
|
---|
4083 | indent.times { print " " }
|
---|
4084 | puts "Port: name:#{@name} port_type:#{@port_type} require:#{@b_require} inline:#{@b_inline} omit:#{@b_omit} optional:#{@b_optional} ref_desc:#{@b_ref_desc} dynamic:#{@b_dynamic}"
|
---|
4085 | (indent+1).times { print " " }
|
---|
4086 | if @signature then
|
---|
4087 | puts "signature: #{@signature.get_name} #{@signature}"
|
---|
4088 | else
|
---|
4089 | puts "signature: NOT defined"
|
---|
4090 | end
|
---|
4091 | if @array_size == "[]" then
|
---|
4092 | (indent+1).times { print " " }
|
---|
4093 | puts "array_size: not specified"
|
---|
4094 | elsif @array_size then
|
---|
4095 | (indent+1).times { print " " }
|
---|
4096 | puts "array_size: #{@array_size}"
|
---|
4097 | end
|
---|
4098 | if @allocator_instance then
|
---|
4099 | (indent+1).times { print " " }
|
---|
4100 | puts "allocator instance:"
|
---|
4101 | @allocator_instance.each { |b,a|
|
---|
4102 | (indent+2).times { print " " }
|
---|
4103 | puts "#{a[0]} #{a[1]} #{b} "
|
---|
4104 | # a[3].show_tree( indent+3 )
|
---|
4105 | }
|
---|
4106 | end
|
---|
4107 | (indent+1).times { print " " }
|
---|
4108 | if @port_type == :CALL then
|
---|
4109 | puts "VMT_useless : #{@b_VMT_useless} skelton_useless : #{@b_skelton_useless} cell_unique : #{@b_cell_unique}"
|
---|
4110 | else
|
---|
4111 | puts "VMT_useless : #{@b_VMT_useless} skelton_useless : #{@b_skelton_useless}"
|
---|
4112 | end
|
---|
4113 | end
|
---|
4114 |
|
---|
4115 | end
|
---|
4116 |
|
---|
4117 | #== Namespace
|
---|
4118 | #
|
---|
4119 | # root namespace だけ、Region クラスのインスタンスとして生成される
|
---|
4120 | # root namespace は、root region を兼ねるため
|
---|
4121 | #
|
---|
4122 | # @cell_list は Region の場合にのみ持つ (mikan @cell_list 関連は Region に移すべき)
|
---|
4123 | #
|
---|
4124 | class Namespace < NSBDNode
|
---|
4125 | # @name:: Symbol # root の場合 "::" (String)
|
---|
4126 | # @global_name:: str
|
---|
4127 | # @name_list:: NamedList Signature,Celltype,CompositeCelltype,Cell,Typedef,Namespace
|
---|
4128 | # @struct_tag_list:: NamedList : StructType
|
---|
4129 | # @namespace_list:: Namespace[] : Region は Namespace の子クラスであり、含まれる
|
---|
4130 | # @signature_list:: Sginature[]
|
---|
4131 | # @celltype_list:: Celltype[]
|
---|
4132 | # @compositecelltype_list:: CompositeCelltype[]
|
---|
4133 | # @cell_list:: Cell[]
|
---|
4134 | # @typedef_list:: Typedef[]
|
---|
4135 | # @decl_list:: ( Typedef | StructType | EnumType )[] 依存関係がある場合に備えて、順番どおりに配列に格納 mikan enum
|
---|
4136 | # @const_decl_list:: Decl[]
|
---|
4137 | # @cache_n_cells:: Integer : get_n_cells の結果をキャッシュする
|
---|
4138 | # @cache_generating_region:: Region : get_n_cells の結果をキャッシュするしているリージョン
|
---|
4139 |
|
---|
4140 | # mikan namespace の push, pop
|
---|
4141 |
|
---|
4142 | # namespace 階層用のスタック
|
---|
4143 | @@namespace_stack = [] # @@namespace_stack[0] = "::" (generator.rb)
|
---|
4144 | @@namespace_sp = -1
|
---|
4145 |
|
---|
4146 | # Generator ネスト用のスタック (namespace 階層用のスタックを対比する)
|
---|
4147 | @@nest_stack_index = -1
|
---|
4148 | @@nest_stack = []
|
---|
4149 |
|
---|
4150 | @@root_namespace = nil
|
---|
4151 |
|
---|
4152 | # Generator ネスト用スタックの push, pop (クラスメソッド)
|
---|
4153 | def self.push
|
---|
4154 | dbgPrint "push Namespace\n"
|
---|
4155 | @@nest_stack_index += 1
|
---|
4156 | @@nest_stack[ @@nest_stack_index ] = [ @@namespace_stack, @@namespace_sp ]
|
---|
4157 | if @@root_namespace then
|
---|
4158 | @@namespace_sp = 0
|
---|
4159 | @@namespace_stack[ @@namespace_sp ] = @@root_namespace
|
---|
4160 | end
|
---|
4161 | end
|
---|
4162 |
|
---|
4163 | def self.pop
|
---|
4164 | dbgPrint "pop Namespace\n"
|
---|
4165 | @@namespace_stack, @@namespace_sp = @@nest_stack[ @@nest_stack_index ]
|
---|
4166 | @@nest_stack_index -= 1
|
---|
4167 | if @@nest_stack_index < -1 then
|
---|
4168 | raise "TooManyRestore"
|
---|
4169 | end
|
---|
4170 | end
|
---|
4171 |
|
---|
4172 | # namespace 階層用スタックの push, pop (インスタンスメソッド)
|
---|
4173 | def push ns
|
---|
4174 | @@namespace_sp += 1
|
---|
4175 | @@namespace_stack[ @@namespace_sp ] = self
|
---|
4176 | dbgPrint "Namespace.PUSH #{@@namespace_sp} #{@name}\n"
|
---|
4177 | end
|
---|
4178 |
|
---|
4179 | def pop
|
---|
4180 | dbgPrint "Namespace.POP #{@@namespace_sp} #{@name}\n"
|
---|
4181 | @@namespace_sp -= 1
|
---|
4182 | if @@namespace_sp < 0 then
|
---|
4183 | raise "StackUnderflow"
|
---|
4184 | end
|
---|
4185 | end
|
---|
4186 |
|
---|
4187 | def initialize( name )
|
---|
4188 |
|
---|
4189 | super()
|
---|
4190 | @name = name
|
---|
4191 |
|
---|
4192 | if( name == "::" )then
|
---|
4193 | if( @@root_namespace != nil )then
|
---|
4194 | # root は一回のみ生成できる
|
---|
4195 | raise "try to re-create root namespace"
|
---|
4196 | end
|
---|
4197 | @@root_namespace = self
|
---|
4198 | @NamespacePath = NamespacePath.new( name, true )
|
---|
4199 | else
|
---|
4200 | ns = @@namespace_stack[ @@namespace_sp ].find( name )
|
---|
4201 | if ns.kind_of? Namespace then
|
---|
4202 | dbgPrint "namespace: re-appear #{@name}\n"
|
---|
4203 | # 登録済み namespace の再登録
|
---|
4204 | ns.push ns
|
---|
4205 | return
|
---|
4206 | elsif ns then
|
---|
4207 | cdl_error( "S1151 $1: not namespace", @name )
|
---|
4208 | prev_locale = ns.get_locale
|
---|
4209 | puts "previous: #{prev_locale[0]}: line #{prev_locale[1]} \'#{name}\' defined here"
|
---|
4210 | end
|
---|
4211 | dbgPrint "namespace: 1st-appear #{@name}\n"
|
---|
4212 | end
|
---|
4213 |
|
---|
4214 | if @@namespace_sp >= 0 then # root は除外
|
---|
4215 | @@namespace_stack[@@namespace_sp].new_namespace( self )
|
---|
4216 | end
|
---|
4217 | push self
|
---|
4218 |
|
---|
4219 | @global_name = Namespace.get_global_name # stack 登録後取る
|
---|
4220 | @name_list = NamedList.new( nil, "symbol in namespace '#{@name}'" )
|
---|
4221 | @struct_tag_list = NamedList.new( nil, "struct tag" )
|
---|
4222 |
|
---|
4223 | @namespace_list = []
|
---|
4224 | @signature_list = []
|
---|
4225 | @celltype_list = []
|
---|
4226 | @compositecelltype_list = []
|
---|
4227 | @cell_list = []
|
---|
4228 | @typedef_list = []
|
---|
4229 | @decl_list = []
|
---|
4230 | @const_decl_list = []
|
---|
4231 | @cache_n_cells = nil
|
---|
4232 | @cache_generating_region = nil
|
---|
4233 | if @NamespacePath == nil then
|
---|
4234 | # root namespace の場合は設定済 (親 namespace が見つからず例外になる)
|
---|
4235 | set_namespace_path # @NamespacePath の設定
|
---|
4236 | end
|
---|
4237 | end
|
---|
4238 |
|
---|
4239 | def end_of_parse
|
---|
4240 | pop
|
---|
4241 | end
|
---|
4242 |
|
---|
4243 | def get_name
|
---|
4244 | @name
|
---|
4245 | end
|
---|
4246 |
|
---|
4247 | #=== Namespace:: global_name を得る
|
---|
4248 | # parse 中のみこのメソッドは使える
|
---|
4249 | # STAGE: P
|
---|
4250 | def self.get_global_name # parse 中有効
|
---|
4251 | if @@namespace_sp <= 0 then
|
---|
4252 | return ""
|
---|
4253 | end
|
---|
4254 |
|
---|
4255 | path = @@namespace_stack[1].get_name.to_s
|
---|
4256 | i = 2
|
---|
4257 | while i <= @@namespace_sp
|
---|
4258 | path = path+"_"+@@namespace_stack[i].get_name.to_s
|
---|
4259 | i += 1
|
---|
4260 | end
|
---|
4261 |
|
---|
4262 | path
|
---|
4263 | end
|
---|
4264 |
|
---|
4265 | def get_global_name
|
---|
4266 | @global_name
|
---|
4267 | end
|
---|
4268 |
|
---|
4269 | #=== Namespace#セルの個数を得る
|
---|
4270 | # 子 region が linkunit, node 指定されていれば、含めない(別のリンク単位)
|
---|
4271 | # プロトタイプ宣言のもののみの個数を含めない
|
---|
4272 | # mikan namespace 下に cell を置けない仕様になると、このメソッドは Region のものでよい
|
---|
4273 | # mikan 上記の場合 instance_of? Namespace の条件判定は不要となる
|
---|
4274 | def get_n_cells
|
---|
4275 | if @cache_generating_region == $generating_region then
|
---|
4276 | # このメソッドは繰り返し呼び出されるため、結果をキャッシュする
|
---|
4277 | return @cache_n_cells
|
---|
4278 | end
|
---|
4279 |
|
---|
4280 | count = 0
|
---|
4281 | @cell_list.each{ |c|
|
---|
4282 | # 定義かプロトタイプ宣言だけかは、new_cell の段階で判断できないため、カウントしなおす
|
---|
4283 | if c.get_f_def == true then
|
---|
4284 | # print "get_n_cells: cell: #{c.get_name}\n"
|
---|
4285 | count += 1
|
---|
4286 | end
|
---|
4287 | }
|
---|
4288 |
|
---|
4289 | @namespace_list.each{ |ns|
|
---|
4290 | if ns.instance_of? Namespace then
|
---|
4291 | count += ns.get_n_cells
|
---|
4292 | else
|
---|
4293 | # ns は Region である
|
---|
4294 | rt = ns.get_region_type
|
---|
4295 | # print "get_n_cells: region: #{ns.get_name}: #{rt}\n"
|
---|
4296 | if rt == :NODE || rt == :LINKUNIT then
|
---|
4297 | # 別の linkunit なので加算しない
|
---|
4298 | else
|
---|
4299 | count += ns.get_n_cells
|
---|
4300 | end
|
---|
4301 | end
|
---|
4302 | }
|
---|
4303 |
|
---|
4304 | @cache_generating_region = $generating_region
|
---|
4305 | @cache_n_cells = count
|
---|
4306 | return count
|
---|
4307 | end
|
---|
4308 |
|
---|
4309 | #=== Namespace.find : in_path で示されるオブジェクトを探す
|
---|
4310 | #in_path:: NamespacePath
|
---|
4311 | #in_path:: Array : 古い形式
|
---|
4312 | # path [ "::", "ns1", "ns2" ] absolute
|
---|
4313 | # path [ "ns1", "ns2" ] relative
|
---|
4314 | def self.find( in_path )
|
---|
4315 |
|
---|
4316 | if in_path.instance_of? Array then
|
---|
4317 | # raise "Namespace.find: old fashion"
|
---|
4318 |
|
---|
4319 | path = in_path
|
---|
4320 | length = path.length
|
---|
4321 | return self.find_one( path[0] ) if length == 1
|
---|
4322 |
|
---|
4323 | name = path[0]
|
---|
4324 | if name == "::" then
|
---|
4325 | i = 1
|
---|
4326 | name = path[i] # 構文的に必ず存在
|
---|
4327 | object = @@root_namespace.find( name ) # root
|
---|
4328 | else
|
---|
4329 | # 相対パス
|
---|
4330 | i = 0
|
---|
4331 | object = @@namespace_stack[@@namespace_sp].find_one( name ) # crrent
|
---|
4332 | end
|
---|
4333 |
|
---|
4334 | elsif in_path.instance_of? NamespacePath then
|
---|
4335 | path = in_path.get_path
|
---|
4336 | length = path.length
|
---|
4337 |
|
---|
4338 | if length == 0 then
|
---|
4339 | if in_path.is_absolute? then
|
---|
4340 | return @@root_namespace
|
---|
4341 | else
|
---|
4342 | raise "path length 0, not absolute"
|
---|
4343 | end
|
---|
4344 | end
|
---|
4345 |
|
---|
4346 | i = 0
|
---|
4347 | name = path[0]
|
---|
4348 | if in_path.is_absolute? then
|
---|
4349 | object = @@root_namespace.find( name ) # root
|
---|
4350 | else
|
---|
4351 | bns = in_path.get_base_namespace
|
---|
4352 | object = bns.find_one( name ) # crrent
|
---|
4353 | end
|
---|
4354 | else
|
---|
4355 | raise "unexpected path"
|
---|
4356 | end
|
---|
4357 |
|
---|
4358 | i += 1
|
---|
4359 | while i < length
|
---|
4360 |
|
---|
4361 | unless object.kind_of?( Namespace ) then
|
---|
4362 | # クラスメソッド内で cdl_error を呼び出すことはできない
|
---|
4363 | # また、前方参照対応後、正確な行番号が出ない問題も生じる
|
---|
4364 | # cdl_error( "S1092 \'$1\' not namespace" , name )
|
---|
4365 | # このメソッドから nil が帰った場合 "not found" が出るので、ここでは出さない
|
---|
4366 | return nil
|
---|
4367 | end
|
---|
4368 |
|
---|
4369 | object = object.find( path[i] )
|
---|
4370 | i += 1
|
---|
4371 | end
|
---|
4372 |
|
---|
4373 | return object
|
---|
4374 | end
|
---|
4375 |
|
---|
4376 |
|
---|
4377 | def find( name )
|
---|
4378 | @name_list.get_item(name)
|
---|
4379 | end
|
---|
4380 |
|
---|
4381 | #=== Namespace# namespace から探す。見つからなければ親 namespace から探す
|
---|
4382 | def self.find_one( name )
|
---|
4383 | return @@namespace_stack[@@namespace_sp].find_one( name )
|
---|
4384 | end
|
---|
4385 |
|
---|
4386 | def find_one( name )
|
---|
4387 |
|
---|
4388 | object = find( name )
|
---|
4389 | # これは出すぎ
|
---|
4390 | # dbgPrint "in '#{@name}' find '#{name}' object #{object ? object.class : "Not found"}\n"
|
---|
4391 |
|
---|
4392 | if object != nil then
|
---|
4393 | return object
|
---|
4394 | elsif @name != "::" then
|
---|
4395 | return @owner.find_one( name )
|
---|
4396 | else
|
---|
4397 | return nil
|
---|
4398 | end
|
---|
4399 | end
|
---|
4400 |
|
---|
4401 | def self.get_current
|
---|
4402 | @@namespace_stack[@@namespace_sp]
|
---|
4403 | end
|
---|
4404 |
|
---|
4405 | def self.find_tag( name )
|
---|
4406 | # mikan tag : namespace の path に対応しない
|
---|
4407 | # namespace の中にあっても、root namespace にあるものと見なされる
|
---|
4408 | # よって カレント namespace から根に向かって探す
|
---|
4409 | i = @@namespace_sp
|
---|
4410 | while i >= 0
|
---|
4411 | res = @@namespace_stack[i].find_tag( name )
|
---|
4412 | if res then
|
---|
4413 | return res
|
---|
4414 | end
|
---|
4415 | i -= 1
|
---|
4416 | end
|
---|
4417 | end
|
---|
4418 |
|
---|
4419 | def find_tag( name )
|
---|
4420 | @struct_tag_list.get_item( name )
|
---|
4421 | end
|
---|
4422 |
|
---|
4423 | ### namespace
|
---|
4424 | def self.new_namespace( namespace )
|
---|
4425 | @@namespace_stack[@@namespace_sp].new_namespace( namespace )
|
---|
4426 | end
|
---|
4427 |
|
---|
4428 | def new_namespace( namespace )
|
---|
4429 | dbgPrint "new_namespace: #{@name}:#{self} #{namespace.get_name}:#{namespace} \n"
|
---|
4430 | namespace.set_owner self # Namespace (Namespace)
|
---|
4431 |
|
---|
4432 | @name_list.add_item( namespace )
|
---|
4433 | @namespace_list << namespace
|
---|
4434 | end
|
---|
4435 |
|
---|
4436 | ### signature
|
---|
4437 | def self.new_signature( signature )
|
---|
4438 | @@namespace_stack[@@namespace_sp].new_signature( signature )
|
---|
4439 | end
|
---|
4440 |
|
---|
4441 | def new_signature( signature )
|
---|
4442 | signature.set_owner self # Signature (Namespace)
|
---|
4443 | @name_list.add_item( signature )
|
---|
4444 | @signature_list << signature
|
---|
4445 | end
|
---|
4446 |
|
---|
4447 | ### celltype
|
---|
4448 | def self.new_celltype( celltype )
|
---|
4449 | @@namespace_stack[@@namespace_sp].new_celltype( celltype )
|
---|
4450 | end
|
---|
4451 |
|
---|
4452 | def new_celltype( celltype )
|
---|
4453 | celltype.set_owner self # Celltype (Namespace)
|
---|
4454 | @name_list.add_item( celltype )
|
---|
4455 | @celltype_list << celltype
|
---|
4456 | end
|
---|
4457 |
|
---|
4458 | ### compositecelltype
|
---|
4459 | def self.new_compositecelltype( compositecelltype )
|
---|
4460 | @@namespace_stack[@@namespace_sp].new_compositecelltype( compositecelltype )
|
---|
4461 | end
|
---|
4462 |
|
---|
4463 | def new_compositecelltype( compositecelltype )
|
---|
4464 | compositecelltype.set_owner self # CompositeCelltype (Namespace)
|
---|
4465 | @name_list.add_item( compositecelltype )
|
---|
4466 | @compositecelltype_list << compositecelltype
|
---|
4467 | end
|
---|
4468 |
|
---|
4469 | ### cell (Namespace)
|
---|
4470 | def self.new_cell( cell )
|
---|
4471 | @@namespace_stack[@@namespace_sp].new_cell( cell )
|
---|
4472 | end
|
---|
4473 |
|
---|
4474 | def new_cell( cell )
|
---|
4475 | dbgPrint "Namespace.new_cell: #{@NamespacePath.get_path_str}::#{cell.get_name}\n"
|
---|
4476 | if ! is_root? && ! ( instance_of? Region ) then
|
---|
4477 | cdl_error( "S9999 '$1' cell cannot be placed under namespace", cell.get_name )
|
---|
4478 | end
|
---|
4479 | cell.set_owner self # Cell (Namespace)
|
---|
4480 | @name_list.add_item( cell )
|
---|
4481 | @cell_list << cell
|
---|
4482 | end
|
---|
4483 |
|
---|
4484 | #=== Namespace# 参照されているが、未定義のセルを探す
|
---|
4485 | # プロトタイプ宣言だけで定義されていないケースをエラーとする
|
---|
4486 | # 受動の未結合セルについて警告する
|
---|
4487 | def check_ref_but_undef
|
---|
4488 | @cell_list.each { |c|
|
---|
4489 | if ! c.get_f_def then # Namespace の @cell_list にはプロトタイプが含まれるケースあり
|
---|
4490 | if c.get_f_ref then
|
---|
4491 | cdl_error( "S1093 $1 : undefined cell" , c.get_namespace_path.get_path_str )
|
---|
4492 | elsif $verbose then
|
---|
4493 | cdl_warning( "W1006 $1 : only prototype, unused and undefined cell" , c.get_namespace_path.get_path_str )
|
---|
4494 | end
|
---|
4495 | else
|
---|
4496 | dbgPrint "check_ref_but_undef: #{c.get_global_name}\n"
|
---|
4497 | ct = c.get_celltype
|
---|
4498 | # if c.get_f_ref == false && c.is_generate? && ct && ct.is_inactive? then
|
---|
4499 | if c.get_f_ref == false && ct && ct.is_inactive? then
|
---|
4500 | cdl_warning( "W1007 $1 : non-active cell has no entry join and no factory" , c.get_namespace_path.get_path_str )
|
---|
4501 | end
|
---|
4502 | end
|
---|
4503 | }
|
---|
4504 | @namespace_list.each { |n|
|
---|
4505 | n.check_ref_but_undef
|
---|
4506 | }
|
---|
4507 | end
|
---|
4508 |
|
---|
4509 | #=== Namespace# セルの受け口の参照カウントを設定する
|
---|
4510 | def set_port_reference_count
|
---|
4511 | @cell_list.each { |c|
|
---|
4512 | c.set_port_reference_count
|
---|
4513 | }
|
---|
4514 | @namespace_list.each { |n|
|
---|
4515 | n.set_port_reference_count
|
---|
4516 | }
|
---|
4517 | end
|
---|
4518 |
|
---|
4519 | ### struct
|
---|
4520 | def self.new_structtype( struct )
|
---|
4521 | @@namespace_stack[@@namespace_sp].new_structtype( struct )
|
---|
4522 | end
|
---|
4523 |
|
---|
4524 | def new_structtype( struct )
|
---|
4525 | # struct.set_owner self # StructType (Namespace) # StructType は BDNode ではない
|
---|
4526 | dup = @struct_tag_list.get_item(struct.get_name)
|
---|
4527 | if dup != nil then
|
---|
4528 | if struct.same? dup then
|
---|
4529 | # 同じものが typedef された
|
---|
4530 | # p "#{struct.get_name}"
|
---|
4531 | return
|
---|
4532 | end
|
---|
4533 | end
|
---|
4534 |
|
---|
4535 | @struct_tag_list.add_item( struct )
|
---|
4536 | @decl_list << struct
|
---|
4537 | end
|
---|
4538 |
|
---|
4539 | ### typedef
|
---|
4540 | def self.new_typedef( typedef )
|
---|
4541 | @@namespace_stack[@@namespace_sp].new_typedef( typedef )
|
---|
4542 | end
|
---|
4543 |
|
---|
4544 | def new_typedef( typedef )
|
---|
4545 | typedef.set_owner self # TypeDef (Namespace)
|
---|
4546 | dup = @name_list.get_item(typedef.get_name)
|
---|
4547 | if dup != nil then
|
---|
4548 | typedef_type = typedef.get_declarator.get_type.get_original_type
|
---|
4549 | dup_type = dup.get_declarator.get_type.get_original_type
|
---|
4550 | # print "typedef: #{typedef.get_name} = #{typedef_type.get_type_str} #{typedef_type.get_type_str_post}\n"
|
---|
4551 | if typedef_type.get_type_str == dup_type.get_type_str &&
|
---|
4552 | typedef_type.get_type_str_post == dup_type.get_type_str_post then
|
---|
4553 | # 同じものが typedef された
|
---|
4554 | # ここへ来るのは C で関数ポインタを typedef しているケース
|
---|
4555 | # 以下のように二重に定義されている場合は type_specifier_qualifier_list として扱われる
|
---|
4556 | # typedef long LONG;
|
---|
4557 | # typedef long LONG;
|
---|
4558 | # bnf.y.rb では declarator に TYPE_NAME を許さないので、ここへ来ることはない
|
---|
4559 | # p "#{typedef.get_declarator.get_type.get_type_str} #{typedef.get_name} #{typedef.get_declarator.get_type.get_type_str_post}"
|
---|
4560 | return
|
---|
4561 | end
|
---|
4562 | # p "prev: #{dup.get_declarator.get_type.get_type_str}#{dup.get_declarator.get_type.get_type_str_post} current:#{typedef.get_declarator.get_type.get_type_str} #{typedef.get_declarator.get_type.get_type_str_post}"
|
---|
4563 | end
|
---|
4564 |
|
---|
4565 | # p "typedef: #{typedef.get_name} #{typedef.get_declarator.get_type.get_original_type.get_type_str}#{typedef.get_declarator.get_type.get_original_type.get_type_str_post}"
|
---|
4566 | # typedef.show_tree 0
|
---|
4567 |
|
---|
4568 | @name_list.add_item( typedef )
|
---|
4569 | @typedef_list << typedef
|
---|
4570 | @decl_list << typedef
|
---|
4571 | end
|
---|
4572 |
|
---|
4573 | def self.is_typename?( str )
|
---|
4574 | i = @@namespace_sp
|
---|
4575 | while i >= 0
|
---|
4576 | if @@namespace_stack[i].is_typename?( str ) then
|
---|
4577 | return true
|
---|
4578 | end
|
---|
4579 | i -= 1
|
---|
4580 | end
|
---|
4581 | false
|
---|
4582 | end
|
---|
4583 |
|
---|
4584 | def is_typename?( str )
|
---|
4585 | if @name_list.get_item( str ).instance_of?( Typedef ) then
|
---|
4586 | true
|
---|
4587 | else
|
---|
4588 | false
|
---|
4589 | end
|
---|
4590 | end
|
---|
4591 |
|
---|
4592 | ### const_decl
|
---|
4593 | def self.new_const_decl( decl )
|
---|
4594 | @@namespace_stack[@@namespace_sp].new_const_decl( decl )
|
---|
4595 | end
|
---|
4596 |
|
---|
4597 | def new_const_decl( decl )
|
---|
4598 | decl.set_owner self # Decl (Namespace:const)
|
---|
4599 | if ! decl.is_const? then # const 修飾さていること
|
---|
4600 | if decl.is_type?( PtrType ) then
|
---|
4601 | cdl_error( "S1094 $1: pointer is not constant. check \'const\'" , decl.get_name )
|
---|
4602 | else
|
---|
4603 | cdl_error( "S1095 $1: not constant" , decl.get_name )
|
---|
4604 | end
|
---|
4605 | elsif ! decl.is_type?( IntType ) && ! decl.is_type?( FloatType ) &&
|
---|
4606 | ! decl.is_type?( BoolType ) && ! decl.is_type?( PtrType ) then
|
---|
4607 | # IntType, FloatType であること
|
---|
4608 | cdl_error( "S1096 $1: should be int, float, bool or pointer type" , decl.get_name )
|
---|
4609 | elsif decl.get_initializer == nil then # 初期値を持つこと
|
---|
4610 | cdl_error( "S1097 $1: has no initializer" , decl.get_name )
|
---|
4611 | # elsif decl.get_initializer.eval_const(nil) == nil then #eval_const は check_init で呼出されるので二重チェック
|
---|
4612 | # # mikan 初期値が型に対し適切であること
|
---|
4613 | # cdl_error( "S1098 $1: has unsuitable initializer" , decl.get_name )
|
---|
4614 | else
|
---|
4615 | decl.get_type.check_init( @locale, decl.get_name, decl.get_initializer, :CONSTANT )
|
---|
4616 | @name_list.add_item( decl )
|
---|
4617 | @const_decl_list << decl
|
---|
4618 | end
|
---|
4619 |
|
---|
4620 | end
|
---|
4621 |
|
---|
4622 | ### region
|
---|
4623 | # def self.new_region( region )
|
---|
4624 | # @@namespace_stack[@@namespace_sp].new_region( region )
|
---|
4625 | # end
|
---|
4626 | #
|
---|
4627 | # def new_region( region )
|
---|
4628 | # region.set_owner self # Rgion (Namespace)
|
---|
4629 | # @name_list.add_item( region )
|
---|
4630 | # end
|
---|
4631 |
|
---|
4632 | ###
|
---|
4633 |
|
---|
4634 | #=== Namespace# すべてのセルの require ポートを設定
|
---|
4635 | # STAGE: S
|
---|
4636 | def set_require_join
|
---|
4637 | @celltype_list.each{ |ct|
|
---|
4638 | ct.set_require_join
|
---|
4639 | }
|
---|
4640 | # すべての namespace について require ポートをセット
|
---|
4641 | @namespace_list.each{ |ns|
|
---|
4642 | ns.set_require_join
|
---|
4643 | }
|
---|
4644 | end
|
---|
4645 |
|
---|
4646 | #=== Namespace# Join への definition の設定とチェック
|
---|
4647 | # セルタイプに属するすべてのセルに対して実施
|
---|
4648 | def set_definition_join
|
---|
4649 | # celltype のコードを生成
|
---|
4650 | @cell_list.each { |c|
|
---|
4651 | dbgPrint "set_definition_join #{c.get_name}\n"
|
---|
4652 | c.set_definition_join
|
---|
4653 | }
|
---|
4654 | @namespace_list.each{ |ns|
|
---|
4655 | ns.set_definition_join
|
---|
4656 | }
|
---|
4657 | end
|
---|
4658 |
|
---|
4659 | #=== Namespace# セルの結合をチェックする
|
---|
4660 | def check_join
|
---|
4661 | @cell_list.each { |c|
|
---|
4662 | dbgPrint "check_join #{c.get_name}\n"
|
---|
4663 | c.check_join
|
---|
4664 | c.check_reverse_require
|
---|
4665 | }
|
---|
4666 | @namespace_list.each{ |ns|
|
---|
4667 | ns.check_join
|
---|
4668 | }
|
---|
4669 | end
|
---|
4670 |
|
---|
4671 | #== Namespace# ルートか?
|
---|
4672 | # ルートネームスペース と ルートリージョンは同じ
|
---|
4673 | def is_root?
|
---|
4674 | @name == "::"
|
---|
4675 | end
|
---|
4676 |
|
---|
4677 | #== Namespace# ルートを得る
|
---|
4678 | # ルートリージョンとルートネームスペースは同じオブジェクト
|
---|
4679 | def self.get_root
|
---|
4680 | @@root_namespace
|
---|
4681 | end
|
---|
4682 |
|
---|
4683 | def show_tree( indent )
|
---|
4684 | indent.times { print " " }
|
---|
4685 | puts "#{self.class}: name: #{@name} path: #{get_namespace_path.get_path_str}"
|
---|
4686 | @struct_tag_list.show_tree( indent + 1 )
|
---|
4687 | @name_list.show_tree( indent + 1 )
|
---|
4688 | end
|
---|
4689 |
|
---|
4690 | end
|
---|
4691 |
|
---|
4692 |
|
---|
4693 | class Join < BDNode
|
---|
4694 | # @name:: string
|
---|
4695 | # @subscript:: nil: not array, -1: subscript not specified, >=0: array_subscript
|
---|
4696 | # @rhs:: Expression | initializer ( array of Expression | initializer (Expression | C_EXP) )
|
---|
4697 | # @definition:: Port, Decl(attribute or var)
|
---|
4698 | #
|
---|
4699 | # available if definition is Port
|
---|
4700 | # @cell_name:: string : 右辺のセルの名前
|
---|
4701 | # @cell:: Cell : 右辺のセル
|
---|
4702 | # @celltype:: Celltype : 右辺のセルタイプ
|
---|
4703 | # @port_name:: string : 右辺の受け口名
|
---|
4704 | # @port:: Port : 右辺の受け口
|
---|
4705 | # @array_member:: rhs array : available only for first appear in the same name
|
---|
4706 | # @array_member2:: Join array : available only for first appear in the same name
|
---|
4707 | # @rhs_subscript:: nil : not array, >=0: 右辺の添数
|
---|
4708 | #
|
---|
4709 |
|
---|
4710 | # @through_list:: @cp_through_list + @region_through_list
|
---|
4711 | # 以下の構造を持つ(@cp_through_list の構造は共通)
|
---|
4712 | # @cp_through_list:: 呼び口に指定された through
|
---|
4713 | # [ [plugin_name, cell_name, plugin_arg], [plugin_name2, cell_name2, plugin_arg], ... ]
|
---|
4714 | # @region_through_list:: region に指定された through
|
---|
4715 | # [ [plugin_name, cell_name, plugin_arg, region], [plugin_name2, cell_name2, plugin_arg, region2], ... ]
|
---|
4716 | #
|
---|
4717 | # @through_generated_list:: [Plugin_class object, ...]: @through_list に対応
|
---|
4718 | # @region_through_generated_list:: [Plugin_class object, ...]: @region_through_list に対応
|
---|
4719 | #
|
---|
4720 |
|
---|
4721 | include PluginModule
|
---|
4722 |
|
---|
4723 | #=== Join# 初期化
|
---|
4724 | #name:: string: 名前(属性名、呼び口名)
|
---|
4725 | #subscript:: Nil=非配列, -1="[]", N="[N]"
|
---|
4726 | #rhs:: Expression: 右辺の式
|
---|
4727 | def initialize( name, subscript, rhs, locale = nil )
|
---|
4728 | # dbgPrint "Join#new: #{name}, #{subscript} #{rhs.eval_const(nil)}\n"
|
---|
4729 | dbgPrint "Join#new: #{name}, #{subscript}\n"
|
---|
4730 |
|
---|
4731 | super()
|
---|
4732 | if locale then
|
---|
4733 | @locale = locale
|
---|
4734 | end
|
---|
4735 |
|
---|
4736 | @name = name
|
---|
4737 | if subscript.instance_of?( Expression ) then
|
---|
4738 | #mikan 配列添数が整数であることを未チェック
|
---|
4739 | @subscript = subscript.eval_const(nil)
|
---|
4740 | if @subscript == nil then
|
---|
4741 | cdl_error( "S1099 array subscript not constant" )
|
---|
4742 | end
|
---|
4743 | else
|
---|
4744 | @subscript = subscript
|
---|
4745 | end
|
---|
4746 |
|
---|
4747 | @rhs = rhs
|
---|
4748 | @definition = nil
|
---|
4749 |
|
---|
4750 | # 配列要素を設定
|
---|
4751 | # 本当は、初出の要素のみ設定するのが適当
|
---|
4752 | # new_join で add_array_member の中で初出要素の array_member に対し設定する
|
---|
4753 | if @subscript == -1 then
|
---|
4754 | @array_member = [self]
|
---|
4755 | @array_member2 = [self]
|
---|
4756 | elsif @subscript != nil then
|
---|
4757 | @array_member = []
|
---|
4758 | @array_member2 = []
|
---|
4759 | @array_member[@subscript] = self
|
---|
4760 | @array_member2[@subscript] = self
|
---|
4761 | end
|
---|
4762 |
|
---|
4763 | @through_list = []
|
---|
4764 | @cp_through_list = []
|
---|
4765 | @region_through_list = []
|
---|
4766 | @through_generated_list = []
|
---|
4767 | @region_through_generated_list = []
|
---|
4768 | end
|
---|
4769 |
|
---|
4770 | #=== Join# 左辺に対応する celltype の定義を設定するとともにチェックする
|
---|
4771 | # STAGE: S
|
---|
4772 | #
|
---|
4773 | # 代入可能かチェックする
|
---|
4774 | #definition:: Decl (attribute,varの時) または Port (callの時) または nil (definition が見つからなかった時)
|
---|
4775 |
|
---|
4776 | def set_definition( definition )
|
---|
4777 |
|
---|
4778 | dbgPrint "set_definition: #{@owner.get_name}.#{@name} = #{definition.class}\n"
|
---|
4779 |
|
---|
4780 | # 二重チェックの防止
|
---|
4781 | if @definition then
|
---|
4782 | # set_definition を個別に行うケースで、二重に行われる可能性がある(異常ではない)
|
---|
4783 | # 二重に set_definition が実行されると through が二重に適用されてしまう
|
---|
4784 | # cdl_warning( "W9999 $1, internal error: set_definition duplicate", @name )
|
---|
4785 | return
|
---|
4786 | end
|
---|
4787 |
|
---|
4788 | @definition = definition
|
---|
4789 |
|
---|
4790 | # mikan 左辺値、右辺値の型チェックなど
|
---|
4791 | if @definition.instance_of?( Decl ) then
|
---|
4792 | check_var_init
|
---|
4793 | elsif @definition.instance_of?( Port ) then
|
---|
4794 | check_call_port_init
|
---|
4795 | if @definition.get_port_type == :CALL then # :ENTRY ならエラー。無視しない
|
---|
4796 | check_and_gen_through
|
---|
4797 | create_allocator_join # through プラグイン生成した後でないと、挿入前のセルのアロケータを結合してしまう
|
---|
4798 | end
|
---|
4799 | elsif @definition == nil then
|
---|
4800 | cdl_error( "S1117 \'$1\' not in celltype", @name )
|
---|
4801 | else
|
---|
4802 | raise "UnknownToken"
|
---|
4803 | end
|
---|
4804 | end
|
---|
4805 |
|
---|
4806 | #=== Join# 変数の初期化チェック
|
---|
4807 | def check_var_init
|
---|
4808 | # attribute, var の場合
|
---|
4809 | if @definition.get_kind == :ATTRIBUTE then
|
---|
4810 | # check_cell_cb_init( definition.get_type, @rhs )
|
---|
4811 | # 右辺で初期化可能かチェック
|
---|
4812 | @definition.get_type.check_init( @locale, @definition.get_identifier, @rhs, :ATTRIBUTE )
|
---|
4813 | elsif @definition.get_kind == :VAR then
|
---|
4814 | # var は初期化できない
|
---|
4815 | cdl_error( "S1100 $1: cannot initialize var" , @name )
|
---|
4816 | else
|
---|
4817 | # Bug trap
|
---|
4818 | raise "UnknownDeclKind"
|
---|
4819 | end
|
---|
4820 | end
|
---|
4821 |
|
---|
4822 | #=== Join# 呼び口の初期化チェック
|
---|
4823 | def check_call_port_init
|
---|
4824 | ### Port
|
---|
4825 |
|
---|
4826 | # 左辺は受け口か(受け口を初期化しようとしている)?
|
---|
4827 | if @definition.get_port_type == :ENTRY then
|
---|
4828 | cdl_error( "S1101 \'$1\' cannot initialize entry port" , @name )
|
---|
4829 | return
|
---|
4830 | end
|
---|
4831 |
|
---|
4832 | # # 配列添数の整合性チェック
|
---|
4833 | # # 呼び口の定義で、非配列なら添数なし、添数なし配列なら添数なし、添数あり配列なら添数あり
|
---|
4834 | as = @definition.get_array_size
|
---|
4835 | if ( @subscript == nil && as != nil ) then
|
---|
4836 | cdl_error( "S1102 $1: must specify array subscript here" , @name )
|
---|
4837 | elsif ( @subscript != nil && as == nil ) then
|
---|
4838 | cdl_error( "S1103 $1: cannot specify array subscript here" , @name )
|
---|
4839 | end
|
---|
4840 | # if @subscript == nil then
|
---|
4841 | # if as != nil then
|
---|
4842 | # cdl_error( "S1103 $1: need array subscript" , @name )
|
---|
4843 | # end
|
---|
4844 | # elsif @subscript == -1 then
|
---|
4845 | # if as != "[]" then
|
---|
4846 | # cdl_error( "S1104 $1: need array subscript number. ex. \'[0]\'" , @name )
|
---|
4847 | # end
|
---|
4848 | # else # @subscript >0
|
---|
4849 | # if as == nil then
|
---|
4850 | # cdl_error( "S1105 $1: cannot specify array subscript here" , @name )
|
---|
4851 | # elsif as == "[]" then
|
---|
4852 | # cdl_error( "S1106 $1: cannot specify array subscript number. use \'[]\'" , @name )
|
---|
4853 | # end
|
---|
4854 | # end
|
---|
4855 |
|
---|
4856 | # mikan Expression の get_type で型導出させる方がスマート
|
---|
4857 | # mikan '=' の左辺が配列かどうか未チェック
|
---|
4858 | #(1) '=' の右辺は "Cell.ePort" の形式か?
|
---|
4859 | # 演算子は "." かつ "." の左辺が :IDENTIFIER
|
---|
4860 | # "." の右辺はチェック不要 (synatax 的に :IDENTIFIER)
|
---|
4861 | #(2) "Cell" は存在するか?(名前が一致するものはあるか)
|
---|
4862 | #(3) "Cell" は cell か?
|
---|
4863 | #(4) "Cell" の celltype は有効か? (無効なら既にエラー)
|
---|
4864 | #(5) "ePort" は "Cell" の celltype 内に存在するか?
|
---|
4865 | #(6) "ePort" は entry port か?
|
---|
4866 | #(7) signature は一致するか
|
---|
4867 |
|
---|
4868 | # 右辺がない(以前の段階でエラー)
|
---|
4869 | return unless @rhs
|
---|
4870 |
|
---|
4871 | # cCall = composite.cCall; のチェック.この形式は属性用
|
---|
4872 | # 呼び口を export するには cCall => composite.cCall; の形式を用いる
|
---|
4873 | if @rhs.instance_of?( Array ) == true && @rhs[0] == :COMPOSITE then
|
---|
4874 | cdl_error( "S1107 to export port, use \'cCall => composite.cCall\'" )
|
---|
4875 | return
|
---|
4876 | elsif ! @rhs.instance_of?( Expression ) then
|
---|
4877 | raise "Unknown bug. specify -t to find problem in source"
|
---|
4878 | end
|
---|
4879 |
|
---|
4880 | # 右辺の Expression の要素を取り出す
|
---|
4881 | ret = @rhs.analyze_cell_join_expression
|
---|
4882 | if ret == nil then #1
|
---|
4883 | cdl_error( "S1108 $1: rhs not \'Cell.ePort\' form" , @name )
|
---|
4884 | return
|
---|
4885 | end
|
---|
4886 |
|
---|
4887 | nsp, @rhs_subscript, @port_name = ret[0], ret[1], ret[2]
|
---|
4888 | @cell_name = nsp.get_name # mikan ns::cellname の形式の考慮
|
---|
4889 |
|
---|
4890 | # composite の定義の中なら object は結合先 cell か、見つからなければ nil が返る
|
---|
4891 | # composite の定義外なら false が返る
|
---|
4892 | object = CompositeCelltype.find( @cell_name )
|
---|
4893 | if object == false then
|
---|
4894 | # mikan 左辺が namespace に対応していないため。 path にして find
|
---|
4895 | # p nsp.get_path_str, nsp.get_path
|
---|
4896 | object = Namespace.find( nsp ) #1
|
---|
4897 | in_composite = false
|
---|
4898 | else
|
---|
4899 | if nsp.get_path.length != 1 then
|
---|
4900 | cdl_error( "$1 cannot have path", nsp.get_path_str )
|
---|
4901 | end
|
---|
4902 | in_composite = true
|
---|
4903 | end
|
---|
4904 |
|
---|
4905 | if object == nil then # (2)
|
---|
4906 | cdl_error( "S1109 \'$1\' not found" , @cell_name )
|
---|
4907 | elsif ! object.instance_of?( Cell ) then # (3)
|
---|
4908 | cdl_error( "S1110 \'$1\' not cell" , @cell_name )
|
---|
4909 | else
|
---|
4910 | dbgPrint "set_definition: set_f_ref #{@owner.get_name}.#{@name} => #{object.get_name}\n"
|
---|
4911 | object.set_f_ref
|
---|
4912 |
|
---|
4913 | # 右辺のセルのセルタイプ
|
---|
4914 | celltype = object.get_celltype
|
---|
4915 |
|
---|
4916 | if celltype then # (4)
|
---|
4917 | object2 = celltype.find( @port_name )
|
---|
4918 | if object2 == nil then # (5)
|
---|
4919 | cdl_error( "S1111 \'$1\' not found" , @port_name )
|
---|
4920 | elsif ! object2.instance_of? Port \
|
---|
4921 | || object2.get_port_type != :ENTRY then # (6)
|
---|
4922 | cdl_error( "S1112 \'$1\' not entry port" , @port_name )
|
---|
4923 | elsif @definition.get_signature != object2.get_signature then # (7)
|
---|
4924 | cdl_error( "S1113 \'$1\' signature mismatch" , @port_name )
|
---|
4925 | elsif object2.get_array_size then
|
---|
4926 | # 受け口配列
|
---|
4927 |
|
---|
4928 | unless @rhs_subscript then
|
---|
4929 | # 右辺に添数指定がなかった
|
---|
4930 | cdl_error( "S1114 \'$1\' should be array" , @port_name )
|
---|
4931 | else
|
---|
4932 |
|
---|
4933 | as = object2.get_array_size
|
---|
4934 | if( as.kind_of?( Integer ) && as <= @rhs_subscript )then
|
---|
4935 | # 受け口配列の大きさに対し、右辺の添数が同じか大きい
|
---|
4936 | cdl_error( "S1115 $1[$2]: subscript out of range (< $3)" , @port_name, @rhs_subscript, as )
|
---|
4937 | else
|
---|
4938 | dbgPrint "Join OK #{@owner.get_name}.#{@name}[#{@rhs_subscript}] = #{object.get_name}.#{@port_name} #{self}\n"
|
---|
4939 | @cell = object
|
---|
4940 | @celltype = celltype
|
---|
4941 | @port = object2
|
---|
4942 | # 右辺のセルの受け口 object2 を参照済みにする
|
---|
4943 | # object2: Port, @definition: Port
|
---|
4944 | @cell.set_entry_port_max_subscript( @port, @rhs_subscript )
|
---|
4945 | end
|
---|
4946 |
|
---|
4947 | # debug
|
---|
4948 | dbgPrint "Join set_definition: rhs: #{@cell} #{@cell.get_name if @cell}\n"
|
---|
4949 |
|
---|
4950 | end
|
---|
4951 | elsif @rhs_subscript then
|
---|
4952 | # 受け口配列でないのに右辺で添数指定されている
|
---|
4953 | cdl_error( "S1116 \'$1\' entry port is not array" , @port_name )
|
---|
4954 | else
|
---|
4955 | dbgPrint "Join OK #{@owner.get_name}.#{@name} = #{object.get_name}.#{@port_name} #{self}\n"
|
---|
4956 | @cell = object
|
---|
4957 | @port = object2
|
---|
4958 | @celltype = celltype
|
---|
4959 |
|
---|
4960 | # 右辺のセル object の受け口 object2 を参照済みにする
|
---|
4961 | # object2: Port, @definition: Port
|
---|
4962 |
|
---|
4963 | # debug
|
---|
4964 | # p "rhs: #{@cell} #{@cell.get_name}"
|
---|
4965 | end # end of port (object2) チェック
|
---|
4966 |
|
---|
4967 | #else
|
---|
4968 | # celltype == nil (すでにエラー)
|
---|
4969 | end # end of celltyep チェック
|
---|
4970 |
|
---|
4971 |
|
---|
4972 | check_region( object )
|
---|
4973 |
|
---|
4974 | end # end of cell (object) チェック
|
---|
4975 |
|
---|
4976 | end
|
---|
4977 |
|
---|
4978 | #=== Join# アロケータの結合を生成
|
---|
4979 | # STAGE: S
|
---|
4980 | #cell:: 呼び口の結合先のセル
|
---|
4981 | #
|
---|
4982 | # ここでは呼び口側に生成されるアロケータ呼び口の結合を生成
|
---|
4983 | # 受け口側は Cell の set_specifier_list で生成
|
---|
4984 | # a[*] の内容は Cell の set_specifier_list を参照
|
---|
4985 | def create_allocator_join
|
---|
4986 |
|
---|
4987 | cell = get_rhs_cell2 # 右辺のセルを得る
|
---|
4988 | port = get_rhs_port2
|
---|
4989 |
|
---|
4990 | if( cell && cell.get_allocator_list ) then # cell == nil なら既にエラー
|
---|
4991 |
|
---|
4992 | dbgPrint "create_allocator_join: #{@owner.get_name}.#{@name}=>#{cell ? cell.get_name : "nil"}\n"
|
---|
4993 |
|
---|
4994 | cell.get_allocator_list.each { |a|
|
---|
4995 |
|
---|
4996 | if( a[0+1] == port && a[1+1] == @rhs_subscript )then
|
---|
4997 | # 名前の一致するものの結合を生成する
|
---|
4998 | # 過不足は、別途チェックされる
|
---|
4999 | cp_name = :"#{@name}_#{a[2+1]}_#{a[3+1]}"
|
---|
5000 | # p "creating allocator join #{cp_name} #{@subscript} #{a[1+1]}"
|
---|
5001 | join = Join.new( cp_name, @subscript, a[4+1], @locale )
|
---|
5002 |
|
---|
5003 | #debug
|
---|
5004 | dbgPrint "create_allocator_join: #{@owner.get_name}.#{cp_name} [#{@subscript}] #{@name}\n"
|
---|
5005 | @owner.new_join join
|
---|
5006 | else
|
---|
5007 | dbgPrint "create_allocator_join:3 not #{@owner.get_name}.#{a[0+1]} #{@name}\n"
|
---|
5008 | end
|
---|
5009 | }
|
---|
5010 | end
|
---|
5011 | end
|
---|
5012 |
|
---|
5013 | #=== Join# リージョン間の結合をチェック
|
---|
5014 | # リージョン間の through による @region_through_list の作成
|
---|
5015 | # 実際の生成は check_and_gen_through で行う
|
---|
5016 | # mikan Cell#distance とRegion へたどり着くまでための処理に共通部分が多い
|
---|
5017 | def check_region( object )
|
---|
5018 |
|
---|
5019 | #debug
|
---|
5020 | dbgPrint "check_region #{@owner.get_name}.#{@name} => #{object.get_name}\n"
|
---|
5021 | # print "DOMAIN: check_region #{@owner.get_name}.#{@name} => #{object.get_name}\n"
|
---|
5022 |
|
---|
5023 | # プラグインで生成されたなかでは生成しない
|
---|
5024 | # さもないとプラグイン生成されたものとの間で、無限に生成される
|
---|
5025 | ## if Generator.get_nest >= 1 then
|
---|
5026 | ## if Generator.get_plugin then # mikan これは必要? (意味解析段階での実行になるので不適切)
|
---|
5027 | if @owner.get_plugin.kind_of?( ThroughPlugin ) then
|
---|
5028 | # プラグイン生成されたセルの場合、結合チェックのみ
|
---|
5029 | return
|
---|
5030 | end
|
---|
5031 |
|
---|
5032 | # region のチェック
|
---|
5033 | r1 = @owner.get_region # 呼び口セルの region
|
---|
5034 | r2 = object.get_region # 受け口セルの region
|
---|
5035 |
|
---|
5036 | if ! r1.equal? r2 then # 同一 region なら呼出し可能
|
---|
5037 |
|
---|
5038 | f1 = r1.get_family_line
|
---|
5039 | len1 = f1.length
|
---|
5040 | f2 = r2.get_family_line
|
---|
5041 | len2 = f2.length
|
---|
5042 |
|
---|
5043 | # 不一致になるところ(兄弟)を探す
|
---|
5044 | i = 1 # i = 0 は :RootRegion なので必ず一致
|
---|
5045 | while( i < len1 && i < len2 )
|
---|
5046 | if( f1[i] != f2[i] )then
|
---|
5047 | break
|
---|
5048 | end
|
---|
5049 | i += 1
|
---|
5050 | end
|
---|
5051 |
|
---|
5052 | sibling_level = i # 兄弟となるレベル、もしくはどちらか一方が終わったレベル
|
---|
5053 |
|
---|
5054 | dbgPrint "sibling_level: #{i}\n"
|
---|
5055 | dbgPrint "from: #{f1[i].get_name}\n" if f1[i]
|
---|
5056 | dbgPrint "to: #{f2[i].get_name}\n" if f2[i]
|
---|
5057 |
|
---|
5058 | if f1[sibling_level] && f2[sibling_level] then
|
---|
5059 | b_to_through = true
|
---|
5060 | else
|
---|
5061 | b_to_through = false
|
---|
5062 | end
|
---|
5063 |
|
---|
5064 |
|
---|
5065 | # 呼び側について呼び元のレベルから兄弟レベルまで(out_through をチェックおよび挿入)
|
---|
5066 | i = len1 -1
|
---|
5067 | if b_to_through then
|
---|
5068 | end_level = sibling_level
|
---|
5069 | else
|
---|
5070 | end_level = sibling_level - 1
|
---|
5071 | end
|
---|
5072 | while i > end_level
|
---|
5073 | # while i > sibling_level
|
---|
5074 | # while i >= sibling_level
|
---|
5075 | dbgPrint "going out from #{f1[i].get_name} level=#{i}\n"
|
---|
5076 | region_count = f1[i].next_out_through_count
|
---|
5077 | out_through_list = f1[i].get_out_through_list # [ plugin_name, plugin_arg ]
|
---|
5078 | domain = f1[i].get_domain_type
|
---|
5079 | if domain then
|
---|
5080 | domain_through = f1[i].get_domain_type.add_through_plugin( self, f1[i], f1[i-1], :OUT_THROUGH )
|
---|
5081 | if domain_through == nil then
|
---|
5082 | cdl_error( "S9999 $1: going out from regin '$2' not permitted by domain '$3'" , @name, f1[i].get_name, f1[i].get_domain_type.get_name )
|
---|
5083 | end
|
---|
5084 | elsif out_through_list.length == 0 then
|
---|
5085 | cdl_error( "S1118 $1: going out from region \'$2\' not permitted" , @name, f1[i].get_name )
|
---|
5086 | end
|
---|
5087 |
|
---|
5088 | out_through_list.each { |ol|
|
---|
5089 | if ol[0] then # plugin_name が指定されていなければ登録しない
|
---|
5090 | plugin_arg = CDLString.remove_dquote ol[1]
|
---|
5091 | through = [ ol[0], :"Join_out_through_", plugin_arg, f1[i], f1[i-1], :OUT_THROUGH, region_count]
|
---|
5092 | @region_through_list << through
|
---|
5093 | end
|
---|
5094 | }
|
---|
5095 | if domain_through && domain_through.length > 0 then
|
---|
5096 | through = [ domain_through[0], :"Join_domain_out_through_", domain_through[1], f1[i], f1[i-1], :OUT_THROUGH, region_count ]
|
---|
5097 | @region_through_list << through
|
---|
5098 | end
|
---|
5099 | i -= 1
|
---|
5100 | end
|
---|
5101 |
|
---|
5102 | # 兄弟レベルにおいて(to_through をチェックおよび挿入)
|
---|
5103 | if f1[sibling_level] && f2[sibling_level] then
|
---|
5104 | dbgPrint "going from #{f1[sibling_level].get_name} to #{f2[sibling_level].get_name}\n"
|
---|
5105 | found = 0
|
---|
5106 | region_count = f1[i].next_to_through_count( f2[sibling_level].get_name ) # to_through の region カウント
|
---|
5107 | f1[sibling_level].get_to_through_list.each { |t|
|
---|
5108 | if t[0][0] == f2[sibling_level].get_name then # region 名が一致するか ?
|
---|
5109 | if t[1] then # plugin_name が指定されていなければ登録しない
|
---|
5110 | plugin_arg = CDLString.remove_dquote t[2]
|
---|
5111 | through = [ t[1], :"Join_to_through__", plugin_arg, f1[sibling_level], f2[sibling_level], :TO_THROUGH, region_count ]
|
---|
5112 | @region_through_list << through
|
---|
5113 | end
|
---|
5114 | found = 1
|
---|
5115 | end
|
---|
5116 | }
|
---|
5117 | domain = f1[sibling_level].get_domain_type
|
---|
5118 | if domain then
|
---|
5119 | domain_through = f1[sibling_level].get_domain_type.add_through_plugin( self, f1[sibling_level], f2[sibling_level], :TO_THROUGH )
|
---|
5120 | if domain_through == nil then
|
---|
5121 | cdl_error( "S9999 $1: going from regin '$2' not permitted by domain'$3'" , @name, f1[sibling_level].get_name, f2[sibling_level].get_domain_type.get_name )
|
---|
5122 | end
|
---|
5123 | if domain_through && domain_through.length > 0 then
|
---|
5124 | through = [ domain_through[0], :"Join_domain_to_through_", domain_through[1], f1[sibling_level], f2[sibling_level], :TO_THROUGH, region_count ]
|
---|
5125 | @region_through_list << through
|
---|
5126 | end
|
---|
5127 | elsif found == 0 then
|
---|
5128 | cdl_error( "S1119 $1: going from region \'$2\' to \'$3\' not permitted" , @name, f1[sibling_level].get_name, f2[sibling_level].get_name )
|
---|
5129 | end
|
---|
5130 | end
|
---|
5131 |
|
---|
5132 | # 受け側について兄弟レベルから受け側のレベルまで(in_through をチェックおよび挿入)
|
---|
5133 | if b_to_through then
|
---|
5134 | i = sibling_level + 1 # to_through を経た場合、最初の in_through は適用しない
|
---|
5135 | else
|
---|
5136 | i = sibling_level
|
---|
5137 | end
|
---|
5138 | while i < len2
|
---|
5139 | dbgPrint "going in to #{f2[i].get_name} level=#{i}\n"
|
---|
5140 | region_count = f2[i].next_in_through_count
|
---|
5141 | in_through_list = f2[i].get_in_through_list # [ plugin_name, plugin_arg ]
|
---|
5142 | domain = f2[i].get_domain_type
|
---|
5143 | if domain then
|
---|
5144 | domain_through = f2[i].get_domain_type.add_through_plugin( self, f2[i-1], f2[i], :IN_THROUGH )
|
---|
5145 | if domain_through == nil then
|
---|
5146 | cdl_error( "S9999 $1: going in from regin '$2' to '$3' not permitted by domain '$4'",
|
---|
5147 | @name, f2[i-1].get_name, f2[i].get_name, f2[i].get_domain_type.get_name )
|
---|
5148 | end
|
---|
5149 | if domain_through && domain_through.length > 0 then
|
---|
5150 | through = [ domain_through[0], :"Join_domain_in_through_", domain_through[1], f2[i-1], f2[i], :IN_THROUGH, region_count ]
|
---|
5151 | @region_through_list << through
|
---|
5152 | end
|
---|
5153 | elsif in_through_list.length == 0 then
|
---|
5154 | cdl_error( "S1120 $1: going in to region \'$2\' not permitted" , @name, f2[i].get_name )
|
---|
5155 | end
|
---|
5156 | in_through_list.each { |il|
|
---|
5157 | if il[0] then # plugin_name が指定されていなければ登録しない
|
---|
5158 | plugin_arg = CDLString.remove_dquote il[1]
|
---|
5159 | through = [ il[0], :"Join_in_through_", plugin_arg, f2[i-1], f2[i],:IN_THROUGH, region_count ]
|
---|
5160 | @region_through_list << through
|
---|
5161 | end
|
---|
5162 | }
|
---|
5163 | i += 1
|
---|
5164 | end
|
---|
5165 |
|
---|
5166 | end
|
---|
5167 | end
|
---|
5168 |
|
---|
5169 |
|
---|
5170 | #=== Join# 生成しないリージョンへの結合かチェック
|
---|
5171 | # 右辺のセルが、生成されないリージョンにあればエラー
|
---|
5172 | # 右辺は、プラグイン生成されたセルがあれば、それを対象とする
|
---|
5173 | def check_region2
|
---|
5174 | lhs_cell = @owner
|
---|
5175 |
|
---|
5176 | # 生成しないリージョンのセルへの結合か?
|
---|
5177 | # if join.get_cell && ! join.get_cell.is_generate? then
|
---|
5178 | # if get_rhs_cell && ! get_rhs_cell.is_generate? then # composite セルがプロタイプ宣言の場合例外
|
---|
5179 | # print "Link root: (caller #{@owner.get_name}) '#{@owner.get_region.get_link_root.get_name}'"
|
---|
5180 | # print " #{@owner.get_region.get_link_root == get_rhs_region.get_link_root ? "==" : "!="} "
|
---|
5181 | # print "'#{get_rhs_region.get_link_root.get_name}' (callee #{@cell_name})\n"
|
---|
5182 |
|
---|
5183 | if get_rhs_region then
|
---|
5184 | dbgPrint "check_region2 #{lhs_cell.get_name} => #{get_rhs_region.get_path_string}#{@rhs.to_s}\n"
|
---|
5185 |
|
---|
5186 | # if get_rhs_region.is_generate? != true then #3
|
---|
5187 | if @owner.get_region.get_link_root != get_rhs_region.get_link_root then
|
---|
5188 | cdl_error( "S1121 \'$1\' in region \'$2\' cannot be directly joined $3 in $4" , lhs_cell.get_name, lhs_cell.get_region.get_namespace_path.get_path_str, @rhs.to_s, get_rhs_region.get_namespace_path.get_path_str )
|
---|
5189 | end
|
---|
5190 | else
|
---|
5191 | # rhs のセルが存在しなかった (既にエラー)
|
---|
5192 | end
|
---|
5193 | end
|
---|
5194 |
|
---|
5195 | def get_definition
|
---|
5196 | @definition
|
---|
5197 | end
|
---|
5198 |
|
---|
5199 | #=== Join# specifier を設定
|
---|
5200 | # STAGE: B
|
---|
5201 | # set_specifier_list は、join の解析の最後で呼び出される
|
---|
5202 | # through 指定子を設定
|
---|
5203 | # check_and_gen_through を呼出して、through 生成
|
---|
5204 | def set_specifier_list( specifier_list )
|
---|
5205 |
|
---|
5206 | specifier_list.each { |s|
|
---|
5207 | case s[0]
|
---|
5208 | when :THROUGH
|
---|
5209 | # set plugin_name
|
---|
5210 | plugin_name = s[1].to_s
|
---|
5211 | plugin_name[0] = "#{plugin_name[/^./].upcase}" # 先頭文字を大文字に : ruby のクラス名の制約
|
---|
5212 |
|
---|
5213 | # set cell_name
|
---|
5214 | cell_name = :"#{s[1].to_s}_"
|
---|
5215 |
|
---|
5216 | # set plugin_arg
|
---|
5217 | plugin_arg = CDLString.remove_dquote s[2].to_s
|
---|
5218 | # plugin_arg = s[2].to_s.gsub( /\A"(.*)/, '\1' ) # 前後の "" を取り除く
|
---|
5219 | # plugin_arg.sub!( /(.*)"\z/, '\1' )
|
---|
5220 |
|
---|
5221 | @cp_through_list << [ plugin_name, cell_name, plugin_arg ]
|
---|
5222 | end
|
---|
5223 | }
|
---|
5224 |
|
---|
5225 | end
|
---|
5226 |
|
---|
5227 | #=== Join# through のチェックと生成
|
---|
5228 | # new_join の中の check_region で region 間の through が @region_through に設定される
|
---|
5229 | # set_specifier で呼び口の結合で指定された through が @cp_through 設定される
|
---|
5230 | # その後、このメソッドが呼ばれる
|
---|
5231 | def check_and_gen_through
|
---|
5232 |
|
---|
5233 | dbgPrint "check_and_gen_through #{@owner.get_name}.#{@name}\n"
|
---|
5234 |
|
---|
5235 | if ! @definition.instance_of? Port then
|
---|
5236 | cdl_error( "S1123 $1 : not port: \'through\' can be specified only for port" , @name )
|
---|
5237 | return
|
---|
5238 | end
|
---|
5239 | if @cp_through_list.length > 0 then
|
---|
5240 | # is_empty? must check before is_omit?
|
---|
5241 | if @definition.get_signature && @definition.get_signature.is_empty? then
|
---|
5242 | cdl_warning( "W9999 'through' is specified for empty signature, ignored" )
|
---|
5243 | return
|
---|
5244 | elsif @definition.is_omit? then
|
---|
5245 | cdl_warning( "W9999 'through' is specified for omitted port, ignored" )
|
---|
5246 | return
|
---|
5247 | end
|
---|
5248 | end
|
---|
5249 |
|
---|
5250 | @through_list = @cp_through_list + @region_through_list
|
---|
5251 | # 後から @cp_through_list と @region_through_list に分けたため、このような実装になった
|
---|
5252 |
|
---|
5253 | if @through_list then # nil when the join is not Port
|
---|
5254 | len = @through_list.length # through が連接している数
|
---|
5255 | else
|
---|
5256 | len = 0
|
---|
5257 | end
|
---|
5258 | cp_len = @cp_through_list.length
|
---|
5259 |
|
---|
5260 | if @owner.is_in_composite? && len > 0 then
|
---|
5261 | cdl_error( "S1177 cannot specify 'through' in composite in current version" )
|
---|
5262 | return
|
---|
5263 | end
|
---|
5264 |
|
---|
5265 | # 連続した through について、受け口側から順にセルを生成し解釈する
|
---|
5266 | i = len - 1
|
---|
5267 | while i >= 0
|
---|
5268 |
|
---|
5269 | through = @through_list[ i ]
|
---|
5270 | plugin_name = through[ 0 ]
|
---|
5271 | generating_cell_name = through[ 1 ]
|
---|
5272 | plugin_arg = through[ 2 ]
|
---|
5273 |
|
---|
5274 | if i != len - 1 then
|
---|
5275 |
|
---|
5276 | begin
|
---|
5277 | next_cell_nsp = @through_generated_list[ i + 1 ].get_cell_namespace_path
|
---|
5278 | next_port_name = @through_generated_list[ i + 1 ].get_through_entry_port_name
|
---|
5279 | rescue Exception => evar
|
---|
5280 | cdl_error( "S1124 $1: plugin function failed: \'get_through_entry_port_name\'" , plugin_name )
|
---|
5281 | print_exception( evar )
|
---|
5282 | i -= 1
|
---|
5283 | next
|
---|
5284 | end
|
---|
5285 |
|
---|
5286 | next_cell = Namespace.find( next_cell_nsp ) #1
|
---|
5287 | if next_cell == nil then
|
---|
5288 | # p "next_cell_path: #{next_cell_nsp.get_path_str}"
|
---|
5289 | cdl_error( "S1125 $1: not generated cell \'$2\'" , @through_generated_list[ i + 1 ].class, next_cell_nsp.get_path_str )
|
---|
5290 | return
|
---|
5291 | end
|
---|
5292 |
|
---|
5293 | else
|
---|
5294 | # 最後のセルの場合、次のセルの名前、ポート名
|
---|
5295 | next_cell = @cell
|
---|
5296 | next_port_name = @port_name
|
---|
5297 |
|
---|
5298 | if next_cell == nil then
|
---|
5299 | # 結合先がない
|
---|
5300 | return
|
---|
5301 | end
|
---|
5302 | end
|
---|
5303 |
|
---|
5304 | if i >= cp_len then
|
---|
5305 | # region_through_list 部分
|
---|
5306 | # region から @cell_name.@port_name への through がないか探す
|
---|
5307 | # rp = @through_list[i][3].find_cell_port_through_plugin( @cell_name, @port_name ) #762
|
---|
5308 | rp = @through_list[i][3].find_cell_port_through_plugin( @cell.get_global_name, @port_name )
|
---|
5309 | # @through_list[i] と @region_through_list[i-cp_len] は同じ
|
---|
5310 | # 共用しないようにするには、見つからなかったことにすればよい
|
---|
5311 | # rp = nil
|
---|
5312 | else
|
---|
5313 | # region 以外のものは共有しない
|
---|
5314 | # 呼び口側に指定されているし、plugin_arg が異なるかもしれない
|
---|
5315 | rp = nil
|
---|
5316 | end
|
---|
5317 |
|
---|
5318 | if rp == nil then
|
---|
5319 | if( load_plugin( plugin_name, ThroughPlugin ) ) then
|
---|
5320 | gen_through_cell_code_and_parse( plugin_name, i, next_cell, next_port_name )
|
---|
5321 | end
|
---|
5322 | else
|
---|
5323 | # 見つかったものを共用する
|
---|
5324 | @through_generated_list[ i ] = rp
|
---|
5325 | end
|
---|
5326 |
|
---|
5327 | if i >= cp_len then
|
---|
5328 | # @through_generated_list のうち @region_through_listに対応する部分
|
---|
5329 | @region_through_generated_list[ i - cp_len ] = @through_generated_list[ i ]
|
---|
5330 | if rp == nil then
|
---|
5331 | # 生成したものを region(@through_list[i][3]) のリストに追加
|
---|
5332 | # @through_list[i][3].add_cell_port_through_plugin( @cell_name, @port_name, @through_generated_list[i] ) #762
|
---|
5333 | @through_list[i][3].add_cell_port_through_plugin( @cell.get_global_name, @port_name, @through_generated_list[i] )
|
---|
5334 | end
|
---|
5335 | end
|
---|
5336 |
|
---|
5337 | if i == 0 then
|
---|
5338 | # 最も呼び口側のセルは、CDL 上の結合がないため、参照されたことにならない
|
---|
5339 | # mikan namespace 対応
|
---|
5340 | # cell = Namespace.find( [ @through_generated_list[0].get_cell_name] ) #1
|
---|
5341 | if @through_generated_list[0] == nil then
|
---|
5342 | return # plugin_object の生成に失敗している
|
---|
5343 | end
|
---|
5344 | cell = Namespace.find( @through_generated_list[0].get_cell_namespace_path ) #1
|
---|
5345 | if cell.instance_of? Cell then
|
---|
5346 | cell.set_f_ref
|
---|
5347 | end
|
---|
5348 | end
|
---|
5349 |
|
---|
5350 | i -= 1
|
---|
5351 | end
|
---|
5352 |
|
---|
5353 | end
|
---|
5354 |
|
---|
5355 | @@through_count = { }
|
---|
5356 | def get_through_count name
|
---|
5357 | sym = name.to_sym
|
---|
5358 | if @@through_count[ sym ] then
|
---|
5359 | @@through_count[ sym ] += 1
|
---|
5360 | else
|
---|
5361 | @@through_count[ sym ] = 0
|
---|
5362 | end
|
---|
5363 | return @@through_count[ sym ]
|
---|
5364 | end
|
---|
5365 |
|
---|
5366 | #=== Join# through プラグインを呼び出して CDL 生成させるとともに、import する
|
---|
5367 | def gen_through_cell_code_and_parse( plugin_name, i, next_cell, next_port_name )
|
---|
5368 |
|
---|
5369 | through = @through_list[ i ]
|
---|
5370 | plugin_name = through[ 0 ]
|
---|
5371 | generating_cell_name = :"#{through[ 1 ]}_#{get_through_count through[ 1 ]}"
|
---|
5372 | plugin_arg = through[ 2 ]
|
---|
5373 | if through[ 3 ] then
|
---|
5374 | # region 間の through の場合
|
---|
5375 | @@start_region = through[ 3 ]
|
---|
5376 | if next_cell.get_region.equal? @@start_region then
|
---|
5377 | @@end_region = @@start_region
|
---|
5378 | else
|
---|
5379 | @@end_region = through[ 4 ]
|
---|
5380 | end
|
---|
5381 | @@through_type = through[ 5 ]
|
---|
5382 | @@region_count = through[ 6 ]
|
---|
5383 | else
|
---|
5384 | # 呼び口の through の場合
|
---|
5385 | @@start_region = @owner.get_region # 呼び口側セルの region
|
---|
5386 | @@end_region = next_cell.get_region # 次のセルの region
|
---|
5387 | @@through_type = :THROUGH # 呼び口の through 指定
|
---|
5388 | @@region_count = 0
|
---|
5389 | end
|
---|
5390 | @@plugin_creating_join = self
|
---|
5391 |
|
---|
5392 | caller_cell = @owner
|
---|
5393 |
|
---|
5394 | plugin_object = nil
|
---|
5395 | eval_str = "plugin_object = #{plugin_name}.new( '#{generating_cell_name}'.to_sym, plugin_arg.to_s, next_cell, '#{next_port_name}'.to_sym, @definition.get_signature, @celltype, caller_cell )"
|
---|
5396 | if $verbose then
|
---|
5397 | print "new through: #{eval_str}\n"
|
---|
5398 | end
|
---|
5399 |
|
---|
5400 | begin
|
---|
5401 | eval( eval_str ) # plugin を生成
|
---|
5402 | plugin_object.set_locale @locale
|
---|
5403 | rescue Exception => evar
|
---|
5404 | cdl_error( "S1126 $1: fail to new" , plugin_name )
|
---|
5405 | if @celltype && @definition.get_signature && caller_cell && next_cell then
|
---|
5406 | print "signature: #{@definition.get_signature.get_name} from: #{caller_cell.get_name} to: #{next_cell.get_name} of celltype: #{@celltype.get_name}\n"
|
---|
5407 | end
|
---|
5408 | print "eval( #{eval_str} )\n"
|
---|
5409 |
|
---|
5410 | print_exception( evar )
|
---|
5411 | return
|
---|
5412 | end
|
---|
5413 |
|
---|
5414 | @through_generated_list[ i ] = plugin_object
|
---|
5415 |
|
---|
5416 | # Region に関する情報を設定
|
---|
5417 | # 後から追加したので、new の引数外で設定
|
---|
5418 | # plugin_object.set_through_info( start_region, end_region, through_type )
|
---|
5419 |
|
---|
5420 | generate_and_parse plugin_object
|
---|
5421 | end
|
---|
5422 |
|
---|
5423 | #プラグインへの引数で渡さないものを、一時的に記憶しておく
|
---|
5424 | # プラグインの initialize の中でコールバックして設定する
|
---|
5425 | @@plugin_creating_join = nil
|
---|
5426 | @@start_region = nil
|
---|
5427 | @@end_region = nil
|
---|
5428 | @@through_type = nil
|
---|
5429 | @@region_count = nil
|
---|
5430 |
|
---|
5431 | #=== Join# ThroughPlugin の追加情報を設定する
|
---|
5432 | # このメソッドは ThroughPlugin#initialize から呼び出される
|
---|
5433 | # plugin_object を生成する際の引数では不足する情報を追加する
|
---|
5434 | def self.set_through_info plugin_object
|
---|
5435 | plugin_object.set_through_info( @@start_region, @@end_region, @@through_type,
|
---|
5436 | @@plugin_creating_join,
|
---|
5437 | @@plugin_creating_join.get_cell,
|
---|
5438 | @@region_count )
|
---|
5439 | end
|
---|
5440 |
|
---|
5441 | def get_name
|
---|
5442 | @name
|
---|
5443 | end
|
---|
5444 |
|
---|
5445 | #=== Join#配列添数を得る
|
---|
5446 | # @subscript の説明を参照のこと
|
---|
5447 | def get_subscript
|
---|
5448 | @subscript
|
---|
5449 | end
|
---|
5450 |
|
---|
5451 | def get_cell_name # 受け口セル名
|
---|
5452 | @cell_name
|
---|
5453 | end
|
---|
5454 |
|
---|
5455 | def get_celltype
|
---|
5456 | @celltype
|
---|
5457 | end
|
---|
5458 |
|
---|
5459 | def get_cell
|
---|
5460 | @cell
|
---|
5461 | end
|
---|
5462 |
|
---|
5463 | #=== Join# 右辺の実セルを得る
|
---|
5464 | # 実セルとは through で挿入されたもの、composite の内部など実際に結合される先
|
---|
5465 | # このメソッドは get_rhs_port と対になっている
|
---|
5466 | # このメソッドは、意味解析段階では呼び出してはならない (対象セルの意味解析が済む前には正しい結果を返さない)
|
---|
5467 | def get_rhs_cell
|
---|
5468 | # through 指定あり?
|
---|
5469 | if @through_list[0] then
|
---|
5470 | # mikan through で生成したものが root namespace 限定
|
---|
5471 | if @through_generated_list[0] then
|
---|
5472 | # cell = Namespace.find( [ "::", @through_generated_list[0].get_cell_name.to_sym ] ) #1
|
---|
5473 | cell = Namespace.find( @through_generated_list[0].get_cell_namespace_path ) #1
|
---|
5474 | # cell が nil になるのはプラグインの get_cell_namespace_path が正しくないか、
|
---|
5475 | # プラグイン生成コードがエラーになっている。
|
---|
5476 | # できの悪いプラグインが多ければ、cell == nil をはじいた方がよい。
|
---|
5477 | return cell.get_real_cell( @through_generated_list[0].get_through_entry_port_name )
|
---|
5478 | else
|
---|
5479 | return nil # generate に失敗している
|
---|
5480 | end
|
---|
5481 | elsif @cell then
|
---|
5482 | return @cell.get_real_cell( @port_name )
|
---|
5483 | else
|
---|
5484 | # 右辺が未定義の場合 @cell は nil (既にエラー)
|
---|
5485 | return nil
|
---|
5486 | end
|
---|
5487 | end
|
---|
5488 |
|
---|
5489 | #=== Join# 右辺のセルを得る
|
---|
5490 | # 右辺のセルを得る。ただし、composite 展開されていない
|
---|
5491 | # composite 展開されたものを得るには get_rhs_cell を使う
|
---|
5492 | # プロトタイプ宣言しかされていない場合には、こちらしか使えない
|
---|
5493 | # このメソッドは get_rhs_port2 と対になっている
|
---|
5494 | def get_rhs_cell2
|
---|
5495 | # through 指定あり?
|
---|
5496 | if @through_list[0] then
|
---|
5497 | # mikan through で生成したものが root namespace 限定
|
---|
5498 | # cell = Namespace.find( [ "::", @through_generated_list[0].get_cell_name ] )
|
---|
5499 | if @through_generated_list[0] then
|
---|
5500 | # cell = Namespace.find( [ @through_generated_list[0].get_cell_name ] ) #1
|
---|
5501 | cell = Namespace.find( @through_generated_list[0].get_cell_namespace_path ) #1
|
---|
5502 | else
|
---|
5503 | cell = @cell # generate に失敗している
|
---|
5504 | end
|
---|
5505 | else
|
---|
5506 | cell = @cell
|
---|
5507 | end
|
---|
5508 |
|
---|
5509 | return cell
|
---|
5510 | end
|
---|
5511 |
|
---|
5512 | #=== Join# 右辺のセルを得る
|
---|
5513 | # through は適用しないが、composite は展開した後のセル
|
---|
5514 | # (意味解析が終わっていないと、composite 展開が終わっていない)
|
---|
5515 | # このメソッドは get_rhs_port3 と対になっている
|
---|
5516 | def get_rhs_cell3
|
---|
5517 | if @cell then
|
---|
5518 | return @cell.get_real_cell( @port_name )
|
---|
5519 | end
|
---|
5520 | end
|
---|
5521 |
|
---|
5522 | #=== Join# 右辺のセルのリージョンを得る
|
---|
5523 | # 右辺が未定義の場合、nil を返す
|
---|
5524 | # composite の場合、実セルではなく composite cell の region を返す(composite はすべて同じ region に属する)
|
---|
5525 | # composite の cell がプロトタイプ宣言されているとき get_rhs_cell/get_real_cell は ruby の例外となる
|
---|
5526 | def get_rhs_region
|
---|
5527 | # through 指定あり?
|
---|
5528 | if @through_list[0] then
|
---|
5529 | if @through_generated_list[0] then
|
---|
5530 | # mikan through で生成したものが root namespace 限定
|
---|
5531 | # cell = Namespace.find( [ "::", @through_generated_list[0].get_cell_name.to_sym ] ) #1
|
---|
5532 | cell = Namespace.find( @through_generated_list[0].get_cell_namespace_path ) #1
|
---|
5533 | if cell then
|
---|
5534 | return cell.get_region
|
---|
5535 | end
|
---|
5536 | else
|
---|
5537 | return nil # generate に失敗している
|
---|
5538 | end
|
---|
5539 | elsif @cell then
|
---|
5540 | return @cell.get_region
|
---|
5541 | end
|
---|
5542 | # 右辺が未定義の場合 @cell は nil (既にエラー)
|
---|
5543 | return nil
|
---|
5544 | end
|
---|
5545 |
|
---|
5546 | def get_cell_global_name # 受け口セル名(コンポジットなら展開した内側のセル)
|
---|
5547 |
|
---|
5548 | # debug
|
---|
5549 | dbgPrint "cell get_cell_global_name: #{@cell_name}\n"
|
---|
5550 | # @cell.show_tree( 1 )
|
---|
5551 |
|
---|
5552 | if @cell then
|
---|
5553 | return @cell.get_real_global_name( @port_name )
|
---|
5554 | else
|
---|
5555 | return "NonDefinedCell?"
|
---|
5556 | end
|
---|
5557 |
|
---|
5558 | end
|
---|
5559 |
|
---|
5560 | #=== Join# 結合の右辺の受け口の名前
|
---|
5561 | # namespace 名 + '_' + セル名 + '_' + 受け口名 (このセルが composite ならば展開後のセル名、受け口名)
|
---|
5562 | #subscript:: Integer 呼び口配列の時添数 または nil 呼び口配列でない時
|
---|
5563 | def get_port_global_name( subscript = nil ) # 受け口名(コンポジットなら展開した内側のセル)
|
---|
5564 |
|
---|
5565 | # debug
|
---|
5566 | dbgPrint "Cell get_port_global_name: #{@cell_name}\n"
|
---|
5567 |
|
---|
5568 | # through 指定あり?
|
---|
5569 | if @through_list[0] then
|
---|
5570 |
|
---|
5571 | # mikan through で生成したものが root namespace 限定
|
---|
5572 | # cell = Namespace.find( [ "::", @through_generated_list[0].get_cell_name.to_sym ] ) #1
|
---|
5573 | cell = Namespace.find( @through_generated_list[0].get_cell_namespace_path ) #1
|
---|
5574 |
|
---|
5575 | # through で挿入されたセルで、実際に接続されるセル(compositeの場合内部の)の受け口の C 言語名前
|
---|
5576 | return cell.get_real_global_port_name( @through_generated_list[0].get_through_entry_port_name )
|
---|
5577 | else
|
---|
5578 |
|
---|
5579 | # 実際に接続されるセルの受け口の C 言語名前
|
---|
5580 | if @cell then
|
---|
5581 | return @cell.get_real_global_port_name( @port_name )
|
---|
5582 | else
|
---|
5583 | return "UndefinedCellsPort?"
|
---|
5584 | end
|
---|
5585 |
|
---|
5586 | end
|
---|
5587 |
|
---|
5588 | end
|
---|
5589 |
|
---|
5590 | def get_port_name
|
---|
5591 | @port_name
|
---|
5592 | end
|
---|
5593 |
|
---|
5594 | def get_rhs
|
---|
5595 | @rhs
|
---|
5596 | end
|
---|
5597 |
|
---|
5598 | def get_rhs_subscript
|
---|
5599 | @rhs_subscript
|
---|
5600 | end
|
---|
5601 |
|
---|
5602 | #=== Join# 右辺のポートを得る
|
---|
5603 | # 右辺が composite の場合は、内部の繋がるセルのポート, through の場合は挿入されたセルのポート
|
---|
5604 | # このメソッドは get_rhs_cell と対になっている
|
---|
5605 | def get_rhs_port
|
---|
5606 | # through 指定あり?
|
---|
5607 | if @through_list[0] then
|
---|
5608 | # mikan through で生成したものが root namespace 限定
|
---|
5609 | # through で生成されたセルを探す
|
---|
5610 | # cell = Namespace.find( [ "::", @through_generated_list[0].get_cell_name.to_sym ] ) #1
|
---|
5611 | cell = Namespace.find( @through_generated_list[0].get_cell_namespace_path ) #1
|
---|
5612 | # cell のプラグインで生成されたポート名のポートを探す (composite なら内部の繋がるポート)
|
---|
5613 | return cell.get_real_port( @through_generated_list[0].get_through_entry_port_name )
|
---|
5614 | else
|
---|
5615 | # ポートを返す(composite なら内部の繋がるポートを返す)
|
---|
5616 | return @cell.get_real_port( @port_name )
|
---|
5617 | end
|
---|
5618 | end
|
---|
5619 |
|
---|
5620 | #=== Join# 右辺のポートを得る
|
---|
5621 | # 右辺のポートを得る。
|
---|
5622 | # これはプロトタイプ宣言しかされていない場合には、こちらしか使えない
|
---|
5623 | def get_rhs_port2
|
---|
5624 | # through 指定あり?
|
---|
5625 | if @through_list[0] then
|
---|
5626 | if @through_generated_list[0] then
|
---|
5627 | port = @through_generated_list[0].get_through_entry_port_name.to_sym
|
---|
5628 | else
|
---|
5629 | port = @port_name # generate に失敗している
|
---|
5630 | end
|
---|
5631 | else
|
---|
5632 | port = @port_name
|
---|
5633 | end
|
---|
5634 |
|
---|
5635 | return port
|
---|
5636 | end
|
---|
5637 |
|
---|
5638 | #=== Join# 右辺のポートを得る
|
---|
5639 | # through は適用しないが、composite は展開した後のセルの対応するポート
|
---|
5640 | def get_rhs_port3
|
---|
5641 | if @cell then
|
---|
5642 | return @cell.get_real_port( @port_name )
|
---|
5643 | end
|
---|
5644 | end
|
---|
5645 |
|
---|
5646 | #=== Join# 呼び口配列の2番目以降の要素を追加する
|
---|
5647 | # 一番最初に定義された配列要素が全要素の初期値の配列を持つ
|
---|
5648 | # このメソッドは非配列の場合も呼出される(join 重複エラーの場合)
|
---|
5649 | #join2:: Join 呼び口配列要素の Join
|
---|
5650 | def add_array_member join2
|
---|
5651 |
|
---|
5652 | # subscript2: join2 の左辺添数
|
---|
5653 | subscript2 = join2.get_subscript
|
---|
5654 |
|
---|
5655 | if @subscript == nil then # not array : initialize duplicate
|
---|
5656 | # 非配列の場合、join が重複している
|
---|
5657 | cdl_error( "S1127 \'$1\' duplicate", @name )
|
---|
5658 | # print "add_array_member2: #{@owner.get_name}\n"
|
---|
5659 |
|
---|
5660 | elsif @subscript >= 0 then
|
---|
5661 | # 添数指定ありの場合
|
---|
5662 | if( subscript2 == nil || subscript2 < 0 ) then
|
---|
5663 | # join2 左辺は非配列または添数なし
|
---|
5664 | # 配列が不一致
|
---|
5665 | cdl_error( "S1128 \'$1\' inconsistent array definition", @name )
|
---|
5666 | elsif @array_member[subscript2] != nil then
|
---|
5667 | # 同じ添数が既に定義済み
|
---|
5668 | cdl_error( "S1129 \'$1\' redefinition of subscript $2" ,@name, subscript2 )
|
---|
5669 | else
|
---|
5670 | # 添数の位置に要素を追加
|
---|
5671 | @array_member[subscript2] = join2.get_rhs
|
---|
5672 | @array_member2[subscript2] = join2
|
---|
5673 | # p "0:#{join2.get_rhs}"
|
---|
5674 | end
|
---|
5675 |
|
---|
5676 | else
|
---|
5677 | # 添数指定なしの場合
|
---|
5678 | if( subscript2 == nil || subscript2 >= 0 ) then
|
---|
5679 | # join2 左辺は非配列または添数有
|
---|
5680 | # 配列が不一致
|
---|
5681 | cdl_error( "S1130 \'R1\' inconsistent array definition", @name )
|
---|
5682 | end
|
---|
5683 |
|
---|
5684 | # 添数なし配列の場合、配列要素を追加
|
---|
5685 | @array_member << join2.get_rhs
|
---|
5686 | @array_member2 << join2
|
---|
5687 | end
|
---|
5688 | end
|
---|
5689 |
|
---|
5690 | def get_array_member
|
---|
5691 | @array_member
|
---|
5692 | end
|
---|
5693 |
|
---|
5694 | def get_array_member2
|
---|
5695 | @array_member2
|
---|
5696 | end
|
---|
5697 |
|
---|
5698 | def change_name name
|
---|
5699 | # debug
|
---|
5700 | dbgPrint "change_name: #{@name} to #{name}\n"
|
---|
5701 |
|
---|
5702 | @name = name
|
---|
5703 |
|
---|
5704 | if @array_member2 then
|
---|
5705 | i = 0
|
---|
5706 | while i < @array_member2.length
|
---|
5707 | if @array_member2[i] != self && @array_member[i] != nil then
|
---|
5708 | # @array_member2[i] が nil になるのは optional の時と、
|
---|
5709 | # Join の initialize で無駄に @array_member2 が設定されている場合
|
---|
5710 | # 無駄に設定されているものについては、再帰的に呼び出す必要はない(clone_for_composite では対策している)
|
---|
5711 | @array_member2[i].change_name( name )
|
---|
5712 | end
|
---|
5713 | i += 1
|
---|
5714 | end
|
---|
5715 | end
|
---|
5716 | end
|
---|
5717 |
|
---|
5718 | # composite cell を展開したセルの結合を clone したセルの名前に変更
|
---|
5719 | def change_rhs_port( clone_cell_list, celltype )
|
---|
5720 |
|
---|
5721 | # debug
|
---|
5722 | if $debug then
|
---|
5723 | dbgPrint "change_rhs name: #{@name} cell_name: #{@cell_name} #{@cell} #{self}\n"
|
---|
5724 |
|
---|
5725 | clone_cell_list.each{ |cell, ce|
|
---|
5726 | dbgPrint "change_rhs: #{cell.get_name}=#{cell} : #{ce.get_name}\n"
|
---|
5727 | }
|
---|
5728 | end
|
---|
5729 |
|
---|
5730 | c = clone_cell_list[@cell]
|
---|
5731 | return if c == nil
|
---|
5732 |
|
---|
5733 | # debug
|
---|
5734 | dbgPrint " cell_name: #{@cell_name} => #{c.get_global_name}, #{c.get_name}\n"
|
---|
5735 |
|
---|
5736 | # @rhs の内容を調整しておく(この内容は、subscript を除いて、後から使われていない)
|
---|
5737 | elements = @rhs.get_elements
|
---|
5738 | if elements[0] == :OP_SUBSC then # 右辺:受け口配列?
|
---|
5739 | elements = elements[1]
|
---|
5740 | end
|
---|
5741 |
|
---|
5742 | # 右辺が cell.ePort の形式でない
|
---|
5743 | if elements[0] != :OP_DOT || elements[1][0] != :IDENTIFIER then #1
|
---|
5744 | return
|
---|
5745 | else
|
---|
5746 | # セル名を composite 内部の名前から、外部の名前に入れ替える
|
---|
5747 | # elements[1][1] = Token.new( c.get_name, nil, nil, nil )
|
---|
5748 | elements[1][1] = NamespacePath.new( c.get_name, false, c.get_namespace )
|
---|
5749 | end
|
---|
5750 |
|
---|
5751 | @cell_name = c.get_name
|
---|
5752 | @cell = c
|
---|
5753 | # @definition = nil # @definition が有効: チェック済み(とは、しない)
|
---|
5754 |
|
---|
5755 | if @array_member2 then
|
---|
5756 |
|
---|
5757 | # debug
|
---|
5758 | # p "array_member2.len : #{@array_member.length}"
|
---|
5759 |
|
---|
5760 | i = 0
|
---|
5761 | while i < @array_member2.length
|
---|
5762 | # @array_member2[i] が nil になるのは optional の時と、
|
---|
5763 | # Join の initialize で無駄に @array_member2 が設定されている場合
|
---|
5764 | # 無駄に設定されているものについては、再帰的に呼び出す必要はない(clone_for_composite では対策している)
|
---|
5765 | if @array_member2[i] != self && @array_member[i] != nil then
|
---|
5766 | @array_member2[i].change_rhs_port( clone_cell_list, celltype )
|
---|
5767 | end
|
---|
5768 | i += 1
|
---|
5769 | end
|
---|
5770 | end
|
---|
5771 |
|
---|
5772 | end
|
---|
5773 |
|
---|
5774 | #=== Join# composite セル用にクローン
|
---|
5775 | #cell_global_name:: string : 親セルのグローバル名
|
---|
5776 | # 右辺の C_EXP に含まれる $id$, $cell$, $ct$ を置換
|
---|
5777 | # ここで置換するのは composite の attribute の C_EXP を composite セルタイプおよびセル名に置換するため
|
---|
5778 | # (内部セルの C_EXP もここで置換される)
|
---|
5779 | # @through_list などもコピーされるので、これが呼び出される前に確定する必要がある
|
---|
5780 | def clone_for_composite( ct_name, cell_name, locale, b_need_recursive = true )
|
---|
5781 |
|
---|
5782 | # debug
|
---|
5783 | dbgPrint "join.clone_for_composite : #{@name} #{@cell_name} #{self}\n"
|
---|
5784 | cl = self.clone
|
---|
5785 |
|
---|
5786 | if @array_member2 && b_need_recursive then
|
---|
5787 | cl.clone_array_member( @array_member, @array_member2, ct_name, cell_name, self, locale )
|
---|
5788 | end
|
---|
5789 |
|
---|
5790 | rhs = CDLInitializer.clone_for_composite( @rhs, ct_name, cell_name, locale )
|
---|
5791 | cl.change_rhs rhs
|
---|
5792 |
|
---|
5793 | # debug
|
---|
5794 | dbgPrint "join cloned : #{cl}\n"
|
---|
5795 | return cl
|
---|
5796 | end
|
---|
5797 |
|
---|
5798 | def clone_array_member( array_member, array_member2, ct_name, cell_name, prev, locale )
|
---|
5799 | # 配列のコピーを作る
|
---|
5800 | am = array_member.clone
|
---|
5801 | am2 = array_member2.clone
|
---|
5802 |
|
---|
5803 | # 配列要素のコピーを作る
|
---|
5804 | i = 0
|
---|
5805 | while i < am2.length
|
---|
5806 | if array_member2[i] == prev then
|
---|
5807 | # 自分自身である(ので、呼出すと無限再帰呼出しとなる)
|
---|
5808 | am2[i] = self
|
---|
5809 | elsif array_member2[i] then
|
---|
5810 | am2[i] = array_member2[i].clone_for_composite( ct_name, cell_name, locale, false )
|
---|
5811 | else
|
---|
5812 | # 以前のエラーで array_member2[i] は nil になっている
|
---|
5813 | end
|
---|
5814 |
|
---|
5815 | # debug
|
---|
5816 | dbgPrint "clone_array_member: #{@name} #{am2[i]} #{array_member2[i]}\n"
|
---|
5817 |
|
---|
5818 | i += 1
|
---|
5819 | end
|
---|
5820 |
|
---|
5821 | # i = 0 は、ここで自分自身を設定
|
---|
5822 | # am2[0] = self
|
---|
5823 |
|
---|
5824 | @array_member = am
|
---|
5825 | @array_member2 = am2
|
---|
5826 |
|
---|
5827 | end
|
---|
5828 |
|
---|
5829 | #=== Join# rhs を入れ換える
|
---|
5830 | #rhs:: Expression | initializer
|
---|
5831 | # 右辺を入れ換える.
|
---|
5832 | # このメソッドは、composite で cell の属性の初期値を attribute の値で置き換えるのに使われる
|
---|
5833 | # このメソッドは composite 内の cell の属性の初期値が定数ではなく式になった場合、不要になる
|
---|
5834 | def change_rhs rhs
|
---|
5835 | @rhs = rhs
|
---|
5836 | end
|
---|
5837 |
|
---|
5838 | #=== Join# clone された join の owner を変更
|
---|
5839 | def set_cloned( owner )
|
---|
5840 | dbgPrint "Join#set_cloned: #{@name} prev owner: #{@owner.get_name} new owner: #{owner.get_name}\n"
|
---|
5841 | @owner = owner
|
---|
5842 | end
|
---|
5843 |
|
---|
5844 | def show_tree( indent )
|
---|
5845 | indent.times { print " " }
|
---|
5846 | puts "Join: name: #{@name} owner: #{@owner.get_name} id: #{self}"
|
---|
5847 | if @subscript == nil then
|
---|
5848 | elsif @subscript >= 0 then
|
---|
5849 | (indent+1).times { print " " }
|
---|
5850 | puts "subscript: #{@subscript}"
|
---|
5851 | else
|
---|
5852 | (indent+1).times { print " " }
|
---|
5853 | puts "subscript: not specified"
|
---|
5854 | end
|
---|
5855 | (indent+1).times { print " " }
|
---|
5856 | puts "rhs: "
|
---|
5857 | if @rhs.instance_of?( Array )then
|
---|
5858 | @rhs.each{ |i|
|
---|
5859 | if i.instance_of?( Array )then
|
---|
5860 | i.each{ |j|
|
---|
5861 | j.show_tree( indent + 3 )
|
---|
5862 | }
|
---|
5863 | elsif i.instance_of? Symbol then
|
---|
5864 | (indent+2).times { print " " }
|
---|
5865 | print i
|
---|
5866 | print "\n"
|
---|
5867 | else
|
---|
5868 | i.show_tree( indent + 2 )
|
---|
5869 | end
|
---|
5870 | }
|
---|
5871 | else
|
---|
5872 | @rhs.show_tree( indent + 2 )
|
---|
5873 | (indent+1).times { print " " }
|
---|
5874 | if @definition then
|
---|
5875 | puts "definition:"
|
---|
5876 | @definition.show_tree( indent + 2 )
|
---|
5877 | else
|
---|
5878 | puts "definition: not found"
|
---|
5879 | end
|
---|
5880 | end
|
---|
5881 | if @definition.instance_of?( Port ) then
|
---|
5882 | (indent+2).times { print " " }
|
---|
5883 | if @cell then
|
---|
5884 | puts "cell: #{@cell_name} #{@cell} port: #{@port_name} cell_global_name: #{@cell.get_global_name}"
|
---|
5885 | else
|
---|
5886 | puts "cell: #{@cell_name} port: #{@port_name} (cell not found)"
|
---|
5887 | end
|
---|
5888 | end
|
---|
5889 | if @through_list then
|
---|
5890 | i = 0
|
---|
5891 | @through_list.each { |t|
|
---|
5892 | (indent+2).times { print " " }
|
---|
5893 | puts "through: plugin name : '#{t[0]}' arg : '#{t[2]}'"
|
---|
5894 | if @through_generated_list[i] then
|
---|
5895 | @through_generated_list[i].show_tree( indent+3 )
|
---|
5896 | end
|
---|
5897 | i += 1
|
---|
5898 | }
|
---|
5899 | end
|
---|
5900 | if @array_member2 then
|
---|
5901 | (indent+1).times { print " " }
|
---|
5902 | puts "array member:"
|
---|
5903 | i = 0
|
---|
5904 | @array_member2.each { |j|
|
---|
5905 | if j then
|
---|
5906 | (indent+2).times { print " " }
|
---|
5907 | puts "[#{i}]: #{j.get_name} id: #{j}"
|
---|
5908 | j.get_rhs.show_tree(indent+3)
|
---|
5909 | (indent+3).times { print " " }
|
---|
5910 | puts "cell global name: #{j.get_cell_global_name}"
|
---|
5911 | (indent+3).times { print " " }
|
---|
5912 | puts "port global name: #{j.get_port_global_name}"
|
---|
5913 | else
|
---|
5914 | (indent+2).times { print " " }
|
---|
5915 | puts "[#{i}]: [optional] id: #{j}"
|
---|
5916 | end
|
---|
5917 | i += 1
|
---|
5918 | }
|
---|
5919 | end
|
---|
5920 | end
|
---|
5921 |
|
---|
5922 | end
|
---|
5923 |
|
---|
5924 | #== 逆結合
|
---|
5925 | class ReverseJoin < BDNode
|
---|
5926 | #@ep_name:: Symbol
|
---|
5927 | #@ep_subscript:: Expression or nil
|
---|
5928 | #@cell_nsp: NamespacePath
|
---|
5929 | #@cp_name:: Symbol
|
---|
5930 | #@cp_subscript:: Expression or nil
|
---|
5931 | def initialize( ep_name, ep_subscript, cell_nsp, cp_name, cp_subscript = nil )
|
---|
5932 | super()
|
---|
5933 | @ep_name = ep_name
|
---|
5934 | @ep_subscript = ep_subscript
|
---|
5935 | @cell_nsp = cell_nsp
|
---|
5936 | @cp_name = cp_name
|
---|
5937 | @cp_subscript = cp_subscript
|
---|
5938 | end
|
---|
5939 |
|
---|
5940 | def get_name
|
---|
5941 | @ep_name
|
---|
5942 | end
|
---|
5943 |
|
---|
5944 | def get_rhs_cell_and_port
|
---|
5945 | [ @ep_subscript, @cell_nsp, @cp_name, @cp_subscript ]
|
---|
5946 | end
|
---|
5947 | end
|
---|
5948 |
|
---|
5949 | # CLASS: CompositeCelltype 用の Join
|
---|
5950 | # REM: CompositeCelltype が export するもの
|
---|
5951 | class CompositeCelltypeJoin < BDNode
|
---|
5952 | # @export_name:: string : CompositeCelltype が export する名前(呼び口、受け口、属性)
|
---|
5953 | # @internal_cell_name:: string : CompositeCelltype 内部のセルの名前
|
---|
5954 | # @internal_cell_elem_name:: string : CompositeCelltype 内部のセルの呼び口、受け口、属性の名前
|
---|
5955 | # @cell : Cell : Cell:: internal cell : CompositeCelltyep 内部のセル(in_compositeセル)
|
---|
5956 | # @port_decl:: Port | Decl
|
---|
5957 | # @b_pseudo: bool :
|
---|
5958 |
|
---|
5959 | def initialize( export_name, internal_cell_name,
|
---|
5960 | internal_cell_elem_name, cell, port_decl )
|
---|
5961 | super()
|
---|
5962 | @export_name = export_name
|
---|
5963 | @internal_cell_name = internal_cell_name
|
---|
5964 | @internal_cell_elem_name = internal_cell_elem_name
|
---|
5965 | @cell = cell
|
---|
5966 | @port_decl = port_decl
|
---|
5967 |
|
---|
5968 | end
|
---|
5969 |
|
---|
5970 | #=== CompositeCelltypeJoin# CompositeCelltypeJoin の対象セルか?
|
---|
5971 | #cell:: Cell 対象かどうかチェックするセル
|
---|
5972 | #
|
---|
5973 | # CompositeCelltypeJoin と cell の名前が一致するかチェックする
|
---|
5974 | # port_decl が指定された場合は、現状使われていない
|
---|
5975 | def match?( cell, port_decl = nil )
|
---|
5976 |
|
---|
5977 | #debug
|
---|
5978 | if port_decl
|
---|
5979 | dbgPrint( "match?" )
|
---|
5980 | dbgPrintf( " @cell: %-20s %08x\n", @cell.get_name, @cell.object_id )
|
---|
5981 | dbgPrintf( " @port_decl: %-20s %08x\n", @port_decl.get_name, @port_decl.object_id )
|
---|
5982 | dbgPrintf( " cell: %-20s %08x\n", cell.get_name, cell.object_id )
|
---|
5983 | dbgPrintf( " port_decl: %-20s %08x\n", port_decl.get_name, port_decl.object_id )
|
---|
5984 | dbgPrint( " cell_name: #{cell.get_name.class}=#{cell.get_name} cell_elem_name: #{port_decl.get_name.class}=#{port_decl.get_name}\n" )
|
---|
5985 | dbgPrint( " @cell_name: #{@cell.get_name.class}=#{@cell.get_name} cell_elem_name: #{@port_decl.get_name.class}=#{@port_decl.get_name}\n" )
|
---|
5986 |
|
---|
5987 | end
|
---|
5988 |
|
---|
5989 | # if @cell.equal?( cell ) && ( port_decl == nil || @port_decl.equal?( port_decl ) ) then
|
---|
5990 | # なぜ port_decl が一致しなければならなかったか忘れた。
|
---|
5991 | # recursive_composite で名前の一致に変更 060917
|
---|
5992 | if((@cell.get_name == cell.get_name) && (port_decl == nil || @port_decl.get_name == port_decl.get_name))then
|
---|
5993 | true
|
---|
5994 | else
|
---|
5995 | false
|
---|
5996 | end
|
---|
5997 | end
|
---|
5998 |
|
---|
5999 | def check_dup_init
|
---|
6000 | return if get_port_type != :CALL
|
---|
6001 |
|
---|
6002 | if @cell.get_join_list.get_item @internal_cell_elem_name then
|
---|
6003 | cdl_error( "S1131 \'$1.$2\' has duplicate initializer" , @internal_cell_name, @internal_cell_elem_name )
|
---|
6004 | end
|
---|
6005 | end
|
---|
6006 |
|
---|
6007 | def get_name
|
---|
6008 | @export_name
|
---|
6009 | end
|
---|
6010 |
|
---|
6011 | def get_cell_name
|
---|
6012 | @internal_cell_name
|
---|
6013 | end
|
---|
6014 |
|
---|
6015 | def get_cell
|
---|
6016 | @cell
|
---|
6017 | end
|
---|
6018 |
|
---|
6019 | def get_cell_elem_name
|
---|
6020 | @internal_cell_elem_name
|
---|
6021 | end
|
---|
6022 |
|
---|
6023 | # @port_decl が Port の場合のみ呼び出してよい
|
---|
6024 | def get_port_type
|
---|
6025 | if @port_decl then
|
---|
6026 | @port_decl.get_port_type
|
---|
6027 | end
|
---|
6028 | end
|
---|
6029 |
|
---|
6030 | def get_port_decl
|
---|
6031 | @port_decl
|
---|
6032 | end
|
---|
6033 |
|
---|
6034 | #=== CompositeCelltypeJoin#get_allocator_instance
|
---|
6035 | def get_allocator_instance
|
---|
6036 | if @port_decl.instance_of? Port then
|
---|
6037 | return @port_decl.get_allocator_instance
|
---|
6038 | elsif @port_decl
|
---|
6039 | raise "CompositeCelltypeJoin#get_allocator_instance: not port"
|
---|
6040 | else
|
---|
6041 | return nil
|
---|
6042 | end
|
---|
6043 | end
|
---|
6044 |
|
---|
6045 | # @port_decl が Port の場合のみ呼び出してよい
|
---|
6046 | def is_require?
|
---|
6047 | if @port_decl then
|
---|
6048 | @port_decl.is_require?
|
---|
6049 | end
|
---|
6050 | end
|
---|
6051 |
|
---|
6052 | # @port_decl が Port の場合のみ呼び出してよい
|
---|
6053 | def is_allocator_port?
|
---|
6054 | if @port_decl then
|
---|
6055 | @port_decl.is_allocator_port?
|
---|
6056 | end
|
---|
6057 | end
|
---|
6058 |
|
---|
6059 | # @port_decl が Port の場合のみ呼び出してよい
|
---|
6060 | def is_optional?
|
---|
6061 | if @port_decl then
|
---|
6062 | @port_decl.is_optional?
|
---|
6063 | end
|
---|
6064 | end
|
---|
6065 |
|
---|
6066 | #=== CompositeCelltypeJoin# 右辺が Decl ならば初期化子(式)を返す
|
---|
6067 | # このメソッドは Cell の check_join から初期値チェックのために呼び出される
|
---|
6068 | def get_initializer
|
---|
6069 | if @port_decl.instance_of? Decl then
|
---|
6070 | @port_decl.get_initializer
|
---|
6071 | end
|
---|
6072 | end
|
---|
6073 |
|
---|
6074 | def get_size_is
|
---|
6075 | if @port_decl.instance_of? Decl then
|
---|
6076 | @port_decl.get_size_is
|
---|
6077 | end
|
---|
6078 | end
|
---|
6079 |
|
---|
6080 | #=== CompositeCelltypeJoin# 配列サイズを得る
|
---|
6081 | #RETURN:: nil: not array, "[]": 大きさ指定なし, Integer: 大きさ指定あり
|
---|
6082 | def get_array_size
|
---|
6083 | @port_decl.get_array_size
|
---|
6084 | end
|
---|
6085 |
|
---|
6086 | #=== CompositeCelltypeJoin# signature を得る
|
---|
6087 | # @port_decl が Port の時のみ呼び出してもよい
|
---|
6088 | def get_signature
|
---|
6089 | @port_decl.get_signature
|
---|
6090 | end
|
---|
6091 |
|
---|
6092 | #=== CompositeCelltypeJoin# get_type
|
---|
6093 | def get_type
|
---|
6094 | if @port_decl.instance_of? Decl
|
---|
6095 | @port_decl.get_type
|
---|
6096 | end
|
---|
6097 | end
|
---|
6098 |
|
---|
6099 | #=== CompositeCelltypeJoin# get_initializer
|
---|
6100 | def get_initializer
|
---|
6101 | if @port_decl.instance_of? Decl
|
---|
6102 | @port_decl.get_initializer
|
---|
6103 | end
|
---|
6104 | end
|
---|
6105 |
|
---|
6106 | #=== CompositeCelltypeJoin# get_choice_list
|
---|
6107 | def get_choice_list
|
---|
6108 | if @port_decl.instance_of? Decl
|
---|
6109 | @port_decl.get_choice_list
|
---|
6110 | end
|
---|
6111 | end
|
---|
6112 |
|
---|
6113 | def show_tree( indent )
|
---|
6114 | indent.times { print " " }
|
---|
6115 | puts "CompositeCelltypeJoin: export_name: #{@export_name} #{self}"
|
---|
6116 | (indent+1).times { print " " }
|
---|
6117 | puts "internal_cell_name: #{@internal_cell_name}"
|
---|
6118 | (indent+1).times { print " " }
|
---|
6119 | puts "internal_cell_elem_name: #{@internal_cell_elem_name}"
|
---|
6120 | if @port_decl then
|
---|
6121 | @port_decl.show_tree( indent + 1 )
|
---|
6122 | end
|
---|
6123 | end
|
---|
6124 | end
|
---|
6125 |
|
---|
6126 | class Factory < BDNode
|
---|
6127 | # @name:: string
|
---|
6128 | # @file_name:: string
|
---|
6129 | # @format:: string
|
---|
6130 | # @arg_list:: Expression の elements と同じ形式 [ [:IDENTIFIER, String], ... ]
|
---|
6131 | # @f_celltype:: bool : true: celltype factory, false: cell factory
|
---|
6132 |
|
---|
6133 | @@f_celltype = false
|
---|
6134 |
|
---|
6135 | def initialize( name, file_name, format, arg_list )
|
---|
6136 | super()
|
---|
6137 | @f_celltype = @@f_celltype
|
---|
6138 |
|
---|
6139 | case name
|
---|
6140 | when :write
|
---|
6141 | # write 関数
|
---|
6142 | @name = name
|
---|
6143 |
|
---|
6144 | # write 関数の第一引数:出力先ファイル名
|
---|
6145 | # 式を評価する(通常単一の文字列であるから、単一の文字列が返される)
|
---|
6146 | @file_name = file_name.eval_const(nil).val # file_name : Expression
|
---|
6147 | if ! @file_name.instance_of?( String ) then
|
---|
6148 | # 文字列定数ではなかった
|
---|
6149 | cdl_error( "S1132 $1: 1st parameter is not string(file name)" , @name )
|
---|
6150 | @file_name = nil
|
---|
6151 | end
|
---|
6152 |
|
---|
6153 | # write 関数の第二引数:フォーマット文字列
|
---|
6154 | @format = format.eval_const(nil).val # format : Expression
|
---|
6155 | # 式を評価する(通常単一の文字列であるから、単一の文字列が返される)
|
---|
6156 | if ! @format.instance_of?( String ) then
|
---|
6157 | # 文字列定数ではなかった
|
---|
6158 | cdl_error( "S1133 $1: 2nd parameter is not string(fromat)" , @name )
|
---|
6159 | @format = nil
|
---|
6160 | end
|
---|
6161 |
|
---|
6162 | # 第三引数以降を引数リストとする mikan 引数のチェック
|
---|
6163 | @arg_list = arg_list
|
---|
6164 |
|
---|
6165 | else
|
---|
6166 | cdl_error( "S1134 $1: unknown factory function" , name )
|
---|
6167 | end
|
---|
6168 | Celltype.new_factory( self )
|
---|
6169 | end
|
---|
6170 |
|
---|
6171 | def check_arg( celltype )
|
---|
6172 | if ! @arg_list then
|
---|
6173 | return
|
---|
6174 | end
|
---|
6175 |
|
---|
6176 | if @f_celltype then
|
---|
6177 | cdl_error( "S1135 celltype factory can\'t have parameter(s)" )
|
---|
6178 | return
|
---|
6179 | end
|
---|
6180 |
|
---|
6181 | @arg_list.each{ |elements|
|
---|
6182 |
|
---|
6183 | case elements[0]
|
---|
6184 | when :IDENTIFIER #1
|
---|
6185 | obj = celltype.find( elements[1] )
|
---|
6186 | if obj == nil then
|
---|
6187 | cdl_error( "S1136 \'$1\': not found" , elements[1] )
|
---|
6188 | elsif ! obj.instance_of?( Decl ) || obj.get_kind != :ATTRIBUTE then
|
---|
6189 | cdl_error( "S1137 \'$1\': not attribute" , elements[1] )
|
---|
6190 | end
|
---|
6191 | when :STRING_LITERAL
|
---|
6192 | else
|
---|
6193 | cdl_error( "S1138 internal error Factory.check_arg()" )
|
---|
6194 | end
|
---|
6195 |
|
---|
6196 | }
|
---|
6197 | end
|
---|
6198 |
|
---|
6199 | def self.set_f_celltype( f_celltype )
|
---|
6200 | @@f_celltype = f_celltype
|
---|
6201 | end
|
---|
6202 |
|
---|
6203 | def get_f_celltype
|
---|
6204 | @f_celltype
|
---|
6205 | end
|
---|
6206 |
|
---|
6207 | def get_name
|
---|
6208 | @name
|
---|
6209 | end
|
---|
6210 |
|
---|
6211 | def get_file_name
|
---|
6212 | @file_name
|
---|
6213 | end
|
---|
6214 |
|
---|
6215 | def get_format
|
---|
6216 | @format
|
---|
6217 | end
|
---|
6218 |
|
---|
6219 | def get_arg_list
|
---|
6220 | @arg_list
|
---|
6221 | end
|
---|
6222 |
|
---|
6223 | def show_tree( indent )
|
---|
6224 | indent.times { print " " }
|
---|
6225 | puts "Factory: name: #{@name}"
|
---|
6226 | if @arg_list then
|
---|
6227 | (indent+1).times { print " " }
|
---|
6228 | puts "argument(s):"
|
---|
6229 | @arg_list.each { |l|
|
---|
6230 | (indent+2).times { print " " }
|
---|
6231 | print "\"#{l}\"\n"
|
---|
6232 | }
|
---|
6233 | end
|
---|
6234 | end
|
---|
6235 | end
|
---|
6236 |
|
---|
6237 | #== Domain
|
---|
6238 | #
|
---|
6239 | # region の domain を記憶するクラス
|
---|
6240 | class DomainType < Node
|
---|
6241 | #@name::Symbol : ドメインタイプの名前 ex) HRP2
|
---|
6242 | #@region::Region
|
---|
6243 | #@plugin_name::Symbol : ex) HRP2Plugin
|
---|
6244 | #@option::String : ex) "trusted", "nontrusted"
|
---|
6245 | #@plugin::DomainPlugin の子クラス
|
---|
6246 |
|
---|
6247 | include PluginModule
|
---|
6248 |
|
---|
6249 | # ドメインに属する region の Hash
|
---|
6250 | # domain 指定が一度も行われない場合、このリストは空である
|
---|
6251 | # ルートリージョンは option = "OutOfDomain" で登録される (domain 指定が無ければ登録されない)
|
---|
6252 | @@domain_regions = { } # { :domain_type => [ region, ... ] }
|
---|
6253 |
|
---|
6254 | def initialize( region, name, option )
|
---|
6255 | super()
|
---|
6256 | @name = name
|
---|
6257 | @plugin_name = (name.to_s + "Plugin").to_sym
|
---|
6258 | load_plugin( @plugin_name, DomainPlugin )
|
---|
6259 | @region = region
|
---|
6260 | @option = option
|
---|
6261 |
|
---|
6262 | if @@domain_regions[ name ] then
|
---|
6263 | if ! @@domain_regions[ name ].include?( region ) then
|
---|
6264 | @@domain_regions[ name ] << region
|
---|
6265 | end
|
---|
6266 | else
|
---|
6267 | @@domain_regions[ name ] = [ region ]
|
---|
6268 | end
|
---|
6269 | end
|
---|
6270 |
|
---|
6271 | def create_domain_plugin
|
---|
6272 | if ! @plugin then
|
---|
6273 | pluginClass = Object.const_get @plugin_name
|
---|
6274 | @plugin = pluginClass.new( @region, @name, @option )
|
---|
6275 | end
|
---|
6276 | end
|
---|
6277 |
|
---|
6278 | def add_through_plugin( join, from_region, to_region, through_type )
|
---|
6279 | # print( "DOMAIN: add_through_plugin: from=#{from_region.get_name}#{join.get_owner.get_name}.#{join.get_name} to=#{to_region}#{join.get_cell.get_name}.#{join.get_port_name} through_type=#{through_type}\n" )
|
---|
6280 | return @plugin.add_through_plugin( join, from_region, to_region, through_type )
|
---|
6281 | end
|
---|
6282 |
|
---|
6283 | def joinable?( from_region, to_region, through_type )
|
---|
6284 | # print( "DOMAIN: joinable? from_region=#{from_region.get_name} to_region=#{to_region} through_type=#{through_type}\n" )
|
---|
6285 | return @plugin.joinable?( from_region, to_region, through_type )
|
---|
6286 | end
|
---|
6287 |
|
---|
6288 | def get_name
|
---|
6289 | @name
|
---|
6290 | end
|
---|
6291 |
|
---|
6292 | #== Domain リージョンの Hash を得る
|
---|
6293 | # @@domain_regions の説明参照
|
---|
6294 | def self.get_domain_regions
|
---|
6295 | return @@domain_regions
|
---|
6296 | end
|
---|
6297 |
|
---|
6298 | def get_regions
|
---|
6299 | return @@domain_regions[ @name ]
|
---|
6300 | end
|
---|
6301 |
|
---|
6302 | def get_option
|
---|
6303 | @option
|
---|
6304 | end
|
---|
6305 |
|
---|
6306 | def show_tree( indent )
|
---|
6307 | (indent+1).times { print( " " ) }
|
---|
6308 | puts "domain: name=#{@name} plugin=#{@plugin_name} option=#{@option}"
|
---|
6309 | end
|
---|
6310 | end
|
---|
6311 |
|
---|
6312 | #== Region クラス
|
---|
6313 | #
|
---|
6314 | # Region は Namespace を継承している
|
---|
6315 | # root region は特殊で、root namespace と同じである
|
---|
6316 | #
|
---|
6317 | # cell は region に属する
|
---|
6318 | # region に属する cell のリストは Namespace クラスのインスタンス変数として記憶される
|
---|
6319 | #
|
---|
6320 | class Region < Namespace
|
---|
6321 | # @name:: string
|
---|
6322 | # @in_through_list:: [ [ plugin_name, plugin_arg ], ... ] : plungin_name = nil の時 in 禁止
|
---|
6323 | # @out_through_list:: [ [ plugin_name, plugin_arg ], ... ] : plungin_name = nil の時 out 禁止
|
---|
6324 | # @to_through_list:: [ [ dst_region, plugin_name, plugin_arg ], ... ]
|
---|
6325 | # @cell_port_throug_plugin_list:: { "#{cell_name}.#{port_name}" => through_generated_list の要素 }
|
---|
6326 | # この region から cell_name.port_name への through プラグインで生成されたオブジェクト
|
---|
6327 | # @region_type::Symbol : :NODE, :LINKUNIT, :DOMAIN, :CLASS
|
---|
6328 | # @region_type_param::Symbol : domain, class の名前. node, linkunit では nil
|
---|
6329 | # @link_root:: Region : linkUnit の根っことなる region (node, linkunit が指定された region)
|
---|
6330 | # @family_line:: [ @region_root, ...,@region_me ] 家系
|
---|
6331 | # @in_through_count:: Integer : n 番目の in_through 結合 (n>=0)
|
---|
6332 | # @out_through_count:: Integer : n 番目の out_through 結合 (n>=0)
|
---|
6333 | # @to_through_count:: { :RegionName => Integer }: RegionName への n 番目の to_through 結合 (n>=0)
|
---|
6334 | # @domain_type::DomainType : domain 指定されていない場合、nil
|
---|
6335 | # @domain_root::Region : domain 指定されていなる Region (root の場合 nil)
|
---|
6336 |
|
---|
6337 | @@in_through_list = []
|
---|
6338 | @@out_through_list = []
|
---|
6339 | @@to_through_list = []
|
---|
6340 | @@region_type = nil
|
---|
6341 | @@region_type_param = nil
|
---|
6342 | @@domain_name = nil
|
---|
6343 | @@domain_option = nil # Token が入る
|
---|
6344 |
|
---|
6345 | @@link_roots = []
|
---|
6346 |
|
---|
6347 | def initialize( name )
|
---|
6348 | # mikan name の Namespace 修飾
|
---|
6349 | # object = Namespace.find( [ name ] ) # 親まで捜しにいく
|
---|
6350 | if name != "::" then
|
---|
6351 | object = Namespace.get_current.find( name ) #1
|
---|
6352 | else
|
---|
6353 | # root リージョン
|
---|
6354 | object = nil
|
---|
6355 | @@region_type = :NODE
|
---|
6356 | end
|
---|
6357 |
|
---|
6358 | @in_through_list = @@in_through_list
|
---|
6359 | @out_through_list = @@out_through_list
|
---|
6360 | @to_through_list = @@to_through_list
|
---|
6361 | @region_type = @@region_type
|
---|
6362 | @region_type_param = @@region_type_param
|
---|
6363 |
|
---|
6364 | if @@domain_name then
|
---|
6365 | domain_option = CDLString.remove_dquote @@domain_option.to_s
|
---|
6366 | @domain_type = DomainType.new( self, @@domain_name, domain_option )
|
---|
6367 | @@domain_name = nil
|
---|
6368 | @@domain_option = nil
|
---|
6369 | else
|
---|
6370 | @domain_type = nil
|
---|
6371 | end
|
---|
6372 |
|
---|
6373 | @@in_through_list = []
|
---|
6374 | @@out_through_list = []
|
---|
6375 | @@to_through_list = []
|
---|
6376 | @@region_type = nil
|
---|
6377 | @@region_type_param = nil
|
---|
6378 |
|
---|
6379 | @in_through_count = -1
|
---|
6380 | @out_through_count = -1
|
---|
6381 | @to_through_count = {}
|
---|
6382 |
|
---|
6383 | super( name )
|
---|
6384 | if object then
|
---|
6385 |
|
---|
6386 | if object.instance_of?( Region ) then
|
---|
6387 | dbgPrint "Region.new: re-appear #{@name}\n"
|
---|
6388 |
|
---|
6389 | # # Region path が前回出現と一致するか?
|
---|
6390 | # if @@region_stack[ @@region_stack_sp - 1 ] then
|
---|
6391 | # my_path = @@region_stack[ @@region_stack_sp - 1 ].get_path_string.to_s + "." + @name.to_s
|
---|
6392 | # else
|
---|
6393 | # my_path = @name.to_s
|
---|
6394 | # end
|
---|
6395 | # if my_path != object.get_path_string then
|
---|
6396 | # cdl_error( "S1139 $1: region path mismatch. previous path: $2" , my_path, object.get_path_string )
|
---|
6397 | # end
|
---|
6398 |
|
---|
6399 | # 再出現
|
---|
6400 | # @@region_stack[@@region_stack_sp] = object
|
---|
6401 |
|
---|
6402 | # 再出現時に specifier が指定されているか?
|
---|
6403 | if( @in_through_list.length != 0 || @out_through_list.length != 0 || @to_through_list.length != 0 || @region_type != nil )then
|
---|
6404 | cdl_error( "S1140 $1: region specifier must place at first appearence" , name )
|
---|
6405 | end
|
---|
6406 | return
|
---|
6407 |
|
---|
6408 | else
|
---|
6409 | # エラー用ダミー定義
|
---|
6410 |
|
---|
6411 | # 異なる同名のオブジェクトが定義済み
|
---|
6412 | cdl_error( "S1141 $1 duplication, previous one : $2" , name, object.class )
|
---|
6413 | # @@region_stack[@@region_stack_sp] = self # エラー時暫定 region
|
---|
6414 | end
|
---|
6415 | else
|
---|
6416 | # 初出現
|
---|
6417 | dbgPrint "Region.new: #{@name}\n"
|
---|
6418 | set_region_family_line
|
---|
6419 |
|
---|
6420 | if @region_type == :NODE || @region_type == :LINKUNIT then
|
---|
6421 | dbgPrint "new LinkRoot: #{@name}\n"
|
---|
6422 | @@link_roots << self
|
---|
6423 | end
|
---|
6424 | end
|
---|
6425 |
|
---|
6426 | @cell_port_throug_plugin_list = {}
|
---|
6427 |
|
---|
6428 | # p @name
|
---|
6429 | # p @in_through_list
|
---|
6430 | # p @out_through_list
|
---|
6431 | # p @to_through_list
|
---|
6432 |
|
---|
6433 | end
|
---|
6434 |
|
---|
6435 | def self.end_of_parse
|
---|
6436 | Namespace.get_current.create_domain_plugin
|
---|
6437 | Namespace.get_current.end_of_parse
|
---|
6438 | end
|
---|
6439 |
|
---|
6440 | def self.new_in_through( plugin_name = nil, plugin_arg = nil )
|
---|
6441 | @@in_through_list << [ plugin_name, plugin_arg ]
|
---|
6442 | end
|
---|
6443 |
|
---|
6444 | def self.new_out_through( plugin_name = nil, plugin_arg = nil )
|
---|
6445 | @@out_through_list << [ plugin_name, plugin_arg ]
|
---|
6446 | end
|
---|
6447 |
|
---|
6448 | def self.new_to_through( dst_region, plugin_name, plugin_arg )
|
---|
6449 | # p "New to_through #{dst_region}"
|
---|
6450 | @@to_through_list << [ dst_region, plugin_name, plugin_arg ]
|
---|
6451 | end
|
---|
6452 |
|
---|
6453 | def self.set_type( type, param = nil )
|
---|
6454 | if @@region_type then
|
---|
6455 | Generator.error( "S1178 $1 region type specifier duplicate, previous $2", type, @@region_type )
|
---|
6456 | end
|
---|
6457 | @@region_type = type
|
---|
6458 | @@region_type_param = param
|
---|
6459 | end
|
---|
6460 |
|
---|
6461 | def self.set_domain( name, option )
|
---|
6462 | if @@domain_name then
|
---|
6463 | Generator.error( "S9999 $1 domain specifier duplicate, previous $2", type, @@region_type )
|
---|
6464 | end
|
---|
6465 | @@domain_name = name
|
---|
6466 | @@domain_option = option
|
---|
6467 | end
|
---|
6468 |
|
---|
6469 | #== Region ルートリージョンを得る
|
---|
6470 | # ルートリージョンは、ルートネームスペースと同じである
|
---|
6471 | def self.get_root
|
---|
6472 | Namespace.get_root
|
---|
6473 | end
|
---|
6474 |
|
---|
6475 | def set_region_family_line
|
---|
6476 |
|
---|
6477 | dbgPrint "set_region_family_line: Region: #{@name} \n"
|
---|
6478 | # root namespace (root region) の region type は :NODE
|
---|
6479 | if @name == "::" then
|
---|
6480 | @region_type = :NODE
|
---|
6481 | end
|
---|
6482 |
|
---|
6483 | if @region_type == :NODE || @region_type == :LINKUNIT then
|
---|
6484 | @link_root = self
|
---|
6485 | else
|
---|
6486 | @link_root = @owner.get_link_root
|
---|
6487 | end
|
---|
6488 |
|
---|
6489 | if @domain_type != nil || @owner == nil then
|
---|
6490 | @domain_root = self
|
---|
6491 | else
|
---|
6492 | @domain_root = @owner.get_domain_root
|
---|
6493 | end
|
---|
6494 |
|
---|
6495 | if @domain_type then
|
---|
6496 | # ルートリージョンが最初から @domain_type 設定されることはないの
|
---|
6497 | # で @owner == nil を調べる必要はない
|
---|
6498 | @owner.set_domain_type @domain_type
|
---|
6499 | end
|
---|
6500 |
|
---|
6501 | if @owner then
|
---|
6502 | @family_line = ( @owner.get_family_line.dup ) << self
|
---|
6503 | else
|
---|
6504 | @family_line = [ self ] # root region
|
---|
6505 | end
|
---|
6506 |
|
---|
6507 | =begin
|
---|
6508 | @family_line = []
|
---|
6509 | @link_root = nil
|
---|
6510 |
|
---|
6511 | # @family_line を作成する
|
---|
6512 | # @link_root もみつける
|
---|
6513 | # (上位にたどっていって Region で node または linkunit のいずれか先に見つかったものが @link_root となる)
|
---|
6514 | # root namespace は Region かつ node なので必ず @link_root は見つかる
|
---|
6515 | # mikan: self が node, linkUnit の場合、ここで期待したとおりに設定されないため、Region#initialize で再設定
|
---|
6516 | obj = self
|
---|
6517 | while 1
|
---|
6518 | if obj.instance_of? Region then
|
---|
6519 | @family_line << obj
|
---|
6520 | if @link_root == nil then
|
---|
6521 | if obj.get_region_type == :NODE || obj.get_region_type == :LINKUNIT then
|
---|
6522 | @link_root = obj
|
---|
6523 | end
|
---|
6524 | end
|
---|
6525 | else
|
---|
6526 | # さもなければ Namespace
|
---|
6527 | # namespace の下に region がある場合
|
---|
6528 | end
|
---|
6529 |
|
---|
6530 | # root namespace にたどり着けば終り
|
---|
6531 | break if obj.get_name == "::"
|
---|
6532 |
|
---|
6533 | obj = obj.get_owner
|
---|
6534 | end
|
---|
6535 | # print "#{@name}: linkRoot: #{@link_root.get_name} (this can be wrong if #{@name} is node or linkunit, and corret later\n"
|
---|
6536 | @family_line.reverse!
|
---|
6537 | =end
|
---|
6538 |
|
---|
6539 | end
|
---|
6540 |
|
---|
6541 | #== Region#ドメインを設定する
|
---|
6542 | def set_domain_type domain_type
|
---|
6543 | if @region_type == :NODE then
|
---|
6544 | if @domain_type then
|
---|
6545 | if @domain_type.get_name != domain_type.get_name then
|
---|
6546 | cdl_error( "S9999 '$1' node root cannot belong to both $2 and $3", @name, @domain_type.get_name, domain_type.get_name )
|
---|
6547 | end
|
---|
6548 | else
|
---|
6549 | @domain_type = DomainType.new( self, domain_type.get_name, "OutOfDomain" )
|
---|
6550 | @domain_type.create_domain_plugin
|
---|
6551 | end
|
---|
6552 | elsif @domain_type == nil then
|
---|
6553 | @owner.set_domain_type domain_type
|
---|
6554 | end
|
---|
6555 | end
|
---|
6556 |
|
---|
6557 | def self.get_link_roots
|
---|
6558 | @@link_roots
|
---|
6559 | end
|
---|
6560 |
|
---|
6561 | def get_family_line
|
---|
6562 | @family_line
|
---|
6563 | end
|
---|
6564 |
|
---|
6565 | def get_in_through_list
|
---|
6566 | @in_through_list
|
---|
6567 | end
|
---|
6568 |
|
---|
6569 | def get_out_through_list
|
---|
6570 | @out_through_list
|
---|
6571 | end
|
---|
6572 |
|
---|
6573 | def get_to_through_list
|
---|
6574 | @to_through_list
|
---|
6575 | end
|
---|
6576 |
|
---|
6577 | def get_link_root
|
---|
6578 | @link_root
|
---|
6579 | end
|
---|
6580 |
|
---|
6581 | def get_domain_type
|
---|
6582 | @domain_type
|
---|
6583 | end
|
---|
6584 |
|
---|
6585 | #== Region# domain の根っことなる region を得る
|
---|
6586 | # Region のインスタンスを返す
|
---|
6587 | # domain 指定子があれば、そのリージョンがドメインルートである
|
---|
6588 | # なければ、親リージョンのドメインルートとする
|
---|
6589 | def get_domain_root
|
---|
6590 | @domain_root
|
---|
6591 | end
|
---|
6592 |
|
---|
6593 | def get_path_string
|
---|
6594 | pstring = ""
|
---|
6595 | delim = ""
|
---|
6596 | @family_line.each{ |p|
|
---|
6597 | pstring = "#{pstring}#{delim}#{p.get_name}"
|
---|
6598 | delim = "."
|
---|
6599 | }
|
---|
6600 | dbgPrint "get_path_string: #{pstring}\n"
|
---|
6601 | pstring
|
---|
6602 | end
|
---|
6603 |
|
---|
6604 | def get_region_type
|
---|
6605 | @region_type
|
---|
6606 | end
|
---|
6607 |
|
---|
6608 | def get_name
|
---|
6609 | @name
|
---|
6610 | end
|
---|
6611 |
|
---|
6612 | def next_in_through_count
|
---|
6613 | @in_through_count += 1
|
---|
6614 | end
|
---|
6615 |
|
---|
6616 | def next_out_through_count
|
---|
6617 | @out_through_count += 1
|
---|
6618 | end
|
---|
6619 |
|
---|
6620 | def next_to_through_count( symRegionName )
|
---|
6621 | if @to_through_count[ symRegionName ] == nil then
|
---|
6622 | @to_through_count[ symRegionName ] = 0
|
---|
6623 | else
|
---|
6624 | @to_through_count[ symRegionName ] += 1
|
---|
6625 | end
|
---|
6626 | end
|
---|
6627 |
|
---|
6628 | #=== Region# 構文解析中の region を得る
|
---|
6629 | # 構文解析中 Namespace (あるいは子クラスの Region) の上位をたどって Region を見つける
|
---|
6630 | # cell が namespace 下におくことができなければ、ループをまわす必要はない
|
---|
6631 | def self.get_current
|
---|
6632 | # @@region_stack[@@region_stack_sp]
|
---|
6633 | region = Namespace.get_current
|
---|
6634 | while 1
|
---|
6635 | if region.instance_of? Region
|
---|
6636 | break
|
---|
6637 | end
|
---|
6638 | region = region.get_owner
|
---|
6639 | end
|
---|
6640 | return region
|
---|
6641 | end
|
---|
6642 |
|
---|
6643 | #=== Region# through プラグインで、この region から cell_name.port_name へのプラグインオブジェクトを登録
|
---|
6644 | # mikan namesppace 対応 (cell_name)
|
---|
6645 | def add_cell_port_through_plugin( cell_name, port_name, through_plugin_object )
|
---|
6646 | @cell_port_throug_plugin_list[ "#{cell_name}.#{port_name}" ] = through_plugin_object
|
---|
6647 | end
|
---|
6648 |
|
---|
6649 | def find_cell_port_through_plugin( cell_name, port_name )
|
---|
6650 | return @cell_port_throug_plugin_list[ "#{cell_name}.#{port_name}" ]
|
---|
6651 | end
|
---|
6652 |
|
---|
6653 | def create_domain_plugin
|
---|
6654 | if @domain_type then
|
---|
6655 | @domain_type.create_domain_plugin
|
---|
6656 | end
|
---|
6657 | end
|
---|
6658 |
|
---|
6659 | #=== Region# to_region への距離(unreachable な場合 nil)
|
---|
6660 | # mikan Cell#check_region とRegion へたどり着くまでための処理に共通性が高い
|
---|
6661 | # region#distance は require で用いられる
|
---|
6662 | def distance( to_region )
|
---|
6663 |
|
---|
6664 | r1 = self # 出発 region
|
---|
6665 | r2 = to_region # 目的 region
|
---|
6666 | dist = 0
|
---|
6667 |
|
---|
6668 | if ! r1.equal? r2 then # 同一 region なら呼出し可能
|
---|
6669 |
|
---|
6670 | # mikan namespace 対応
|
---|
6671 | f1 = r1.get_family_line
|
---|
6672 | len1 = f1.length
|
---|
6673 | f2 = r2.get_family_line
|
---|
6674 | len2 = f2.length
|
---|
6675 |
|
---|
6676 | # 不一致になるところ(兄弟)を探す
|
---|
6677 | i = 1 # i = 0 は :RootRegion なので必ず一致
|
---|
6678 | while( i < len1 && i < len2 )
|
---|
6679 | if( f1[i] != f2[i] )then
|
---|
6680 | break
|
---|
6681 | end
|
---|
6682 | i += 1
|
---|
6683 | end
|
---|
6684 |
|
---|
6685 | sibling_level = i # 兄弟となるレベル、もしくはどちらか一方が終わったレベル
|
---|
6686 |
|
---|
6687 | # p "sibling_level: #{i}"
|
---|
6688 | # p "from: #{f1[i].get_name}" if f1[i]
|
---|
6689 | # p "to: #{f2[i].get_name}" if f2[i]
|
---|
6690 |
|
---|
6691 | # 呼び側について呼び元のレベルから兄弟レベルまで(out_through をチェックおよび挿入)
|
---|
6692 | i = len1 -1
|
---|
6693 | while i >= sibling_level
|
---|
6694 | dbgPrint "going out from #{f1[i].get_name} level=#{i}\n"
|
---|
6695 | # print "DOMAIN: going out from #{f1[i].get_name} level=#{i}\n"
|
---|
6696 | domain = f1[i].get_domain_type
|
---|
6697 | domain_ok = false
|
---|
6698 | if domain then
|
---|
6699 | if ! f1[i].get_domain_type.joinable?( f1[i], f1[i-1], :OUT_THROUGH ) then
|
---|
6700 | return nil
|
---|
6701 | end
|
---|
6702 | domain_ok = true
|
---|
6703 | end
|
---|
6704 | if ! domain_ok then
|
---|
6705 | out_through_list = f1[i].get_out_through_list # [ plugin_name, plugin_arg ]
|
---|
6706 | if out_through_list.length == 0 then
|
---|
6707 | return nil
|
---|
6708 | end
|
---|
6709 | end
|
---|
6710 | i -= 1
|
---|
6711 | dist += 1
|
---|
6712 | end
|
---|
6713 |
|
---|
6714 | # 兄弟レベルにおいて(to_through をチェックおよび挿入)
|
---|
6715 | if f1[sibling_level] && f2[sibling_level] then
|
---|
6716 | dbgPrint "going from #{f1[sibling_level].get_name} to #{f2[sibling_level].get_name}\n"
|
---|
6717 | # print "DOMAIN: going from #{f1[sibling_level].get_name} to #{f2[sibling_level].get_name}\n"
|
---|
6718 | domain = f1[sibling_level].get_domain_type
|
---|
6719 | domain_ok = false
|
---|
6720 | if domain then
|
---|
6721 | if ! f1[i].get_domain_type.joinable?( f1[i], f1[i-1], :TO_THROUGH ) then
|
---|
6722 | return nil
|
---|
6723 | end
|
---|
6724 | domain_ok = true
|
---|
6725 | end
|
---|
6726 | if ! domain_ok then
|
---|
6727 | found = 0
|
---|
6728 | f1[sibling_level].get_to_through_list.each { |t|
|
---|
6729 | if t[0][0] == f2[sibling_level].get_name then # region 名が一致するか ?
|
---|
6730 | found = 1
|
---|
6731 | end
|
---|
6732 | }
|
---|
6733 | if found == 0 then
|
---|
6734 | return nil
|
---|
6735 | end
|
---|
6736 | end
|
---|
6737 | dist += 1
|
---|
6738 | end
|
---|
6739 |
|
---|
6740 | # 受け側について兄弟レベルから受け側のレベルまで(in_through をチェックおよび挿入)
|
---|
6741 | i = sibling_level
|
---|
6742 | while i < len2
|
---|
6743 | dbgPrint "going in to #{f2[i].get_name} level=#{i}\n"
|
---|
6744 | # print "DOMAIN: going in to #{f2[i].get_name} level=#{i}\n"
|
---|
6745 | domain = f2[i].get_domain_type
|
---|
6746 | domain_ok = false
|
---|
6747 | if domain then
|
---|
6748 | if ! f2[i].get_domain_type.joinable?( f2[i-1], f2[i], :IN_THROUGH ) then
|
---|
6749 | return nil
|
---|
6750 | end
|
---|
6751 | domain_ok = true
|
---|
6752 | end
|
---|
6753 | if ! domain_ok then
|
---|
6754 | in_through_list = f2[i].get_in_through_list # [ plugin_name, plugin_arg ]
|
---|
6755 | if in_through_list.length == 0 then
|
---|
6756 | return nil
|
---|
6757 | end
|
---|
6758 | end
|
---|
6759 | i += 1
|
---|
6760 | dist += 1
|
---|
6761 | end
|
---|
6762 | end
|
---|
6763 |
|
---|
6764 | dbgPrint "dsitance=#{dist} from #{r1.get_name} to #{r2.get_name}\n"
|
---|
6765 |
|
---|
6766 | return dist
|
---|
6767 | end
|
---|
6768 |
|
---|
6769 | def show_tree( indent )
|
---|
6770 | super
|
---|
6771 | (indent+1).times { print( " " ) }
|
---|
6772 | puts "path: #{get_path_string}"
|
---|
6773 | (indent+1).times { print( " " ) }
|
---|
6774 | puts "namespace: #{@namespace ? @namespace.get_name : "nil"} owner: #{@owner.class}.#{@owner ? @owner.get_name : "nil"}"
|
---|
6775 | if @domain
|
---|
6776 | @domain.show_tree( indent+1 )
|
---|
6777 | end
|
---|
6778 | end
|
---|
6779 | end
|
---|
6780 |
|
---|
6781 | class Import_C < Node
|
---|
6782 |
|
---|
6783 | # ヘッダの名前文字列のリスト
|
---|
6784 | @@header_list = {}
|
---|
6785 | @@header_list2 = []
|
---|
6786 | @@define_list = {}
|
---|
6787 |
|
---|
6788 | #=== Import_C# import_C の生成(ヘッダファイルを取込む)
|
---|
6789 | #header:: Token : import_C の第一引数文字列リテラルトークン
|
---|
6790 | #define:: Token : import_C の第二引数文字列リテラルトークン
|
---|
6791 | def initialize( header, define = nil )
|
---|
6792 | super()
|
---|
6793 | # ヘッダファイル名文字列から前後の "" を取り除く
|
---|
6794 | # header = header.to_s.gsub( /\A"(.*)"\z/, '\1' )
|
---|
6795 | header = CDLString.remove_dquote header.to_s
|
---|
6796 |
|
---|
6797 | if define then
|
---|
6798 | # 前後の "" を取り除く
|
---|
6799 | # def_opt = define.to_s.gsub( /\A"(.*)/, '\1' )
|
---|
6800 | # def_opt.sub!( /(.*)"\z/, '\1' )
|
---|
6801 | def_opt = CDLString.remove_dquote define.to_s
|
---|
6802 |
|
---|
6803 | # "," を -D に置き換え
|
---|
6804 | def_opt = def_opt.gsub( /,/, " -D " )
|
---|
6805 |
|
---|
6806 | # 先頭に -D を挿入 # mikan 不適切な define 入力があった場合、CPP 時にエラー
|
---|
6807 | def_opt = def_opt.gsub( /^/, "-D " )
|
---|
6808 |
|
---|
6809 | end
|
---|
6810 |
|
---|
6811 | # コマンドライン指定された DEFINE
|
---|
6812 | $define.each{ |define|
|
---|
6813 | if $IN_EXERB then
|
---|
6814 | q = ""
|
---|
6815 | else
|
---|
6816 | if define =~ /'/ then
|
---|
6817 | q = '"'
|
---|
6818 | else
|
---|
6819 | q = "'"
|
---|
6820 | end
|
---|
6821 | end
|
---|
6822 | def_opt = "#{def_opt} -D #{q}#{define}#{q}"
|
---|
6823 | }
|
---|
6824 |
|
---|
6825 | include_opt = ""
|
---|
6826 | found = false
|
---|
6827 | header_path = ""
|
---|
6828 | $import_path.each{ |path|
|
---|
6829 | include_opt = "#{include_opt} -I #{path}"
|
---|
6830 | if found == false then
|
---|
6831 | begin
|
---|
6832 | # ファイルの stat を取ってみる(なければ例外発生)
|
---|
6833 | File.stat( "#{path}/#{header}" )
|
---|
6834 |
|
---|
6835 | # cdl を見つかったファイルパスに再設定
|
---|
6836 | header_path = "#{path}/#{header}"
|
---|
6837 | found = true
|
---|
6838 | rescue => evar
|
---|
6839 | found = false
|
---|
6840 | # print_exception( evar )
|
---|
6841 | end
|
---|
6842 | end
|
---|
6843 | }
|
---|
6844 |
|
---|
6845 | if found == false then
|
---|
6846 | cdl_error( "S1142 $1 not found in search path" , header )
|
---|
6847 | return
|
---|
6848 | end
|
---|
6849 |
|
---|
6850 | # 読込み済み?
|
---|
6851 | if( @@header_list[ header ] ) then
|
---|
6852 | # 第二引数 define が以前と異なる
|
---|
6853 | if @@define_list[ header ].to_s != define.to_s then
|
---|
6854 | cdl_error( "S1143 import_C: arg2: mismatch with previous one" )
|
---|
6855 | end
|
---|
6856 | # いずれにせよ読み込まない
|
---|
6857 | return
|
---|
6858 | end
|
---|
6859 |
|
---|
6860 | # ヘッダのリストを記録
|
---|
6861 | @@header_list[ header ] = header_path
|
---|
6862 | @@header_list2 << header
|
---|
6863 | @@define_list[ header ] = define
|
---|
6864 |
|
---|
6865 | begin
|
---|
6866 | tmp_C = "#{$gen}/tmp_C_src.c"
|
---|
6867 | file = File.open( tmp_C, "w" )
|
---|
6868 | rescue => evar
|
---|
6869 | cdl_error( "S1144 $1: temporary C source: open error" , tmp_C )
|
---|
6870 | print_exception( evar )
|
---|
6871 | end
|
---|
6872 |
|
---|
6873 | begin
|
---|
6874 | print_defines file
|
---|
6875 |
|
---|
6876 | file.print( "#include \"#{header}\"\n" )
|
---|
6877 | rescue => evar
|
---|
6878 | cdl_error( "S1145 $1: temporary C source: writing error" , tmp_C )
|
---|
6879 | print_exception( evar )
|
---|
6880 | ensure
|
---|
6881 | file.close
|
---|
6882 | end
|
---|
6883 |
|
---|
6884 | # CPP 出力用 tmp ファイル名
|
---|
6885 | tmp_header = header.gsub( /\//, "_" )
|
---|
6886 | tmp_header = "#{$gen}/tmp_#{tmp_header}"
|
---|
6887 |
|
---|
6888 | # CPP コマンドラインを作成
|
---|
6889 | cmd = "#{$cpp} #{def_opt} #{include_opt} #{tmp_C}"
|
---|
6890 |
|
---|
6891 | begin
|
---|
6892 | if( $verbose )then
|
---|
6893 | puts "CPP: #{cmd}"
|
---|
6894 | end
|
---|
6895 |
|
---|
6896 | # プリプロセッサコマンドを pipe として開く
|
---|
6897 | # cmd は cygwin/Linux では bash(sh) 経由で実行される
|
---|
6898 | # Exerb 版では cmd.exe 経由で実行される
|
---|
6899 | # この差は引き数の (), $, % などシェルの特別な文字の評価に現れるので注意
|
---|
6900 | cpp = IO.popen( cmd, "r:ASCII-8BIT" )
|
---|
6901 | begin
|
---|
6902 | tmp_file = nil
|
---|
6903 | tmp_file = File.open( tmp_header, "w:ASCII-8BIT" )
|
---|
6904 | cpp.each { |line|
|
---|
6905 | line = line.gsub( /^#(.*)$/, '/* \1 */' )
|
---|
6906 | tmp_file.puts( line )
|
---|
6907 | }
|
---|
6908 | rescue => evar
|
---|
6909 | cdl_error( "S1146 $1: error occured while CPP" , header )
|
---|
6910 | print_exception( evar )
|
---|
6911 | ensure
|
---|
6912 | tmp_file.close if tmp_file # mikan File.open に失敗した時 tmp_file == nil は保証されている ?
|
---|
6913 | cpp.close
|
---|
6914 | end
|
---|
6915 | rescue => evar
|
---|
6916 | cdl_error( "S1147 $1: popen for CPP failed" , header )
|
---|
6917 | print_exception( evar )
|
---|
6918 | end
|
---|
6919 |
|
---|
6920 | # C 言語のパーサインスタンスを生成
|
---|
6921 | c_parser = C_parser.new
|
---|
6922 |
|
---|
6923 | # tmp_header をパース
|
---|
6924 | c_parser.parse( [tmp_header] )
|
---|
6925 |
|
---|
6926 | # 終期化 パーサスタックを戻す
|
---|
6927 | c_parser.finalize
|
---|
6928 |
|
---|
6929 | end
|
---|
6930 |
|
---|
6931 | def print_defines file
|
---|
6932 | if ! $b_no_gcc_extension_support then
|
---|
6933 |
|
---|
6934 | file.print <<EOT
|
---|
6935 |
|
---|
6936 | #ifndef TECS_NO_GCC_EXTENSION_SUPPORT
|
---|
6937 |
|
---|
6938 | /*
|
---|
6939 | * these extension can be eliminated also by spefcifying option
|
---|
6940 | * --no-gcc-extension-support for tecsgen.
|
---|
6941 | */
|
---|
6942 | #ifndef __attribute__
|
---|
6943 | #define __attribute__(x)
|
---|
6944 | #endif
|
---|
6945 |
|
---|
6946 | #ifndef __extension__
|
---|
6947 | #define __extension__
|
---|
6948 | #endif
|
---|
6949 |
|
---|
6950 | #ifndef __builtin_va_list
|
---|
6951 | #define __builtin_va_list va_list
|
---|
6952 | #endif
|
---|
6953 |
|
---|
6954 | #ifndef __asm__
|
---|
6955 | #define __asm__(x)
|
---|
6956 | #endif
|
---|
6957 |
|
---|
6958 | #endif /* TECS_NO_GCC_EXTENSION_SUPPORT */
|
---|
6959 | EOT
|
---|
6960 | end
|
---|
6961 |
|
---|
6962 | file.print <<EOT
|
---|
6963 |
|
---|
6964 | /* va_list is not supported in C_parser.y.rb */
|
---|
6965 | typedef struct { int dummy; } va_list;
|
---|
6966 |
|
---|
6967 | EOT
|
---|
6968 | end
|
---|
6969 |
|
---|
6970 | def self.get_header_list
|
---|
6971 | @@header_list
|
---|
6972 | end
|
---|
6973 | def self.get_header_list2
|
---|
6974 | @@header_list2
|
---|
6975 | end
|
---|
6976 |
|
---|
6977 | end
|
---|
6978 |
|
---|
6979 | class Import < Node
|
---|
6980 | # @b_reuse::bool: 再利用.セルタイプの template 生成不要
|
---|
6981 | # @b_reuse_real::bool: 実際に再利用
|
---|
6982 | # @cdl:: string: import する CDL
|
---|
6983 | # @cdl_path:: string: CDL のパス
|
---|
6984 | # @b_imported:: bool: import された(コマンドライン指定されていない)
|
---|
6985 |
|
---|
6986 | # ヘッダの名前文字列のリスト 添字:expand したパス、値:Import
|
---|
6987 | @@import_list = {}
|
---|
6988 |
|
---|
6989 | @@nest_stack_index = -1
|
---|
6990 | @@nest_stack = []
|
---|
6991 | @@current_object = nil
|
---|
6992 |
|
---|
6993 | def self.push object
|
---|
6994 | @@nest_stack_index += 1
|
---|
6995 | @@nest_stack[ @@nest_stack_index ] = @@current_object
|
---|
6996 | @@current_object = object
|
---|
6997 | end
|
---|
6998 |
|
---|
6999 | def self.pop
|
---|
7000 | @@current_object = @@nest_stack[ @@nest_stack_index ]
|
---|
7001 | @@nest_stack_index -= 1
|
---|
7002 | if @@nest_stack_index < -1 then
|
---|
7003 | raise "TooManyRestore"
|
---|
7004 | end
|
---|
7005 | end
|
---|
7006 |
|
---|
7007 | #=== Import# import を行う
|
---|
7008 | #cdl:: string cdl へのパス."" で囲まれていることを仮定
|
---|
7009 | #b_reuse:: bool true: template を生成しない
|
---|
7010 | def initialize( cdl, b_reuse = false, b_imported = true )
|
---|
7011 | Import.push self
|
---|
7012 | @b_imported = b_imported
|
---|
7013 | super()
|
---|
7014 | @@current_import = self
|
---|
7015 | # ヘッダファイル名文字列から前後の "", <> を取り除くn
|
---|
7016 | @cdl = cdl.to_s.gsub( /\A["<](.*)[">]\z/, '\1' )
|
---|
7017 |
|
---|
7018 | # サーチパスから探す
|
---|
7019 | found = false
|
---|
7020 | @cdl_path = ""
|
---|
7021 |
|
---|
7022 | @b_reuse = b_reuse
|
---|
7023 | @b_reuse_real = @b_reuse || Generator.is_reuse?
|
---|
7024 |
|
---|
7025 | if Generator.get_plugin then
|
---|
7026 | # plugin から import されている場合 gen をサーチパスの先頭に加える
|
---|
7027 | search_path = [ $gen ] + $import_path
|
---|
7028 | else
|
---|
7029 | search_path = $import_path
|
---|
7030 | end
|
---|
7031 |
|
---|
7032 | search_path.each{ |path|
|
---|
7033 | dbgPrint "import: searching #{path}/#{@cdl}"
|
---|
7034 | begin
|
---|
7035 | if path == "."
|
---|
7036 | cdl_path = @cdl
|
---|
7037 | else
|
---|
7038 | cdl_path = "#{path}/#{@cdl}"
|
---|
7039 | end
|
---|
7040 |
|
---|
7041 | # ファイルの stat を取ってみる(なければ例外発生)
|
---|
7042 | File.stat( cdl_path )
|
---|
7043 |
|
---|
7044 | # cdl を見つかったファイルパスに再設定
|
---|
7045 | @cdl_path = cdl_path
|
---|
7046 | found = true
|
---|
7047 | dbgPrint ": found\n"
|
---|
7048 | break
|
---|
7049 | rescue => evar
|
---|
7050 | found = false
|
---|
7051 | dbgPrint ": not found\n"
|
---|
7052 | # print_exception( evar )
|
---|
7053 | end
|
---|
7054 | }
|
---|
7055 |
|
---|
7056 | if found == false then
|
---|
7057 | cdl_error( "S1148 $1 not found in search path" , @cdl )
|
---|
7058 | return
|
---|
7059 | end
|
---|
7060 |
|
---|
7061 | # 読込み済みなら、読込まない
|
---|
7062 | prev = @@import_list[ File.expand_path( @cdl_path ) ]
|
---|
7063 | if( prev ) then
|
---|
7064 | if prev.is_reuse_real? != @b_reuse_real then
|
---|
7065 | cdl_warning( "W1008 $1: reuse designation mismatch with previous import" , @cdl )
|
---|
7066 | end
|
---|
7067 | return
|
---|
7068 | end
|
---|
7069 |
|
---|
7070 | # import リストを記録
|
---|
7071 | @@import_list[ File.expand_path( @cdl_path ) ] = self
|
---|
7072 |
|
---|
7073 | # plugin から import されている場合
|
---|
7074 | plugin = Generator.get_plugin
|
---|
7075 |
|
---|
7076 | # パーサインスタンスを生成(別パーサで読み込む)
|
---|
7077 | parser = Generator.new
|
---|
7078 |
|
---|
7079 | # plugin から import されている場合の plugin 設定
|
---|
7080 | parser.set_plugin plugin
|
---|
7081 |
|
---|
7082 | # reuse フラグを設定
|
---|
7083 | parser.set_reuse @b_reuse_real
|
---|
7084 |
|
---|
7085 | # cdl をパース
|
---|
7086 | parser.parse( [@cdl_path] )
|
---|
7087 |
|
---|
7088 | # 終期化 パーサスタックを戻す
|
---|
7089 | parser.finalize
|
---|
7090 | Import.pop
|
---|
7091 | end
|
---|
7092 |
|
---|
7093 | def self.get_list
|
---|
7094 | @@import_list
|
---|
7095 | end
|
---|
7096 |
|
---|
7097 | def get_cdl_path
|
---|
7098 | @cdl_path
|
---|
7099 | end
|
---|
7100 |
|
---|
7101 | def is_reuse_real?
|
---|
7102 | @b_reuse_real
|
---|
7103 | end
|
---|
7104 |
|
---|
7105 | def self.get_current
|
---|
7106 | @@current_object
|
---|
7107 | end
|
---|
7108 |
|
---|
7109 | def is_imported?
|
---|
7110 | @b_imported
|
---|
7111 | end
|
---|
7112 |
|
---|
7113 | #=== cdl の名前を返す
|
---|
7114 | # 引数で指定されている cdl 名。一部パスを含む可能性がある
|
---|
7115 | def get_cdl_name
|
---|
7116 | @cdl
|
---|
7117 | end
|
---|
7118 | end
|
---|
7119 |
|
---|
7120 | #== generate: signature プラグインのロードと実行
|
---|
7121 | class Generate < Node
|
---|
7122 | #@plugin_name:: Symbol
|
---|
7123 | #@signature_nsp:: NamespacePath
|
---|
7124 | #@option:: String '"', '"' で囲まれている
|
---|
7125 |
|
---|
7126 | include PluginModule
|
---|
7127 |
|
---|
7128 | def initialize( plugin_name, signature_nsp, option )
|
---|
7129 | super()
|
---|
7130 | @plugin_name = plugin_name
|
---|
7131 | @signature_nsp = signature_nsp
|
---|
7132 | option = option.to_s # option は Token
|
---|
7133 | @option = option
|
---|
7134 |
|
---|
7135 | signature = Namespace.find( signature_nsp ) #mikan Namespace #1
|
---|
7136 | if ! signature.instance_of? Signature then
|
---|
7137 | cdl_error( "S1149 $1 not signature" , signature_nsp )
|
---|
7138 | return
|
---|
7139 | elsif signature.is_empty? then
|
---|
7140 | cdl_warning( "S9999 $1 is empty. cannot apply signature plugin. ignored" , signature_nsp )
|
---|
7141 | return
|
---|
7142 | end
|
---|
7143 |
|
---|
7144 | load_plugin( plugin_name, SignaturePlugin )
|
---|
7145 |
|
---|
7146 | plugin_object = nil
|
---|
7147 | eval_str = "plugin_object = #{plugin_name}.new( signature, option )"
|
---|
7148 | if $verbose then
|
---|
7149 | print "new through: #{eval_str}\n"
|
---|
7150 | end
|
---|
7151 |
|
---|
7152 | begin
|
---|
7153 | eval( eval_str ) # plugin を生成
|
---|
7154 | plugin_object.set_locale @locale
|
---|
7155 | rescue Exception => evar
|
---|
7156 | cdl_error( "S1150 $1: fail to new" , plugin_name )
|
---|
7157 | print "eval( #{eval_str} )\n"
|
---|
7158 |
|
---|
7159 | print_exception( evar )
|
---|
7160 | end
|
---|
7161 | generate_and_parse plugin_object
|
---|
7162 | end
|
---|
7163 | end
|
---|
7164 |
|
---|
7165 | #== 名前空間パス
|
---|
7166 | class NamespacePath < Node
|
---|
7167 | #@b_absolute::Bool
|
---|
7168 | #@path::[ Symbol,... ]
|
---|
7169 | #@namespace::Namespace: @b_absolute == false のとき、基点となる namespace
|
---|
7170 |
|
---|
7171 | #=== NamespacePath# initialize
|
---|
7172 | #ident::Symbol 最初の名前, ただし "::" のみの場合は String
|
---|
7173 | #b_absolute:Bool "::" で始まっている場合 true
|
---|
7174 | #namespace::Namespace b_absolute = false かつ、構文解釈段階以外で呼び出す場合は、必ず指定すること
|
---|
7175 | def initialize( ident, b_absolute, namespace = nil )
|
---|
7176 | super()
|
---|
7177 |
|
---|
7178 | if ident == "::" then # RootNamespace
|
---|
7179 | @path = []
|
---|
7180 | @b_absolute = true
|
---|
7181 | else
|
---|
7182 | @path = [ ident ]
|
---|
7183 | @b_absolute = b_absolute
|
---|
7184 | end
|
---|
7185 |
|
---|
7186 | if namespace then
|
---|
7187 | @namespace = namespace
|
---|
7188 | if b_absolute == true then
|
---|
7189 | raise "NamespacePath#initialize: naamespace specified for absolute path"
|
---|
7190 | end
|
---|
7191 | else
|
---|
7192 | if b_absolute == false then
|
---|
7193 | @namespace = Namespace.get_current
|
---|
7194 | else
|
---|
7195 | @namespace = nil
|
---|
7196 | end
|
---|
7197 | end
|
---|
7198 | end
|
---|
7199 |
|
---|
7200 | #=== NamespacePath# append する
|
---|
7201 | #RETURN self
|
---|
7202 | # このメソッドは、元の NamespacePath オブジェクトを変形して返す
|
---|
7203 | def append!( ident )
|
---|
7204 | @path << ident
|
---|
7205 | return self
|
---|
7206 | end
|
---|
7207 | #=== NamespacePath# append する
|
---|
7208 | # このメソッドは、元の NamespacePath オブジェクトを変形しない
|
---|
7209 | #RETURN:: 複製した NamespacePath
|
---|
7210 | def append( ident )
|
---|
7211 | cl = self.clone
|
---|
7212 | cl.set_clone
|
---|
7213 | cl.append!( ident )
|
---|
7214 | return cl
|
---|
7215 | end
|
---|
7216 |
|
---|
7217 | def set_clone
|
---|
7218 | @path = @path.clone
|
---|
7219 | end
|
---|
7220 |
|
---|
7221 | def get_name
|
---|
7222 | @path[ @path.length - 1 ]
|
---|
7223 | end
|
---|
7224 |
|
---|
7225 | #=== NamespacePath#クローンを作成して名前を変更する
|
---|
7226 | def change_name name
|
---|
7227 | cl = self.clone
|
---|
7228 | cl.set_clone
|
---|
7229 | cl.change_name_no_clone name
|
---|
7230 | return cl
|
---|
7231 | end
|
---|
7232 | alias :change_name_clone :change_name
|
---|
7233 |
|
---|
7234 | #=== NamespacePath#名前を変更する
|
---|
7235 | # このインスタンスを参照するすべてに影響を与えることに注意
|
---|
7236 | def change_name_no_clone name
|
---|
7237 | @path[ @path.length - 1 ] = name
|
---|
7238 | nil
|
---|
7239 | end
|
---|
7240 |
|
---|
7241 | #=== NamespacePath:: path 文字列を得る
|
---|
7242 | # CDL 用の path 文字列を生成
|
---|
7243 | def to_s
|
---|
7244 | get_path_str
|
---|
7245 | end
|
---|
7246 | def get_path_str
|
---|
7247 | first = true
|
---|
7248 | if @b_absolute then
|
---|
7249 | path = "::"
|
---|
7250 | else
|
---|
7251 | path = ""
|
---|
7252 | end
|
---|
7253 | @path.each{ |n|
|
---|
7254 | if first then
|
---|
7255 | path = "#{path}#{n}"
|
---|
7256 | first = false
|
---|
7257 | else
|
---|
7258 | path += "::#{n}"
|
---|
7259 | end
|
---|
7260 | }
|
---|
7261 | return path
|
---|
7262 | end
|
---|
7263 |
|
---|
7264 | def is_absolute?
|
---|
7265 | @b_absolute
|
---|
7266 | end
|
---|
7267 | def is_name_only?
|
---|
7268 | @path.length == 1 && @b_absolute == false
|
---|
7269 | end
|
---|
7270 |
|
---|
7271 | #=== NamespacePath:: パスの配列を返す
|
---|
7272 | # is_absolute? true の場合、ルートからのパス
|
---|
7273 | # false の場合、base_namespace からの相対
|
---|
7274 | # ルート namespace の場合、長さ0の配列を返す
|
---|
7275 | #
|
---|
7276 | def get_path
|
---|
7277 | @path
|
---|
7278 | end
|
---|
7279 |
|
---|
7280 | #=== NamespacePath#フルパスの配列を返す
|
---|
7281 | # 返された配列を書き換えてはならない
|
---|
7282 | def get_full_path
|
---|
7283 | if @b_absolute then
|
---|
7284 | return @path
|
---|
7285 | else
|
---|
7286 | return @namespace.get_namespace_path.get_full_path.clone + @path
|
---|
7287 | end
|
---|
7288 | end
|
---|
7289 |
|
---|
7290 | #=== NamespacePath:: 相対パスのベースとなる namespace
|
---|
7291 | # is_absolute? == false の時のみ有効な値を返す (true なら nil)
|
---|
7292 | def get_base_namespace
|
---|
7293 | @namespace
|
---|
7294 | end
|
---|
7295 |
|
---|
7296 | #=== NamespacePath:: C 言語グローバル名を得る
|
---|
7297 | def get_global_name
|
---|
7298 | if @b_absolute then
|
---|
7299 | global_name = ""
|
---|
7300 | else
|
---|
7301 | global_name = @namespace.get_global_name
|
---|
7302 | end
|
---|
7303 |
|
---|
7304 | @path.each{ |n|
|
---|
7305 | if global_name != "" then
|
---|
7306 | global_name = "#{global_name}_#{n}"
|
---|
7307 | else
|
---|
7308 | global_name = n.to_s
|
---|
7309 | end
|
---|
7310 | }
|
---|
7311 | global_name
|
---|
7312 | end
|
---|
7313 |
|
---|
7314 | #=== NamespacePath:: 分解して NamespacePath インスタンスを生成する
|
---|
7315 | #path_str:: String : namespace または region のパス ex) "::path::A" , "::", "ident"
|
---|
7316 | #b_force_absolute:: Bool : "::" で始まっていない場合でも絶対パスに扱う
|
---|
7317 | #
|
---|
7318 | # NamespacePath は通常構文解析されて作成される
|
---|
7319 | # このメソッドは、オプションなどで指定される文字列を分解して NamespacePath を生成するのに用いる
|
---|
7320 | # チェックはゆるい。不適切なパス指定は、不適切な NamespacePath が生成される
|
---|
7321 | def self.analyze( path_str, b_force_absolute = false )
|
---|
7322 |
|
---|
7323 | if path_str == "::" then
|
---|
7324 | return self.new( "::", true )
|
---|
7325 | end
|
---|
7326 |
|
---|
7327 | pa = path_str.split( "::" )
|
---|
7328 | if pa[0] == "" then
|
---|
7329 | pa.shift
|
---|
7330 | b_absolute = true
|
---|
7331 | else
|
---|
7332 | if b_force_absolute then
|
---|
7333 | b_absolute = true
|
---|
7334 | else
|
---|
7335 | b_absolute = false
|
---|
7336 | end
|
---|
7337 | end
|
---|
7338 |
|
---|
7339 | if pa[0] then
|
---|
7340 | nsp = self.new( pa[0].to_sym, b_absolute )
|
---|
7341 | else
|
---|
7342 | nsp = self.new( "::", b_absolute )
|
---|
7343 | end
|
---|
7344 | pa.shift
|
---|
7345 |
|
---|
7346 | pa.each{ |a|
|
---|
7347 | if a then
|
---|
7348 | nsp.append! a.to_sym
|
---|
7349 | else
|
---|
7350 | nsp.append! "::"
|
---|
7351 | end
|
---|
7352 | }
|
---|
7353 |
|
---|
7354 | return nsp
|
---|
7355 | end
|
---|
7356 |
|
---|
7357 | end
|
---|
7358 |
|
---|
7359 | # 以下単体テストコード
|
---|
7360 | if $unit_test then
|
---|
7361 | root_namespace = Namespace.new("::")
|
---|
7362 |
|
---|
7363 | puts( "===== Unit Test: NamespacePath ===== (componentobj.rb)")
|
---|
7364 | a = NamespacePath.new( :"ABC", true )
|
---|
7365 | printf( "Path: %-10s global_name: %s\n", a.get_path_str, a.get_global_name )
|
---|
7366 |
|
---|
7367 | a.append( :"DEF" )
|
---|
7368 | printf( "Path: %-10s global_name: %s\n", a.get_path_str, a.get_global_name )
|
---|
7369 |
|
---|
7370 | a = NamespacePath.new( :"abc", false )
|
---|
7371 | printf( "Path: %-10s global_name: %s\n", a.get_path_str, a.get_global_name )
|
---|
7372 |
|
---|
7373 | a.append( :"def" )
|
---|
7374 | printf( "Path: %-10s global_name: %s\n", a.get_path_str, a.get_global_name )
|
---|
7375 |
|
---|
7376 | puts ""
|
---|
7377 | end
|
---|