source: EcnlProtoTool/trunk/asp3_dcre/utils/gentest.rb@ 321

Last change on this file since 321 was 321, checked in by coas-nagasima, 7 years ago

文字コードを設定

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