source: asp3_tinet_ecnl_arm/trunk/asp3_dcre/utils/gentest.rb@ 352

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

arm向けASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby;charset=UTF-8
File size: 13.0 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 /^ISR([0-9]*)$/
127 @count_var = "isr#{$1}_count"
128 when /^INTHDR([0-9]*)$/
129 @count_var = "inthdr#{$1}_count"
130 when /^CPUEXC([0-9]*)$/
131 @count_var = "cpuexc#{$1}_count"
132 when /^EXTSVC([0-9]*)$/
133 @count_var = "extsvc#{$1}_count"
134 else
135 @count_var = puName + "_count"
136 end
137 end
138
139 # 処理カウントの設定
140 def setCount(count)
141 @countFlag = true if count != ""
142 @currentCount = count
143 end
144
145 # 処理カウントのインクリメント
146 def incrementCount
147 if @currentCount != ""
148 @currentCount = (@currentCount.to_i + 1).to_s
149 end
150 end
151
152 # コードの追加
153 def append(*lines)
154 lines.each do |line|
155 @code[@currentCount].push(line)
156 end
157 end
158
159 # 変数の追加
160 def addVariable(varName, typeName)
161 @variableList[varName] = typeName
162 end
163
164 # SILの使用
165 def useSil
166 @silFlag = true
167 end
168
169 # 処理単位のコードの出力
170 def generateCode
171 # 不要な処理単位の判定
172 return if @code.length == 0
173
174 # 処理カウント変数の生成
175 if @countFlag
176 print("\nstatic uint_t\t#{@count_var} = 0;\n")
177 end
178
179 # 関数ヘッダの生成
180 case @puName
181 when /^TASK([0-9]*)$/
182 print("\nvoid\n")
183 print("task#{$1}(intptr_t exinf)\n")
184 when /^CYC([0-9]*)$/
185 print("\nvoid\n")
186 print("cyclic#{$1}_handler(intptr_t exinf)\n")
187 when /^ALM([0-9]*)$/
188 print("\nvoid\n")
189 print("alarm#{$1}_handler(intptr_t exinf)\n")
190 when /^OVR$/
191 print("\nvoid\n")
192 print("overrun_handler(ID tskid, intptr_t exinf)\n")
193 when /^ISR([0-9]*)$/
194 print("\nvoid\n")
195 print("isr#{$1}(intptr_t exinf)\n")
196 when /^INTHDR([0-9]*)$/
197 print("\nvoid\n")
198 print("inthdr#{$1}_handler(void)\n")
199 when /^CPUEXC([0-9]*)$/
200 print("\nvoid\n")
201 print("cpuexc#{$1}_handler(void *p_excinf)\n")
202 when /^EXTSVC([0-9]*)$/
203 print("\nER_UINT\n")
204 print("extsvc#{$1}_routine")
205 print("(intptr_t par1, intptr_t par2, intptr_t par3,\n")
206 print("\t\t\t\t\t\t\t\tintptr_t par4, intptr_t par5, ID cdmid)\n")
207 else
208 if $functionValue[@puName]
209 print("\n#{$functionValue[@puName]}\n")
210 else
211 print("\nvoid\n")
212 end
213 print(@puName)
214 if $functionParameters[@puName]
215 print("(#{$functionParameters[@puName]})\n")
216 else
217 print("(void)\n")
218 end
219 end
220
221 print("{\n")
222
223 @variableList.each do |varName, varType|
224 if /^(.+)\w*\*$/ =~ varType
225 varBaseType = $1
226 print("\t#{varBaseType}")
227 print(varBaseType.length < 4 ? "\t\t*" : "\t*")
228 else
229 print("\t#{varType}")
230 print(varType.length < 4 ? "\t\t" : "\t")
231 end
232 print("#{varName};\n")
233 end
234 if @silFlag
235 print("\tSIL_PRE_LOC;\n")
236 end
237 print("\n")
238
239 if @countFlag
240 print("\tswitch (++#{@count_var}) {\n")
241 @code.keys.sort_by { |c| c.to_i }.each do |count|
242 print("\tcase #{count}:\n")
243 @code[count].each do |line|
244 print("\t",line) if line != ""
245 print("\n")
246 end
247 print("\t\tcheck_point(0);\n\n")
248 end
249 print("\tdefault:\n")
250 print("\t\tcheck_point(0);\n")
251 print("\t}\n")
252 else
253 @code[""].each do |line|
254 print(line,"\n")
255 end
256 end
257
258 print("\tcheck_point(0);\n")
259 if /^EXTSVC([0-9]*)$/ =~ @puName
260 print("\treturn(E_SYS);\n")
261 elsif $functionReturn[@pu_nama]
262 print("\treturn(#{$functionReturn[@puName]});\n")
263 end
264 print("}\n")
265 end
266end
267
268#
269# サービスコール呼び出しの読み込み
270#
271def genServiceCall(pu, svc_call, error_code)
272 pu.addVariable("ercd", "ER_UINT")
273 pu.append("\tercd = #{svc_call};")
274
275 if /^([a-z_]+)\((.*)\)$/ =~ svc_call
276 svcName = $1;
277 params = $2.split(/\s*,\s*/)
278
279 if $parameterDefinition.has_key?(svcName)
280 $parameterDefinition[svcName].each do |pos, type|
281 if params.size >= pos
282 varName = params[pos - 1].sub(/^\&/, "")
283 pu.addVariable(varName, type)
284 end
285 end
286 end
287 end
288
289 if !error_code
290 # E_OKが返る場合
291 pu.append("\tcheck_ercd(ercd, E_OK);", "")
292 elsif error_code == "noreturn"
293 # リターンしない場合
294 pu.append("")
295 else
296 pu.append("\tcheck_ercd(ercd, #{error_code});", "")
297 end
298end
299
300#
301# テスト開始コードの生成
302#
303def testStartCode(pu)
304 # テスト開始コードは一度のみ出力する
305 if $startFlag == 0
306 pu.append("\ttest_start(__FILE__);", "")
307 $startFlag = 1
308 end
309end
310
311#
312# ターゲット依存部関数の振る舞いの読み込み
313#
314def targetFunction(line, checkNum)
315 if /^([a-zA-Z_]+)\s*(.*)$/ =~ line
316 functionName = $1
317 line = $2
318 if (pu = $puList[functionName]).nil?
319 # 新しい処理単位の生成
320 pu = $puList[functionName] = PUCode.new(functionName)
321 pu.setCount("1")
322 testStartCode(pu)
323 end
324 end
325
326 if /\-\>\s*([^\s]+)\s*(.*)$/ =~ line
327 retval = $1
328 line = $2
329 end
330 if /\<\-\s*([^\s]+)\s*(.*)$/ =~ line
331 param = $1
332 line = $2
333 end
334
335 pu.append("\tcheck_point(#{checkNum});");
336 if param && $functionCheckParameter[functionName]
337 pu.append(sprintf("\tcheck_assert(%s == %s);",
338 $functionCheckParameter[functionName], param), "")
339 end
340 if retval
341 pu.append("\treturn(#{retval});", "")
342 else
343 pu.append("\treturn;", "")
344 end
345 pu.incrementCount()
346end
347
348#
349# テストスクリプトの読み込み
350#
351def parseLine(line)
352 if /^==\s*(([a-zA-Z_]+)[0-9]*)(.*)$/ =~ line
353 # 処理単位の開始
354 $procFlag = 1
355 puName = $1
356 line2 = $3
357 if (pu = $puList[puName]).nil?
358 # 新しい処理単位の生成
359 pu = $puList[puName] = PUCode.new(puName)
360 end
361 $currentPu = pu
362
363 case line2
364 when /^\-([0-9]+)(.*)$/
365 pu.setCount($1)
366 when /^\-[nN](.*)$/
367 # do nothing.
368 else
369 pu.setCount("")
370 end
371 testStartCode(pu) if /^START/ !~ puName
372 elsif $procFlag != 0
373 pu = $currentPu
374 if /^([0-9]+\:)\s*(.*)$/ =~ line
375 # チェックポイント番号の処理
376 originalCheckNum = $1
377 line = $2
378 checkNum = ($lastCheckPoint += 1).to_s
379 $outputLine.sub!(/#{originalCheckNum}/, "#{checkNum}:")
380
381 case line
382 when /^END$/
383 pu.append("\tcheck_finish(#{checkNum});")
384 $procFlag = 0
385 return
386 when /^HOOK\((.*)\)$/
387 pu.append(sprintf("\t#{$1};", checkNum))
388 return
389 when /^\[(.*)\]$/
390 targetFunction($1, checkNum)
391 return
392 else
393 pu.append("\tcheck_point(#{checkNum});")
394 end
395 end
396
397 case line
398 when /^((assert|state|ipm)\(.*\))$/
399 pu.append("\tcheck_#{$1};", "")
400 when /^(call|DO)\((.*)\)$/
401 call_string = $2
402 pu.append("\t#{call_string};", "")
403 pu.useSil() if /^SIL_..._INT\(\)$/ =~ call_string
404 when /^RETURN((\(.*\))?)$/
405 pu.append("\treturn#{$1};", "")
406 pu.incrementCount()
407 when /^GOTO\((.*)\)$/
408 pu.append("\tgoto #{$1};", "")
409 when /^LABEL\((.*)\)$/
410 pu.append("#{$1}:", "")
411 when /^([a-z_]+\(.*\))\s*(\-\>\s*([A-Za-z0-9_]*))?\s*$/
412 genServiceCall(pu, $1, $3)
413 else
414 warn("Error: #{line}")
415 end
416 end
417end
418
419#
420# エラーチェック
421#
422if ARGV.length < 1
423 abort("Usage: ruby gentest.rb <test_program>")
424end
425
426#
427# 初期化
428#
429inFileName = ARGV.shift
430
431#
432# スクリプトファイル読み込み処理
433#
434$lastCheckPoint = 0 # 最後のチェックポイント番号
435$procFlag = 0 # スクリプト処理中フラグ
436$startFlag = 0 # テスト開始コードの出力フラグ
437$currentPu = nil # 読み込み中の処理単位
438$puList = {} # 処理単位のリスト
439
440begin
441 inFile = File.open(inFileName)
442rescue Errno::ENOENT, Errno::EACCES => ex
443 abort(ex.message)
444end
445
446while line = inFile.gets do
447 $outputLine = line.dup
448 line.chomp!
449 line.sub!(/^\s*\*\s*/, "")
450 line.sub!(/\s*\/\/.*$/, "")
451 line.sub!(/\s*\.\.\..*$/, "")
452
453 while line.sub!(/\\$/, "") do
454 line1 = inFile.gets
455 $outputLine += line1.dup
456 line1.chomp!
457 line1.sub!(/^\s*\*\s*/, "")
458 line1.sub!(/\s*\/\/.*$/, "")
459 line1.sub!(/\s*\.\.\..*$/, "")
460 line += line1
461 end
462 parseLine(line) if line != ""
463 print($outputLine)
464 break if /DO NOT DELETE THIS LINE/ =~ $outputLine
465end
466
467#
468# テストプログラム出力処理
469#
470$puList.keys.sort.each do |puName|
471 $puList[puName].generateCode()
472end
Note: See TracBrowser for help on using the repository browser.