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 | # mikan through plugin: namespace が考慮されていない
|
---|
41 |
|
---|
42 | #== スループラグインの共通の親クラス かつ (何もせず)スルーするセルを挿入するスループラグイン
|
---|
43 | # スループラグインは ThroughPlugin の子クラスとして定義する
|
---|
44 | class ThroughPlugin < Plugin
|
---|
45 | #@cell_name:: Symbol 生成するセル名(複数セルを生成する場合、受け口側のセル)
|
---|
46 | #@plugin_arg_str:: string through で指定された引数
|
---|
47 | #@next_cell:: Cell 呼び口を結合するセル
|
---|
48 | #@next_cell_port_name:: Symbol 呼び口を結合する受口の名前
|
---|
49 | #@next_cell_port_subscript::Nil|Integer 呼び口を結合する受口の配列添数.受け口配列でない場合 nil
|
---|
50 | #@signature:: Signature シグニチャ
|
---|
51 | #@celltype:: Celltype 呼び先のセルのセルタイプ. through が連接する場合、最終的な呼び先のセルのセルタイプ
|
---|
52 | #@entry_port_name::Symbol 生成するセルの受け口名 "eThroughEntry"
|
---|
53 | #@call_port_name:: Symbol 生成するセルの呼び口名 "cCall"
|
---|
54 | #@ct_name:: Symbol 生成するセルのセルタイプ名 "t#{self.class.name}_#{@signature.get_global_name}"
|
---|
55 | #@plugin_arg_list:: Hash プラグイン引数をパースした結果のハッシュ変数
|
---|
56 | #@caller_cell:: Cell 呼び元のセル.through プラグインが連接する場合では、最も呼び元のセル.($source$)
|
---|
57 | # through プラグインが合流するケースでは、1つ目の呼び元セルのみ引数として与えられる
|
---|
58 | # 従って TracePlugin の呼び元の判別に利用する場合は、異なる呼び元から呼ばれる可能性があることに注意しなくてはならない
|
---|
59 | #@callee_cell:: Cell 呼び先のセル($destination$)
|
---|
60 | #@plugin_arg_check_proc_tab:: [string => Proc] プラグイン引数名⇒チェック関数
|
---|
61 | # 以下の変数は、initialize ではなく、後から設定される
|
---|
62 | #@start_@region:: Region 始まりのリージョン: caller_cell のリージョンとは異なる可能性がある ($start_region$)
|
---|
63 | #@end_region:: Region 終わりのリージョン: next_cell のリージョンとは異なる可能性がある ($end_region$)
|
---|
64 | #@region:: Region @start_region と @end_region のいずれかで、cell を置くのが好ましいリージョン ($preferred_region$)
|
---|
65 | #@through_type:: Symbol :THROUGH, :TO_THROUGH, :IN_THROUGH, :OUT_THROUGH のいずれか
|
---|
66 |
|
---|
67 | # この Plugin が生成したセルタイプのリスト
|
---|
68 | @@generated_celltype = {}
|
---|
69 |
|
---|
70 | #=== ThroughPlugin の初期化
|
---|
71 | # through が指定された時点で生成が行われる
|
---|
72 | # 初期化では、指定された引数を記録するに留める
|
---|
73 | #cell_name:: Symbol 生成すべきセル名(受口側)
|
---|
74 | #plugin_arg:: string through で指定された引数
|
---|
75 | #next_cell:: Cell 呼び口を接続するセル
|
---|
76 | #next_cell_port_name:: Symbol 呼び口を接続する受口の名前
|
---|
77 | #next_cell_port_subscript:: Nil|Integer 呼び口を接続する受口配列添数
|
---|
78 | #signature:: Signature シグニチャ
|
---|
79 | #celltype:: Celltype セルタイプ (呼び先のセルのセルタイプ)
|
---|
80 | #caller_cell:: Cell 呼び元のセル.@caller_cell の項を参照
|
---|
81 | def initialize( cell_name, plugin_arg, next_cell, next_cell_port_name, next_cell_port_subscript, signature, celltype, caller_cell )
|
---|
82 | super()
|
---|
83 | @cell_name = cell_name # 生成すべきセル名(受け口側のセル名)
|
---|
84 | # この呼び先に別セルを生成する場合、この名前を接頭辞とすべき
|
---|
85 | @next_cell = next_cell # 呼び先のセル
|
---|
86 | @next_cell_port_name = next_cell_port_name
|
---|
87 | @next_cell_port_subscript = next_cell_port_subscript
|
---|
88 | @signature = signature
|
---|
89 | @entry_port_name = :"eThroughEntry"
|
---|
90 | @call_port_name = :"cCall"
|
---|
91 | @ct_name = :"t#{self.class.name}_#{@signature.get_global_name}"
|
---|
92 | @celltype = celltype
|
---|
93 | @plugin_arg_str = plugin_arg
|
---|
94 | @plugin_arg_list = {} # プラグイン引数をパースした結果のハッシュ変数
|
---|
95 | @caller_cell = caller_cell
|
---|
96 | Join.set_through_info self # 引数で渡らない(後から追加された)ものは set_through_info で設定される
|
---|
97 | print( "#{self.class.name}.new( '#{cell_name}', '#{plugin_arg}', '#{next_cell.get_name}', '#{next_cell_port_name}', #{celltype.get_name} )\n" )
|
---|
98 | end
|
---|
99 |
|
---|
100 | #=== 情報を設定する
|
---|
101 | # 共有チャンネルの場合 caller_cell, next_cell のいずれの region でもないケースがある
|
---|
102 | # 後から追加したので initialize の引数ではなく、別メソッドで設定
|
---|
103 | # このメソッドは、オーバーライドしないでください
|
---|
104 | # Join と ThrougPlugin の間の連絡用で、今後とも引数が追加される可能性があるため
|
---|
105 | # このメソッドは V1.C.0.34 で位置が移動され、ThroughPlugin#initialize で呼び出される
|
---|
106 | def set_through_info( start_region, end_region, through_type, join, callee_cell, count )
|
---|
107 | @start_region = start_region
|
---|
108 | @end_region = end_region
|
---|
109 | @through_type = through_type
|
---|
110 | @join = join
|
---|
111 | @callee_cell = callee_cell
|
---|
112 | @count = count
|
---|
113 |
|
---|
114 | # preferred_region の設定
|
---|
115 | case through_type
|
---|
116 | when :IN_THROUGH, :THROUGH
|
---|
117 | @region = end_region
|
---|
118 | when :OUT_THROUGH, :TO_THROUGH
|
---|
119 | @region = start_region
|
---|
120 | else
|
---|
121 | raise "Unknown through_type #{through_type}"
|
---|
122 | end
|
---|
123 | end
|
---|
124 |
|
---|
125 | #=== セルの名前を得る
|
---|
126 | def get_cell_name
|
---|
127 | @cell_name
|
---|
128 | end
|
---|
129 |
|
---|
130 | #=== NamespacePath を得る
|
---|
131 | # 生成するセルの namespace path を生成する
|
---|
132 | def get_cell_namespace_path
|
---|
133 | # nsp = @region.get_namespace.get_namespace_path
|
---|
134 | nsp = @region.get_namespace_path
|
---|
135 | return nsp.append( @cell_name )
|
---|
136 | end
|
---|
137 |
|
---|
138 | #=== 生成されたセルの受け口の名前を得る
|
---|
139 | def get_through_entry_port_name
|
---|
140 | @entry_port_name
|
---|
141 | end
|
---|
142 |
|
---|
143 | #=== 生成されたセルの受け口配列添数を得る
|
---|
144 | def get_through_entry_port_subscript
|
---|
145 | @entry_port_subscript
|
---|
146 | end
|
---|
147 |
|
---|
148 | #=== 宣言コードの生成
|
---|
149 | # typedef, signature, celltype など(cell 以外)のコードを生成
|
---|
150 | # 重複して生成してはならない(すでに生成されている場合は出力しないこと)
|
---|
151 | #file:: FILE 生成するファイル
|
---|
152 | def gen_plugin_decl_code( file )
|
---|
153 |
|
---|
154 | # このセルタイプ(同じシグニチャ)は既に生成されているか?
|
---|
155 | if @@generated_celltype[ @ct_name ] == nil then
|
---|
156 | @@generated_celltype[ @ct_name ] = [ self ]
|
---|
157 | else
|
---|
158 | @@generated_celltype[ @ct_name ] << self
|
---|
159 | return
|
---|
160 | end
|
---|
161 |
|
---|
162 | file2 = CFile.open( "#{$gen}/#{@ct_name}.cdl", "w" )
|
---|
163 |
|
---|
164 | send_receive = []
|
---|
165 | if @signature != nil then
|
---|
166 | @signature.each_param{ |fd,param|
|
---|
167 | dir =param.get_direction
|
---|
168 | case dir
|
---|
169 | when :SEND, :RECEIVE
|
---|
170 | send_receive << [ dir, fd, param ]
|
---|
171 | end
|
---|
172 | }
|
---|
173 | end
|
---|
174 |
|
---|
175 | file2.print <<EOT
|
---|
176 | celltype #{@ct_name} {
|
---|
177 | EOT
|
---|
178 |
|
---|
179 | if send_receive.length > 0 then
|
---|
180 | file2.print " [ allocator(\n"
|
---|
181 | delim = ""
|
---|
182 | send_receive.each { |a|
|
---|
183 | file2.print "#{delim}\t#{a[1].get_name}.#{a[2].get_name}<=#{@call_port_name}.#{a[1].get_name}.#{a[2].get_name}"
|
---|
184 | delim = ",\n"
|
---|
185 | }
|
---|
186 | file2.print "\n )]\n"
|
---|
187 | end
|
---|
188 |
|
---|
189 | file2.print <<EOT
|
---|
190 | entry #{@signature.get_namespace_path} #{@entry_port_name};
|
---|
191 | call #{@signature.get_namespace_path} #{@call_port_name};
|
---|
192 | };
|
---|
193 | EOT
|
---|
194 | file2.close
|
---|
195 |
|
---|
196 | file.print "import( \"#{$gen}/#{@ct_name}.cdl\" );\n"
|
---|
197 | end
|
---|
198 |
|
---|
199 | #=== CDL ファイルの生成
|
---|
200 | #file:: FILE 生成するファイル
|
---|
201 | def gen_cdl_file( file )
|
---|
202 | gen_plugin_decl_code( file )
|
---|
203 | gen_through_cell_code( file )
|
---|
204 | end
|
---|
205 |
|
---|
206 | #=== セルコードの生成
|
---|
207 | # through 指定により生じるセルコード(CDL)を生成する
|
---|
208 | #file:: FILE 生成するファイル
|
---|
209 | def gen_through_cell_code( file )
|
---|
210 |
|
---|
211 | nest = @region.gen_region_str_pre file
|
---|
212 | nest_str = " " * nest
|
---|
213 |
|
---|
214 | file.print <<EOT
|
---|
215 | #{nest_str}cell #{@ct_name} #{@cell_name} {
|
---|
216 | #{nest_str} #{@call_port_name} = #{@next_cell.get_namespace_path.get_path_str}.#{@next_cell_port_name};
|
---|
217 | #{nest_str}};
|
---|
218 | EOT
|
---|
219 | @region.gen_region_str_post file
|
---|
220 |
|
---|
221 | end
|
---|
222 |
|
---|
223 | #=== 後ろのコードを生成
|
---|
224 | #プラグインの後ろのコード (CDL) を生成
|
---|
225 | #file:: File:
|
---|
226 | def self.gen_post_code( file )
|
---|
227 | # 複数のプラグインの post_code が一つのファイルに含まれるため、以下のような見出しをつけること
|
---|
228 | # file.print "/* '#{self.class.name}' post code */\n"
|
---|
229 | end
|
---|
230 |
|
---|
231 | #=== 受け口関数の本体(C言語)を生成する
|
---|
232 | # 通常であれば、ジェネレータは受け口関数のテンプレートを生成する
|
---|
233 | # プラグインの場合、変更する必要のないセルタイプコードを生成する
|
---|
234 | #file:: FILE 出力先ファイル
|
---|
235 | #b_singleton:: bool true if singleton
|
---|
236 | #ct_name:: Symbol
|
---|
237 | #global_ct_name:: string
|
---|
238 | #sig_name:: string
|
---|
239 | #ep_name:: string
|
---|
240 | #func_name:: string
|
---|
241 | #func_global_name:: string
|
---|
242 | #func_type:: class derived from Type
|
---|
243 | def gen_ep_func_body( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params )
|
---|
244 |
|
---|
245 | ret_type = func_type.get_type
|
---|
246 | b_ret_void = ret_type.is_void?
|
---|
247 |
|
---|
248 | if ! b_ret_void then
|
---|
249 | file.print( " #{ret_type.get_type_str} retval;\n" )
|
---|
250 | end
|
---|
251 |
|
---|
252 | if ! b_singleton then
|
---|
253 |
|
---|
254 | file.print <<EOT
|
---|
255 | #{ct_name}_CB *p_cellcb;
|
---|
256 | if( VALID_IDX( idx ) ){
|
---|
257 | p_cellcb = #{global_ct_name}_GET_CELLCB(idx);
|
---|
258 | }else{
|
---|
259 | /* エラー処理コードをここに記述 */
|
---|
260 | }
|
---|
261 |
|
---|
262 | EOT
|
---|
263 | end
|
---|
264 |
|
---|
265 | # p "celltype_name, sig_name, func_name, func_global_name"
|
---|
266 | # p "#{ct_name}, #{sig_name}, #{func_name}, #{func_global_name}"
|
---|
267 |
|
---|
268 | delim = ""
|
---|
269 | if ! b_ret_void then
|
---|
270 | file.print( " retval = " )
|
---|
271 | end
|
---|
272 |
|
---|
273 | file.print( "#{@call_port_name}_#{func_name}(" )
|
---|
274 |
|
---|
275 | # if ( ! b_singleton ) then
|
---|
276 | # file.print( " tecs_this" )
|
---|
277 | # delim = ","
|
---|
278 | # end
|
---|
279 |
|
---|
280 | params.each{ |param|
|
---|
281 | file.printf( "#{delim} #{param.get_name}" )
|
---|
282 | delim = ","
|
---|
283 | }
|
---|
284 |
|
---|
285 | file.print( " );\n" )
|
---|
286 |
|
---|
287 | if ! b_ret_void then
|
---|
288 | file.print( " return retval;\n" )
|
---|
289 | end
|
---|
290 | end
|
---|
291 |
|
---|
292 | #=== Through プラグインの引数の名前を置換する
|
---|
293 | def check_plugin_arg( ident, rhs )
|
---|
294 | rhs = subst_name rhs
|
---|
295 | super( ident, rhs )
|
---|
296 | end
|
---|
297 |
|
---|
298 | #=== ThroughPlugin#名前の置換
|
---|
299 | # プラグインオプション引数内の文字列を置換する
|
---|
300 | # $source$ … 呼び元のセル名
|
---|
301 | # $destination$ … 呼び先のセル名
|
---|
302 | # $SOURCE$ … 呼び元のセル名 (リージョン名を '_' で連結した global_name)
|
---|
303 | # $DESTINATION$ … 呼び先のセル名 (リージョン名を '_' で連結した global_name)
|
---|
304 | # $next$ … 次のセル名
|
---|
305 | # 複数の through がつながっている場合、すぐ後ろに来るもの
|
---|
306 | # $NEXT$ … 次のセル名 (リージョン名を '_' で連結した global_name)
|
---|
307 | # 複数の through がつながっている場合、すぐ後ろに来るもの
|
---|
308 | # $start_region$ … $source$ のセルの存在する region (global_name)
|
---|
309 | # $end_region$ … $destination$ のセルの存在する region (global_name)
|
---|
310 | # $preferred_region$ … 適切な region (global_name), start_region または end_region
|
---|
311 | # $count$ … region 間の through の適用数
|
---|
312 | # $$ … $ に置換
|
---|
313 | def subst_name( str )
|
---|
314 | # セル名の置換
|
---|
315 | str = str.gsub( /(^|[^\$])\$source\$/, "\\1#{@caller_cell.get_name}" )
|
---|
316 | str = str.gsub( /(^|[^\$])\$destination\$/, "\\1#{@callee_cell.get_name}" )
|
---|
317 | str = str.gsub( /(^|[^\$])\$SOURCE\$/, "\\1#{@caller_cell.get_global_name}" )
|
---|
318 | str = str.gsub( /(^|[^\$])\$DESTINATION\$/, "\\1#{@callee_cell.get_global_name}" )
|
---|
319 | str = str.gsub( /(^|[^\$])\$next\$/, "\\1#{@next_cell.get_name}" )
|
---|
320 | str = str.gsub( /(^|[^\$])\$NEXT\$/, "\\1#{@next_cell.get_global_name}" )
|
---|
321 | # region 名の置換
|
---|
322 | str = str.gsub( /(^|[^\$])\$start_region\$/, "\\1#{@start_region.get_global_name}" )
|
---|
323 | str = str.gsub( /(^|[^\$])\$end_region\$/, "\\1#{@end_region.get_global_name}" )
|
---|
324 | str = str.gsub( /(^|[^\$])\$preferred_region\$/, "\\1#{@region.get_global_name}" )
|
---|
325 | str = str.gsub( /(^|[^\$])\$count\$/, "\\1#{@count}" )
|
---|
326 |
|
---|
327 | str = str.gsub( /\$\$/, "\$" ) # $$ を $ に置換
|
---|
328 |
|
---|
329 | return str
|
---|
330 | end
|
---|
331 |
|
---|
332 | def show_tree( indent )
|
---|
333 | indent.times { print " " }
|
---|
334 | puts "Plugin: celltype: #{@ct_name} cell: #{@cell_name}"
|
---|
335 | (indent+1).times { print " " }
|
---|
336 | puts "next: signature: #{@signature.get_namespace_path} call = #{@next_cell.get_name}.#{@next_cell_port_name}"
|
---|
337 | end
|
---|
338 | end
|
---|
339 |
|
---|