source: asp3_wo_tecs/trunk/utils/gentest.rb@ 304

Last change on this file since 304 was 304, checked in by ertl-honda, 7 years ago

コンフィギュレータをruby版に変更

File size: 12.6 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 578 2016-02-03 07:23:53Z ertl-hiro $
55#
56
57#
58# テストプログラム生成ツール
59#
60
61#
62# 生成動作を決めるための設定
63#
64$parameterPosition = {
65 "get_tst" => 2,
66 "get_pri" => 2,
67 "get_inf" => 1,
68 "ref_tsk" => 2,
69 "ref_sem" => 2,
70 "ref_flg" => 2,
71 "ref_dtq" => 2,
72 "ref_pdq" => 2,
73 "ref_mtx" => 2,
74 "ref_mbf" => 2,
75 "ref_mpf" => 2,
76 "get_tim" => 1,
77 "ref_cyc" => 2,
78 "ref_alm" => 2,
79 "ref_ovr" => 2,
80 "get_tid" => 1,
81 "iget_tid" => 1,
82 "get_lod" => 2,
83 "get_nth" => 3,
84 "get_ipm" => 1,
85 "wai_flg" => 4,
86 "pol_flg" => 4,
87 "twai_flg" => 4,
88 "rcv_dtq" => 2,
89 "prcv_dtq" => 2,
90 "trcv_dtq" => 2,
91}
92
93$parameterType = {
94 "get_tst" => "STAT",
95 "get_pri" => "PRI",
96 "get_inf" => "intptr_t",
97 "ref_tsk" => "T_RTSK",
98 "ref_sem" => "T_RSEM",
99 "ref_flg" => "T_RFLG",
100 "ref_dtq" => "T_RDTQ",
101 "ref_pdq" => "T_RPDQ",
102 "ref_mtx" => "T_RMTX",
103 "ref_mbf" => "T_RMBF",
104 "ref_mpf" => "T_RMPF",
105 "get_tim" => "SYSTIM",
106 "ref_cyc" => "T_RCYC",
107 "ref_alm" => "T_RALM",
108 "ref_ovr" => "T_ROVR",
109 "get_tid" => "ID",
110 "iget_tid" => "ID",
111 "get_lod" => "uint_t",
112 "get_nth" => "ID",
113 "get_ipm" => "PRI",
114 "wai_flg" => "FLGPTN",
115 "pol_flg" => "FLGPTN",
116 "twai_flg" => "FLGPTN",
117 "rcv_dtq" => "intptr_t",
118 "prcv_dtq" => "intptr_t",
119 "trcv_dtq" => "intptr_t",
120}
121
122$functionParameters = {
123 "target_hrt_set_event" => "HRTCNT hrtcnt",
124}
125
126$functionValue = {
127 "target_hrt_get_current" => "HRTCNT",
128}
129
130$functionReturn = {
131 "target_hrt_get_current" => "0U",
132}
133
134$functionCheckParameter = {
135 "target_hrt_set_event" => "hrtcnt",
136}
137
138#
139# 処理単位のコードを格納するクラス
140#
141class PUCode
142 # 初期化
143 def initialize(puName)
144 @puName = puName # 処理単位の名前
145 @currentCount = "" # 処理カウント
146 @countFlag = false # 処理カウントが使われたか
147 @code = Hash.new { |h,k| h[k] = [] } # 処理単位のコード
148 @variableList = {} # 処理単位の変数
149 @silFlag = false # SILが使われたか
150
151 # 処理カウント変数名の生成
152 case puName
153 when /^TASK([0-9]*)$/
154 @count_var = "task#{$1}_count"
155 when /^CYC([0-9]*)$/
156 @count_var = "cyclic#{$1}_count"
157 when /^ALM([0-9]*)$/
158 @count_var = "alarm#{$1}_count"
159 when /^OVR$/
160 @count_var = "overrun_count"
161 when /^CPUEXC([0-9]*)$/
162 @count_var = "cpuexc#{$1}_count"
163 when /^EXTSVC([0-9]*)$/
164 @count_var = "extsvc#{$1}_count"
165 else
166 @count_var = puName + "_count"
167 end
168 end
169
170 # 処理カウントの設定
171 def setCount(count)
172 @countFlag = true if count != ""
173 @currentCount = count
174 end
175
176 # 処理カウントのインクリメント
177 def incrementCount
178 if @currentCount != ""
179 @currentCount = (@currentCount.to_i + 1).to_s
180 end
181 end
182
183 # コードの追加
184 def append(*lines)
185 lines.each do |line|
186 @code[@currentCount].push(line)
187 end
188 end
189
190 # 変数の追加
191 def addVariable(varName, typeName)
192 @variableList[varName] = typeName
193 end
194
195 # SILの使用
196 def useSil
197 @silFlag = true
198 end
199
200 # 処理単位のコードの出力
201 def generateCode
202 # 不要な処理単位の判定
203 return if @code.length == 0
204
205 # 処理カウント変数の生成
206 if @countFlag
207 print("\nstatic uint_t\t#{@count_var} = 0;\n")
208 end
209
210 # 関数ヘッダの生成
211 case @puName
212 when /^TASK([0-9]*)$/
213 print("\nvoid\n")
214 print("task#{$1}(intptr_t exinf)\n")
215 when /^CYC([0-9]*)$/
216 print("\nvoid\n")
217 print("cyclic#{$1}_handler(intptr_t exinf)\n")
218 when /^ALM([0-9]*)$/
219 print("\nvoid\n")
220 print("alarm#{$1}_handler(intptr_t exinf)\n")
221 when /^OVR$/
222 print("\nvoid\n")
223 print("overrun_handler(ID tskid, intptr_t exinf)\n")
224 when /^CPUEXC([0-9]*)$/
225 print("\nvoid\n")
226 print("cpuexc#{$1}_handler(void *p_excinf)\n")
227 when /^EXTSVC([0-9]*)$/
228 print("\nER_UINT\n")
229 print("extsvc#{$1}_routine")
230 print("(intptr_t par1, intptr_t par2, intptr_t par3,\n")
231 print("\t\t\t\t\t\t\t\tintptr_t par4, intptr_t par5, ID cdmid)\n")
232 else
233 if $functionValue[@puName]
234 print("\n#{$functionValue[@puName]}\n")
235 else
236 print("\nvoid\n")
237 end
238 print(@puName)
239 if $functionParameters[@puName]
240 print("(#{$functionParameters[@puName]})\n")
241 else
242 print("(void)\n")
243 end
244 end
245
246 print("{\n")
247
248 @variableList.keys.each do |varName|
249 print("\t#{@variableList[varName]}")
250 print(@variableList[varName].length < 4 ? "\t\t" : "\t")
251 print("#{varName};\n")
252 end
253 if @silFlag
254 print("\tSIL_PRE_LOC;\n")
255 end
256 print("\n")
257
258 if @countFlag
259 print("\tswitch (++#{@count_var}) {\n")
260 @code.keys.sort_by { |c| c.to_i }.each do |count|
261 print("\tcase #{count}:\n")
262 @code[count].each do |line|
263 print("\t",line) if line != ""
264 print("\n")
265 end
266 print("\t\tcheck_point(0);\n\n")
267 end
268 print("\tdefault:\n")
269 print("\t\tcheck_point(0);\n")
270 print("\t}\n")
271 else
272 @code[""].each do |line|
273 print(line,"\n")
274 end
275 end
276
277 print("\tcheck_point(0);\n")
278 if /^EXTSVC([0-9]*)$/ =~ @puName
279 print("\treturn(E_SYS);\n")
280 elsif $functionReturn[@pu_nama]
281 print("\treturn(#{$functionReturn[@puName]});\n")
282 end
283 print("}\n")
284 end
285end
286
287#
288# サービスコール呼び出しの読み込み
289#
290def genServiceCall(pu, svc_call, error_code)
291 pu.addVariable("ercd", "ER_UINT")
292 pu.append("\tercd = #{svc_call};")
293
294 if /^([a-z_]+)\((.*)\)$/ =~ svc_call
295 svcName = $1;
296 params = $2.split(/\s*,\s*/)
297
298 if !$parameterPosition[svcName].nil? \
299 && params.size >= $parameterPosition[svcName]
300 varName = params[$parameterPosition[svcName] - 1].sub(/^\&/, "")
301 typeName = $parameterType[svcName]
302 pu.addVariable(varName, typeName)
303 end
304 end
305
306 if !error_code
307 # E_OKが返る場合
308 pu.append("\tcheck_ercd(ercd, E_OK);", "")
309 elsif error_code == "noreturn"
310 # リターンしない場合
311 pu.append("")
312 else
313 pu.append("\tcheck_ercd(ercd, #{error_code});", "")
314 end
315end
316
317#
318# テスト開始コードの生成
319#
320def testStartCode(pu)
321 # テスト開始コードは一度のみ出力する
322 if $startFlag == 0
323 pu.append("\ttest_start(__FILE__);", "")
324 $startFlag = 1
325 end
326end
327
328#
329# ターゲット依存部関数の振る舞いの読み込み
330#
331def targetFunction(line, checkNum)
332 if /^([a-zA-Z_]+)\s*(.*)$/ =~ line
333 functionName = $1
334 line = $2
335 if (pu = $puList[functionName]).nil?
336 # 新しい処理単位の生成
337 pu = $puList[functionName] = PUCode.new(functionName)
338 pu.setCount("1")
339 testStartCode(pu)
340 end
341 end
342
343 if /\-\>\s*([^\s]+)\s*(.*)$/ =~ line
344 retval = $1
345 line = $2
346 end
347 if /\<\-\s*([^\s]+)\s*(.*)$/ =~ line
348 param = $1
349 line = $2
350 end
351
352 pu.append("\tcheck_point(#{checkNum});");
353 if param && $functionCheckParameter[functionName]
354 pu.append(sprintf("\tcheck_assert(%s == %s);",
355 $functionCheckParameter[functionName], param), "")
356 end
357 if retval
358 pu.append("\treturn(#{retval});", "")
359 else
360 pu.append("\treturn;", "")
361 end
362 pu.incrementCount()
363end
364
365#
366# テストスクリプトの読み込み
367#
368def parseLine(line)
369 if /^==\s*(([a-zA-Z_]+)[0-9]*)(.*)$/ =~ line
370 # 処理単位の開始
371 $procFlag = 1
372 puName = $1
373 line2 = $3
374 if (pu = $puList[puName]).nil?
375 # 新しい処理単位の生成
376 pu = $puList[puName] = PUCode.new(puName)
377 end
378 $currentPu = pu
379
380 case line2
381 when /^\-([0-9]+)(.*)$/
382 pu.setCount($1)
383 when /^\-[nN](.*)$/
384 # do nothing.
385 else
386 pu.setCount("")
387 end
388 testStartCode(pu) if /^START/ !~ puName
389 elsif $procFlag != 0
390 pu = $currentPu
391 if /^([0-9]+\:)\s*(.*)$/ =~ line
392 # チェックポイント番号の処理
393 originalCheckNum = $1
394 line = $2
395 checkNum = ($lastCheckPoint += 1).to_s
396 $outputLine.sub!(/#{originalCheckNum}/, "#{checkNum}:")
397
398 case line
399 when /^END$/
400 pu.append("\tcheck_finish(#{checkNum});")
401 $procFlag = 0
402 return
403 when /^HOOK\((.*)\)$/
404 pu.append(sprintf("\t#{$1};", checkNum))
405 return
406 when /^\[(.*)\]$/
407 targetFunction($1, checkNum)
408 return
409 else
410 pu.append("\tcheck_point(#{checkNum});")
411 end
412 end
413
414 case line
415 when /^((assert|state|ipm)\(.*\))$/
416 pu.append("\tcheck_#{$1};", "")
417 when /^(call|DO)\((.*)\)$/
418 call_string = $2
419 pu.append("\t#{call_string};", "")
420 pu.useSil() if /^SIL_..._INT\(\)$/ =~ call_string
421 when /^RETURN((\(.*\))?)$/
422 pu.append("\treturn#{$1};", "")
423 pu.incrementCount()
424 when /^GOTO\((.*)\)$/
425 pu.append("\tgoto #{$1};", "")
426 when /^LABEL\((.*)\)$/
427 pu.append("#{$1}:", "")
428 when /^([a-z_]+\(.*\))\s*(\-\>\s*([A-Za-z0-9_]*))?\s*$/
429 genServiceCall(pu, $1, $3)
430 else
431 warn("Error: #{line}")
432 end
433 end
434end
435
436#
437# エラーチェック
438#
439if ARGV.length < 1
440 abort("Usage: ruby gentest.rb <test_program>")
441end
442
443#
444# 初期化
445#
446inFileName = ARGV.shift
447
448#
449# スクリプトファイル読み込み処理
450#
451$lastCheckPoint = 0 # 最後のチェックポイント番号
452$procFlag = 0 # スクリプト処理中フラグ
453$startFlag = 0 # テスト開始コードの出力フラグ
454$currentPu = nil # 読み込み中の処理単位
455$puList = {} # 処理単位のリスト
456
457begin
458 inFile = File.open(inFileName)
459rescue Errno::ENOENT, Errno::EACCES => ex
460 abort(ex.message)
461end
462
463while line = inFile.gets do
464 $outputLine = line.dup
465 line.chomp!
466 line.sub!(/^\s*\*\s*/, "")
467 line.sub!(/\s*\/\/.*$/, "")
468 line.sub!(/\s*\.\.\..*$/, "")
469
470 while line.sub!(/\\$/, "") do
471 line1 = inFile.gets
472 $outputLine += line1.dup
473 line1.chomp!
474 line1.sub!(/^\s*\*\s*/, "")
475 line1.sub!(/\s*\/\/.*$/, "")
476 line1.sub!(/\s*\.\.\..*$/, "")
477 line += line1
478 end
479 parseLine(line) if line != ""
480 print($outputLine)
481 break if /DO NOT DELETE THIS LINE/ =~ $outputLine
482end
483
484#
485# テストプログラム出力処理
486#
487$puList.keys.sort.each do |puName|
488 $puList[puName].generateCode()
489end
Note: See TracBrowser for help on using the repository browser.