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

Last change on this file since 439 was 429, checked in by coas-nagasima, 4 years ago

ASP3, TINET, mbed を更新

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