source: asp3_tinet_ecnl_rx/trunk/asp3_dcre/tecsgen/tecslib/core/optimize.rb@ 374

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

mbed関連を更新
シリアルドライバをmbedのHALを使うよう変更
ファイルディスクリプタの処理を更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby;charset=UTF-8
File size: 15.7 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# TECS Generator
4# Generator for TOPPERS Embedded Component System
5#
6# Copyright (C) 2008-2018 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=begin
41This file includes the processes between semantics analysis and code generation.
42Optimize is one of them.
43Other processes are setting ID for each cell and setting domain information
44
45このファイルには、意味解析からコード生成の間で行うべき処理が含まれる.
46最適化もその一つである.
47その他に、セル毎の ID 付け、ドメインわけを行う.
48コード生成対象となるセルを対象に処理を行うものが含まれる.
49=end
50
51class Namespace
52
53 #=== 各セルに ID (整数値)を割付ける
54 def set_cell_id_and_domain
55 # celltype の各セルに ID を割付ける
56 @celltype_list.each { |t|
57 t.set_cell_id_and_domain
58 }
59
60 # サブネームスペースの各セルに ID を割付ける
61 @namespace_list.each { |n|
62 n.set_cell_id_and_domain
63 }
64 end
65
66 def optimize
67 # celltype の最適化
68 @celltype_list.each { |t|
69 t.optimize
70 }
71
72 # サブネームスペースの最適化
73 @namespace_list.each { |n|
74 n.optimize
75 }
76 end
77
78 def reset_optimize
79 # celltype の最適化
80 @celltype_list.each { |t|
81 t.reset_optimize
82 }
83
84 # サブネームスペースの最適化
85 @namespace_list.each { |n|
86 n.reset_optimize
87 }
88 end
89end
90
91class Celltype
92
93 ID_BASE = 1 # reset_optimize でリセットする
94 @@ID_BASE = ID_BASE
95
96 def set_cell_id_and_domain
97 set_cell_id
98 set_domain
99 end
100
101 #=== 各セルに ID (整数値)を割付ける
102 def set_cell_id
103
104 if $verbose then
105 print( "=== id for the cells of celltype #{get_namespace_path.to_s} ===\n" )
106 end
107
108 if $unique_id then
109 @id_base = @@ID_BASE # id をシステム全体で連番にする
110 else
111 @id_base = 1 # base を常に 1 から始める
112 end
113
114 id_specified_cells = []
115 no_id_specified_cells = []
116
117 # プロトタイプを除いた数を求める
118 @cell_list.each{ |c|
119 if c.is_generate? then
120 # c.set_id( @id_base + @n_cell_gen )
121 id = c.get_specified_id
122 if id then
123 id_specified_cells << c
124 else
125 no_id_specified_cells << c
126 end
127
128 # p "#{c.get_name} #{@id_base+@n_cell_gen}"
129 @@ID_BASE += 1
130 @n_cell_gen += 1
131 end
132 }
133
134 @ordered_cell_list = [] # id = 1 が添数 0 に格納される
135 # ID 指定されているセルに id 番号を与える
136 id_specified_cells.each{ |c|
137 id = c.get_specified_id
138 if id > 0 then
139 if id >= @n_cell_gen then
140 cdl_error( "S3001 $1: id too large $2 (max=$3)", c.get_name, id, @n_cell_gen )
141 next
142 end
143 else
144 if - id >= @n_cell_gen then
145 cdl_error( "S3002 $1: id too large $2 (max=$3)", c.get_name, id, @n_cell_gen )
146 next
147 end
148 id = @n_cell_gen + id + 1
149 end
150
151 if @ordered_cell_list[ id - 1 ] then
152 cdl_error( "S3003 $1: id number '$2' conflict with $3", c.get_name, id, @ordered_cell_list[ id - 1 ].get_name )
153 end
154 @ordered_cell_list[ id - 1 ] = c
155 # 通し番号とする場合のため @id_base を加える
156 c.set_id( @id_base - 1 + id )
157 if $verbose then
158 print( "#{c.get_name}: id=#{c.get_id} specified id=#{c.get_specified_id}\n" )
159 end
160 }
161
162 # ID 指定されていないセルに id 番号を与える
163 i = 0
164 no_id_specified_cells.each{ |c|
165 while( @ordered_cell_list[i] != nil )
166 i += 1
167 end
168 @ordered_cell_list[ i ] = c
169 c.set_id( @id_base + i )
170 if $verbose then
171 print( "#{c.get_name}: id=#{c.get_id}\n" )
172 end
173 }
174 if @n_cell_gen >0 && i >= @n_cell_gen then
175 raise "id over id=#{i} N=#{@n_cell_gen}"
176 end
177 end
178
179 def set_domain
180 domain_cells = {}
181 @cell_list.each{ |c|
182 if c.is_generate? then
183 dr = c.get_region.get_domain_root
184 if dr.get_domain_type then
185 dn = dr.get_domain_type.get_name
186 else
187 dn = nil
188 end
189 if @domain_roots[ dn ] then
190 @domain_roots[ dn ] << dr
191 else
192 @domain_roots[ dn ] = [ dr ]
193 end
194 if domain_cells[ dr ] then
195 domain_cells[ dr ] << c
196 else
197 domain_cells[ dr ] = [ c ]
198 end
199 end
200 }
201
202 @domain_roots.each{ |dn, drs|
203 drs.uniq!
204 if $verbose && dn then
205 print "[domain] celltype=#{@name} domainType=#{dn} domainRootRegions={"
206 delim = ""
207 drs.each{ |r|
208 print delim, r.get_name
209 delim = ", "
210 }
211 print "}\n"
212 drs.each{ |r|
213 print "[domain] celltype=#{@name} domainRootRegion=#{r.get_name} domainType=#{dn} domainKind=#{r.get_domain_root.get_domain_type.get_kind} domainCells={"
214 delim = ""
215 domain_cells[r].each{ |c|
216 print delim, c.get_name
217 delim = ", "
218 }
219 print "}\n"
220 }
221 end
222 }
223 if @domain_roots.length > 1 then
224 p @domain_roots
225 raise "ambigous DomainType"
226 end
227
228 @domain_roots.each{ |dn, regions|
229 # domain_type は一つのノードに一つしかないので、一つの要素を無条件で取り出す
230 if regions.length > 1 then
231 if $verbose then
232 cdl_info( "I9999 celltype '$1' has cells in multi-domain.\n", @name )
233 end
234 # if @idx_is_id == false then
235 # cdl_info( "I9999 celltype '$1' forcely set idx_is_id\n", @name )
236 # end
237 @b_need_ptab = true
238 # @idx_is_id_act = true
239 end
240 }
241 end
242
243 def optimize
244
245 # port の参照するセルタイプの数、セルの数を求める
246 if $verbose then
247 print "=== optimizing celltype #{get_namespace_path.to_s} ===\n"
248 end
249
250 optimize_call
251 if $unopt_entry == false then
252 optimize_entry
253 end
254 end
255
256 #=== Celltype#呼び口最適化
257 def optimize_call
258 @port.each{ |port|
259 next if port.get_port_type != :CALL
260 if port.is_omit? then
261 # 呼び口最適化実施
262 @b_cp_optimized = true
263 @n_call_port_omitted_in_CB += 1 # CB で省略する呼び口
264 port.set_skelton_useless # スケルトン関数不要最適化
265 port.set_VMT_useless # VMT 不要最適化 (直接受け口関数を呼出す)
266 if $verbose then
267 print "optimized by omit: port: #{port.get_name} : o\n"
268 end
269 next
270 elsif port.is_dynamic? then
271 if $verbose then
272 print "unoptimized by dynamic: port: #{port.get_name}\n"
273 end
274 next
275 elsif port.is_ref_desc? then
276 if $verbose then
277 print "unoptimized by ref_desc: port: #{port.get_name}\n"
278 end
279 next
280 end
281
282 if $verbose then
283 print "optimizing port : #{port.get_name}\n"
284 end
285
286 port_cells = [] # 呼び先セル
287 port_ports = [] # 呼び先のポート
288
289 # セルの参照するセルを集める(ポートも一緒に集める)
290 @cell_list.each{ |cell|
291
292 if ! cell.is_generate? then
293 next
294 end
295
296 jl = cell.get_join_list
297 j = jl.get_item( port.get_name )
298
299 if j then
300 if j.get_array_member2 then
301 # 呼び口配列の場合、全部の結合先を集める
302 j.get_array_member2.each { |j2|
303 if j2 then
304 port_cells << j2.get_rhs_cell
305 port_ports << j2.get_rhs_port # 右辺のポート
306 else
307 # optional で、ある添数のみ初期化されていない(すべて初期化されない場合は、下)
308 port_cells << nil
309 port_ports << nil
310 end
311 }
312 else
313 # 全ての結合先を集める
314 port_cells << j.get_rhs_cell
315 port_ports << j.get_rhs_port # 右辺のポート
316 end
317 else
318 # optional で初期化されていない(nil を要素に加えておく)
319 port_cells << nil
320 port_ports << nil # 右辺のポート
321 end
322 }
323
324 # 重複要素を取り除く
325 port_cells.uniq!
326 port_ports.uniq!
327
328 # 呼び口の呼び先が一つのポートだけか?
329 if port_ports.length == 1 then
330
331 # 呼び口配列が可変長の場合、最適化しない
332 # mikan 呼び口配列要素数マクロ不具合暫定対策
333 # より望ましい修正は、受け口へのポインタは省略するが、配列個数は出力する(#_CP_#, #_TCP_#)
334 # さらに配列個数が定数化できるのであれば、定数マクロを出力 (#_NCPA_#)
335 next if port.get_array_size == "[]"
336
337 # 呼び口最適化実施
338 @b_cp_optimized = true
339
340 # 呼び先が一つのセルだけか?
341 if port_cells.length == 1 then
342
343 # 呼び口は optional で初期化されていない、または受け口は配列ではないか?
344 if port_ports[0] == nil || port_ports[0].get_array_size == nil then
345
346 @n_call_port_omitted_in_CB += 1 # CB で省略する呼び口
347 port.set_cell_unique # セル一つだけ最適化
348 port.set_skelton_useless # スケルトン関数不要最適化
349 port.set_VMT_useless # VMT 不要最適化 (直接受け口関数を呼出す)
350
351 if $verbose then
352 print "cell_unique, VMT_useless & skelton_useless optimize\n"
353 end
354 else
355 port.set_VMT_useless # VMT 不要最適化 (スケルトン関数を呼出す)
356
357 if $verbose then
358 print "VMT_useless optimize\n"
359 end
360 end
361
362 else # 呼び先が複数のセル(単一のポート)
363
364 # 呼び口は optional で初期化されていない、または受け口は配列ではないか?
365 if port_ports[0] == nil || port_ports[0].get_array_size == nil then
366 if ! @singleton then
367 port.set_skelton_useless # スケルトン関数不要最適化
368 port.set_VMT_useless # VMT 不要最適化 (スケルトン関数 or 受け口関数を呼出す)
369
370 if $verbose then
371 print "VMT_useless & skelton useless optimize\n"
372 end
373 else
374 port.set_VMT_useless # VMT 不要最適化 (スケルトン関数 or 受け口関数を呼出す)
375
376 if $verbose then
377 print "VMT_useless optimize\n"
378 end
379 end
380 end
381 end
382
383 port.set_only_callee( port_ports[0], port_cells[0] )
384 # set_cell_unique でない場合 cell は意味がない
385
386 end
387
388 # debug
389 dbgPrint "#{port.get_name} : # of cells : #{port_cells.length} # of ports : #{port_ports.length}\n"
390 }
391 end
392
393 #=== Celltype#受け口最適化
394 # optimize_entry は、呼び口最適化の結果を使用している
395 def optimize_entry
396 # 受け口最適化の設定
397 @port.each{ |port|
398 next if port.get_port_type != :CALL
399
400 # 呼び口側の最適化状態
401 b_VMT_useless = port.is_VMT_useless?
402 b_skelton_useless = port.is_skelton_useless?
403
404 # セルの参照するセルを集める(ポートも一緒に集める)
405 @cell_list.each{ |cell|
406
407 if ! cell.is_generate? then
408 next
409 end
410
411 jl = cell.get_join_list
412 j = jl.get_item( port.get_name )
413
414 if j then # optional で結合されていない場合 nil
415 if j.get_array_member2 then
416 # 呼び口配列
417 j.get_array_member2.each { |j2|
418 if j2 then
419 port2 = j2.get_rhs_port # 右辺のポート
420 # 受け口側の最適化可能性を設定
421 port2.set_entry_VMT_skelton_useless( b_VMT_useless, b_skelton_useless )
422 #else
423 # optional で呼び口配列要素が初期化されていない
424 end
425 }
426 else
427 port2 = j.get_rhs_port # 右辺のポート
428 # 受け口側の最適化可能性を設定
429 port2.set_entry_VMT_skelton_useless( b_VMT_useless, b_skelton_useless )
430 end
431 end
432 }
433 }
434 end
435
436 #Celltype# リセットする
437 def reset_optimize
438 @@ID_BASE = ID_BASE # 本当は一回だけでよい
439 @id_base = 1 # set_cell_id でリセットされるので不要
440
441 @b_cp_optimized = false # 呼び口最適化
442 @n_call_port_omitted_in_CB = 0 # 呼び口最適化により不生成となったポートの数
443 @n_cell_gen = 0 # 生成セル個数
444 @port.each{ |p|
445 p.reset_optimize
446 }
447 @included_header = {}
448 @domain_roots = {}
449 end
450
451 #Celltype# ヘッダは include されているか
452 #hname::Symbol : ヘッダ名
453 #RETURN:: bool_t: false インクルードされていない、true インクルードされている
454 # #_ISH_#, #_ICT_# でヘッダが取り込まれているかチェックする
455 # false が返った場合、hname は登録されて、次回の呼び出しでは true が返る
456 def header_included?( hname )
457 if @included_header[ hname ] == nil then
458 @included_header[ hname ] = true
459 return false
460 else
461 return true
462 end
463 end
464end
465
466
Note: See TracBrowser for help on using the repository browser.