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

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

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

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby
File size: 14.6 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# 上記著作権者
9は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
10# ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
11# 変・再é…
12å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
13# (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
14# 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
15# スコード中に含まれていること.
16# (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
17# 用できる形で再é…
18å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
19å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
20# 者
21マニュアルなど)に,上記の著作権表示,この利用条件および下記
22# の無保証規定を掲載すること.
23# (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
24# 用できない形で再é…
25å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
26# と.
27# (a) 再é…
28å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
29マニュアルなど)に,上記の著
30# 作権表示,この利用条件および下記の無保証規定を掲載すること.
31# (b) 再é…
32å¸ƒã®å½¢æ…
33‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
34# 報告すること.
35# (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
36# 害からも,上記著作権者
37およびTOPPERSプロジェクトをå…
38è²¬ã™ã‚‹ã“と.
39# また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
40# 由に基づく請求からも,上記著作権者
41およびTOPPERSプロジェクトを
42# å…
43è²¬ã™ã‚‹ã“と.
44#
45# 本ソフトウェアは,無保証で提供されているものである.上記著作権者
46お
47# よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
48# に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
49# アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
50# の責任を負わない.
51#
52# $Id: optimize.rb 1011 2016-07-11 02:20:01Z coas-nagasima $
53#++
54
55=begin
56This file includes the processes between semantics analysis and code generation.
57Optimize is one of them.
58Other processes are setting ID for each cell and setting domain information
59
60このファイルには、意味解析からコード生成の間で行うべき処理が含まれる.
61最適化もその一つである.
62その他に、セル毎の ID 付け、ドメインわけを行う.
63コード生成対象となるセルを対象に処理を行うものが含まれる.
64=end
65
66class Namespace
67
68 #=== 各セルに ID (整数値)を割付ける
69 def set_cell_id_and_domain
70 # celltype の各セルに ID を割付ける
71 @celltype_list.each { |t|
72 t.set_cell_id_and_domain
73 }
74
75 # サブネームスペースの各セルに ID を割付ける
76 @namespace_list.each { |n|
77 n.set_cell_id_and_domain
78 }
79 end
80
81 def optimize
82 # celltype の最適化
83 @celltype_list.each { |t|
84 t.optimize
85 }
86
87 # サブネームスペースの最適化
88 @namespace_list.each { |n|
89 n.optimize
90 }
91 end
92
93 def reset_optimize
94 # celltype の最適化
95 @celltype_list.each { |t|
96 t.reset_optimize
97 }
98
99 # サブネームスペースの最適化
100 @namespace_list.each { |n|
101 n.reset_optimize
102 }
103 end
104end
105
106class Celltype
107
108 ID_BASE = 1 # reset_optimize でリセットする
109 @@ID_BASE = ID_BASE
110
111 def set_cell_id_and_domain
112 set_cell_id
113 set_domain
114 end
115
116 #=== 各セルに ID (整数値)を割付ける
117 def set_cell_id
118
119 if $verbose then
120 print( "=== id for the cells of celltype #{get_namespace_path.to_s} ===\n" )
121 end
122
123 if $unique_id then
124 @id_base = @@ID_BASE # id をシステムå…
125¨ä½“で連番にする
126 else
127 @id_base = 1 # base を常に 1 から始める
128 end
129
130 id_specified_cells = []
131 no_id_specified_cells = []
132
133 # プロトタイプを除いた数を求める
134 @cell_list.each{ |c|
135 if c.is_generate? then
136 # c.set_id( @id_base + @n_cell_gen )
137 id = c.get_specified_id
138 if id then
139 id_specified_cells << c
140 else
141 no_id_specified_cells << c
142 end
143
144 # p "#{c.get_name} #{@id_base+@n_cell_gen}"
145 @@ID_BASE += 1
146 @n_cell_gen += 1
147 end
148 }
149
150 @ordered_cell_list = [] # id = 1 が添数 0 に格納される
151 # ID 指定されているセルに id 番号を与える
152 id_specified_cells.each{ |c|
153 id = c.get_specified_id
154 if id > 0 then
155 if id >= @n_cell_gen then
156 cdl_error( "S3001 $1: id too large $2 (max=$3)", c.get_name, id, @n_cell_gen )
157 next
158 end
159 else
160 if - id >= @n_cell_gen then
161 cdl_error( "S3002 $1: id too large $2 (max=$3)", c.get_name, id, @n_cell_gen )
162 next
163 end
164 id = @n_cell_gen + id + 1
165 end
166
167 if @ordered_cell_list[ id - 1 ] then
168 cdl_error( "S3003 $1: id number '$2' conflict with $3", c.get_name, id, @ordered_cell_list[ id - 1 ].get_name )
169 end
170 @ordered_cell_list[ id - 1 ] = c
171 # 通し番号とする場合のため @id_base を加える
172 c.set_id( @id_base - 1 + id )
173 if $verbose then
174 print( "#{c.get_name}: id=#{c.get_id} specified id=#{c.get_specified_id}\n" )
175 end
176 }
177
178 # ID 指定されていないセルに id 番号を与える
179 i = 0
180 no_id_specified_cells.each{ |c|
181 while( @ordered_cell_list[i] != nil )
182 i += 1
183 end
184 @ordered_cell_list[ i ] = c
185 c.set_id( @id_base + i )
186 if $verbose then
187 print( "#{c.get_name}: id=#{c.get_id}\n" )
188 end
189 }
190 if @n_cell_gen >0 && i >= @n_cell_gen then
191 raise "id over id=#{i} N=#{@n_cell_gen}"
192 end
193 end
194
195 def set_domain
196 @cell_list.each{ |c|
197 if c.is_generate? then
198 dr = c.get_region.get_domain_root
199 if dr.get_domain_type then
200 dn = dr.get_domain_type.get_name
201 else
202 dn = nil
203 end
204 if @domain_roots[ dn ] then
205 @domain_roots[ dn ] << dr
206 else
207 @domain_roots[ dn ] = [ dr ]
208 end
209 end
210 }
211
212 @domain_roots.each{ |dn, drs|
213 drs.uniq!
214 if ! $debug then
215 dbgPrint "domains celltype:#{@name} domain=#{dn} "
216 drs.each{ |r|
217 dbgPrint " region=#{r.get_name}"
218 }
219 dbgPrint "\n"
220 end
221 }
222 if @domain_roots.length > 1 then
223 p @domain_roots
224 raise "ambigous DomainType"
225 end
226
227 @domain_roots.each{ |dn, regions|
228 # domain_type は一つのノードに一つしかないので、一つの要素を無条件で取り出す
229 if regions.length > 1 then
230 cdl_info( "celltype:#{@name} has cells in multi domain.\n" )
231 if @idx_is_id == false then
232 cdl_info( "celltype:#{@name} forcely set idx_is_id\n" )
233 end
234 @idx_is_id_act = true
235 end
236 }
237 end
238
239 def optimize
240
241 # port の参ç…
242§ã™ã‚‹ã‚»ãƒ«ã‚¿ã‚¤ãƒ—の数、セルの数を求める
243 if $verbose then
244 print "=== optimizing celltype #{get_namespace_path.to_s} ===\n"
245 end
246
247 @port.each{ |port|
248 next if port.get_port_type != :CALL
249 if port.is_omit? then
250 # 呼び口最適化実施
251 @b_cp_optimized = true
252 @n_call_port_omitted_in_CB += 1 # CB で省略する呼び口
253 port.set_skelton_useless # スケルトン関数不要最適化
254 port.set_VMT_useless # VMT 不要最適化 (直接受け口関数を呼出す)
255 if $verbose then
256 print "optimized by omit: port: #{port.get_name} : o\n"
257 end
258 next
259 end
260
261 if $verbose then
262 print "optimizing port : #{port.get_name}\n"
263 end
264
265 port_cells = [] # 呼びå…
266ˆã‚»ãƒ«
267 port_ports = [] # 呼びå…
268ˆã®ãƒãƒ¼ãƒˆ
269
270 # セルの参ç…
271§ã™ã‚‹ã‚»ãƒ«ã‚’集める(ポートも一緒に集める)
272 @cell_list.each{ |cell|
273
274 if ! cell.is_generate? then
275 next
276 end
277
278 jl = cell.get_join_list
279 j = jl.get_item( port.get_name )
280
281 if j then
282 if j.get_array_member2 then
283 # 呼び口é…
284åˆ—の場合、å…
285¨éƒ¨ã®çµåˆå…
286ˆã‚’集める
287 j.get_array_member2.each { |j2|
288 if j2 then
289 port_cells << j2.get_rhs_cell
290 port_ports << j2.get_rhs_port # 右辺のポート
291 else
292 # optional で、ある添数のみ初期化されていない(すべて初期化されない場合は、下)
293 port_cells << nil
294 port_ports << nil
295 end
296 }
297 else
298 # å…
299¨ã¦ã®çµåˆå…
300ˆã‚’集める
301 port_cells << j.get_rhs_cell
302 port_ports << j.get_rhs_port # 右辺のポート
303 end
304 else
305 # optional で初期化されていない(nil を要素に加えておく)
306 port_cells << nil
307 port_ports << nil # 右辺のポート
308 end
309 }
310
311 # 重複要素を取り除く
312 port_cells.uniq!
313 port_ports.uniq!
314
315 # 呼び口の呼びå…
316ˆãŒä¸€ã¤ã®ãƒãƒ¼ãƒˆã ã‘か?
317 if port_ports.length == 1 then
318
319 # 呼び口é…
320åˆ—が可変長の場合、最適化しない
321 # mikan 呼び口é…
322åˆ—要素数マクロ不å…
323·åˆæš«å®šå¯¾ç­–
324 # より望ましい修正は、受け口へのポインタは省略するが、é…
325åˆ—個数は出力する(#_CP_#, #_TCP_#)
326 # さらにé…
327åˆ—個数が定数化できるのであれば、定数マクロを出力 (#_NCPA_#)
328 next if port.get_array_size == "[]"
329
330 # 呼び口最適化実施
331 @b_cp_optimized = true
332
333 # 呼びå…
334ˆãŒä¸€ã¤ã®ã‚»ãƒ«ã ã‘か?
335 if port_cells.length == 1 then
336
337 # 呼び口は optional で初期化されていない、または受け口はé…
338åˆ—ではないか?
339 if port_ports[0] == nil || port_ports[0].get_array_size == nil then
340
341 @n_call_port_omitted_in_CB += 1 # CB で省略する呼び口
342 port.set_cell_unique # セル一つだけ最適化
343 port.set_skelton_useless # スケルトン関数不要最適化
344 port.set_VMT_useless # VMT 不要最適化 (直接受け口関数を呼出す)
345
346 if $verbose then
347 print "cell_unique, VMT_useless & skelton_useless optimize\n"
348 end
349 else
350 port.set_VMT_useless # VMT 不要最適化 (スケルトン関数を呼出す)
351
352 if $verbose then
353 print "VMT_useless optimize\n"
354 end
355 end
356
357 else # 呼びå…
358ˆãŒè¤‡æ•°ã®ã‚»ãƒ«ï¼ˆå˜ä¸€ã®ãƒãƒ¼ãƒˆï¼‰
359
360 # 呼び口は optional で初期化されていない、または受け口はé…
361åˆ—ではないか?
362 if port_ports[0] == nil || port_ports[0].get_array_size == nil then
363 if ! @singleton then
364 port.set_skelton_useless # スケルトン関数不要最適化
365 port.set_VMT_useless # VMT 不要最適化 (スケルトン関数 or 受け口関数を呼出す)
366
367 if $verbose then
368 print "VMT_useless & skelton useless optimize\n"
369 end
370 else
371 port.set_VMT_useless # VMT 不要最適化 (スケルトン関数 or 受け口関数を呼出す)
372
373 if $verbose then
374 print "VMT_useless optimize\n"
375 end
376 end
377 end
378 end
379
380 port.set_only_callee( port_ports[0], port_cells[0] )
381 # set_cell_unique でない場合 cell は意味がない
382
383 end
384
385 # debug
386 dbgPrint "#{port.get_name} : # of cells : #{port_cells.length} # of ports : #{port_ports.length}\n"
387 }
388
389 # 受け口最適化の設定
390 @port.each{ |port|
391 next if port.get_port_type != :CALL
392
393 # 呼び口側の最適化状æ…
394‹
395 b_VMT_useless = port.is_VMT_useless?
396 b_skelton_useless = port.is_skelton_useless?
397
398 # セルの参ç…
399§ã™ã‚‹ã‚»ãƒ«ã‚’集める(ポートも一緒に集める)
400 @cell_list.each{ |cell|
401
402 if ! cell.is_generate? then
403 next
404 end
405
406 jl = cell.get_join_list
407 j = jl.get_item( port.get_name )
408
409 if j then # optional で結合されていない場合 nil
410 if j.get_array_member2 then
411 # 呼び口é…
412åˆ—
413 j.get_array_member2.each { |j2|
414 if j2 then
415 port2 = j2.get_rhs_port # 右辺のポート
416 # 受け口側の最適化可能性を設定
417 port2.set_entry_VMT_skelton_useless( b_VMT_useless, b_skelton_useless )
418 #else
419 # optional で呼び口é…
420åˆ—要素が初期化されていない
421 end
422 }
423 else
424 port2 = j.get_rhs_port # 右辺のポート
425 # 受け口側の最適化可能性を設定
426 port2.set_entry_VMT_skelton_useless( b_VMT_useless, b_skelton_useless )
427 end
428 end
429 }
430 }
431 end
432
433 #Celltype# リセットする
434 def reset_optimize
435 @@ID_BASE = ID_BASE # 本当は一回だけでよい
436 @id_base = 1 # set_cell_id でリセットされるので不要
437
438 @b_cp_optimized = false # 呼び口最適化
439 @n_call_port_omitted_in_CB = 0 # 呼び口最適化により不生成となったポートの数
440 @n_cell_gen = 0 # 生成セル個数
441 @port.each{ |p|
442 p.reset_optimize
443 }
444 @included_header = {}
445 @domain_roots = {}
446 end
447
448 #Celltype# ヘッダは include されているか
449 #hname::Symbol : ヘッダ名
450 #RETURN:: bool_t: false インクルードされていない、true インクルードされている
451 # #_ISH_#, #_ICT_# でヘッダが取り込まれているかチェックする
452 # false が返った場合、hname は登録されて、次回の呼び出しでは true が返る
453 def header_included?( hname )
454 if @included_header[ hname ] == nil then
455 @included_header[ hname ] = true
456 return false
457 else
458 return true
459 end
460 end
461end
462
463
Note: See TracBrowser for help on using the repository browser.