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

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

ASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby;charset=UTF-8
File size: 14.9 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# TECS Generator
4# Generator for TOPPERS Embedded Component System
5#
6# Copyright (C) 2008-2014 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: optimize.rb 2633 2017-04-02 06:02:05Z okuma-top $
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 @cell_list.each{ |c|
181 if c.is_generate? then
182 dr = c.get_region.get_domain_root
183 if dr.get_domain_type then
184 dn = dr.get_domain_type.get_name
185 else
186 dn = nil
187 end
188 if @domain_roots[ dn ] then
189 @domain_roots[ dn ] << dr
190 else
191 @domain_roots[ dn ] = [ dr ]
192 end
193 end
194 }
195
196 @domain_roots.each{ |dn, drs|
197 drs.uniq!
198 if ! $debug then
199 dbgPrint "domains celltype:#{@name} domain=#{dn} "
200 drs.each{ |r|
201 dbgPrint " region=#{r.get_name}"
202 }
203 dbgPrint "\n"
204 end
205 }
206 if @domain_roots.length > 1 then
207 p @domain_roots
208 raise "ambigous DomainType"
209 end
210
211 @domain_roots.each{ |dn, regions|
212 # domain_type は一つのノードに一つしかないので、一つの要素を無条件で取り出す
213 if regions.length > 1 then
214 cdl_info( "I9999 celltype:#{@name} has cells in multi domain.\n" )
215 if @idx_is_id == false then
216 cdl_info( "I9999 celltype:#{@name} forcely set idx_is_id\n" )
217 end
218 @idx_is_id_act = true
219 end
220 }
221 end
222
223 def optimize
224
225 # port の参照するセルタイプの数、セルの数を求める
226 if $verbose then
227 print "=== optimizing celltype #{get_namespace_path.to_s} ===\n"
228 end
229
230 @port.each{ |port|
231 next if port.get_port_type != :CALL
232 if port.is_omit? then
233 # 呼び口最適化実施
234 @b_cp_optimized = true
235 @n_call_port_omitted_in_CB += 1 # CB で省略する呼び口
236 port.set_skelton_useless # スケルトン関数不要最適化
237 port.set_VMT_useless # VMT 不要最適化 (直接受け口関数を呼出す)
238 if $verbose then
239 print "optimized by omit: port: #{port.get_name} : o\n"
240 end
241 next
242 elsif port.is_dynamic? then
243 if $verbose then
244 print "unoptimized by dynamic: port: #{port.get_name}\n"
245 end
246 next
247 elsif port.is_ref_desc? then
248 if $verbose then
249 print "unoptimized by ref_desc: port: #{port.get_name}\n"
250 end
251 next
252 end
253
254 if $verbose then
255 print "optimizing port : #{port.get_name}\n"
256 end
257
258 port_cells = [] # 呼び先セル
259 port_ports = [] # 呼び先のポート
260
261 # セルの参照するセルを集める(ポートも一緒に集める)
262 @cell_list.each{ |cell|
263
264 if ! cell.is_generate? then
265 next
266 end
267
268 jl = cell.get_join_list
269 j = jl.get_item( port.get_name )
270
271 if j then
272 if j.get_array_member2 then
273 # 呼び口配列の場合、全部の結合先を集める
274 j.get_array_member2.each { |j2|
275 if j2 then
276 port_cells << j2.get_rhs_cell
277 port_ports << j2.get_rhs_port # 右辺のポート
278 else
279 # optional で、ある添数のみ初期化されていない(すべて初期化されない場合は、下)
280 port_cells << nil
281 port_ports << nil
282 end
283 }
284 else
285 # 全ての結合先を集める
286 port_cells << j.get_rhs_cell
287 port_ports << j.get_rhs_port # 右辺のポート
288 end
289 else
290 # optional で初期化されていない(nil を要素に加えておく)
291 port_cells << nil
292 port_ports << nil # 右辺のポート
293 end
294 }
295
296 # 重複要素を取り除く
297 port_cells.uniq!
298 port_ports.uniq!
299
300 # 呼び口の呼び先が一つのポートだけか?
301 if port_ports.length == 1 then
302
303 # 呼び口配列が可変長の場合、最適化しない
304 # mikan 呼び口配列要素数マクロ不具合暫定対策
305 # より望ましい修正は、受け口へのポインタは省略するが、配列個数は出力する(#_CP_#, #_TCP_#)
306 # さらに配列個数が定数化できるのであれば、定数マクロを出力 (#_NCPA_#)
307 next if port.get_array_size == "[]"
308
309 # 呼び口最適化実施
310 @b_cp_optimized = true
311
312 # 呼び先が一つのセルだけか?
313 if port_cells.length == 1 then
314
315 # 呼び口は optional で初期化されていない、または受け口は配列ではないか?
316 if port_ports[0] == nil || port_ports[0].get_array_size == nil then
317
318 @n_call_port_omitted_in_CB += 1 # CB で省略する呼び口
319 port.set_cell_unique # セル一つだけ最適化
320 port.set_skelton_useless # スケルトン関数不要最適化
321 port.set_VMT_useless # VMT 不要最適化 (直接受け口関数を呼出す)
322
323 if $verbose then
324 print "cell_unique, VMT_useless & skelton_useless optimize\n"
325 end
326 else
327 port.set_VMT_useless # VMT 不要最適化 (スケルトン関数を呼出す)
328
329 if $verbose then
330 print "VMT_useless optimize\n"
331 end
332 end
333
334 else # 呼び先が複数のセル(単一のポート)
335
336 # 呼び口は optional で初期化されていない、または受け口は配列ではないか?
337 if port_ports[0] == nil || port_ports[0].get_array_size == nil then
338 if ! @singleton then
339 port.set_skelton_useless # スケルトン関数不要最適化
340 port.set_VMT_useless # VMT 不要最適化 (スケルトン関数 or 受け口関数を呼出す)
341
342 if $verbose then
343 print "VMT_useless & skelton useless optimize\n"
344 end
345 else
346 port.set_VMT_useless # VMT 不要最適化 (スケルトン関数 or 受け口関数を呼出す)
347
348 if $verbose then
349 print "VMT_useless optimize\n"
350 end
351 end
352 end
353 end
354
355 port.set_only_callee( port_ports[0], port_cells[0] )
356 # set_cell_unique でない場合 cell は意味がない
357
358 end
359
360 # debug
361 dbgPrint "#{port.get_name} : # of cells : #{port_cells.length} # of ports : #{port_ports.length}\n"
362 }
363
364 # 受け口最適化の設定
365 @port.each{ |port|
366 next if port.get_port_type != :CALL
367
368 # 呼び口側の最適化状態
369 b_VMT_useless = port.is_VMT_useless?
370 b_skelton_useless = port.is_skelton_useless?
371
372 # セルの参照するセルを集める(ポートも一緒に集める)
373 @cell_list.each{ |cell|
374
375 if ! cell.is_generate? then
376 next
377 end
378
379 jl = cell.get_join_list
380 j = jl.get_item( port.get_name )
381
382 if j then # optional で結合されていない場合 nil
383 if j.get_array_member2 then
384 # 呼び口配列
385 j.get_array_member2.each { |j2|
386 if j2 then
387 port2 = j2.get_rhs_port # 右辺のポート
388 # 受け口側の最適化可能性を設定
389 port2.set_entry_VMT_skelton_useless( b_VMT_useless, b_skelton_useless )
390 #else
391 # optional で呼び口配列要素が初期化されていない
392 end
393 }
394 else
395 port2 = j.get_rhs_port # 右辺のポート
396 # 受け口側の最適化可能性を設定
397 port2.set_entry_VMT_skelton_useless( b_VMT_useless, b_skelton_useless )
398 end
399 end
400 }
401 }
402 end
403
404 #Celltype# リセットする
405 def reset_optimize
406 @@ID_BASE = ID_BASE # 本当は一回だけでよい
407 @id_base = 1 # set_cell_id でリセットされるので不要
408
409 @b_cp_optimized = false # 呼び口最適化
410 @n_call_port_omitted_in_CB = 0 # 呼び口最適化により不生成となったポートの数
411 @n_cell_gen = 0 # 生成セル個数
412 @port.each{ |p|
413 p.reset_optimize
414 }
415 @included_header = {}
416 @domain_roots = {}
417 end
418
419 #Celltype# ヘッダは include されているか
420 #hname::Symbol : ヘッダ名
421 #RETURN:: bool_t: false インクルードされていない、true インクルードされている
422 # #_ISH_#, #_ICT_# でヘッダが取り込まれているかチェックする
423 # false が返った場合、hname は登録されて、次回の呼び出しでは true が返る
424 def header_included?( hname )
425 if @included_header[ hname ] == nil then
426 @included_header[ hname ] = true
427 return false
428 else
429 return true
430 end
431 end
432end
433
434
Note: See TracBrowser for help on using the repository browser.