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 | require_tecsgen_lib "lib/GenOpaqueMarshaler.rb"
|
---|
41 | require_tecsgen_lib "lib/GenParamCopy.rb"
|
---|
42 |
|
---|
43 | #= HRPRPCPlugin プラグイン
|
---|
44 | # スループラグイン (through)
|
---|
45 | # ・OpaqueMarshalerPlugin を使用してマーシャラセルタイプを生成する
|
---|
46 | # ・マーシャラ、TDR、チャンネル、メッセージバッファを生成する
|
---|
47 | #
|
---|
48 | class HRPRPCPlugin < ThroughPlugin
|
---|
49 |
|
---|
50 | include GenOpaqueMarshaler
|
---|
51 | include GenParamCopy
|
---|
52 |
|
---|
53 | # RPCPlugin 専用のオプション
|
---|
54 | HRPRPCPluginArgProc = RPCPluginArgProc.dup # 複製を作って元を変更しないようにする
|
---|
55 | HRPRPCPluginArgProc[ "noClientSemaphore" ] = Proc.new { |obj,rhs| obj.set_noClientSemaphore rhs }
|
---|
56 | HRPRPCPluginArgProc[ "semaphoreCelltype" ] = Proc.new { |obj,rhs| obj.set_semaphoreCelltype rhs }
|
---|
57 | @@isFirstInstance = true
|
---|
58 |
|
---|
59 | #=== RPCPlugin の initialize
|
---|
60 | # 説明は ThroughPlugin (plugin.rb) を参照
|
---|
61 | def initialize( cell_name, plugin_arg, next_cell, next_cell_port_name, next_cell_port_subscript, signature, celltype, caller_cell )
|
---|
62 | super
|
---|
63 | @b_noClientSemaphore = false
|
---|
64 | @semaphoreCelltype = "tSemaphore"
|
---|
65 | initialize_opaque_marshaler
|
---|
66 |
|
---|
67 | # オプション:GenOpaqueMarshaler 参照
|
---|
68 | @plugin_arg_check_proc_tab = HRPRPCPluginArgProc
|
---|
69 | parse_plugin_arg
|
---|
70 |
|
---|
71 | @rpc_channel_celltype_name = "tRPCPlugin_#{@TDRCelltype}_#{@channelCelltype}_#{@signature.get_name}"
|
---|
72 | @rpc_channel_celltype_file_name = "#{$gen}/#{@rpc_channel_celltype_name}.cdl"
|
---|
73 |
|
---|
74 | if @signature.get_context == "non-task" then
|
---|
75 | cdl_error( "HRP9999 RPC cannot be applied to non-task context signature '$1'", @signature.get_name )
|
---|
76 | elsif @signature.get_context == "any" then
|
---|
77 | cdl_info( "HRP9999 RPC is applied to any context signature '$1'", @signature.get_name )
|
---|
78 | end
|
---|
79 |
|
---|
80 | if @signature.need_PPAllocator?(true) then
|
---|
81 | if @PPAllocatorSize == nil then
|
---|
82 | cdl_error( "HRP9999 PPAllocatorSize must be speicified for pointer argments" )
|
---|
83 | # @PPAllocatorSize = 0 # 仮に 0 としておく (cdl の構文エラーを避けるため)
|
---|
84 | end
|
---|
85 | elsif @PPAllocatorSize then
|
---|
86 | cdl_warning( "HRP9999 PPAllocatorSize speicified in spite of PPAllocator unnecessary" )
|
---|
87 | @PPAllocatorSize = nil
|
---|
88 | end
|
---|
89 |
|
---|
90 | # @signature.each_param{ |func_decl, param_decl|
|
---|
91 | # if func_decl.get_type.is_oneway? then
|
---|
92 | # if ( param_decl.get_size || param_decl.get_count ) && param_decl.get_string then
|
---|
93 | # cdl_error( "array of string not supported for oneway function in Transparent RPC" ) # mikan 文字列の配列
|
---|
94 | # elsif param_decl.get_string == -1 then
|
---|
95 | # cdl_error( "length unspecified string is not permited for oneway function in Transparent RPC" ) # mikan 長さ未指定文字列
|
---|
96 | # end
|
---|
97 | # end
|
---|
98 | # }
|
---|
99 |
|
---|
100 | #
|
---|
101 | # tecsgen/tecs/rpcにincludeパスを通す
|
---|
102 | # #include "tecs_rpc.h" を実現するために必要
|
---|
103 | # 大山:削除 Makefile.tecsgen に vpath, INCLUDES を入れるのは、よくない考え
|
---|
104 | # TECSGEN.add_search_path で Makefile_templ に入れるのがよい
|
---|
105 | # if @@isFirstInstance
|
---|
106 | # f = AppFile.open( "#{$gen}/Makefile.tecsgen" )
|
---|
107 | # f.puts "INCLUDES := $(INCLUDES) -I $(TECSPATH) -I $(TECSPATH)/rpc"
|
---|
108 | # f.puts "vpath %.c $(TECSPATH) $(TECSPATH)/rpc"
|
---|
109 | # f.close()
|
---|
110 | # @@isFirstInstance = false
|
---|
111 | # end
|
---|
112 | end
|
---|
113 |
|
---|
114 | #=== plugin の宣言コード (celltype の定義) 生成
|
---|
115 | def gen_plugin_decl_code( file )
|
---|
116 |
|
---|
117 | ct_name = "#{@ct_name}_#{@channelCelltype}"
|
---|
118 |
|
---|
119 | # このセルタイプ(同じシグニチャ)は既に生成されているか?
|
---|
120 | if @@generated_celltype[ ct_name ] == nil then
|
---|
121 | @@generated_celltype[ ct_name ] = [ self ]
|
---|
122 | else
|
---|
123 | @@generated_celltype[ ct_name ] << self
|
---|
124 | return
|
---|
125 | end
|
---|
126 |
|
---|
127 | f = CFile.open( @rpc_channel_celltype_file_name, "w" )
|
---|
128 | # 同じ内容を二度書く可能性あり (AppFile は不可)
|
---|
129 |
|
---|
130 | f.print <<EOT
|
---|
131 | import( <rpc.cdl> );
|
---|
132 | import( <tMessageBufferCEP.cdl> );
|
---|
133 | generate( OpaqueMarshalerPlugin, #{@signature.get_namespace_path}, "" );
|
---|
134 |
|
---|
135 | composite tOpaqueMarshaler_#{@signature.get_global_name}_through {
|
---|
136 | entry #{@signature.get_namespace_path} eThroughEntry;
|
---|
137 | call sTDR cTDR;
|
---|
138 | [optional]
|
---|
139 | call sSemaphore cLockChannel;
|
---|
140 | [optional]
|
---|
141 | call sRPCErrorHandler cErrorHandler;
|
---|
142 |
|
---|
143 | cell tOpaqueMarshaler_#{@signature.get_global_name} Marshaler{
|
---|
144 | cTDR => composite.cTDR;
|
---|
145 | cLockChannel => composite.cLockChannel;
|
---|
146 | cErrorHandler => composite.cErrorHandler;
|
---|
147 | };
|
---|
148 | composite.eThroughEntry => Marshaler.eClientEntry;
|
---|
149 | };
|
---|
150 |
|
---|
151 | EOT
|
---|
152 |
|
---|
153 | f.close
|
---|
154 | end
|
---|
155 |
|
---|
156 | #=== through cell コードを生成
|
---|
157 | #
|
---|
158 | #
|
---|
159 | def gen_through_cell_code( file )
|
---|
160 |
|
---|
161 | gen_plugin_decl_code( file )
|
---|
162 | file.print <<EOT
|
---|
163 | import( <#{@rpc_channel_celltype_file_name}> );
|
---|
164 | EOT
|
---|
165 |
|
---|
166 | case @start_region.get_domain_root.get_domain_type.get_kind
|
---|
167 | when :kernel
|
---|
168 | tacp_str = "\"TACP_KERNEL"
|
---|
169 | when :user
|
---|
170 | tacp_str = "\"TACP(#{@start_region.get_domain_root.get_name})"
|
---|
171 | when :OutOfDomain
|
---|
172 | tacp_str = "\"TACP_SHARED"
|
---|
173 | end
|
---|
174 | # p "end_region=#{@end_region.get_name} kind=#{@end_region.get_domain_root.get_domain_type.get_kind}"
|
---|
175 | case @end_region.get_domain_root.get_domain_type.get_kind
|
---|
176 | when :kernel
|
---|
177 | tacp_str += "|TACP_KERNEL\""
|
---|
178 | when :user
|
---|
179 | tacp_str += "|TACP(#{@end_region.get_domain_root.get_name})\""
|
---|
180 | when :OutOfDomain
|
---|
181 | tacp_str += "|TACP_SHARED\""
|
---|
182 | end
|
---|
183 | nest_str = ""
|
---|
184 | file.print <<EOT
|
---|
185 | #{nest_str} // MessageBuffer client=>server
|
---|
186 | #{nest_str} cell tMessageBuffer #{@clientChannelCell}Body0{
|
---|
187 | #{nest_str} maxMessageSize = 64; /* This value must be same as MessageBufferCEP's buffer size */
|
---|
188 | #{nest_str} bufferSize = 128;
|
---|
189 | #{nest_str} accessPattern1 = C_EXP( #{tacp_str} );
|
---|
190 | #{nest_str} accessPattern2 = C_EXP( #{tacp_str} );
|
---|
191 | #{nest_str} accessPattern3 = C_EXP( #{tacp_str} );
|
---|
192 | #{nest_str} accessPattern4 = C_EXP( #{tacp_str} );
|
---|
193 | #{nest_str} };
|
---|
194 | EOT
|
---|
195 | file.print <<EOT
|
---|
196 |
|
---|
197 | #{nest_str} // MessageBuffer server=>client
|
---|
198 | #{nest_str} cell tMessageBuffer #{@clientChannelCell}Body1{
|
---|
199 | #{nest_str} maxMessageSize = 64; /* This value must be same as MessageBufferCEP's buffer size */
|
---|
200 | #{nest_str} bufferSize = 128;
|
---|
201 | #{nest_str} accessPattern1 = C_EXP( #{tacp_str} );
|
---|
202 | #{nest_str} accessPattern2 = C_EXP( #{tacp_str} );
|
---|
203 | #{nest_str} accessPattern3 = C_EXP( #{tacp_str} );
|
---|
204 | #{nest_str} accessPattern4 = C_EXP( #{tacp_str} );
|
---|
205 | #{nest_str} };
|
---|
206 | EOT
|
---|
207 |
|
---|
208 | ##### クライアント側のセルの生成 #####
|
---|
209 | nest = @start_region.gen_region_str_pre file
|
---|
210 | nest_str = " " * nest
|
---|
211 |
|
---|
212 | # セマフォの生成
|
---|
213 | if @b_noClientSemaphore == false then
|
---|
214 | file.print <<EOT
|
---|
215 | #{nest_str} // Semaphore for Multi-task use ("specify noClientSemaphore" option to delete this)
|
---|
216 | #{nest_str} cell #{@semaphoreCelltype} #{@serverChannelCell}_Semaphore{
|
---|
217 | #{nest_str} initialCount = 1;
|
---|
218 | #{nest_str} };
|
---|
219 | EOT
|
---|
220 | end
|
---|
221 |
|
---|
222 | # クライアント側チャンネル (tMessageBufferCEP)の生成
|
---|
223 | # チャンネルは必ずリージョン下にあるので、 '::' でつなぐ (でなければ、ルートリージョンにないかチェックが必要)
|
---|
224 |
|
---|
225 | file.print <<EOT
|
---|
226 | #{nest_str} // Client Side Channel
|
---|
227 | #{nest_str} cell tMessageBufferCEP #{@clientChannelCell}_CEP{
|
---|
228 | #{nest_str} cMessageBuffer0 = #{@clientChannelCell}Body0.eMessageBuffer;
|
---|
229 | #{nest_str} cMessageBuffer1 = #{@clientChannelCell}Body1.eMessageBuffer;
|
---|
230 | #{nest_str} };
|
---|
231 |
|
---|
232 | #{nest_str} // Client Side TDR
|
---|
233 | #{nest_str} cell tTDR #{@clientChannelCell}_TDR{
|
---|
234 | #{nest_str} cChannel = #{@clientChannelCell}_CEP.eChannel;
|
---|
235 | #{nest_str} };
|
---|
236 |
|
---|
237 | #{nest_str} // Marshaler
|
---|
238 | EOT
|
---|
239 |
|
---|
240 | # セマフォの結合文
|
---|
241 | if @b_noClientSemaphore == false then
|
---|
242 | semaphore = "#{nest_str} cLockChannel = #{@serverChannelCell}_Semaphore.eSemaphore;\n"
|
---|
243 | else
|
---|
244 | semaphore = ""
|
---|
245 | end
|
---|
246 |
|
---|
247 | ### クライアント側チャンネル (マーシャラ+TDR)の生成 ###
|
---|
248 | cell = @next_cell
|
---|
249 | # アロケータの指定があるか?
|
---|
250 | if cell.get_allocator_list.length > 0 then
|
---|
251 |
|
---|
252 | file.print nest_str
|
---|
253 | file.print "[allocator("
|
---|
254 |
|
---|
255 | delim = ""
|
---|
256 | cell.get_allocator_list.each do |type, eport, subsc, func, buf, alloc|
|
---|
257 |
|
---|
258 | alloc_str = alloc.to_s
|
---|
259 | subst = @substituteAllocator[alloc_str.to_sym]
|
---|
260 | if subst then
|
---|
261 | alloc_str = subst[2]+"."+subst[3]
|
---|
262 | end
|
---|
263 |
|
---|
264 | file.print delim
|
---|
265 | delim = ",\n" # 最終行には出さない
|
---|
266 |
|
---|
267 | if subsc then # 配列添数
|
---|
268 | subsc_str = '[#{subsc}]'
|
---|
269 | else
|
---|
270 | subsc_str = ""
|
---|
271 | end
|
---|
272 |
|
---|
273 | eport = "eThroughEntry" #RPCの受け口名に変更
|
---|
274 | file.print nest_str
|
---|
275 | file.print "#{eport}#{subsc_str}.#{func}.#{buf} = #{alloc_str}"
|
---|
276 | end
|
---|
277 |
|
---|
278 | file.puts ")]"
|
---|
279 | end
|
---|
280 |
|
---|
281 | if @clientErrorHandler then
|
---|
282 | clientErrorHandler_str = "#{nest_str} cErrorHandler = #{@clientErrorHandler};\n"
|
---|
283 | else
|
---|
284 | clientErrorHandler_str = ""
|
---|
285 | end
|
---|
286 |
|
---|
287 | file.print <<EOT
|
---|
288 | #{nest_str} cell tOpaqueMarshaler_#{@signature.get_global_name}_through #{@cell_name} {
|
---|
289 | #{nest_str} cTDR = #{@clientChannelCell}_TDR.eTDR;
|
---|
290 | #{clientErrorHandler_str}#{semaphore}#{nest_str} };
|
---|
291 | EOT
|
---|
292 | ### END: クライアント側チャンネル (マーシャラ+TDR)の生成 ###
|
---|
293 | @start_region.gen_region_str_post file
|
---|
294 | file.print "\n\n"
|
---|
295 |
|
---|
296 | ##### サーバー側のセルの生成 #####
|
---|
297 | nest = @end_region.gen_region_str_pre file
|
---|
298 | nest_str = " " * nest
|
---|
299 |
|
---|
300 | if @serverErrorHandler then
|
---|
301 | serverErrorHandler_str = "#{nest_str} cErrorHandler = #{@serverErrorHandler};\n"
|
---|
302 | else
|
---|
303 | serverErrorHandler_str = ""
|
---|
304 | end
|
---|
305 |
|
---|
306 | if @b_genOpener then
|
---|
307 | opener = "#{nest_str} cOpener = #{@serverChannelCell}.eOpener;\n"
|
---|
308 | else
|
---|
309 | opener = ""
|
---|
310 | end
|
---|
311 |
|
---|
312 | # サーバー側チャンネル (tMessageBufferCEP)
|
---|
313 | if @PPAllocatorSize then
|
---|
314 | alloc_cell =<<EOT
|
---|
315 |
|
---|
316 | #{nest_str} cell tPPAllocator #{@serverChannelCell}_PPAllocator {
|
---|
317 | #{nest_str} heapSize = #{@PPAllocatorSize};
|
---|
318 | #{nest_str} };
|
---|
319 | EOT
|
---|
320 | alloc_call_port_join = "#{nest_str} cPPAllocator = #{@serverChannelCell}_PPAllocator.ePPAllocator;\n"
|
---|
321 | else
|
---|
322 | alloc_cell = ""
|
---|
323 | alloc_call_port_join = ""
|
---|
324 | end
|
---|
325 |
|
---|
326 | file.print <<EOT
|
---|
327 | #{nest_str} // Server Side Channel
|
---|
328 | #{nest_str} cell tMessageBufferCEP #{@serverChannelCell}_CEP{
|
---|
329 | #{nest_str} cMessageBuffer0 = #{@clientChannelCell}Body1.eMessageBuffer;
|
---|
330 | #{nest_str} cMessageBuffer1 = #{@clientChannelCell}Body0.eMessageBuffer;
|
---|
331 | #{nest_str} };
|
---|
332 | EOT
|
---|
333 |
|
---|
334 | # サーバー側TDR
|
---|
335 | file.print <<EOT
|
---|
336 |
|
---|
337 | #{nest_str} // Server Side TDR
|
---|
338 | #{nest_str} cell tTDR #{@serverChannelCell}_TDR{
|
---|
339 | #{nest_str} cChannel = #{@serverChannelCell}_CEP.eChannel;
|
---|
340 | #{nest_str} };
|
---|
341 | EOT
|
---|
342 |
|
---|
343 | if @next_cell_port_subscript then
|
---|
344 | subscript = '[' + @next_cell_port_subscript.to_s + ']'
|
---|
345 | else
|
---|
346 | subscript = ""
|
---|
347 | end
|
---|
348 |
|
---|
349 | # サーバー側チャンネル (アンマーシャラ)
|
---|
350 | file.print <<EOT
|
---|
351 | #{alloc_cell}
|
---|
352 | #{nest_str} // Unmarshaler
|
---|
353 | #{nest_str} cell tOpaqueUnmarshaler_#{@signature.get_global_name} #{@serverChannelCell}_Unmarshaler {
|
---|
354 | #{nest_str} cTDR = #{@serverChannelCell}_TDR.eTDR;
|
---|
355 | #{nest_str} cServerCall = #{@next_cell.get_namespace_path.get_path_str}.#{@next_cell_port_name}#{subscript};
|
---|
356 | #{alloc_call_port_join}#{serverErrorHandler_str}#{nest_str} };
|
---|
357 | EOT
|
---|
358 |
|
---|
359 | # サーバー側タスクメイン
|
---|
360 | file.print <<EOT
|
---|
361 |
|
---|
362 | #{nest_str} // Unmarshaler Task Main
|
---|
363 | #{nest_str} cell #{@taskMainCelltype} #{@serverChannelCell}_TaskMain {
|
---|
364 | #{nest_str} cMain = #{@serverChannelCell}_Unmarshaler.eService;
|
---|
365 | #{opener}#{nest_str} };
|
---|
366 | EOT
|
---|
367 |
|
---|
368 | # サーバー側タスク
|
---|
369 | file.print <<EOT
|
---|
370 |
|
---|
371 | #{nest_str} // Unmarshaler Task
|
---|
372 | #{nest_str} cell #{@taskCelltype} #{@serverChannelCell}_Task {
|
---|
373 | #{nest_str} cTaskBody = #{@serverChannelCell}_TaskMain.eMain;
|
---|
374 | #{nest_str} priority = #{@taskPriority};
|
---|
375 | #{nest_str} stackSize = #{@stackSize};
|
---|
376 | #{nest_str} attribute = C_EXP( "TA_ACT" ); /* mikan : marshaler task starts at beginning */
|
---|
377 | #{nest_str} };
|
---|
378 | EOT
|
---|
379 | @end_region.gen_region_str_post file
|
---|
380 | end
|
---|
381 |
|
---|
382 |
|
---|
383 | #=== プラグイン引数 noClientSemaphore のチェック
|
---|
384 | def set_noClientSemaphore rhs
|
---|
385 | rhs = rhs.to_sym
|
---|
386 | if rhs == :true then
|
---|
387 | @b_noClientSemaphore = true
|
---|
388 | elsif rhs == :false then
|
---|
389 | @b_noClientSemaphore = false
|
---|
390 | else
|
---|
391 | cdl_error( "RPCPlugin: specify true or false for noClientSemaphore" )
|
---|
392 | end
|
---|
393 | end
|
---|
394 |
|
---|
395 | #=== プラグイン引数 semaphoreCelltype のチェック
|
---|
396 | def set_semaphoreCelltype rhs
|
---|
397 | @semaphoreCelltype = rhs.to_sym
|
---|
398 | nsp = NamespacePath.analyze( @semaphoreCelltype.to_s )
|
---|
399 | obj = Namespace.find( nsp )
|
---|
400 | if ! obj.instance_of?( Celltype ) && ! obj.instance_of?( CompositeCelltype ) then
|
---|
401 | cdl_error( "RPCPlugin: semaphoreCelltype '#{rhs}' not celltype or not defined" )
|
---|
402 | end
|
---|
403 | end
|
---|
404 |
|
---|
405 | #=== NamespacePath を得る
|
---|
406 | # 生成するセルの namespace path を生成する
|
---|
407 | def get_cell_namespace_path
|
---|
408 | # nsp = @region.get_namespace.get_namespace_path
|
---|
409 | nsp = @start_region.get_namespace_path
|
---|
410 | return nsp.append( @cell_name )
|
---|
411 | end
|
---|
412 |
|
---|
413 | end
|
---|
414 |
|
---|
415 |
|
---|