source: EcnlProtoTool/trunk/asp3_dcre/utils/gentest.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: 12.8 KB
Line 
1#!/usr/bin/env ruby
2# -*- coding: utf-8 -*-
3#
4# TOPPERS Software
5# Toyohashi Open Platform for Embedded Real-Time Systems
6#
7# Copyright (C) 2007-2016 by Embedded and Real-Time Systems Laboratory
8# Graduate School of Information Science, Nagoya Univ., JAPAN
9#
10# 上記著作権者
11は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
12# ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
13# 変・再é…
14å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
15# (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
16# 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
17# スコード中に含まれていること.
18# (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
19# 用できる形で再é…
20å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
21å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
22# 者
23マニュアルなど)に,上記の著作権表示,この利用条件および下記
24# の無保証規定を掲載すること.
25# (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
26# 用できない形で再é…
27å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
28# と.
29# (a) 再é…
30å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
31マニュアルなど)に,上記の著
32# 作権表示,この利用条件および下記の無保証規定を掲載すること.
33# (b) 再é…
34å¸ƒã®å½¢æ…
35‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
36# 報告すること.
37# (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
38# 害からも,上記著作権者
39およびTOPPERSプロジェクトをå…
40è²¬ã™ã‚‹ã“と.
41# また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
42# 由に基づく請求からも,上記著作権者
43およびTOPPERSプロジェクトを
44# å…
45è²¬ã™ã‚‹ã“と.
46#
47# 本ソフトウェアは,無保証で提供されているものである.上記著作権者
48お
49# よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
50# に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
51# アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
52# の責任を負わない.
53#
54# $Id: gentest.rb 1011 2016-07-11 02:20:01Z coas-nagasima $
55#
56
57#
58# テストプログラム生成ツール
59#
60
61#
62# 生成動作を決めるための設定
63#
64$parameterDefinition = {
65 "get_tst" => { 2 => "STAT" },
66 "get_pri" => { 2 => "PRI" },
67 "get_inf" => { 1 => "intptr_t" },
68 "ref_tsk" => { 2 => "T_RTSK" },
69 "ref_sem" => { 2 => "T_RSEM" },
70 "wai_flg" => { 4 => "FLGPTN" },
71 "pol_flg" => { 4 => "FLGPTN" },
72 "twai_flg" => { 4 => "FLGPTN" },
73 "ref_flg" => { 2 => "T_RFLG" },
74 "rcv_dtq" => { 2 => "intptr_t" },
75 "prcv_dtq" => { 2 => "intptr_t" },
76 "trcv_dtq" => { 2 => "intptr_t" },
77 "ref_dtq" => { 2 => "T_RDTQ" },
78 "rcv_pdq" => { 2 => "intptr_t" , 3 => "PRI" },
79 "prcv_pdq" => { 2 => "intptr_t" , 3 => "PRI" },
80 "trcv_pdq" => { 2 => "intptr_t" , 3 => "PRI" },
81 "ref_pdq" => { 2 => "T_RPDQ" },
82 "ref_mtx" => { 2 => "T_RMTX" },
83 "ref_mbf" => { 2 => "T_RMBF" },
84 "get_mpf" => { 2 => "void *" },
85 "pget_mpf" => { 2 => "void *" },
86 "tget_mpf" => { 2 => "void *" },
87 "ref_mpf" => { 2 => "T_RMPF" },
88 "get_tim" => { 1 => "SYSTIM" },
89 "ref_cyc" => { 2 => "T_RCYC" },
90 "ref_alm" => { 2 => "T_RALM" },
91 "ref_ovr" => { 2 => "T_ROVR" },
92 "get_tid" => { 1 => "ID" },
93 "get_did" => { 1 => "ID" },
94 "get_lod" => { 2 => "uint_t" },
95 "mget_lod" => { 3 => "uint_t" },
96 "get_nth" => { 3 => "ID" },
97 "mget_nth" => { 4 => "ID" },
98 "get_ipm" => { 1 => "PRI" },
99 "get_som" => { 1 => "ID" }
100}
101
102$functionParameters = {
103 "target_hrt_set_event" => "HRTCNT hrtcnt"
104}
105
106$functionValue = {
107 "target_hrt_get_current" => "HRTCNT"
108}
109
110$functionReturn = {
111 "target_hrt_get_current" => "0U"
112}
113
114$functionCheckParameter = {
115 "target_hrt_set_event" => "hrtcnt"
116}
117
118#
119# 処理単位のコードを格納するクラス
120#
121class PUCode
122 # 初期化
123 def initialize(puName)
124 @puName = puName # 処理単位の名前
125 @currentCount = "" # 処理カウント
126 @countFlag = false # 処理カウントが使われたか
127 @code = Hash.new { |h,k| h[k] = [] } # 処理単位のコード
128 @variableList = {} # 処理単位の変数
129 @silFlag = false # SILが使われたか
130
131 # 処理カウント変数名の生成
132 case puName
133 when /^TASK([0-9]*)$/
134 @count_var = "task#{$1}_count"
135 when /^CYC([0-9]*)$/
136 @count_var = "cyclic#{$1}_count"
137 when /^ALM([0-9]*)$/
138 @count_var = "alarm#{$1}_count"
139 when /^OVR$/
140 @count_var = "overrun_count"
141 when /^CPUEXC([0-9]*)$/
142 @count_var = "cpuexc#{$1}_count"
143 when /^EXTSVC([0-9]*)$/
144 @count_var = "extsvc#{$1}_count"
145 else
146 @count_var = puName + "_count"
147 end
148 end
149
150 # 処理カウントの設定
151 def setCount(count)
152 @countFlag = true if count != ""
153 @currentCount = count
154 end
155
156 # 処理カウントのインクリメント
157 def incrementCount
158 if @currentCount != ""
159 @currentCount = (@currentCount.to_i + 1).to_s
160 end
161 end
162
163 # コードの追加
164 def append(*lines)
165 lines.each do |line|
166 @code[@currentCount].push(line)
167 end
168 end
169
170 # 変数の追加
171 def addVariable(varName, typeName)
172 @variableList[varName] = typeName
173 end
174
175 # SILの使用
176 def useSil
177 @silFlag = true
178 end
179
180 # 処理単位のコードの出力
181 def generateCode
182 # 不要な処理単位の判定
183 return if @code.length == 0
184
185 # 処理カウント変数の生成
186 if @countFlag
187 print("\nstatic uint_t\t#{@count_var} = 0;\n")
188 end
189
190 # 関数ヘッダの生成
191 case @puName
192 when /^TASK([0-9]*)$/
193 print("\nvoid\n")
194 print("task#{$1}(intptr_t exinf)\n")
195 when /^CYC([0-9]*)$/
196 print("\nvoid\n")
197 print("cyclic#{$1}_handler(intptr_t exinf)\n")
198 when /^ALM([0-9]*)$/
199 print("\nvoid\n")
200 print("alarm#{$1}_handler(intptr_t exinf)\n")
201 when /^OVR$/
202 print("\nvoid\n")
203 print("overrun_handler(ID tskid, intptr_t exinf)\n")
204 when /^CPUEXC([0-9]*)$/
205 print("\nvoid\n")
206 print("cpuexc#{$1}_handler(void *p_excinf)\n")
207 when /^EXTSVC([0-9]*)$/
208 print("\nER_UINT\n")
209 print("extsvc#{$1}_routine")
210 print("(intptr_t par1, intptr_t par2, intptr_t par3,\n")
211 print("\t\t\t\t\t\t\t\tintptr_t par4, intptr_t par5, ID cdmid)\n")
212 else
213 if $functionValue[@puName]
214 print("\n#{$functionValue[@puName]}\n")
215 else
216 print("\nvoid\n")
217 end
218 print(@puName)
219 if $functionParameters[@puName]
220 print("(#{$functionParameters[@puName]})\n")
221 else
222 print("(void)\n")
223 end
224 end
225
226 print("{\n")
227
228 @variableList.each do |varName, varType|
229 if /^(.+)\w*\*$/ =~ varType
230 varBaseType = $1
231 print("\t#{varBaseType}")
232 print(varBaseType.length < 4 ? "\t\t*" : "\t*")
233 else
234 print("\t#{varType}")
235 print(varType.length < 4 ? "\t\t" : "\t")
236 end
237 print("#{varName};\n")
238 end
239 if @silFlag
240 print("\tSIL_PRE_LOC;\n")
241 end
242 print("\n")
243
244 if @countFlag
245 print("\tswitch (++#{@count_var}) {\n")
246 @code.keys.sort_by { |c| c.to_i }.each do |count|
247 print("\tcase #{count}:\n")
248 @code[count].each do |line|
249 print("\t",line) if line != ""
250 print("\n")
251 end
252 print("\t\tcheck_point(0);\n\n")
253 end
254 print("\tdefault:\n")
255 print("\t\tcheck_point(0);\n")
256 print("\t}\n")
257 else
258 @code[""].each do |line|
259 print(line,"\n")
260 end
261 end
262
263 print("\tcheck_point(0);\n")
264 if /^EXTSVC([0-9]*)$/ =~ @puName
265 print("\treturn(E_SYS);\n")
266 elsif $functionReturn[@pu_nama]
267 print("\treturn(#{$functionReturn[@puName]});\n")
268 end
269 print("}\n")
270 end
271end
272
273#
274# サービスコール呼び出しの読み込み
275#
276def genServiceCall(pu, svc_call, error_code)
277 pu.addVariable("ercd", "ER_UINT")
278 pu.append("\tercd = #{svc_call};")
279
280 if /^([a-z_]+)\((.*)\)$/ =~ svc_call
281 svcName = $1;
282 params = $2.split(/\s*,\s*/)
283
284 if $parameterDefinition.has_key?(svcName)
285 $parameterDefinition[svcName].each do |pos, type|
286 if params.size >= pos
287 varName = params[pos - 1].sub(/^\&/, "")
288 pu.addVariable(varName, type)
289 end
290 end
291 end
292 end
293
294 if !error_code
295 # E_OKが返る場合
296 pu.append("\tcheck_ercd(ercd, E_OK);", "")
297 elsif error_code == "noreturn"
298 # リターンしない場合
299 pu.append("")
300 else
301 pu.append("\tcheck_ercd(ercd, #{error_code});", "")
302 end
303end
304
305#
306# テスト開始コードの生成
307#
308def testStartCode(pu)
309 # テスト開始コードは一度のみ出力する
310 if $startFlag == 0
311 pu.append("\ttest_start(__FILE__);", "")
312 $startFlag = 1
313 end
314end
315
316#
317# ターゲット依存部関数の振る舞いの読み込み
318#
319def targetFunction(line, checkNum)
320 if /^([a-zA-Z_]+)\s*(.*)$/ =~ line
321 functionName = $1
322 line = $2
323 if (pu = $puList[functionName]).nil?
324 # 新しい処理単位の生成
325 pu = $puList[functionName] = PUCode.new(functionName)
326 pu.setCount("1")
327 testStartCode(pu)
328 end
329 end
330
331 if /\-\>\s*([^\s]+)\s*(.*)$/ =~ line
332 retval = $1
333 line = $2
334 end
335 if /\<\-\s*([^\s]+)\s*(.*)$/ =~ line
336 param = $1
337 line = $2
338 end
339
340 pu.append("\tcheck_point(#{checkNum});");
341 if param && $functionCheckParameter[functionName]
342 pu.append(sprintf("\tcheck_assert(%s == %s);",
343 $functionCheckParameter[functionName], param), "")
344 end
345 if retval
346 pu.append("\treturn(#{retval});", "")
347 else
348 pu.append("\treturn;", "")
349 end
350 pu.incrementCount()
351end
352
353#
354# テストスクリプトの読み込み
355#
356def parseLine(line)
357 if /^==\s*(([a-zA-Z_]+)[0-9]*)(.*)$/ =~ line
358 # 処理単位の開始
359 $procFlag = 1
360 puName = $1
361 line2 = $3
362 if (pu = $puList[puName]).nil?
363 # 新しい処理単位の生成
364 pu = $puList[puName] = PUCode.new(puName)
365 end
366 $currentPu = pu
367
368 case line2
369 when /^\-([0-9]+)(.*)$/
370 pu.setCount($1)
371 when /^\-[nN](.*)$/
372 # do nothing.
373 else
374 pu.setCount("")
375 end
376 testStartCode(pu) if /^START/ !~ puName
377 elsif $procFlag != 0
378 pu = $currentPu
379 if /^([0-9]+\:)\s*(.*)$/ =~ line
380 # チェックポイント番号の処理
381 originalCheckNum = $1
382 line = $2
383 checkNum = ($lastCheckPoint += 1).to_s
384 $outputLine.sub!(/#{originalCheckNum}/, "#{checkNum}:")
385
386 case line
387 when /^END$/
388 pu.append("\tcheck_finish(#{checkNum});")
389 $procFlag = 0
390 return
391 when /^HOOK\((.*)\)$/
392 pu.append(sprintf("\t#{$1};", checkNum))
393 return
394 when /^\[(.*)\]$/
395 targetFunction($1, checkNum)
396 return
397 else
398 pu.append("\tcheck_point(#{checkNum});")
399 end
400 end
401
402 case line
403 when /^((assert|state|ipm)\(.*\))$/
404 pu.append("\tcheck_#{$1};", "")
405 when /^(call|DO)\((.*)\)$/
406 call_string = $2
407 pu.append("\t#{call_string};", "")
408 pu.useSil() if /^SIL_..._INT\(\)$/ =~ call_string
409 when /^RETURN((\(.*\))?)$/
410 pu.append("\treturn#{$1};", "")
411 pu.incrementCount()
412 when /^GOTO\((.*)\)$/
413 pu.append("\tgoto #{$1};", "")
414 when /^LABEL\((.*)\)$/
415 pu.append("#{$1}:", "")
416 when /^([a-z_]+\(.*\))\s*(\-\>\s*([A-Za-z0-9_]*))?\s*$/
417 genServiceCall(pu, $1, $3)
418 else
419 warn("Error: #{line}")
420 end
421 end
422end
423
424#
425# エラーチェック
426#
427if ARGV.length < 1
428 abort("Usage: ruby gentest.rb <test_program>")
429end
430
431#
432# 初期化
433#
434inFileName = ARGV.shift
435
436#
437# スクリプトファイル読み込み処理
438#
439$lastCheckPoint = 0 # 最後のチェックポイント番号
440$procFlag = 0 # スクリプト処理中フラグ
441$startFlag = 0 # テスト開始コードの出力フラグ
442$currentPu = nil # 読み込み中の処理単位
443$puList = {} # 処理単位のリスト
444
445begin
446 inFile = File.open(inFileName)
447rescue Errno::ENOENT, Errno::EACCES => ex
448 abort(ex.message)
449end
450
451while line = inFile.gets do
452 $outputLine = line.dup
453 line.chomp!
454 line.sub!(/^\s*\*\s*/, "")
455 line.sub!(/\s*\/\/.*$/, "")
456 line.sub!(/\s*\.\.\..*$/, "")
457
458 while line.sub!(/\\$/, "") do
459 line1 = inFile.gets
460 $outputLine += line1.dup
461 line1.chomp!
462 line1.sub!(/^\s*\*\s*/, "")
463 line1.sub!(/\s*\/\/.*$/, "")
464 line1.sub!(/\s*\.\.\..*$/, "")
465 line += line1
466 end
467 parseLine(line) if line != ""
468 print($outputLine)
469 break if /DO NOT DELETE THIS LINE/ =~ $outputLine
470end
471
472#
473# テストプログラム出力処理
474#
475$puList.keys.sort.each do |puName|
476 $puList[puName].generateCode()
477end
Note: See TracBrowser for help on using the repository browser.