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

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

文字コードを設定

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby;charset=UTF-8
File size: 14.5 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$
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( "celltype:#{@name} has cells in multi domain.\n" )
215 if @idx_is_id == false then
216 cdl_info( "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 end
243
244 if $verbose then
245 print "optimizing port : #{port.get_name}\n"
246 end
247
248 port_cells = [] # 呼び先セル
249 port_ports = [] # 呼び先のポート
250
251 # セルの参照するセルを集める(ポートも一緒に集める)
252 @cell_list.each{ |cell|
253
254 if ! cell.is_generate? then
255 next
256 end
257
258 jl = cell.get_join_list
259 j = jl.get_item( port.get_name )
260
261 if j then
262 if j.get_array_member2 then
263 # 呼び口配列の場合、全部の結合先を集める
264 j.get_array_member2.each { |j2|
265 if j2 then
266 port_cells << j2.get_rhs_cell
267 port_ports << j2.get_rhs_port # 右辺のポート
268 else
269 # optional で、ある添数のみ初期化されていない(すべて初期化されない場合は、下)
270 port_cells << nil
271 port_ports << nil
272 end
273 }
274 else
275 # 全ての結合先を集める
276 port_cells << j.get_rhs_cell
277 port_ports << j.get_rhs_port # 右辺のポート
278 end
279 else
280 # optional で初期化されていない(nil を要素に加えておく)
281 port_cells << nil
282 port_ports << nil # 右辺のポート
283 end
284 }
285
286 # 重複要素を取り除く
287 port_cells.uniq!
288 port_ports.uniq!
289
290 # 呼び口の呼び先が一つのポートだけか?
291 if port_ports.length == 1 then
292
293 # 呼び口配列が可変長の場合、最適化しない
294 # mikan 呼び口配列要素数マクロ不具合暫定対策
295 # より望ましい修正は、受け口へのポインタは省略するが、配列個数は出力する(#_CP_#, #_TCP_#)
296 # さらに配列個数が定数化できるのであれば、定数マクロを出力 (#_NCPA_#)
297 next if port.get_array_size == "[]"
298
299 # 呼び口最適化実施
300 @b_cp_optimized = true
301
302 # 呼び先が一つのセルだけか?
303 if port_cells.length == 1 then
304
305 # 呼び口は optional で初期化されていない、または受け口は配列ではないか?
306 if port_ports[0] == nil || port_ports[0].get_array_size == nil then
307
308 @n_call_port_omitted_in_CB += 1 # CB で省略する呼び口
309 port.set_cell_unique # セル一つだけ最適化
310 port.set_skelton_useless # スケルトン関数不要最適化
311 port.set_VMT_useless # VMT 不要最適化 (直接受け口関数を呼出す)
312
313 if $verbose then
314 print "cell_unique, VMT_useless & skelton_useless optimize\n"
315 end
316 else
317 port.set_VMT_useless # VMT 不要最適化 (スケルトン関数を呼出す)
318
319 if $verbose then
320 print "VMT_useless optimize\n"
321 end
322 end
323
324 else # 呼び先が複数のセル(単一のポート)
325
326 # 呼び口は optional で初期化されていない、または受け口は配列ではないか?
327 if port_ports[0] == nil || port_ports[0].get_array_size == nil then
328 if ! @singleton then
329 port.set_skelton_useless # スケルトン関数不要最適化
330 port.set_VMT_useless # VMT 不要最適化 (スケルトン関数 or 受け口関数を呼出す)
331
332 if $verbose then
333 print "VMT_useless & skelton useless optimize\n"
334 end
335 else
336 port.set_VMT_useless # VMT 不要最適化 (スケルトン関数 or 受け口関数を呼出す)
337
338 if $verbose then
339 print "VMT_useless optimize\n"
340 end
341 end
342 end
343 end
344
345 port.set_only_callee( port_ports[0], port_cells[0] )
346 # set_cell_unique でない場合 cell は意味がない
347
348 end
349
350 # debug
351 dbgPrint "#{port.get_name} : # of cells : #{port_cells.length} # of ports : #{port_ports.length}\n"
352 }
353
354 # 受け口最適化の設定
355 @port.each{ |port|
356 next if port.get_port_type != :CALL
357
358 # 呼び口側の最適化状態
359 b_VMT_useless = port.is_VMT_useless?
360 b_skelton_useless = port.is_skelton_useless?
361
362 # セルの参照するセルを集める(ポートも一緒に集める)
363 @cell_list.each{ |cell|
364
365 if ! cell.is_generate? then
366 next
367 end
368
369 jl = cell.get_join_list
370 j = jl.get_item( port.get_name )
371
372 if j then # optional で結合されていない場合 nil
373 if j.get_array_member2 then
374 # 呼び口配列
375 j.get_array_member2.each { |j2|
376 if j2 then
377 port2 = j2.get_rhs_port # 右辺のポート
378 # 受け口側の最適化可能性を設定
379 port2.set_entry_VMT_skelton_useless( b_VMT_useless, b_skelton_useless )
380 #else
381 # optional で呼び口配列要素が初期化されていない
382 end
383 }
384 else
385 port2 = j.get_rhs_port # 右辺のポート
386 # 受け口側の最適化可能性を設定
387 port2.set_entry_VMT_skelton_useless( b_VMT_useless, b_skelton_useless )
388 end
389 end
390 }
391 }
392 end
393
394 #Celltype# リセットする
395 def reset_optimize
396 @@ID_BASE = ID_BASE # 本当は一回だけでよい
397 @id_base = 1 # set_cell_id でリセットされるので不要
398
399 @b_cp_optimized = false # 呼び口最適化
400 @n_call_port_omitted_in_CB = 0 # 呼び口最適化により不生成となったポートの数
401 @n_cell_gen = 0 # 生成セル個数
402 @port.each{ |p|
403 p.reset_optimize
404 }
405 @included_header = {}
406 @domain_roots = {}
407 end
408
409 #Celltype# ヘッダは include されているか
410 #hname::Symbol : ヘッダ名
411 #RETURN:: bool_t: false インクルードされていない、true インクルードされている
412 # #_ISH_#, #_ICT_# でヘッダが取り込まれているかチェックする
413 # false が返った場合、hname は登録されて、次回の呼び出しでは true が返る
414 def header_included?( hname )
415 if @included_header[ hname ] == nil then
416 @included_header[ hname ] = true
417 return false
418 else
419 return true
420 end
421 end
422end
423
424
Note: See TracBrowser for help on using the repository browser.