[337] | 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 | require_tecsgen_lib "lib/GenOpaqueMarshaler.rb"
|
---|
| 41 | require_tecsgen_lib "lib/GenParamCopy.rb"
|
---|
| 42 |
|
---|
| 43 | #= SharedOpaqueRPC プラグイン
|
---|
| 44 | # SharedOpaqueRPC チャンネルを生成する
|
---|
| 45 | # プラグイン引数は GenTransparentMarshaler 参照
|
---|
| 46 |
|
---|
| 47 | # mikan through plugin: namespace が考慮されていない
|
---|
| 48 | # これを利用する場合、以下のように toppers_jsp.cdl sChannel.cdl を指定する必要がある
|
---|
| 49 | # tecsgen toppers_jsp.cdl sChannel.cdl your_description.cdl
|
---|
| 50 |
|
---|
| 51 | # 以下を仮定(制限事項)
|
---|
| 52 | # 呼び元、呼び先のエンディアン、char, short, int_t, long_t, intptr_t のサイズが同じ
|
---|
| 53 | # 有符号、無符号でサイズが同じ
|
---|
| 54 |
|
---|
| 55 | class SharedOpaqueRPCPlugin < ThroughPlugin
|
---|
| 56 |
|
---|
| 57 | # チャンネルを共有するプラグインオブジェクトへのハッシュリスト
|
---|
| 58 | @@shared_channel_list = {} # { chan_name => [ Plugin_obj0, Plugin_Obj1, ... ] }
|
---|
| 59 |
|
---|
| 60 | attr_reader :cell_name, :start_region, :end_region
|
---|
| 61 | include GenOpaqueMarshaler
|
---|
| 62 | include GenParamCopy
|
---|
| 63 |
|
---|
| 64 | # SharedOpaqueRPCPlugin 専用のオプション
|
---|
| 65 | SharedOpaqueRPCPluginArgProc = RPCPluginArgProc.dup # 複製を作って元を変更しないようにする
|
---|
| 66 | SharedOpaqueRPCPluginArgProc[ "sharedChannelName" ] = Proc.new { |obj,rhs| obj.set_sharedChannelName rhs }
|
---|
| 67 |
|
---|
| 68 | #=== RPCPlugin の initialize
|
---|
| 69 | # 説明は ThroughPlugin (plugin.rb) を参照
|
---|
[374] | 70 | def initialize( cell_name, plugin_arg, next_cell, next_cell_port_name, next_cell_port_subscript, signature, celltype, caller_cell )
|
---|
[337] | 71 | super
|
---|
| 72 | initialize_opaque_marshaler
|
---|
| 73 | @entry_port_name = :"eClientEntry" # Marshaler の受け口名 (through セルの入り口)
|
---|
| 74 |
|
---|
| 75 | # オプション:GenOpaqueMarshaler 参照
|
---|
| 76 | @plugin_arg_check_proc_tab = SharedOpaqueRPCPluginArgProc
|
---|
| 77 | @sharedChannelName = nil
|
---|
| 78 | parse_plugin_arg
|
---|
| 79 | check_opener_code
|
---|
| 80 | check_PPAllocator
|
---|
| 81 |
|
---|
| 82 | @shared_channel_ct_name = :"tSharedOpaqueRPCPluginChannel_tTDR"
|
---|
| 83 | @shared_channel_server_ct_name = :"#{@shared_channel_ct_name}_Server"
|
---|
| 84 | @shared_channel_client_ct_name = :"#{@shared_channel_ct_name}_Client"
|
---|
| 85 | @shared_channel_ct_file_name = "#{$gen}/#{@shared_channel_ct_name}.cdl"
|
---|
| 86 | if @sharedChannelName == nil then
|
---|
| 87 | cdl_error( "'sharedChannelName' option: mandatory")
|
---|
| 88 | else
|
---|
| 89 | @shared_channel_cell = @sharedChannelName
|
---|
| 90 | end
|
---|
| 91 |
|
---|
| 92 | if @@shared_channel_list[ @shared_channel_cell ] == nil then
|
---|
| 93 | @@shared_channel_list[ @shared_channel_cell ] = [ self ]
|
---|
| 94 | else
|
---|
| 95 | @@shared_channel_list[ @shared_channel_cell ] << self
|
---|
| 96 | end
|
---|
| 97 | @sub_channel_no = ( @@shared_channel_list[ @shared_channel_cell ].length ) -1
|
---|
| 98 |
|
---|
| 99 | prev_start = @@shared_channel_list[ @shared_channel_cell ][0].start_region
|
---|
| 100 | if @start_region != prev_start then
|
---|
| 101 | # 初出と start リージョン不一致 (初出は、自分自身とチェックされる。無駄だが小さいので放置)
|
---|
| 102 | cdl_error( "SharedRPCPlugin: start region mismatch current: #{@region.get_name} previous: #{prev_start.get_name}")
|
---|
| 103 | end
|
---|
| 104 |
|
---|
| 105 | prev_end = @@shared_channel_list[ @shared_channel_cell ][0].end_region
|
---|
| 106 | if @end_region != prev_end then
|
---|
| 107 | # 初出と end リージョン不一致 (初出は、自分自身とチェックされる。無駄だが小さいので放置)
|
---|
| 108 | cdl_error( "SharedRPCPlugin: end region mismatch current: #{@region.get_name} previous: #{prev_end.get_name}")
|
---|
| 109 | end
|
---|
| 110 |
|
---|
| 111 | end
|
---|
| 112 |
|
---|
| 113 | # def set_through_info( start_region, end_region, through_type )
|
---|
| 114 | # super
|
---|
| 115 | # end
|
---|
| 116 |
|
---|
| 117 | #=== プラグイン引数 sharedChannelCell のチェック
|
---|
| 118 | def set_sharedChannelName( rhs )
|
---|
| 119 | @sharedChannelName = rhs
|
---|
| 120 | # path = [ "::", rhs ]
|
---|
| 121 | # obj = Namespace.find( path )
|
---|
| 122 | # if ! obj.instance_of?( Cell ) then
|
---|
| 123 | # cdl_error( "SharedOpaqueRPCPlugin: sharedChannelName '#{rhs}' not cell" )
|
---|
| 124 | # end
|
---|
| 125 | end
|
---|
| 126 |
|
---|
| 127 | def gen_plugin_decl_code( file )
|
---|
| 128 |
|
---|
| 129 | # このセルタイプ(同じシグニチャ)は既に生成されているか?
|
---|
| 130 | if @@generated_celltype[ @shared_channel_server_ct_name ] == nil then
|
---|
| 131 | @@generated_celltype[ @shared_channel_server_ct_name ] = [ self ]
|
---|
| 132 | else
|
---|
| 133 | @@generated_celltype[ @shared_channel_server_ct_name ] << self
|
---|
| 134 | end
|
---|
| 135 |
|
---|
| 136 | gen_marshaler_celltype
|
---|
| 137 |
|
---|
| 138 | # 同じ内容を二度書く可能性あり (AppFile は不可)
|
---|
| 139 |
|
---|
| 140 | if @PPAllocatorSize then
|
---|
| 141 | alloc_call_port = " call sPPAllocator cPPAllocator;\n"
|
---|
| 142 | alloc_call_port_join = " cPPAllocator => composite.cPPAllocator;\n"
|
---|
| 143 | else
|
---|
| 144 | alloc_call_port = ""
|
---|
| 145 | alloc_call_port_join = ""
|
---|
| 146 | end
|
---|
| 147 |
|
---|
| 148 | f = CFile.open( @shared_channel_ct_file_name, "w" )
|
---|
| 149 | # 同じ内容を二度書く可能性あり (AppFile は不可)
|
---|
| 150 |
|
---|
| 151 | f.print <<EOT
|
---|
| 152 |
|
---|
| 153 | /* Shared Channel Celltype for Client */
|
---|
| 154 | composite #{@shared_channel_client_ct_name} {
|
---|
| 155 | entry sTDR eTDR;
|
---|
| 156 | entry sSemaphore eSemaphore[];
|
---|
| 157 | call sChannel cClientChannel;
|
---|
| 158 |
|
---|
| 159 | cell tTDR TDR {
|
---|
| 160 | cChannel => composite.cClientChannel;
|
---|
| 161 | };
|
---|
| 162 | cell tSemaphore Semaphore {
|
---|
| 163 | count = 1;
|
---|
| 164 | attribute = C_EXP("TA_NULL");
|
---|
| 165 | };
|
---|
| 166 | cell tRPCSharedChannelMan SharedChannelMan{
|
---|
| 167 | cSemaphore = Semaphore.eSemaphore;
|
---|
| 168 | cClientSideTDR = TDR.eTDR;
|
---|
| 169 | };
|
---|
| 170 | composite.eSemaphore => SharedChannelMan.eSemaphore;
|
---|
| 171 | composite.eTDR => TDR.eTDR;
|
---|
| 172 | };
|
---|
| 173 |
|
---|
| 174 | /* Shared Channel Celltype for Server */
|
---|
| 175 | [active]
|
---|
| 176 | composite #{@shared_channel_server_ct_name} {
|
---|
| 177 | entry sTDR eTDR;
|
---|
| 178 | call sChannel cServerChannel;
|
---|
| 179 | call sUnmarshalerMain cUnmarshalAndCallFunction[];
|
---|
| 180 | call sServerChannelOpener cOpener;
|
---|
| 181 | attr {
|
---|
| 182 | PRI priority;
|
---|
| 183 | };
|
---|
| 184 |
|
---|
| 185 | cell tTDR TDR {
|
---|
| 186 | cChannel => composite.cServerChannel;
|
---|
| 187 | };
|
---|
| 188 | cell tRPCSharedTaskMainWithOpener RPCSharedTaskMain {
|
---|
| 189 | cUnmarshalAndCallFunction => composite.cUnmarshalAndCallFunction;
|
---|
| 190 | cServerSideTDR = TDR.eTDR;
|
---|
| 191 | cOpener => composite.cOpener;
|
---|
| 192 | };
|
---|
| 193 | cell tTask Task {
|
---|
| 194 | cBody = RPCSharedTaskMain.eMain;
|
---|
| 195 | taskAttribute = C_EXP("TA_ACT");
|
---|
| 196 | stackSize = 4096;
|
---|
| 197 | priority = composite.priority;
|
---|
| 198 | };
|
---|
| 199 | composite.eTDR => TDR.eTDR;
|
---|
| 200 | };
|
---|
| 201 |
|
---|
| 202 | EOT
|
---|
| 203 | f.close
|
---|
| 204 |
|
---|
| 205 | end
|
---|
| 206 |
|
---|
| 207 | #=== through cell コードを生成
|
---|
| 208 | #
|
---|
| 209 | #
|
---|
| 210 | def gen_through_cell_code( file )
|
---|
| 211 |
|
---|
| 212 | gen_plugin_decl_code( file )
|
---|
| 213 |
|
---|
| 214 | file.print <<EOT
|
---|
| 215 |
|
---|
| 216 | import( "#{@marshaler_celltype_file_name}" );
|
---|
| 217 | import( "#{@shared_channel_ct_file_name}" );
|
---|
| 218 | EOT
|
---|
| 219 |
|
---|
| 220 | # nest = @caller_cell.get_region.gen_region_str_pre file
|
---|
| 221 | nest = @start_region.gen_region_str_pre file
|
---|
| 222 | indent_str = " " * nest
|
---|
[374] | 223 | nest_str = " " * nest
|
---|
| 224 | if @next_cell_port_subscript then
|
---|
| 225 | subscript = '[' + @next_cell_port_subscript.to_s + ']'
|
---|
| 226 | else
|
---|
| 227 | subscript = ""
|
---|
| 228 | end
|
---|
[337] | 229 |
|
---|
| 230 | # セルを探す
|
---|
| 231 | # path =["::",@next_cell.get_name]
|
---|
| 232 | # cell = Namespace.find( path )
|
---|
| 233 | cell = Namespace.find( @next_cell.get_namespace_path )
|
---|
| 234 |
|
---|
| 235 | # 共有される通信チャンネルの生成のプロトタイプ宣言
|
---|
| 236 | file.print <<EOT
|
---|
| 237 | #{indent_str}cell #{@shared_channel_client_ct_name} #{@shared_channel_cell};
|
---|
| 238 | EOT
|
---|
| 239 |
|
---|
| 240 | # マーシャラセルの生成(アロケータコードの生成から)
|
---|
| 241 | # アロケータの指定があるか?
|
---|
| 242 | if cell.get_allocator_list.length > 0 then
|
---|
| 243 |
|
---|
| 244 | file.print "#{indent_str}[allocator("
|
---|
| 245 |
|
---|
| 246 | delim = ""
|
---|
| 247 | cell.get_allocator_list.each do |type, eport, subsc, func, buf, alloc|
|
---|
| 248 |
|
---|
| 249 | alloc_str = alloc.to_s
|
---|
| 250 | subst = @substituteAllocator[alloc_str.to_sym]
|
---|
| 251 |
|
---|
| 252 | if subst then
|
---|
| 253 | alloc_str = subst[2]+"."+subst[3]
|
---|
| 254 | end
|
---|
| 255 |
|
---|
| 256 | file.print delim
|
---|
| 257 | delim = ",\n#{indent_str} " # 最終行には出さない
|
---|
| 258 |
|
---|
| 259 | if subsc then # 配列添数
|
---|
| 260 | subsc_str = '[#{subsc}]'
|
---|
| 261 | else
|
---|
| 262 | subsc_str = ""
|
---|
| 263 | end
|
---|
| 264 |
|
---|
| 265 | eport = @entry_port_name #RPCの受け口名に変更
|
---|
| 266 | file.print "#{eport}#{subsc_str}.#{func}.#{buf} = #{alloc_str}"
|
---|
| 267 | end
|
---|
| 268 |
|
---|
| 269 | file.puts ")]"
|
---|
| 270 | end
|
---|
| 271 |
|
---|
| 272 | # マーシャラセル本体生成
|
---|
| 273 | file.print <<EOT
|
---|
| 274 | /* OpaqueRPC Marshaler Cell */
|
---|
| 275 | #{indent_str}cell #{@marshaler_celltype_name} #{@cell_name} {
|
---|
| 276 | #{indent_str} cTDR = #{@shared_channel_cell}.eTDR;
|
---|
| 277 | #{indent_str} cLockChannel = #{@shared_channel_cell}.eSemaphore[#{@sub_channel_no}];
|
---|
| 278 | #{indent_str}};
|
---|
| 279 | EOT
|
---|
| 280 | # @caller_cell.get_region.gen_region_str_post file
|
---|
| 281 | @start_region.gen_region_str_post file
|
---|
| 282 |
|
---|
| 283 | # アンマーシャラセルの出力
|
---|
| 284 | # セル本体の生成
|
---|
| 285 | nest = @end_region.gen_region_str_pre file
|
---|
| 286 |
|
---|
| 287 | file.print <<EOT
|
---|
| 288 | /* Server Channel Cell prototype */
|
---|
| 289 | #{indent_str}cell #{@shared_channel_server_ct_name} #{@sharedChannelName}_Server;
|
---|
| 290 |
|
---|
| 291 | EOT
|
---|
| 292 |
|
---|
| 293 | # PPAllocator が必要か?
|
---|
| 294 | if @PPAllocatorSize then
|
---|
| 295 | if @sub_channel_no == 0 then
|
---|
| 296 | file.print <<EOT
|
---|
| 297 | #{indent_str}cell tPPAllocator PPAllocator_#{@shared_channel_cell}{
|
---|
| 298 | #{indent_str} heapSize = #{@PPAllocatorSize};
|
---|
| 299 | #{indent_str}};
|
---|
| 300 | EOT
|
---|
| 301 | end
|
---|
| 302 |
|
---|
| 303 | ppallocator_join = "#{indent_str} cPPAllocator = PPAllocator_#{@shared_channel_cell}.ePPAllocator;\n"
|
---|
| 304 | else
|
---|
| 305 | ppallocator_join = ""
|
---|
| 306 | end
|
---|
| 307 |
|
---|
| 308 | file.print <<EOT
|
---|
| 309 | #{indent_str}cell #{@unmarshaler_celltype_name} #{@cell_name}_Server {
|
---|
| 310 | #{indent_str} cTDR = #{@shared_channel_cell}_Server.eTDR;
|
---|
[374] | 311 | #{indent_str} cServerCall = #{@next_cell.get_namespace_path.get_path_str}.#{@next_cell_port_name}#{subscript};
|
---|
[337] | 312 | #{ppallocator_join}#{indent_str}};
|
---|
| 313 | EOT
|
---|
| 314 | @end_region.gen_region_str_post file
|
---|
| 315 |
|
---|
| 316 | end
|
---|
| 317 |
|
---|
| 318 | #=== post コード(CDL) を生成
|
---|
| 319 | # プラグインの後のコードを生成
|
---|
| 320 | #file:: File:
|
---|
| 321 | def self.gen_post_code( file )
|
---|
| 322 |
|
---|
| 323 | file.print "/* '#{self.name}' post code */\n"
|
---|
| 324 |
|
---|
| 325 | @@shared_channel_list.each{ |chan_name,plugin_obj_array|
|
---|
| 326 | file.print "/* '#{chan_name}' shared channel */\n"
|
---|
| 327 | plugin_obj_array[0].gen_post_code( file, plugin_obj_array )
|
---|
| 328 | }
|
---|
| 329 |
|
---|
| 330 | end
|
---|
| 331 |
|
---|
| 332 | #=== post コード(CDL) を生成
|
---|
| 333 | # 共有チャンネルを生成する
|
---|
| 334 | # このメソッドは、チャンネルを共有する最初のプラグインオブジェクトのみ呼び出される
|
---|
| 335 | def gen_post_code( file, plugin_obj_array )
|
---|
| 336 |
|
---|
| 337 | # 共有されている通信チャンネルの生成
|
---|
| 338 | # 各プラグインインスタンスでは @shared_channel_ct_name として記憶している
|
---|
| 339 | # region = @caller_cell.get_region
|
---|
| 340 | nest = @start_region.gen_region_str_pre file
|
---|
| 341 | indent_str = " " * nest
|
---|
| 342 | file.print <<EOT
|
---|
| 343 | #{indent_str}cell #{@shared_channel_client_ct_name} #{@sharedChannelName} {
|
---|
| 344 | #{indent_str} cClientChannel = #{@clientChannelCell}.eC0;
|
---|
| 345 | #{indent_str}};
|
---|
| 346 | EOT
|
---|
| 347 | @start_region.gen_region_str_post file
|
---|
| 348 |
|
---|
| 349 | nest = @end_region.gen_region_str_pre file
|
---|
| 350 | indent_str = " " * nest
|
---|
| 351 | file.print "#{indent_str}cell #{@shared_channel_server_ct_name} #{@sharedChannelName}_Server {\n"
|
---|
| 352 | file.print <<EOT
|
---|
| 353 | #{indent_str} cServerChannel = #{@serverChannelCell}.eC1;
|
---|
| 354 | #{indent_str} cOpener = #{@serverChannelCell}.eOpener;
|
---|
| 355 | EOT
|
---|
| 356 | plugin_obj_array.each{ |po|
|
---|
| 357 | file.print <<EOT
|
---|
| 358 | #{indent_str} cUnmarshalAndCallFunction[] = #{po.cell_name}_Server.eService;
|
---|
| 359 | EOT
|
---|
| 360 | }
|
---|
| 361 | file.printf <<EOT
|
---|
| 362 | #{indent_str} priority = #{@taskPriority};
|
---|
| 363 | #{indent_str}};
|
---|
| 364 | EOT
|
---|
| 365 | @end_region.gen_region_str_post file
|
---|
| 366 |
|
---|
| 367 | end
|
---|
| 368 | end
|
---|
| 369 |
|
---|
| 370 |
|
---|