Project

General

Profile

C++TESK Quick Reference » History » Version 7

Alexander Kamkin, 05/22/2014 10:37 AM

1 1 Mikhail Chupilko
h1. C++TESK Quick Reference
2
3 4 Alexander Kamkin
{{toc}}
4
5 1 Mikhail Chupilko
h2. Introduction
6
7
This document is a quick reference of C++TESK Hardware Extension tool (С++TESK, hereafter) included into C++TESK Testing ToolKit and aimed to automated development of test systems for HDL-models (HDL (Hardware Description Language) — class of program languages used for description of hardware) of hardware. The tool architecture bases on general UniTESK (http://www.unitesk.ru) conventions.
8
9
_Test system_ is meant to be a special program which evaluates the functional correctness of _target system_, applying some input data (_stimuli_) and analyzing received results of their application (_reactions_). Typical test system consists of three common components: (1) _stimulus generator_ making sequences of stimuli (_test sequences_), (2) _test oracle_ checking correctness of reactions, and (3) _test completeness evaluator_.
10
11
The document describes facilities of C++TESK aimed to development of mentioned test system components, and consists of four common chapters.
12
* Development of reference model
13
* Development of reference model adapter
14
* Description of test coverage
15
* Development of test scenario
16
17
First two chapters touch upon development of test oracle basic parts: _reference model_ covering functionality of target system, and _reference model adapter_ binding reference model with target system. The third chapter is devoted to the test completeness estimation on the base of _test coverage_. The last chapter concerns development of test scenario which is the main part of stimulus generator.
18
19
More detailed toolkit review is given in _«C++TESK Testing ToolKit: User Guide»_.
20
21
Installation process of C++TESK is described in _«С++TESK Testing ToolKit: Installation Guide»_.
22
23
h2. Supporting obsolete constructions
24
25
Updates of C++TESK do not interfere in the compilation and running of test systems developed for older versions of C++TESK. When the toolkit has incompatible with older versions update, this update is marked by a build number in form of yymmdd, i.e. 110415 – the 15th of April, 2011. The update is available only if macro CPPTESKHW_VERSION (using gcc compiler it can be done by the option –Dmacro_name=value) is appropriately defined. E.g.,
26
-DCPPTESKHW_VERSION=110415 enables usage of incompatible updated having been made by the 15th of April, 2011 (including this date). Each build of the toolkit has the whole list of such changes.
27
28
Obsolete constructions of the toolkit are not described in this document. Possibilities of the toolkit, being incompatible with having become obsolete constructions, are presented with the build number, since which they have been available. E.g., the sentence “the means are supported from 110415 build” means that usage of these means requires two conditions: (1) using toolkit build has the number 110415 or greater, (2) the compilation option -DCPPTESKHW_VERSION=number, where number is not less than 110415, is used.
29
30
If some obsolete constructions are not used or prevent the toolkit from further development, they might become unsupported. In this case, during compilation of test system using these constructions, a message with advices about correction of test system will be shown.
31
32
During compilation of test systems, developed by means of C++TESK, usage of the compiler option -DCPPTESKHW_VERSION=number is highly recommended.
33
34
h2. Naming convention
35
36
The core of the toolkit is developed as a C++ library. Available means are grouped into the following namespaces.
37
38
* cpptesk::hw — means for development of reference models and their adapters;
39
* cpptesk::ts — basic means for test system development;
40
* cpptesk::ts::coverage — means for test coverage description;
41 3 Mikhail Chupilko
* сpptesk::ts::engine  — library with _test engines_ (test engines are toolkit library components used for producing of stimulus sequence, use _test scenario_ (see chapter _“Development of test scenario”_));
42 1 Mikhail Chupilko
* cpptesk::tracer — means for tracing;
43
* cpptesk::tracer::coverage — means for coverage tracing.
44
45
A lot of C++TESK means are implemented in form of macros. To avoid conflicts of names, names of all macros start with prefix CPPTESK_, e.g., CPPTESK_MODEL(name). Generally, each macro has two aliases: shortened name (without CPPTESK_ prefix) and short name, (after additional “compression” of shortened name). E.g., macro CPPTESK_ITERATION_BEGIN has two aliases: ITERATION_BEGIN and IBEGIN. To use shortened and short names, macros CPPTESK_SHORT_NAMES and CPPTESK_SHORT_SHORT_NAMES should be defined, respectively.
46
47
h2. Development of reference model
48
49 3 Mikhail Chupilko
Reference model is a structured set of classes describing functionality of target system at some abstraction level (the toolkit allows developing of both abstract functional models and detailed models describing target system cycle-accurately). Reference model consists of message classes describing format of input and output data (structures of stimuli and reactions), main class and set of auxiliary classes. Hereafter, a main class of reference model will be meant under term reference model.
50 1 Mikhail Chupilko
51
h3. Class of message
52
53
Message classes are declared by macro @CPPTESK_MESSAGE(name)@. Row with macro @CPPTESK_SUPPORT_CLONE(name)@ defining the message clone method @name* clone()@ should be written inside of the each message class declaration.
54
55
Example:
56
<pre><code class="cpp">
57
#include <hw/message.hpp>
58
CPPTESK_MESSAGE(MyMessage) {
59
public:
60
    CPPTESK_SUPPORT_CLONE(MyMessage)
61
    ...
62
};
63
</code></pre>
64
*Notice*: Row @CPPTESK_SUPPORT_CLONE(name)@ is obligatory.
65
66 2 Mikhail Chupilko
h4. Input message randomizer
67 1 Mikhail Chupilko
68
Virtual method @randomize()@ (randomizer of the message) should be overloaded in each input message class. There are two macros @CPPTESK_{DECLARE|DEFINE}_RANDOMIZER@ for this purpose.
69
70
Example:
71
<pre><code class="cpp">
72
CPPTESK_MESSAGE(MyMessage) {
73
    ...
74
    CPPTESK_DECLARE_RANDOMIZER();
75
private:
76
    int data;
77
};
78
79
CPPTESK_DEFINE_RANDOMIZER(MyMessage) {
80
    data = CPPTESK_RANDOM(int);
81
}
82
</code></pre>
83
84
The following macros can be used for randomization of data fields.
85
* @CPPTESK_RANDOM(type)@ — generation of random integer value;
86
* @CPPTESK_RANDOM_WIDTH(type, length)@ — generation of random integer value of given number of bits;
87
* @CPPTESK_RANDOM_FIELD(type, min_bit, max_bit)@ — generation of random integer value with zero bits outside the given range;
88
* @CPPTESK_RANDOM_RANGE(type, min_value, max_value)@ — generation of random integer value from given integer range;
89
* @CPPTESK_RANDOM_CHOICE(type, value_1, ..., value_n)@ — random choice from given set of any type values.
90
91
*Notice*: randomizer may not be defined if all data fields are defined by special macros (see chapter _“Message data fields”_).
92
93 2 Mikhail Chupilko
h4. Comparator of output messages
94 1 Mikhail Chupilko
95
Virtual method @compare()@ (comparator of messages) should  be overloaded in each output message class. There are two macro @CPPTESK_{DECLARE|DEFINE}_COMPARATOR@ for this purpose (build is not less than 110428).
96
97
Example:
98
<pre><code class="cpp">
99
CPPTESK_MESSAGE(MyMessage) {
100
    ...
101
    CPPTESK_DECLARE_COMPARATOR();
102
private:
103
    int data;
104
};
105
106
CPPTESK_DEFINE_COMPARATOR(MyMessage) {
107
    const MyMessage &rhs = CPPTESK_CONST_CAST_MESSAGE(MyMessage);
108
    // in case of difference between messages return not empty string
109
    if(data != rhs.data)
110
        { return "incorrect data"; }
111
    // empty string is interpreted as absence of difference
112
    return COMPARE_OK;
113
}
114
</code></pre>
115
116
*Notice*: comparator may not be defined if all data fields are defined by special macros (see chapter “Message data fields”).
117
118 2 Mikhail Chupilko
h4. Message data fields
119 1 Mikhail Chupilko
120 6 Alexander Kamkin
The following macros are aimed at declaring integer data fields.
121
* @CPPTESK_DECLARE_FIELD(name, length)@ declares an integer field with given name and length.
122
* @CPPTESK_DECLARE_TYPED_FIELD(type, name, length)@ declares a typed field with given name and length.
123
* @CPPTESK_DECLARE_MASKED_FIELD(name, length, mask)@ declares an integer field with given name, length, and mask.
124
* @CPPTESK_DECLARE_BIT(name)@ declares a single-bit field with a given name.
125 1 Mikhail Chupilko
126
Example:
127
<pre><code class="cpp">
128 6 Alexander Kamkin
#include <iostream>
129 1 Mikhail Chupilko
#include <hw/message.hpp>
130 6 Alexander Kamkin
131 7 Alexander Kamkin
enum Cop { READ, WRITE };
132 1 Mikhail Chupilko
133
std::ostream& operator << (std::ostream &out, Cop cop) {
134 6 Alexander Kamkin
    switch(cop) {
135 7 Alexander Kamkin
        case READ:  return out << "read";
136
        case WRITE: return out << "write";
137
        default:    return out << "reserved";
138 6 Alexander Kamkin
    }
139
}
140
141 1 Mikhail Chupilko
CPPTESK_MESSAGE(MyMessage) {
142
public:
143
    CPPTESK_DECLARE_TYPED_FIELD(Cop, cop, 2);
144
    CPPTESK_DECLARE_MASKED_FIELD(addr, 32, 0xffffFFF0);
145
    CPPTESK_DECLARE_FIELD(data, 32);
146 6 Alexander Kamkin
    CPPTESK_DECLARE_BIT(flag);
147 1 Mikhail Chupilko
    ...
148
};
149
</code></pre>
150
151 7 Alexander Kamkin
*Notice*: length of the data fields should not exceed 64 bits (the basic type is @uint64_t@).
152
153
*Notice*: types of the typed fields should be compatible with @uint64_t@.
154 1 Mikhail Chupilko
155
All declared data fields should be registered in message class constructor by means of macro @CPPTESK_ADD_FIELD(full_name)@ or, when the data field should not be taken into account by comparator, by means of @CPPTESK_ADD_INCOMPARABLE_FIELD(full_name)@.
156
157
Example:
158
<pre><code class="cpp">
159
MyMessage::MyMessage() {
160 6 Alexander Kamkin
    CPPTESK_ADD_FIELD(MyMessage::cop);
161 1 Mikhail Chupilko
    CPPTESK_ADD_FIELD(MyMessage::addr);
162
    CPPTESK_ADD_FIELD(MyMessage::data);
163
    CPPTESK_ADD_INCOMPARABLE_FIELD(MyMessage::flag);
164
    ...
165
}
166
</code></pre>
167
168
*Notice*: full_name means usage both name of method and name of class.
169
170 2 Mikhail Chupilko
h4. Optional messages
171 1 Mikhail Chupilko
172
Output message can be declared to be optional (not obligatory for receiving) if the following method is used.
173
<pre><code class="cpp">void setOptional(optional_or_not_optional);</code></pre>
174
*Notice*: Default value of the parameter “optional_or_not_optional” is true, i.e. if there has not been correspondent implementation output message by a certain timeout, the message will be simply deleted without showing of an error. At the same time, the optional message is added to the interface arbiter and might affect to the matching of other output messages. If correspondent implementation reactions are received after the timeout and they are to be ignored, the flag of the message being optional should be set in message class constructor.
175
176
h2. Reference model
177
178 2 Mikhail Chupilko
Reference model (main class of the reference model) is declared by macro @CPPTESK_MODEL(name)@.
179
180 1 Mikhail Chupilko
Example:
181 2 Mikhail Chupilko
<pre><code class="cpp">
182 1 Mikhail Chupilko
#include <hw/model.hpp>
183
CPPTESK_MODEL(MyModel) {
184
    ...
185
};
186 2 Mikhail Chupilko
</code></pre>
187
188 1 Mikhail Chupilko
Reference model contains declaration of input and output interfaces, operations, auxiliary processes, and data necessary for operation description.
189 2 Mikhail Chupilko
190
h3. Interface
191
192
Input and output interfaces of the reference model are declared by means of two macros @CPPTESK_DECLARE_{INPUT|OUTPUT}(name)@, respectively.
193
194 1 Mikhail Chupilko
Example:
195 2 Mikhail Chupilko
<pre><code class="cpp">
196 1 Mikhail Chupilko
#include <hw/model.hpp>
197
CPPTESK_MODEL(MyModel) {
198
public:
199
    CPPTESK_DECLARE_INPUT(input_iface);
200
    CPPTESK_DECLARE_OUTPUT(output_iface);
201
    ...
202
};
203 2 Mikhail Chupilko
</code></pre>
204
205
All declared interfaces should be registered in reference model constructor by means of two macros @CPPTESK_ADD_{INPUT|OUTPUT}(name)@.
206
207 1 Mikhail Chupilko
Example:
208 2 Mikhail Chupilko
<pre><code>
209 1 Mikhail Chupilko
MyModel::MyModel() {
210
    CPPTESK_ADD_INPUT(input_iface);
211
    CPPTESK_ADD_OUTPUT(output_iface);
212
    ...
213
}
214 2 Mikhail Chupilko
</code></pre>
215
216
h3. Setting up ignoring of failures on output interface
217
218 1 Mikhail Chupilko
To disable showing errors of a certain type on a given interface is possible by means of the method:
219 2 Mikhail Chupilko
<pre><code class="cpp">
220 1 Mikhail Chupilko
void setFailureIgnoreTypes(disabling_error_types_mask);
221 2 Mikhail Chupilko
</code></pre>
222
223
Disabling error types include errors of implementation reaction absence (@MISSING_REACTION@) and specification reaction absence (@UNEXPECTED_REACTION@) on the given interface. Error types can be grouped by bit operation “or”.
224
225
h3. Process
226
227
Processes are the main means of functional specification of hardware. Processes are subdivided into operations (see chapter _“Operation”_) and internal processes. Operations describe processing of stimuli of a certain types by the target system. Internal processes are used for definition of the other, more complex processes, including operations.
228
229
Declaration and definition of reference model processes are made by means of macros @CPPTESK_{DECLARE|DEFINE}_PROCESS(name)@. Definition of the process should be started by calling macro @CPPTESK_START_PROCESS()@, and finished by calling macro @CPPTESK_STOP_PROCESS()@.
230
231 1 Mikhail Chupilko
Example:
232 2 Mikhail Chupilko
<pre><code class="cpp">
233 1 Mikhail Chupilko
#include <hw/model.hpp>
234
CPPTESK_MODEL(MyModel) {
235
public:
236
    ...
237
    CPPTESK_DECLARE_PROCESS(internal_process);
238
    ...
239
};
240
241
CPPTESK_DEFINE_PROCESS(MyModel::internal_process) {
242
    CPPTESK_START_PROCESS();
243
    ...
244
    CPPTESK_STOP_PROCESS();
245
}
246 2 Mikhail Chupilko
</code></pre>
247
248
*Notice*: macro @CPPTESK_START_PROCESS()@ may be used only once in definition of the process, and usually precedes the main process code. Semantics of @CPPTESK_STOP_PROCESS()@ is similar to the semantics of operator return — when the macro is called, the process finished.
249
250
*Notice*: keyword process is reserved and cannot be used for naming of processes.
251
252
h3. Process parameters
253
254 1 Mikhail Chupilko
Process should have three obligatory parameters: (1) process execution context, (2) associated with process interface, and (3) message. To access process parameters is possible by means of the following macros.
255 2 Mikhail Chupilko
* @CPPTESK_GET_PROCESS()@ — get process context;
256
* @CPPTESK_GET_IFACE()@ — get process interface;
257
* @CPPTESK_GET_MESSAGE()@ — get message.
258
259 1 Mikhail Chupilko
To cast message parameter to the necessary type is possible by means of the following macros.
260 2 Mikhail Chupilko
* @CPPTESK_CAST_MESSAGE(message_class)@;
261
* @CPPTESK_CONST_CAST_MESSAGE(message_class)@.
262
263 1 Mikhail Chupilko
Example:
264 2 Mikhail Chupilko
<pre><code class="cpp">
265 1 Mikhail Chupilko
#include <hw/model.hpp>
266
CPPTESK_DEFINE_PROCESS(MyModel::internal_process) {
267
    // copy message to the local variable
268
    MyMessage msg = CPPTESK_CAST_MESSAGE(MyMessage);
269
    // get reference to the message
270
    MyMessage &msg_ref = CPPTESK_CAST_MESSAGE(MyMessage);
271
    // get constant reference to the message
272
    const MyMessage &const_msg_ref = CPPTESK_CONST_CAST_MESSAGE(MyMessage);
273
    ...
274
}
275 2 Mikhail Chupilko
</code></pre>
276
277
h3. Process priority
278
279
During execution, each process is assigned with a priority, unsigned integer value from range @[1, 255]@ (0 is reserved). Priority affects the order of process execution inside of one cycle (processes with higher priority run first). Priorities may be used in matching of implementation and specification reactions (see chapter _“Reaction arbiter”_). When started, all processes are assigned with the same priority (@NORMAL_PRIORITY@). To change the priority is possible by means of the following macros.
280
* @CPPTESK_GET_PRIORITY()@ — get process priority.
281
* @CPPTESK_SET_PRIORITY(priority)@ — set process priority.
282
283
Some priority values are defined in the enumeration type @priority_t (cpptesk::hw namespace)@. The most general of them are the following ones.
284
* @NORMAL_PRIORITY@ — normal priority;
285
* @LOWEST_PRIORITY@ — the lowest priority;
286
* @HIGHEST_PRIORITY@ — the highest priority.
287
288 1 Mikhail Chupilko
Example:
289 2 Mikhail Chupilko
<pre><code class="cpp">
290 1 Mikhail Chupilko
#include <hw/model.hpp>
291
#include <iostream>
292
CPPTESK_DEFINE_PROCESS(MyModel::internal_process) {
293
    ...
294
    std::cout << "process priority is " << std::dec
295
              << CPPTESK_GET_PRIORITY() << std::end;
296
    ...
297
    CPPTESK_SET_PRIORITY(cpptesk::hw::HIGHEST_PRIORITY);
298
    ...
299
}
300 2 Mikhail Chupilko
</code></pre>
301
302
h3. Modeling of delays
303
304 1 Mikhail Chupilko
To model delays in processes is possible by means of the following macros.
305 2 Mikhail Chupilko
* @CPPTESK_CYCLE()@ - delay of one cycle.
306
* @CPPTESK_DELAY(number_of_cycles)@ - delay of several cycles.
307
* @CPPTESK_WAIT(condition)@ - delay till condition is satisfied.
308
* @CPPTESK_WAIT_TIMEOUT(condition, timeout)@ - limited in time delay till condition is satisfied.
309
310 1 Mikhail Chupilko
Example:
311 2 Mikhail Chupilko
<pre><code class="cpp">
312 1 Mikhail Chupilko
#include <hw/model.hpp>
313
#include <iostream>
314
CPPTESK_DEFINE_PROCESS(MyModel::internal_process) {
315
    ...
316
    std::cout << "cycle: " << std::dec << time() << std::end;
317
    // delay of one cycle
318
    CPPTESK_CYCLE();
319
    std::cout << "cycle: " << std::dec << time() << std::end;
320
    ...
321
    // wait till outputs.ready is true,
322
    // but not more than 100 cycles
323
    CPPTESK_WAIT_TIMEOUT(outputs.ready, 100);
324
    ...
325
}
326 2 Mikhail Chupilko
</code></pre>
327
328
h3. Process calling
329
330
Reference model process calling from another process is made by means of macro @CPPTESK_CALL_PROCESS(mode, process_name, interface, message)@, where mode might be either @PARALLEL@ or @SEQUENTIAL@. In the first case separated process is created, which is executed in parallel with the parent process. In the second case consequent execution is performed, where returning to the parent process execution is possible only after child process has been finished.
331
332 1 Mikhail Chupilko
Example:
333 2 Mikhail Chupilko
<pre><code class="cpp">
334 1 Mikhail Chupilko
#include <hw/model.hpp>
335
CPPTESK_DEFINE_PROCESS(MyModel::some_process) {
336
    ...
337
    // call separated process
338
    CPPTESK_CALL_PROCESS(PARALLEL, internal_process,
339
        CPPTESK_GET_IFACE(), CPPTESK_GET_MESSAGE());
340
    ...
341
    // call process and wait till it has been finished
342
    CPPTESK_CALL_PROCESS(SEQUENTIAL, internal_process,
343
        CPPTESK_GET_IFACE(), CPPTESK_GET_MESSAGE());
344
    ...
345
}
346 2 Mikhail Chupilko
</code></pre>
347
348
*Notice*: to call new processes is possible from any reference model methods, not only from methods describing processes. Macro @CPPTESK_CALL_PARALLEL(process_name, interface, message)@ should be used in this case. Calling process with mode @SEQUENTIAL@ from the method not being a process is prohibited.
349
350
h3. Stimulus receiving
351
352
Inside of the process, receiving of stimulus on one of the input interfaces can be modeled. It is possible by means of macro @CPPTESK_RECV_STIMULUS(mode, interface, message)@. Executing this macro, test system applies the stimulus to the target system via adapter of the correspondent input interface (see chapter _«Input interface adapter»_). Semantics of the mode parameter is described in the chapter _«Process calling»_.
353
354 1 Mikhail Chupilko
Example:
355 2 Mikhail Chupilko
<pre><code class="cpp">
356 1 Mikhail Chupilko
#include <hw/model.hpp>
357
CPPTESK_DEFINE_PROCESS(MyModel::some_process) {
358
    // modeling of stimulus receiving
359
    CPPTESK_RECV_STIMULUS(PARALLEL, input_iface, input_msg);
360
    ...
361
}
362 2 Mikhail Chupilko
</code></pre>
363
364
h3. Reaction sending
365
366
Modeling of reaction sending is done by the macro @CPPTESK_SEND_REACTION(mode, interface, message)@. Executing this macro, test system calls adapter of the correspondent output interface. The adapter starts waiting for the proper implementation reaction. When being received, the reaction is transformed into object of the correspondent message class (see chapter _“Adapter of the output interface”_). Then test system compares reference message with received message by means of comparator (see chapter _“Comparator of output messages”_). Semantics of the mode parameter is described in the chapter _“Process calling”_.
367
368 1 Mikhail Chupilko
Example:
369 2 Mikhail Chupilko
<pre><code class="cpp">
370 1 Mikhail Chupilko
#include <hw/model.hpp>
371
CPPTESK_DEFINE_PROCESS(MyModel::some_process) {
372
    // modeling of reaction sending
373
    CPPTESK_SEND_REACTION(SEQUENTIAL, output_iface, output_msg);
374
    ...
375
}
376 2 Mikhail Chupilko
</code></pre>
377
378
h3. Operation
379
380
Declaration and definition of interface operations of reference model is made by means of macros @CPPTESK_{DECLARE|DEFINE}_STIMULUS(name)@. The definition should start from macro @CPPTESK_START_STIMULUS(mode)@, and stop by macro @CPPTESK_STOP_STIMULUS()@.
381
382 1 Mikhail Chupilko
Example:
383 2 Mikhail Chupilko
<pre><code class="cpp">
384 1 Mikhail Chupilko
#include <hw/model.hpp>
385
CPPTESK_MODEL(MyModel) {
386
public:
387
    CPPTESK_DECLARE_STIMULUS(operation);
388
    ...
389
};
390
391
CPPTESK_DEFINE_STIMULUS(MyModel::operation) {
392
    CPPTESK_START_STIMULUS(PARALLEL);
393
    ...
394
    CPPTESK_STOP_STIMULUS();
395
}
396 2 Mikhail Chupilko
</code></pre>
397
398
*Notice*: operations are particular cases of processes, so that all the constructions from chapter _“Process”_ can be used in them.
399
400
*Notice*: calling macro @CPPTESK_START_STIMULUS(mode)@ is equivalent to the calling macro @CPPTESK_RECV_STIMULUS(mode, ...)@, where interface and message parameters are assigned with correspondent operation parameters.
401
402
h3. Callback function
403
404
In the main class of reference model, several callback functions are defined. The functions can be overloaded in the reference model. The main callback function is @onEveryCycle()@.
405
406
h4. Function onEveryCycle
407
408
Function @onEveryCycle()@ is called at the beginning of each reference model execution cycle.
409
410 1 Mikhail Chupilko
Example:
411 2 Mikhail Chupilko
<pre><code class="cpp">
412 1 Mikhail Chupilko
#include <hw/model.hpp>
413
CPPTESK_MODEL(MyModel) {
414
public:
415
    virtual void onEveryCycle();
416
    ...
417
};
418
419
void MyModel::onEveryCycle() {
420
    std::cout << "onEveryCycle: time=" << std::dec << time() << std::endl;
421
}
422 2 Mikhail Chupilko
</code></pre>
423
424
h2. Development of reference model adapter
425
426
_Reference model adapter_ (_mediator_) is a component of test system, binding reference model with target system. The adapter _serializes_ input message objects into sequences of input signal values, _deserializes_ sequences of output signal values into output message objects, and matches received from target system reactions with reference values.
427
428
h3. Reference model adapter
429
430
Reference model adapter is a subclass of reference model class. It is declared by means of the macro @CPPTESK_ADAPTER(adapter_name, model_name)@.
431
432 1 Mikhail Chupilko
Example:
433 2 Mikhail Chupilko
<pre><code class="cpp">
434 1 Mikhail Chupilko
#include <hw/media.hpp>
435
CPPTESK_ADAPTER(MyAdapter, MyModel) {
436
    ...
437
};
438 2 Mikhail Chupilko
</code></pre>
439
440
_Synchronization methods_, _input_ and _output interface adapters_, _output interface listeners_, and _reaction arbiters_ are declared in reference model adapter.
441
442
h4. Synchronizer
443
444 1 Mikhail Chupilko
Synchronizer is a low-level part of reference model adapter, responsible for synchronization of test system with being tested HDL-model. Synchronizer is implemented by overloading the following five methods of reference model adapter.
445 2 Mikhail Chupilko
* @void initialize()@ — test system initialization;
446
* @void finialize()@ — test system finalization;
447
* @void setInputs()@ — synchronization of inputs;
448
* @void getOutputs()@ — synchronization of outputs;
449
* @void simulate()@ — synchronization of time.
450
451 3 Mikhail Chupilko
When hardware models written in Verilog being verified, these methods can be implemented by standard interface VPI (Verilog Procedural Interface). Also, tool VeriTool (http://forge.ispras.ru/projects/veritool) can be used for automation of synchronizer development. In this case, macro @CPPTESK_VERITOOL_ADAPTER(adapter_name, model_name)@ can be used for facilitating of the efforts.
452 2 Mikhail Chupilko
453 1 Mikhail Chupilko
Example:
454 2 Mikhail Chupilko
<pre><code class="cpp">
455 1 Mikhail Chupilko
#include <hw/veritool/media.hpp>
456
// file generated by tool VeriTool
457
#include <interface.h>
458
CPPTESK_VERITOOL_ADAPTER(MyAdapter, MyModel) {
459
    ...
460
};
461
</code></pre>
462
463
Used for definition of synchronization methods functions and data structures (fields inputs and outputs) are generated automatically by tool VeriTool analyzing Verilog hardware model interface.
464 3 Mikhail Chupilko
465
*Notice*: when macro @CPPTESK_VERITOOL_ADAPTER@ being used, fields inputs и outputs should not be declared and methods and methods of synchronizer should not be overloaded.
466
467
*Notice*: tool VeriTool provides access to values of all HDL-model signals, including internal ones. To get access is possible by means of macros @CPPTESK_GET_SIGNAL(signal_type, signal_name)@ for getting value of signal @testbench.target.signal_name@ (@signal_type@ is meant to be from the following list: int, uint64_t, etc.), and @CPPTESK_SET_SIGNAL(signal_type, signal_name, new_value)@ for setting to a new value the signal @testbench.target.signal_name@ (@signal_type@ is meant to be the same as for getting value macro).
468
469
h4. Input interface adapter
470
471
_Input interface adapter_ is a process defined in reference model adapter and bound with one of the input interfaces. Input interface adapter is called by @CPPTESK_START_STIMULUS(mode)@ macro (see chapter _“Operation”_) or by @CPPTESK_RECV_STIMULUS(mode, interface, message)@ macro (see chapter _“Stimulus receiving”_). Declaration and definition of input interface adapters are done in typical for processes way.
472
473
It should be noticed, that just before the serialization, the input interface adapter should capture the interface. Capturing is made by macro @CPPTESK_CAPTURE_IFACE()@. Correspondingly, after the serialization, the interface should be released by macro @CPPTESK_RELEASE_IFACE()@.
474
475 1 Mikhail Chupilko
Example:
476 3 Mikhail Chupilko
<pre><code class="cpp">
477 1 Mikhail Chupilko
#include <hw/media.hpp>
478
CPPTESK_ADAPTER(MyAdapter, MyModel) {
479
    CPPTESK_DECLARE_PROCESS(serialize_input);
480
    ...
481
};
482
483
CPPTESK_DEFINE_PROCESS(MyAdapter::serialize_input) {
484
    MyMessage msg = CPPTESK_CAST_MESSAGE(MyMessage);
485
    // start serialization process
486
    CPPTESK_START_PROCESS();
487
    // capture input interface
488
    CPPTESK_CAPTURE_IFACE();
489
    // set operation start strobe
490
    inputs.start = 1;
491
    // set information signals
492
    inputs.addr  = msg.get_addr();
493
    inputs.data  = msg.get_data();
494
    // one cycle delay
495
    CPPTESK_CYCLE();
496
    // reset of operation strobe
497
    inputs.start = 0;
498
    // release input interface
499
    CPPTESK_RELEASE_IFACE();
500
    // stop serialization process
501
    CPPTESK_STOP_PROCESS();
502
}
503 3 Mikhail Chupilko
</code></pre>
504
505
Binding of adapter and interface is made in reference model constructor by means of macro @CPPTESK_SET_INPUT_ADAPTER(interface_name, adapter_full_name)@.
506
507 1 Mikhail Chupilko
Example:
508 3 Mikhail Chupilko
<pre><code class="cpp">
509 1 Mikhail Chupilko
MyAdapter::MyAdapter{
510
    CPPTESK_SET_INPUT_ADAPTER(input_iface, MyAdater::serialize_input);
511
    ...
512
};
513 3 Mikhail Chupilko
</code></pre>
514
515
*Notice*: when input interface adapter being registered, its full name (including the name of reference model adapter class) should be used.
516
517
h4. Output interface adapter
518
519
Output interface adapter is a process defined in reference model adapter and bound with one of the output interfaces, Output interface adapter is called by @CPPTESK_SEND_REACTION(mode, interface, message)@ macro (see chapter _“Reaction sending”_). Declaration and definition of output interface adapters are done by means of the following macros.
520
* @CPPTESK_WAIT_REACTION(condition)@ - wait for reaction and allow reaction arbiter to access the reaction;
521
* @CPPTESK_NEXT_REACTION()@ - releasing of reaction arbiter (see chapter _“Reaction arbiter”_).
522
523 1 Mikhail Chupilko
Example:
524 3 Mikhail Chupilko
<pre><code class="cpp">
525 1 Mikhail Chupilko
#include <hw/media.hpp>
526
CPPTESK_ADAPTER(MyAdapter, MyModel) {
527
    CPPTESK_DECLARE_PROCESS(deserialize_output);
528
    ...
529
};
530
531
CPPTESK_DEFINE_PROCESS(MyAdapter::deserialize_input) {
532
    // get reference to the message object
533
    MyMessage &msg = CPPTESK_CAST_MESSAGE(MyMessage);
534
    // start deserialization process
535
    CPPTESK_START_PROCESS();
536
    // wait for result strobe
537
    CPPTESK_WAIT_REACTION(outputs.result);
538
    // read data
539
    msg.set_data(outputs.data);
540
    // release reaction arbiter
541
    CPPTESK_NEXT_REACTION();
542
    // stop deserialization process
543
    CPPTESK_STOP_PROCESS();
544
}
545 3 Mikhail Chupilko
</code></pre>
546
547
The waiting for the implementation reaction time is restricted by a timeout. The timeout is set by macro @CPPTESK_SET_REACTION_TIMEOUT(timeout)@, which as well as macro @CPPTESK_SET_OUTPUT_ADAPTER(interface_name, adapter_full_name)@ is called in constructor of reference model adapter.
548
549 1 Mikhail Chupilko
Example:
550 3 Mikhail Chupilko
<pre><code class="cpp">
551 1 Mikhail Chupilko
MyAdapter::MyAdapter{
552
    CPPTESK_SET_OUTPUT_ADAPTER(output_iface, MyAdater::deserialize_output);
553
    CPPTESK_SET_REACTION_TIMEOUT(100);
554
    ...
555
};
556 3 Mikhail Chupilko
</code></pre>
557
558
*Notice*: when output interface adapter being registered, its full name (including the name of reference model adapter class) should be used.
559
560
h4. Output interface listener (deprecated feature)
561
562
_Output interface listener_ is a special-purpose process, waiting for appearing of implementation reactions at the beginning of each cycle, and registering error in case of unexpected reactions. Definition of listeners is made by @CPPTESK_DEFINE_BASIC_OUTPUT_LISTENER(name, interface_name, condition)@ macro.
563
564 1 Mikhail Chupilko
Example:
565 3 Mikhail Chupilko
<pre><code class="cpp">
566 1 Mikhail Chupilko
#include <hw/media.hpp>
567
CPPTESK_ADAPTER(MyAdapter, MyModel) {
568
    CPPTESK_DEFINE_BASIC_OUTPUT_LISTENER(output_listener,
569
        output_iface, outputs.result);
570
    ...
571
};
572 3 Mikhail Chupilko
</code></pre>
573
574
Output interface listener is started in constructor of reference model adapter by macro @CPPTESK_CALL_OUTPUT_LISTENER(listener_full_name, interface_name)@.
575
576 1 Mikhail Chupilko
Example:
577 3 Mikhail Chupilko
<pre><code class="cpp">
578 1 Mikhail Chupilko
MyAdapter::MyAdapter{
579
    ...
580
    CPPTESK_CALL_OUTPUT_LISTENER(MyAdapter::output_listener, output_iface);
581
    ...
582
};
583 3 Mikhail Chupilko
</code></pre>
584
585
h4. Reaction arbiter
586
587
_Reaction arbiter_ (_output interface arbiter_) is aimed for matching implementation reactions (received from HDL-model) with specification reactions (calculated by reference model). Having been matched, the reaction pairs are sent to comparator, showing an error if there is difference in data between two reactions (see chapter _“Comparator of output messages”_).
588
589 1 Mikhail Chupilko
The common types of arbiters are the following.
590 3 Mikhail Chupilko
* @CPPTESK_FIFO_ARBITER@ — implementation reaction having been received, the arbiter prefers specification reaction which was created by the earliest among the other reactions call of macro @CPPTESK_SEND_REACTION()@ (see chapter _“Reaction sending”_).
591
* @CPPTESK_PRIORITY_ARBITER@ — the arbiter prefers specification reaction which was created with the highest priority by macro @CPPTESK_SEND_REACTION()@ (see chapter _“Process priority”_).
592
593
To declare reaction arbiter in reference model adapter class is possible by means of macro @CPPTESK_DECLARE_ARBITER(type, name)@. To bind arbiter with output interface is possible by means of macro @CPPTESK_SET_ARBITER(interface, arbiter)@, which should be called in constructor of reference model adapter.
594
595 1 Mikhail Chupilko
Example:
596 3 Mikhail Chupilko
<pre><code class="cpp">
597 1 Mikhail Chupilko
#include <hw/media.hpp>
598
CPPTESK_ADAPTER(MyAdapter, MyModel) {
599
    CPPTESK_DECLARE_ARBITER(CPPTESK_FIFO_ARBITER, output_iface_arbiter);
600
    ...
601
};
602
603
MyAdapter::MyAdapter() {
604
    CPPTESK_SET_ARBITER(output_iface, output_iface_arbiter);
605
    ...
606
}
607 3 Mikhail Chupilko
</code></pre>
608
609
h2. Test coverage description
610
611
_Test coverage_ is aimed for evaluation of _test completeness_. As a rule, test coverage structure is described explicitly by enumerating of all possible in the test situations (test situations). To describe complex test situations, composition of simpler test coverage structures is used.
612
613
Test coverage can be described in the main class of reference model or moved to external class (test coverage class). In the second case, the class with test coverage description should have a reference to the reference model (see chapter _“Test coverage class”_).
614
615
h3. Class of test coverage
616
617
Class of test coverage is a class containing definition of test coverage structure and functions calculating test situations. As test coverage is defined in terms of reference model, test coverage class should have a reference to the main class of reference model. To trace test situations, test coverage class has test situation tracer — an object of @CoverageTracker@ class (@namespace cpptesk::tracer::coverage@) and function tracing test situations.
618
619 1 Mikhail Chupilko
Example:
620 3 Mikhail Chupilko
<pre><code class="cpp">
621 1 Mikhail Chupilko
#include <ts/coverage.hpp>
622
#include <tracer/tracer.hpp>
623
class MyModel;
624
625
// Declaration of test coverage class
626
class MyCoverage {
627
public:
628
    MyCoverage(MyModel &model): model(model) {}
629
630
    // Test situation tracer
631
    CoverageTracker tracker;
632
633
    // Description of test coverage structure
634
    CPPTESK_DEFINE_ENUMERATED_COVERAGE(MY_COVERAGE, "My coverage", (
635
         (SITUATION_1, "Situation 1"),
636
         ...
637
         (SITUATION_N, "Situation N")
638
    ));
639
640
    // Function calculating test situation: signature of the function
641
    // contains all necessary for it parameters
642
    MY_COVERAGE cov_MY_COVERAGE(...) const;
643
644
    // Function tracing test situations: signature of the function
645
    // is the same as signature of the previous function
646
    void trace_MY_COVERAGE(...);
647
    ...
648
private:
649
    // Reference to the reference model
650
    MyModel &model;
651
};
652 3 Mikhail Chupilko
</code></pre>
653
654
h3. Test coverage structure
655
656
Test coverage structure is described by means of _enumerated coverage_, _coverage compositions_, _excluded coverage composition_, and _test coverage aliases_.
657
658
h4. Enumerated coverage
659
660
_Enumerated coverage_, as it goes from the coverage name, is defined by explicit enumeration of all possible test situations by macro @CPPTESK_DEFINE_ENUMERATED_COVERAGE(coverage, description, situations)@, where coverage is an identifier of the coverage type, description is a string, and situations is the list of situations like @((id, description), ...)@.
661
662 1 Mikhail Chupilko
Example:
663 3 Mikhail Chupilko
<pre><code class="cpp">
664 1 Mikhail Chupilko
#include <ts/coverage.hpp>
665
CPPTESK_DEFINE_ENUMERATED_COVERAGE(FIFO_FULLNESS, "FIFO fullness", (
666
    (FIFO_EMPTY, "Empty"),
667
     ...
668
    (FIFO_FULL, "Full")
669
));
670 3 Mikhail Chupilko
</code></pre>
671
672
h4. Coverage composition
673 5 Alexander Kamkin
674 3 Mikhail Chupilko
_Coverage composition_ allows creation of test situation structure basing on two test coverage structures, containing Cartesian product of situations from both initial structures. Coverage composition is made by means of macro @CPPTESK_DEFINE_COMPOSED_COVERAGE(type, description, coverage_1, coverage_2)@. Description of new test situations is made according to the pattern @"%s,%s"@.
675
676 1 Mikhail Chupilko
Example:
677 3 Mikhail Chupilko
<pre><code class="cpp">
678 1 Mikhail Chupilko
#include <ts/coverage.hpp>
679
CPPTESK_DEFINE_ENUMERATED_COVERAGE(COVERAGE_A, "Coverage A", (
680
    (A1, "A one"),
681
    (A2, "A two")
682
));
683
684
CPPTESK_DEFINE_ENUMERATED_COVERAGE(COVERAGE_B, "Coverage B", (
685
    (B1, "B one"),
686
    (B2, "B two")
687
));
688
689
// Product of structures A and B makes the following situations:
690
// (COVERAGE_AxB::Id(A1, B1), "A one, B one")
691
// (COVERAGE_AxB::Id(A1, B2), "A one, B two")
692
// (COVERAGE_AxB::Id(A2, B1), "A two, B one")
693
// (COVERAGE_AxB::Id(A2, B2), "A two, B two")
694
CPPTESK_DEFINE_COMPOSED_COVERAGE(COVERAGE_AxB, "Coverage AxB",
695
    COVERAGE_A, COVERAGE_B);
696 3 Mikhail Chupilko
</code></pre>
697
698
h4. Excluded coverage composition
699
700
To make product of test coverage structures and exclude unreachable test situations is possible by macro @CPPTESK_DEFINE_COMPOSED_COVERAGE_EXCLUDING(type, description, coverage_1, coverage_2, excluded)@, where excluded is the list like @({coverage_1::id, coverage_2::id}, ... )@. Instead of test situation identifier, macro @ANY()@ can be used. To product coverage structures being products themselves, correspondent tuples should be used instead of pairs.
701
702 1 Mikhail Chupilko
Example:
703 3 Mikhail Chupilko
<pre><code class="cpp">
704 1 Mikhail Chupilko
#include <ts/coverage.hpp>
705
CPPTESK_DEFINE_ENUMERATED_COVERAGE(COVERAGE_A, "Coverage A", (
706
    (A1, "A one"),
707
    (A2, "A two")
708
));
709
710
CPPTESK_DEFINE_ENUMERATED_COVERAGE(COVERAGE_B, "Coverage B", (
711
    (B1, "B one"),
712
    (B2, "B two")
713
));
714
715
// The following composition makes the following test situations:
716
// (COVERAGE_AxB::Id(A1, B2), "A one, B two")
717
// (COVERAGE_AxB::Id(A2, B1), "A two, B one")
718
// (COVERAGE_AxB::Id(A2, B2), "A two, B two")
719
CPPTESK_DEFINE_COMPOSED_COVERAGE_EXCLUDING(COVERAGE_AxB, "Coverage AxB",
720
    COVERAGE_A, COVERAGE_B, ({COVERAGE_A::A1, COVERAGE_B::B1}));
721 3 Mikhail Chupilko
</code></pre>
722
723
h4. Test coverage alias
724
725
To make a test coverage alias (test coverage with different name, but with the same test situations), macro @CPPTESK_DEFINE_ALIAS_COVERAGE(alias, description, coverage)@ should be used.
726
727 1 Mikhail Chupilko
Example:
728 3 Mikhail Chupilko
<pre><code class="cpp">
729 1 Mikhail Chupilko
#include <ts/coverage.hpp>
730
CPPTESK_DEFINE_ENUMERATED_COVERAGE(COVERAGE_A, "Coverage A", (
731
    (A1, "A one"),
732
    (A2, "A two")
733
));
734
735
// COVERAGE_B – alias of COVERAGE_A
736
CPPTESK_DEFINE_ALIAS_COVERAGE(COVERAGE_B, "Coverage B", COVERAGE_A);
737 3 Mikhail Chupilko
</code></pre>
738
739
h3. Calculating current test situation function
740
741
_Calculating current test situation function_ is a function, which returns identifier of the current test situation (see chapter _“Structure of the test coverage”_), having analyzed the reference model state and (possibly) input parameters of the operation. Identifier of test situation for enumerated coverage looks like @coverage::identifier@ and @class::coverage::identifier@ when used outside of test coverage class. Calculating current test situation function for production of coverage structures can be obtained by calling functions for particular coverage structures and “production” of their results (operator @*@ should be appropriately overloaded).
742
743 1 Mikhail Chupilko
Example:
744 3 Mikhail Chupilko
<pre><code class="cpp">
745 1 Mikhail Chupilko
#include <ts/coverage.hpp>
746
class MyCoverage {
747
    // definition of the enumerated coverage structure COVERAGE_A
748
    CPPTESK_DEFINE_ENUMERATED_COVERAGE(COVERAGE_A, "Coverage A", (
749
        (A1, "A one"),
750
        (A2, "A two")
751
    ));
752
    // test situation calculating function for coverage COVERAGE_A
753
    COVERAGE_A cov_COVERAGE_A(int a) const {
754
        switch(a) {
755
        case 1: return COVERAGE_A::A1;
756
        case 2: return COVERAGE_A::A2;
757
        }
758
        assert(false);
759
    }
760
    
761
    // definition of COVERAGE_B – alias of COVERAGE_A
762
    CPPTESK_DEFINE_ALIAS_COVERAGE(COVERAGE_B, "Coverage B", COVERAGE_A);
763
    // test situation calculating function for coverage COVERAGE_B
764
    COVERAGE_B cov_COVERAGE_B(int b) const {
765
        return cov_COVERAGE_A(b);
766
    }
767
768
    // definition of COVERAGE_AxB – production of COVERAGE_A and COVERAGE_B
769
    CPPTESK_DEFINE_COMPOSED_COVERAGE(COVERAGE_AxB, "Coverage AxB",
770
        COVERAGE_A, COVERAGE_B);s
771
    // test situation calculating function of coverage COVERAGE_AxB
772
    COVERAGE_AxB cov_COVERAGE_AxB(int a, int b) const {
773
        return cov_COVERAGE_A(a) * cov_COVERAGE_B(b);
774
    }
775
    ...
776
};
777 3 Mikhail Chupilko
</code></pre>
778
779
h3. Tracing test situation function
780
781
_Tracing test situation function_ is defined for each upper-level test coverage structure. As tracing function calls test situation calculating function, their parameters usually coincide. Implementation of this function is based on test situation tracer, being an object of class @CoverageTracker@ (@namespace cpptesk::tracer::coverage@).
782
783 1 Mikhail Chupilko
Example:
784 3 Mikhail Chupilko
<pre><code class="cpp">
785 1 Mikhail Chupilko
#include <ts/coverage.hpp>
786
#include <tracer/tracer.hpp>
787
CoverageTracker tracer;
788
void trace_COVERAGE_A(int a) {
789
    tracer << cov_COVERAGE_A(a);
790
}
791 3 Mikhail Chupilko
</code></pre>
792
793
h2. Development of test scenario
794
795
_Test scenario_ is a high-level specification of test, which being interpreted by test engine (see chapter _“Test scenario running”_) is used by test system for test sequence generation. Test scenario is developed as a special class named scenario class.
796
797
h3. Class of scenario
798
799
Scenario class is declared by macro @CPPTESK_SCENARIO(name)@.
800
801 1 Mikhail Chupilko
Example:
802 3 Mikhail Chupilko
<pre><code class="cpp">
803 1 Mikhail Chupilko
#include <ts/scenario.hpp>
804
CPPTESK_SCENARIO(MyScenario) {
805
    ...
806
private:
807
    // testing is done via reference model adapter
808
    MyAdapter dut;
809
};
810 3 Mikhail Chupilko
</code></pre>
811
812
_Test scenario initialization_ and _finalization methods_, _scenario methods_, and _current state function_ are declared in scenario class.
813
814
h4. Test scenario initialization method
815
816
_Test scenario initialization method_ includes actions which should have been made right before test start. It is defined by overloading of base class virtual method @bool init(int argc, char **argv)@. It returns true in case of successful initialization and false in case of some problem.
817
818
Example:
819
<pre><code class="cpp">
820 1 Mikhail Chupilko
#include <ts/scenario.hpp>
821
CPPTESK_SCENARIO(MyScenario) {
822
public:
823
    virtual bool init(int argc, char **argv) {
824
        dut.initialize();
825
        std::cout << "Test has started..." << std::endl;
826
    }
827
    ...
828
};
829 3 Mikhail Chupilko
</code></pre>
830
831
h4. Test scenario finalizing method
832
833
_Test scenario finalizing method_ contains actions which should be done right after test finish. It is defined by overloading of base class virtual method @void finish()@.
834
835 1 Mikhail Chupilko
Example:
836 3 Mikhail Chupilko
<pre><code class="cpp">
837 1 Mikhail Chupilko
#include <ts/scenario.hpp>
838
CPPTESK_SCENARIO(MyScenario) {
839
public:
840
    virtual void finish() {
841
        dut.finalize();	
842
        std::cout << "Test has finished..." << std::endl;
843
    }
844
    ...
845
};
846 3 Mikhail Chupilko
</code></pre>
847
848
h4. Scenario method
849
850
_Scenario methods_ iterate parameters of input messages and run operations by means of reference model adapter. One scenario class may contain several scenario method declarations. Scenario method returns value of bool type, which is interpreted as a flag of some problem. The only parameter of scenario method is an iteration context, which is an object containing variables to be iterated by scenario method (iteration variables). Definition of scenario method starts from calling  macro @CPPTESK_ITERATION_BEGIN@, and finishes with @CPPTESK_ITERATION_END@.
851
852 1 Mikhail Chupilko
Example:
853 3 Mikhail Chupilko
<pre><code class="cpp">
854 1 Mikhail Chupilko
#include <ts/scenario.hpp>
855
CPPTESK_SCENARIO(MyScenario) {
856
public:
857
    bool scenario(cpptesk::ts::IntCtx &ctx);
858
    ...
859
};
860
861
bool MyScenario::scenario(cpptesk::ts::IntCtx &ctx) {
862
    CPPTESK_ITERATION_BEGIN
863
    ...
864
    CPPTESK_ITERATION_END
865
}
866 3 Mikhail Chupilko
</code></pre>
867
868
Scenario methods are registered by macro @CPPTESK_ADD_SCENARIO_METHOD(full_name)@ in scenario class constructor.
869
870 1 Mikhail Chupilko
Example:
871 3 Mikhail Chupilko
<pre><code class="cpp">
872 1 Mikhail Chupilko
MyScenario::MyScenario() {
873
    CPPTESK_ADD_SCENARIO_METHOD(MyScenario::scenario);
874
    ...
875
}
876 3 Mikhail Chupilko
</code></pre>
877
878
h4. Access to iteration variables
879
880
_Iteration variables_ are fields of _iteration context_, which is a parameter of scenario method. To access iteration variables is possible by macro @CPPTESK_ITERATION_VARIABLE(name)@, where name is a name of one of the iteration context fields.
881
882 1 Mikhail Chupilko
Example:
883 3 Mikhail Chupilko
<pre><code class="cpp">
884 1 Mikhail Chupilko
#include <ts/scenario.hpp>
885
bool MyScenario::scenario(cpptesk::ts::IntCtx &ctx) {
886
    // get reference to iteration variable
887
    int &i = CPPTESK_ITERATION_VARIABLE(i);
888
    CPPTESK_ITERATION_BEGIN
889
    for(i = 0; i < 10; i++) {
890
        ...
891
    }
892
    CPPTESK_ITERATION_END
893
}
894 3 Mikhail Chupilko
</code></pre>
895
896
h4. Test action block
897
898
_Test action_ (preparation of input message and start of operation) is made in a code block @CPPTESK_ITERATION_ACTION{...}@ located in scenario method.
899
900 1 Mikhail Chupilko
Example:
901 3 Mikhail Chupilko
<pre><code class="cpp">
902 1 Mikhail Chupilko
#include <ts/scenario.hpp>
903
...
904
CPPTESK_ITERATION_BEGIN
905
for(i = 0; i < 10; i++) {
906
     ...
907
     // test action block
908
     CPPTESK_ITERATION_ACTION {
909
         // input message randomization
910
         CPPTESK_RANDOMIZE_MESSAGE(input_msg);
911
         input_msg.set_addr(i);
912
         // start operation
913
         CPPTESK_CALL_STIMULUS_OF(dut, MyModel::operation,
914
             dut.input_iface, input_msg);
915
         ...
916
     }
917
}
918
CPPTESK_ITERATION_END
919 3 Mikhail Chupilko
</code></pre>
920
921
h4. Scenario action finishing
922
923
Each iteration of scenario method is finished by @CPPTESK_ITERATION_YIELD(verdict)@ macro, quitting from scenario method. When being called next time, scenario method will continue its execution from next iteration.
924
925 1 Mikhail Chupilko
Example:
926 3 Mikhail Chupilko
<pre><code class="cpp">
927 1 Mikhail Chupilko
#include <ts/scenario.hpp>
928
...
929
CPPTESK_ITERATION_BEGIN
930
for(i = 0; i < 10; i++) {
931
     ...
932
     // test action block
933
     CPPTESK_ITERATION_ACTION {
934
         ...
935
         // quit from scenario method and return verdict
936
         CPPTESK_ITERATION_YIELD(dut.verdict());
937
     }
938
}
939
CPPTESK_ITERATION_END
940 3 Mikhail Chupilko
</code></pre>
941
942
h4. Delays
943
944
Making _delays_ (sending of stimuli at different time of HDL-model simulation) in tests requires development of at least one method with calling reference model method @cycle()@. In case of possibility of parallel stimulus running, the most convenient way of usage method @cycle()@ is to call this method from purposely created scenario method @nop()@ (name of this method is unrestricted). Notice that in this case method @cycle()@ should not be called from any other method.
945
946
Example:
947
<pre><code class="cpp">
948 1 Mikhail Chupilko
#include <ts/scenario.hpp>
949
bool MyScenario::nop(cpptesk::ts::IntCtx& ctx) {
950
    CPPTESK_ITERATION_BEGIN
951
    CPPTESK_ITERATION_ACTION {
952
        dut.cycle();
953
        CPPTESK_ITERATION_YIELD(dut.verdict());
954
    }
955
    CPPTESK_ITERATION_END
956
}
957 3 Mikhail Chupilko
</code></pre>
958
959
*Notice*: scenario method @nop()@ should be registered before any other scenario methods.
960
961
h3. Calculating current state function
962
963
_Calculating current state function_ is needed for test engines, using exploration of target system state graph for creation of test sequences. Returning by function value is interpreted as system state. Type of the returning value and function name are unrestricted. Method does not allow parameters.
964
965 1 Mikhail Chupilko
Example:
966 3 Mikhail Chupilko
<pre><code class="cpp">
967 1 Mikhail Chupilko
#include <ts/scenario.hpp>
968
CPPTESK_SCENARIO(MyScenario) {
969
public:
970
    ...
971
    int get_model_state() {
972
        return dut.buffer.size();
973
    }
974
};
975 3 Mikhail Chupilko
</code></pre>
976
977
Setting up of calculating current state function is made by method @void setup(...)@. in test scenario constructor.
978
979 1 Mikhail Chupilko
Example:
980 3 Mikhail Chupilko
<pre><code class="cpp">
981 1 Mikhail Chupilko
#include <ts/scenario.hpp>
982
MyScenario::MyScenario() {
983
    setup("My scenario",
984
    UseVirtual::init,
985
    UseVirtual::finish,
986
    &MyScenario::get_model_state);
987
    ...
988
}
989 3 Mikhail Chupilko
</code></pre>
990
991
h3. Test scenario running
992
993
Test scenario running at local computer is made by calling function @localmain(engine, scenario.getTestScenario(), argc, argv)@ (namespace @cpptesk::ts@).
994
995
Available test engines are the following (namespace @cpptesk::ts::engine@).
996
* @fsm@ — generator of test sequence based on state graph exploration;
997
* @rnd@ — generator of randomized test sequence.
998
999 1 Mikhail Chupilko
Example:
1000 3 Mikhail Chupilko
<pre><code class="cpp">
1001 1 Mikhail Chupilko
#include <netfsm/engines.hpp>
1002
using namespace cpptesk::ts;
1003
using namespace cpptesk::ts::engine;
1004
...
1005
MyScenario scenario;
1006
localmain(fsm, scenario.getTestScenario(), argc, argv);
1007 3 Mikhail Chupilko
</code></pre>
1008
1009
h2. Auxiliary possibilities
1010
1011 1 Mikhail Chupilko
C++TESK toolkit includes the following auxiliary possibilities: assertions and debug print. These possibilities can be used in reference models and in all test system components (adapters, test scenarios, etc). Their main aim is to facilitate debug of test system.
1012 3 Mikhail Chupilko
1013
h3. Assertions
1014
1015
_Assertions_ are predicates (logic constructions) used for description of program properties and, as a rule, checked during runtime. If assertion is violated (predicate shows false), error is fixed and program is stopped. To make assertions is possible by @CPPTESK_ASSERTION(predicate, description)@ macro, where predicate is a checking property, and description is a string describing error bound with violation of this property.
1016
1017 1 Mikhail Chupilko
Example:
1018 3 Mikhail Chupilko
<pre><code class="cpp">
1019 1 Mikhail Chupilko
#include <hw/assertion.hpp>
1020
...
1021
CPPTESK_ASSERTION(pointer, "pointer is null");
1022 3 Mikhail Chupilko
</code></pre>
1023
1024
h3. Debug print
1025
1026
_Debug print_ is devoted to debug of test system. In contrast to typical printing by means of, e.g., STL streams, adjustment of debug print is easier (turning on/off, changing of printing color, etc).
1027
1028
h4. Debug print macros
1029
1030
Debug print is commonly made by macro @CPPTESK_DEBUG_PRINT(level, message)@, where level is a level of debug print (see chapter _“Debug print levels”_) and message is a printing debug message, and macro @CPPTESK_DEBUG_PRINTF(level, formal, parameters)@, where @(format, parameters)@ is a formatted string and values of used in the string parameters in the same format as they are used by C library function @printf()@.
1031
1032 1 Mikhail Chupilko
Example:
1033 3 Mikhail Chupilko
<pre><code class="cpp">
1034 1 Mikhail Chupilko
#include <hw/debug.hpp>
1035
using namespace cpptesk::hw;
1036
...
1037
CPPTESK_DEBUG_PRINT(DEBUG_USER, "The input message is "
1038
    << CPPTESK_GET_MESSAGE());
1039
...
1040
CPPTESK_DEBUG_PRINTF(DEBUG_USER, "counter=%d", counter);
1041 3 Mikhail Chupilko
</code></pre>
1042
1043
*Notice*: as a debug message in macro @CPPTESK_DEBUG_PRINT()@ any “stream expression” (allowed for usage in standard C++ STL output streams expressions) can be used.
1044
1045
To add location information of debug macro to debug message (file name and string number) is possible by means of macros @CPPTESK_DEBUG_PRINT_FILE_LINE()@ and @CPPTESK_DEBUG_PRINTF_FILE_LINE()@. Their parameters are the same as of macros mentioned above.
1046
1047
h3. Process call stack printing
1048
1049
To print process call stack of reference model is possible by macro @CPPTESK_CALL_STACK()@, which can be used inside and instead of debug message of macro @CPPTESK_DEBUG_PRINT()@.
1050
1051 1 Mikhail Chupilko
Example:
1052 3 Mikhail Chupilko
<pre><code class="cpp">
1053 1 Mikhail Chupilko
#include <hw/model.hpp>
1054
CPPTESK_DEFINE_PROCESS(MyModel::some_process) {
1055
    CPPTESK_START_PROCESS();
1056
1057
    CPPTESK_DEBUG_PRINT(DEBUG_USER, "Call stack is "
1058
        << CPPTESK_CALL_STACK());
1059
    ...
1060
    CPPTESK_STOP_PROCESS();
1061
}
1062 3 Mikhail Chupilko
</code></pre>
1063
1064
*Notice*: macro @CPPTESK_CALL_STACK()@ can be used only inside on reference model.
1065
1066
h3. Colored debug print
1067
1068
To facilitate manual search of debug messages of a certain type among all debug print is possible by means of colored debug print macros @CPPTESK_COLORED_DEBUG_PRINT(level, color, background_color, message)@, @CPPTESK_COLORED_DEBUG_PRINTF(level, color, background_color, format, parameters)@, and also macros @CPPTESK_COLORED_DEBUG_PRINT_FILE_LINE()@ and @CPPTESK_COLORED_DEBUG_PRINTF_FILE_LINE()@.
1069
1070
The following color constants are defined (namespace @cpptesk::hw@):
1071
* @BLACK@ — black;
1072
* @RED@ — red;
1073
* @GREEN@ — green;
1074
* @YELLOW@ — yellow;
1075
* @BLUE@ — blue;
1076
* @MAGENTA@ — purple;
1077
* @CYAN@ — cyan;
1078
* @WHITE@ — white.
1079
1080 1 Mikhail Chupilko
Example:
1081 3 Mikhail Chupilko
<pre><code class="cpp">
1082 1 Mikhail Chupilko
#include <hw/debug.hpp>
1083
using namespace cpptesk::hw;
1084
...
1085
CPPTESK_COLORED_DEBUG_PRINT_FILE_LINE(DEBUG_USER, RED, BLACK,
1086
    "The input message is " << CPPTESK_GET_MESSAGE());
1087
...
1088
CPPTESK_COLORED_DEBUG_PRINTF(DEBUG_USER, WHITE, BLACK,
1089
    "counter=%d", counter);
1090 3 Mikhail Chupilko
</code></pre>
1091
1092
h3. Controlling indents in debug print
1093
1094
To control indents in debug print is possible by @CPPTESK_SET_DEBUG_INDENT(indent)@, @CPPTESK_BEGIN_DEBUG_INDENT@, and @CPPTESK_END_DEBUG_INDENT@ macros. Macro @CPPTESK_SET_DEBUG_INDENT@ sets indent value (not negative integer) returning its old value. Macros @CPPTESK_BEGIN_DEBUG_INDENT@ and @CPPTESK_END_DEBUG_INDENT@ are used in complementary way: the first one increases indent, the second one decreases indent by one point.
1095
1096 1 Mikhail Chupilko
Example:
1097 3 Mikhail Chupilko
<pre><code class="cpp">
1098 1 Mikhail Chupilko
#include <hw/debug.hpp>
1099
using namespace cpptesk::hw;
1100
...
1101
unsigned old_indent = CPPTESK_SET_DEBUG_INDENT(2);
1102
...
1103
CPPTESK_BEGIN_DEBUG_INDENT
1104
{
1105
    CPPTESK_DEBUG_PRINT(DEBUG_USER, "Some message");
1106
    ...
1107
}
1108
CPPTESK_END_DEBUG_INDENT
1109 3 Mikhail Chupilko
</code></pre>
1110
1111
h3. Debug print levels
1112
1113
There is a level of debug message parameter among other debug print parameters. Level characterizes importance of the message. Usually, debug messages of different levels are colored differently. The following debug levels are defined (namespace @cpptesk::hw@):
1114
* @DEBUG_MORE@ — detailed debug messages produced by toolkit itself;
1115
* @DEBUG_INFO@ — basic debug messages produced by toolkit itself;
1116
* @DEBUG_USER@ — user’s debug messages;
1117
* @DEBUG_WARN@ — warnings (typically, produced by toolkit itself);
1118
* @DEBUG_FAIL@ — messages about failures (typically, produced by toolkit itself).
1119
1120
The most “important” level is @DEBUG_FAIL@, then @DEBUG_WARN@, etc. @DEBUG_USER@ is the only one level for user’s messages.
1121
1122
h3. Debug print setting up
1123
1124
To set up the volume of debug print messages is possible by selection of debug print level, and only those messages will be printed, which has debug level being not less than selected one. It is done by macro @CPPTESK_SET_DEBUG_LEVEL(debug_level, colored)@. This macro has an additional Boolean parameter colored, turning on/off coloring. Debug level @DEBUG_INFO@ is set by default. Special level @DEBUG_NONE@ can be used to switch off debug print totally.
1125
1126
Each debug print level can be assigned with colors for messages of this level. It is done by macro @CPPTESK_SET_DEBUG_STYLE(level, tag_color, tag_background_color, color, background_color)@.
1127
1128 1 Mikhail Chupilko
Example:
1129 3 Mikhail Chupilko
<pre><code class="cpp">
1130 1 Mikhail Chupilko
#include <hw/model.hpp>
1131
using namespace cpptesk::hw;
1132
...
1133
// reference model constructor
1134
MyModel::MyModel() {
1135
    // print messages with failures only,
1136
    // switch on message coloring
1137
    CPPTESK_SET_DEBUG_LEVEL(DEBUG_FAIL, true);
1138
    // [FAIL] Error message style.
1139
    CPPTESK_SET_DEBUG_STYLE(DEBUG_FAIL, BLACK, RED, RED, BLACK);
1140
}
1141 3 Mikhail Chupilko
</code></pre>