Project

General

Profile

C++TESK Quick Reference » History » Version 1

Mikhail Chupilko, 09/19/2013 05:48 PM

1 1 Mikhail Chupilko
h1. C++TESK Quick Reference
2
3
h2. Introduction
4
5
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.
6
7
_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_.
8
9
The document describes facilities of C++TESK aimed to development of mentioned test system components, and consists of four common chapters.
10
* Development of reference model
11
* Development of reference model adapter
12
* Description of test coverage
13
* Development of test scenario
14
15
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.
16
17
More detailed toolkit review is given in _«C++TESK Testing ToolKit: User Guide»_.
18
19
Installation process of C++TESK is described in _«С++TESK Testing ToolKit: Installation Guide»_.
20
21
h2. Supporting obsolete constructions
22
23
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.,
24
-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.
25
26
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.
27
28
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.
29
30
During compilation of test systems, developed by means of C++TESK, usage of the compiler option -DCPPTESKHW_VERSION=number is highly recommended.
31
32
h2. Naming convention
33
34
The core of the toolkit is developed as a C++ library. Available means are grouped into the following namespaces.
35
36
* cpptesk::hw — means for development of reference models and their adapters;
37
* cpptesk::ts — basic means for test system development;
38
* cpptesk::ts::coverage — means for test coverage description;
39
* сpptesk::ts::engine  — library with test engines4;
40
* cpptesk::tracer — means for tracing;
41
* cpptesk::tracer::coverage — means for coverage tracing.
42
43
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.
44
45
h2. Development of reference model
46
47
Reference model is a structured set of classes describing functionality of target system at some abstraction level5. 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.
48
49
h3. Class of message
50
51
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.
52
53
Example:
54
<pre><code class="cpp">
55
#include <hw/message.hpp>
56
CPPTESK_MESSAGE(MyMessage) {
57
public:
58
    CPPTESK_SUPPORT_CLONE(MyMessage)
59
    ...
60
};
61
</code></pre>
62
*Notice*: Row @CPPTESK_SUPPORT_CLONE(name)@ is obligatory.
63
64
*Input message randomizer*
65
66
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.
67
68
Example:
69
<pre><code class="cpp">
70
CPPTESK_MESSAGE(MyMessage) {
71
    ...
72
    CPPTESK_DECLARE_RANDOMIZER();
73
private:
74
    int data;
75
};
76
77
CPPTESK_DEFINE_RANDOMIZER(MyMessage) {
78
    data = CPPTESK_RANDOM(int);
79
}
80
</code></pre>
81
82
The following macros can be used for randomization of data fields.
83
* @CPPTESK_RANDOM(type)@ — generation of random integer value;
84
* @CPPTESK_RANDOM_WIDTH(type, length)@ — generation of random integer value of given number of bits;
85
* @CPPTESK_RANDOM_FIELD(type, min_bit, max_bit)@ — generation of random integer value with zero bits outside the given range;
86
* @CPPTESK_RANDOM_RANGE(type, min_value, max_value)@ — generation of random integer value from given integer range;
87
* @CPPTESK_RANDOM_CHOICE(type, value_1, ..., value_n)@ — random choice from given set of any type values.
88
89
*Notice*: randomizer may not be defined if all data fields are defined by special macros (see chapter _“Message data fields”_).
90
91
*Comparator of output messages*
92
93
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).
94
95
Example:
96
<pre><code class="cpp">
97
CPPTESK_MESSAGE(MyMessage) {
98
    ...
99
    CPPTESK_DECLARE_COMPARATOR();
100
private:
101
    int data;
102
};
103
104
CPPTESK_DEFINE_COMPARATOR(MyMessage) {
105
    const MyMessage &rhs = CPPTESK_CONST_CAST_MESSAGE(MyMessage);
106
    // in case of difference between messages return not empty string
107
    if(data != rhs.data)
108
        { return "incorrect data"; }
109
    // empty string is interpreted as absence of difference
110
    return COMPARE_OK;
111
}
112
</code></pre>
113
114
*Notice*: comparator may not be defined if all data fields are defined by special macros (see chapter “Message data fields”).
115
116
*Message data fields*
117
118
The following macros are aimed to declaration of integer data fields.
119
* @CPPTESK_DECLARE_FIELD(name, length)@ declares integer field with given name and length.
120
* @CPPTESK_DECLARE_MASKED_FIELD(name, length, mask)@ declares integer field with given name, length, and mask.
121
* @CPPTESK_DECLARE_BIT(name)@ declares bit field with given name.
122
123
Example:
124
<pre><code class="cpp">
125
#include <hw/message.hpp>
126
CPPTESK_MESSAGE(MyMessage) {
127
public:
128
    CPPTESK_DECLARE_MASKED_FIELD(addr, 32, 0xffffFFF0);
129
    CPPTESK_DECLARE_FIELD(data, 32);
130
    CPPTESK_DECLARE_BIT(flag);
131
    ...
132
};
133
</code></pre>
134
135
*Notice*: length of the data fields should not exceed 64 bits.
136
137
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)@.
138
139
Example:
140
<pre><code class="cpp">
141
MyMessage::MyMessage() {
142
    CPPTESK_ADD_FIELD(MyMessage::addr);
143
    CPPTESK_ADD_FIELD(MyMessage::data);
144
    CPPTESK_ADD_INCOMPARABLE_FIELD(MyMessage::flag);
145
    ...
146
}
147
</code></pre>
148
149
*Notice*: full_name means usage both name of method and name of class.
150
151
*Optional messages*
152
153
Output message can be declared to be optional (not obligatory for receiving) if the following method is used.
154
<pre><code class="cpp">void setOptional(optional_or_not_optional);</code></pre>
155
*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.
156
157
h2. Reference model
158
159
Reference model (main class of the reference model) is declared by macro CPPTESK_MODEL(name).
160
Example:
161
#include <hw/model.hpp>
162
CPPTESK_MODEL(MyModel) {
163
    ...
164
};
165
Reference model contains declaration of input and output interfaces, operations, auxiliary processes, and data necessary for operation description.
166
Interface
167
Input and output interfaces of the reference model are declared by means of two macros CPPTESK_DECLARE_{INPUT|OUTPUT}(name), respectively.
168
Example:
169
#include <hw/model.hpp>
170
CPPTESK_MODEL(MyModel) {
171
public:
172
    CPPTESK_DECLARE_INPUT(input_iface);
173
    CPPTESK_DECLARE_OUTPUT(output_iface);
174
    ...
175
};
176
All declared interfaces should be registered in reference model constructor by means of two macros CPPTESK_ADD_{INPUT|OUTPUT}(name).
177
Example:
178
MyModel::MyModel() {
179
    CPPTESK_ADD_INPUT(input_iface);
180
    CPPTESK_ADD_OUTPUT(output_iface);
181
    ...
182
}
183
Setting up ignoring of failures on output interface
184
To disable showing errors of a certain type on a given interface is possible by means of the method:
185
void setFailureIgnoreTypes(disabling_error_types_mask);
186
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”.
187
Process
188
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.
189
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().
190
Example:
191
#include <hw/model.hpp>
192
CPPTESK_MODEL(MyModel) {
193
public:
194
    ...
195
    CPPTESK_DECLARE_PROCESS(internal_process);
196
    ...
197
};
198
199
CPPTESK_DEFINE_PROCESS(MyModel::internal_process) {
200
    CPPTESK_START_PROCESS();
201
    ...
202
    CPPTESK_STOP_PROCESS();
203
}
204
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.
205
Notice: keyword process is reserved and cannot be used for naming of processes.
206
Process parameters
207
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.
208
CPPTESK_GET_PROCESS() — get process context;
209
CPPTESK_GET_IFACE() — get process interface;
210
CPPTESK_GET_MESSAGE() — get message.
211
To cast message parameter to the necessary type is possible by means of the following macros.
212
CPPTESK_CAST_MESSAGE(message_class);
213
CPPTESK_CONST_CAST_MESSAGE(message_class).
214
Example:
215
#include <hw/model.hpp>
216
CPPTESK_DEFINE_PROCESS(MyModel::internal_process) {
217
    // copy message to the local variable
218
    MyMessage msg = CPPTESK_CAST_MESSAGE(MyMessage);
219
    // get reference to the message
220
    MyMessage &msg_ref = CPPTESK_CAST_MESSAGE(MyMessage);
221
    // get constant reference to the message
222
    const MyMessage &const_msg_ref = CPPTESK_CONST_CAST_MESSAGE(MyMessage);
223
    ...
224
}
225
Process priority
226
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.
227
CPPTESK_GET_PRIORITY() — get process priority.
228
CPPTESK_SET_PRIORITY(priority) — set process priority.
229
Some priority values are defined in the enumeration type priority_t (cpptesk::hw namespace). The most general of them are the following ones.
230
NORMAL_PRIORITY — normal priority;
231
LOWEST_PRIORITY — the lowest priority;
232
HIGHEST_PRIORITY — the highest priority.
233
Example:
234
#include <hw/model.hpp>
235
#include <iostream>
236
CPPTESK_DEFINE_PROCESS(MyModel::internal_process) {
237
    ...
238
    std::cout << "process priority is " << std::dec
239
              << CPPTESK_GET_PRIORITY() << std::end;
240
    ...
241
    CPPTESK_SET_PRIORITY(cpptesk::hw::HIGHEST_PRIORITY);
242
    ...
243
}
244
Modeling of delays
245
To model delays in processes is possible by means of the following macros.
246
CPPTESK_CYCLE()
247
delay of one cycle.
248
CPPTESK_DELAY(number_of_cycles)
249
delay of several cycles.
250
CPPTESK_WAIT(condition)
251
delay till condition is satisfied.
252
CPPTESK_WAIT_TIMEOUT(condition, timeout)
253
limited in time delay till condition is satisfied.
254
Example:
255
#include <hw/model.hpp>
256
#include <iostream>
257
CPPTESK_DEFINE_PROCESS(MyModel::internal_process) {
258
    ...
259
    std::cout << "cycle: " << std::dec << time() << std::end;
260
    // delay of one cycle
261
    CPPTESK_CYCLE();
262
    std::cout << "cycle: " << std::dec << time() << std::end;
263
    ...
264
    // wait till outputs.ready is true,
265
    // but not more than 100 cycles
266
    CPPTESK_WAIT_TIMEOUT(outputs.ready, 100);
267
    ...
268
}
269
Process calling
270
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.
271
Example:
272
#include <hw/model.hpp>
273
CPPTESK_DEFINE_PROCESS(MyModel::some_process) {
274
    ...
275
    // call separated process
276
    CPPTESK_CALL_PROCESS(PARALLEL, internal_process,
277
        CPPTESK_GET_IFACE(), CPPTESK_GET_MESSAGE());
278
    ...
279
    // call process and wait till it has been finished
280
    CPPTESK_CALL_PROCESS(SEQUENTIAL, internal_process,
281
        CPPTESK_GET_IFACE(), CPPTESK_GET_MESSAGE());
282
    ...
283
}
284
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.
285
Stimulus receiving
286
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».
287
Example:
288
#include <hw/model.hpp>
289
CPPTESK_DEFINE_PROCESS(MyModel::some_process) {
290
    // modeling of stimulus receiving
291
    CPPTESK_RECV_STIMULUS(PARALLEL, input_iface, input_msg);
292
    ...
293
}
294
Reaction sending
295
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”.
296
Example:
297
#include <hw/model.hpp>
298
CPPTESK_DEFINE_PROCESS(MyModel::some_process) {
299
    // modeling of reaction sending
300
    CPPTESK_SEND_REACTION(SEQUENTIAL, output_iface, output_msg);
301
    ...
302
}
303
Operation
304
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().
305
Example:
306
#include <hw/model.hpp>
307
CPPTESK_MODEL(MyModel) {
308
public:
309
    CPPTESK_DECLARE_STIMULUS(operation);
310
    ...
311
};
312
313
CPPTESK_DEFINE_STIMULUS(MyModel::operation) {
314
    CPPTESK_START_STIMULUS(PARALLEL);
315
    ...
316
    CPPTESK_STOP_STIMULUS();
317
}
318
Notice: operations are particular cases of processes, so that all the constructions from chapter “Process” can be used in them.
319
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.
320
Callback function
321
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().
322
Function onEveryCycle
323
Function onEveryCycle() is called at the beginning of each reference model execution cycle.
324
Example:
325
#include <hw/model.hpp>
326
CPPTESK_MODEL(MyModel) {
327
public:
328
    virtual void onEveryCycle();
329
    ...
330
};
331
332
void MyModel::onEveryCycle() {
333
    std::cout << "onEveryCycle: time=" << std::dec << time() << std::endl;
334
}
335
Development of reference model adapter
336
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.
337
Reference model adapter
338
Reference model adapter is a subclass of reference model class. It is declared by means of the macro CPPTESK_ADAPTER(adapter_name, model_name).
339
Example:
340
#include <hw/media.hpp>
341
CPPTESK_ADAPTER(MyAdapter, MyModel) {
342
    ...
343
};
344
Synchronization methods, input and output interface adapters, output interface listeners, and reaction arbiters are declared in reference model adapter.
345
Synchronizer
346
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.
347
void initialize() — test system initialization;
348
void finialize() — test system finalization;
349
void setInputs() — synchronization of inputs;
350
void getOutputs() — synchronization of outputs;
351
void simulate()— synchronization of time.
352
When hardware models written in Verilog being verified, these methods can be implemented by standard interface VPI (Verilog Procedural Interface). Also, tool VeriTool6 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.
353
Example:
354
#include <hw/veritool/media.hpp>
355
// file generated by tool VeriTool
356
#include <interface.h>
357
CPPTESK_VERITOOL_ADAPTER(MyAdapter, MyModel) {
358
    ...
359
};
360
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.
361
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.
362
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).
363
Input interface adapter
364
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.
365
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(). Correspondently, after the serialization, the interface should be released by macro CPPTESK_RELEASE_IFACE().
366
Example:
367
#include <hw/media.hpp>
368
CPPTESK_ADAPTER(MyAdapter, MyModel) {
369
    CPPTESK_DECLARE_PROCESS(serialize_input);
370
    ...
371
};
372
373
CPPTESK_DEFINE_PROCESS(MyAdapter::serialize_input) {
374
    MyMessage msg = CPPTESK_CAST_MESSAGE(MyMessage);
375
    // start serialization process
376
    CPPTESK_START_PROCESS();
377
    // capture input interface
378
    CPPTESK_CAPTURE_IFACE();
379
    // set operation start strobe
380
    inputs.start = 1;
381
    // set information signals
382
    inputs.addr  = msg.get_addr();
383
    inputs.data  = msg.get_data();
384
    // one cycle delay
385
    CPPTESK_CYCLE();
386
    // reset of operation strobe
387
    inputs.start = 0;
388
    // release input interface
389
    CPPTESK_RELEASE_IFACE();
390
    // stop serialization process
391
    CPPTESK_STOP_PROCESS();
392
}
393
Binding of adapter and interface is made in reference model constructor by means of macro CPPTESK_SET_INPUT_ADAPTER(interface_name, adapter_full_name).
394
Example:
395
MyAdapter::MyAdapter{
396
    CPPTESK_SET_INPUT_ADAPTER(input_iface, MyAdater::serialize_input);
397
    ...
398
};
399
Notice: when input interface adapter being registered, its full name (including the name of reference model adapter class) should be used.
400
Output interface adapter
401
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.
402
CPPTESK_WAIT_REACTION(condition)
403
wait for reaction and allow reaction arbiter to access the reaction;
404
CPPTESK_NEXT_REACTION()
405
releasing of reaction arbiter (see chapter “Reaction arbiter”).
406
Example:
407
#include <hw/media.hpp>
408
CPPTESK_ADAPTER(MyAdapter, MyModel) {
409
    CPPTESK_DECLARE_PROCESS(deserialize_output);
410
    ...
411
};
412
413
CPPTESK_DEFINE_PROCESS(MyAdapter::deserialize_input) {
414
    // get reference to the message object
415
    MyMessage &msg = CPPTESK_CAST_MESSAGE(MyMessage);
416
    // start deserialization process
417
    CPPTESK_START_PROCESS();
418
    // wait for result strobe
419
    CPPTESK_WAIT_REACTION(outputs.result);
420
    // read data
421
    msg.set_data(outputs.data);
422
    // release reaction arbiter
423
    CPPTESK_NEXT_REACTION();
424
    // stop deserialization process
425
    CPPTESK_STOP_PROCESS();
426
}
427
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.
428
Example:
429
MyAdapter::MyAdapter{
430
    CPPTESK_SET_OUTPUT_ADAPTER(output_iface, MyAdater::deserialize_output);
431
    CPPTESK_SET_REACTION_TIMEOUT(100);
432
    ...
433
};
434
Notice: when output interface adapter being registered, its full name (including the name of reference model adapter class) should be used.
435
Output interface listener (deprecated feature)
436
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.
437
Example:
438
#include <hw/media.hpp>
439
CPPTESK_ADAPTER(MyAdapter, MyModel) {
440
    CPPTESK_DEFINE_BASIC_OUTPUT_LISTENER(output_listener,
441
        output_iface, outputs.result);
442
    ...
443
};
444
Output interface listener is started in constructor of reference model adapter by macro CPPTESK_CALL_OUTPUT_LISTENER(listener_full_name, interface_name).
445
Example:
446
MyAdapter::MyAdapter{
447
    ...
448
    CPPTESK_CALL_OUTPUT_LISTENER(MyAdapter::output_listener, output_iface);
449
    ...
450
};
451
Reaction arbiter
452
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”).
453
The common types of arbiters are the following.
454
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”).
455
CPPTESK_PRIORITY_ARBITER — the arbiter prefers specification reaction which was created with the highest priority by macro CPPTESK_SEND_REACTION() (see chapter “Process priority”).
456
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.
457
Example:
458
#include <hw/media.hpp>
459
CPPTESK_ADAPTER(MyAdapter, MyModel) {
460
    CPPTESK_DECLARE_ARBITER(CPPTESK_FIFO_ARBITER, output_iface_arbiter);
461
    ...
462
};
463
464
MyAdapter::MyAdapter() {
465
    CPPTESK_SET_ARBITER(output_iface, output_iface_arbiter);
466
    ...
467
}
468
Test coverage description
469
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.
470
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”).
471
Class of test coverage
472
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.
473
Example:
474
#include <ts/coverage.hpp>
475
#include <tracer/tracer.hpp>
476
class MyModel;
477
478
// Declaration of test coverage class
479
class MyCoverage {
480
public:
481
    MyCoverage(MyModel &model): model(model) {}
482
483
    // Test situation tracer
484
    CoverageTracker tracker;
485
486
    // Description of test coverage structure
487
    CPPTESK_DEFINE_ENUMERATED_COVERAGE(MY_COVERAGE, "My coverage", (
488
         (SITUATION_1, "Situation 1"),
489
         ...
490
         (SITUATION_N, "Situation N")
491
    ));
492
493
    // Function calculating test situation: signature of the function
494
    // contains all necessary for it parameters
495
    MY_COVERAGE cov_MY_COVERAGE(...) const;
496
497
    // Function tracing test situations: signature of the function
498
    // is the same as signature of the previous function
499
    void trace_MY_COVERAGE(...);
500
    ...
501
private:
502
    // Reference to the reference model
503
    MyModel &model;
504
};
505
Test coverage structure
506
Test coverage structure is described by means of enumerated coverage, coverage compositions, excluded coverage composition, and test coverage aliases.
507
Enumerated coverage
508
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), ...).
509
Example:
510
#include <ts/coverage.hpp>
511
CPPTESK_DEFINE_ENUMERATED_COVERAGE(FIFO_FULLNESS, "FIFO fullness", (
512
    (FIFO_EMPTY, "Empty"),
513
     ...
514
    (FIFO_FULL, "Full")
515
));
516
Coverage composition
517
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".
518
Example:
519
#include <ts/coverage.hpp>
520
CPPTESK_DEFINE_ENUMERATED_COVERAGE(COVERAGE_A, "Coverage A", (
521
    (A1, "A one"),
522
    (A2, "A two")
523
));
524
525
CPPTESK_DEFINE_ENUMERATED_COVERAGE(COVERAGE_B, "Coverage B", (
526
    (B1, "B one"),
527
    (B2, "B two")
528
));
529
530
// Product of structures A and B makes the following situations:
531
// (COVERAGE_AxB::Id(A1, B1), "A one, B one")
532
// (COVERAGE_AxB::Id(A1, B2), "A one, B two")
533
// (COVERAGE_AxB::Id(A2, B1), "A two, B one")
534
// (COVERAGE_AxB::Id(A2, B2), "A two, B two")
535
CPPTESK_DEFINE_COMPOSED_COVERAGE(COVERAGE_AxB, "Coverage AxB",
536
    COVERAGE_A, COVERAGE_B);
537
Excluded coverage composition
538
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.
539
Example:
540
#include <ts/coverage.hpp>
541
CPPTESK_DEFINE_ENUMERATED_COVERAGE(COVERAGE_A, "Coverage A", (
542
    (A1, "A one"),
543
    (A2, "A two")
544
));
545
546
CPPTESK_DEFINE_ENUMERATED_COVERAGE(COVERAGE_B, "Coverage B", (
547
    (B1, "B one"),
548
    (B2, "B two")
549
));
550
551
// The following composition makes the following test situations:
552
// (COVERAGE_AxB::Id(A1, B2), "A one, B two")
553
// (COVERAGE_AxB::Id(A2, B1), "A two, B one")
554
// (COVERAGE_AxB::Id(A2, B2), "A two, B two")
555
CPPTESK_DEFINE_COMPOSED_COVERAGE_EXCLUDING(COVERAGE_AxB, "Coverage AxB",
556
    COVERAGE_A, COVERAGE_B, ({COVERAGE_A::A1, COVERAGE_B::B1}));
557
Test coverage alias
558
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.
559
Example:
560
#include <ts/coverage.hpp>
561
CPPTESK_DEFINE_ENUMERATED_COVERAGE(COVERAGE_A, "Coverage A", (
562
    (A1, "A one"),
563
    (A2, "A two")
564
));
565
566
// COVERAGE_B – alias of COVERAGE_A
567
CPPTESK_DEFINE_ALIAS_COVERAGE(COVERAGE_B, "Coverage B", COVERAGE_A);
568
Calculating current test situation function
569
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).
570
Example:
571
#include <ts/coverage.hpp>
572
class MyCoverage {
573
    // definition of the enumerated coverage structure COVERAGE_A
574
    CPPTESK_DEFINE_ENUMERATED_COVERAGE(COVERAGE_A, "Coverage A", (
575
        (A1, "A one"),
576
        (A2, "A two")
577
    ));
578
    // test situation calculating function for coverage COVERAGE_A
579
    COVERAGE_A cov_COVERAGE_A(int a) const {
580
        switch(a) {
581
        case 1: return COVERAGE_A::A1;
582
        case 2: return COVERAGE_A::A2;
583
        }
584
        assert(false);
585
    }
586
    
587
    // definition of COVERAGE_B – alias of COVERAGE_A
588
    CPPTESK_DEFINE_ALIAS_COVERAGE(COVERAGE_B, "Coverage B", COVERAGE_A);
589
    // test situation calculating function for coverage COVERAGE_B
590
    COVERAGE_B cov_COVERAGE_B(int b) const {
591
        return cov_COVERAGE_A(b);
592
    }
593
594
    // definition of COVERAGE_AxB – production of COVERAGE_A and COVERAGE_B
595
    CPPTESK_DEFINE_COMPOSED_COVERAGE(COVERAGE_AxB, "Coverage AxB",
596
        COVERAGE_A, COVERAGE_B);s
597
    // test situation calculating function of coverage COVERAGE_AxB
598
    COVERAGE_AxB cov_COVERAGE_AxB(int a, int b) const {
599
        return cov_COVERAGE_A(a) * cov_COVERAGE_B(b);
600
    }
601
    ...
602
};
603
Tracing test situation function
604
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).
605
Example:
606
#include <ts/coverage.hpp>
607
#include <tracer/tracer.hpp>
608
CoverageTracker tracer;
609
void trace_COVERAGE_A(int a) {
610
    tracer << cov_COVERAGE_A(a);
611
}
612
Development of test scenario
613
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.
614
Class of scenario
615
Scenario class is declared by macro CPPTESK_SCENARIO(name).
616
Example:
617
#include <ts/scenario.hpp>
618
CPPTESK_SCENARIO(MyScenario) {
619
    ...
620
private:
621
    // testing is done via reference model adapter
622
    MyAdapter dut;
623
};
624
Test scenario initialization and finalization methods, scenario methods, and current state function are declared in scenario class.
625
Test scenario initialization method
626
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.
627
Exmple:
628
#include <ts/scenario.hpp>
629
CPPTESK_SCENARIO(MyScenario) {
630
public:
631
    virtual bool init(int argc, char **argv) {
632
        dut.initialize();
633
        std::cout << "Test has started..." << std::endl;
634
    }
635
    ...
636
};
637
Test scenario finalizing method
638
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().
639
Example:
640
#include <ts/scenario.hpp>
641
CPPTESK_SCENARIO(MyScenario) {
642
public:
643
    virtual void finish() {
644
        dut.finalize();	
645
        std::cout << "Test has finished..." << std::endl;
646
    }
647
    ...
648
};
649
Scenario method
650
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.
651
Example:
652
#include <ts/scenario.hpp>
653
CPPTESK_SCENARIO(MyScenario) {
654
public:
655
    bool scenario(cpptesk::ts::IntCtx &ctx);
656
    ...
657
};
658
659
bool MyScenario::scenario(cpptesk::ts::IntCtx &ctx) {
660
    CPPTESK_ITERATION_BEGIN
661
    ...
662
    CPPTESK_ITERATION_END
663
}
664
Scenario methods are registered by macro CPPTESK_ADD_SCENARIO_METHOD(full_name) in scenario class constructor.
665
Example:
666
MyScenario::MyScenario() {
667
    CPPTESK_ADD_SCENARIO_METHOD(MyScenario::scenario);
668
    ...
669
}
670
Access to iteration variables
671
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.
672
Example:
673
#include <ts/scenario.hpp>
674
bool MyScenario::scenario(cpptesk::ts::IntCtx &ctx) {
675
    // get reference to iteration variable
676
    int &i = CPPTESK_ITERATION_VARIABLE(i);
677
    CPPTESK_ITERATION_BEGIN
678
    for(i = 0; i < 10; i++) {
679
        ...
680
    }
681
    CPPTESK_ITERATION_END
682
}
683
Test action block
684
Test action (preparation of input message and start of operation) is made in a code block CPPTESK_ITERATION_ACTION{ ... } located in scenario method.
685
Example:
686
#include <ts/scenario.hpp>
687
...
688
CPPTESK_ITERATION_BEGIN
689
for(i = 0; i < 10; i++) {
690
     ...
691
     // test action block
692
     CPPTESK_ITERATION_ACTION {
693
         // input message randomization
694
         CPPTESK_RANDOMIZE_MESSAGE(input_msg);
695
         input_msg.set_addr(i);
696
         // start operation
697
         CPPTESK_CALL_STIMULUS_OF(dut, MyModel::operation,
698
             dut.input_iface, input_msg);
699
         ...
700
     }
701
}
702
CPPTESK_ITERATION_END
703
Scenario action finishing
704
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.
705
Example:
706
#include <ts/scenario.hpp>
707
...
708
CPPTESK_ITERATION_BEGIN
709
for(i = 0; i < 10; i++) {
710
     ...
711
     // test action block
712
     CPPTESK_ITERATION_ACTION {
713
         ...
714
         // quit from scenario method and return verdict
715
         CPPTESK_ITERATION_YIELD(dut.verdict());
716
     }
717
}
718
CPPTESK_ITERATION_END
719
Delays
720
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()7. Notice that in this case method cycle() should not be called from any other method.
721
Пример:	
722
#include <ts/scenario.hpp>
723
bool MyScenario::nop(cpptesk::ts::IntCtx& ctx) {
724
    CPPTESK_ITERATION_BEGIN
725
    CPPTESK_ITERATION_ACTION {
726
        dut.cycle();
727
        CPPTESK_ITERATION_YIELD(dut.verdict());
728
    }
729
    CPPTESK_ITERATION_END
730
}
731
Notice: scenario method nop() should be registered before any other scenario methods.
732
Calculating current state function
733
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.
734
Example:
735
#include <ts/scenario.hpp>
736
CPPTESK_SCENARIO(MyScenario) {
737
public:
738
    ...
739
    int get_model_state() {
740
        return dut.buffer.size();
741
    }
742
};
743
Setting up of calculating current state function is made by method void setup(...). in test scenario constructor.
744
Example:
745
#include <ts/scenario.hpp>
746
MyScenario::MyScenario() {
747
    setup("My scenario",
748
    UseVirtual::init,
749
    UseVirtual::finish,
750
    &MyScenario::get_model_state);
751
    ...
752
}
753
Test scenario running
754
Test scenario running at local computer is made by calling function localmain(engine, scenario.getTestScenario(), argc, argv) (namespace cpptesk::ts).
755
Available test engines are the following (namespace cpptesk::ts::engine).
756
fsm — generator of test sequence based on state graph exploration;
757
rnd — generator of randomized test sequence.
758
Example:
759
#include <netfsm/engines.hpp>
760
using namespace cpptesk::ts;
761
using namespace cpptesk::ts::engine;
762
...
763
MyScenario scenario;
764
localmain(fsm, scenario.getTestScenario(), argc, argv);
765
Auxiliary possibilities
766
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.
767
Assertions
768
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.
769
Example:
770
#include <hw/assertion.hpp>
771
...
772
CPPTESK_ASSERTION(pointer, "pointer is null");
773
Debug print
774
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).
775
Debug print macros
776
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().
777
Example:
778
#include <hw/debug.hpp>
779
using namespace cpptesk::hw;
780
...
781
CPPTESK_DEBUG_PRINT(DEBUG_USER, "The input message is "
782
    << CPPTESK_GET_MESSAGE());
783
...
784
CPPTESK_DEBUG_PRINTF(DEBUG_USER, "counter=%d", counter);
785
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.
786
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.
787
Process call stack printing
788
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().
789
Example:
790
#include <hw/model.hpp>
791
CPPTESK_DEFINE_PROCESS(MyModel::some_process) {
792
    CPPTESK_START_PROCESS();
793
794
    CPPTESK_DEBUG_PRINT(DEBUG_USER, "Call stack is "
795
        << CPPTESK_CALL_STACK());
796
    ...
797
    CPPTESK_STOP_PROCESS();
798
}
799
Notice: macro CPPTESK_CALL_STACK() can be used only inside on reference model.
800
Colored debug print
801
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().
802
The following color constants are defined (namespace cpptesk::hw):
803
BLACK — black;
804
RED — red;
805
GREEN — green;
806
YELLOW — yellow;
807
BLUE — blue;
808
MAGENTA — purple;
809
CYAN — cyan;
810
WHITE — white.
811
Example:
812
#include <hw/debug.hpp>
813
using namespace cpptesk::hw;
814
...
815
CPPTESK_COLORED_DEBUG_PRINT_FILE_LINE(DEBUG_USER, RED, BLACK,
816
    "The input message is " << CPPTESK_GET_MESSAGE());
817
...
818
CPPTESK_COLORED_DEBUG_PRINTF(DEBUG_USER, WHITE, BLACK,
819
    "counter=%d", counter);
820
Controlling indents in debug print
821
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.
822
Example:
823
#include <hw/debug.hpp>
824
using namespace cpptesk::hw;
825
...
826
unsigned old_indent = CPPTESK_SET_DEBUG_INDENT(2);
827
...
828
CPPTESK_BEGIN_DEBUG_INDENT
829
{
830
    CPPTESK_DEBUG_PRINT(DEBUG_USER, "Some message");
831
    ...
832
}
833
CPPTESK_END_DEBUG_INDENT
834
Debug print levels
835
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):
836
DEBUG_MORE — detailed debug messages produced by toolkit itself;
837
DEBUG_INFO — basic debug messages produced by toolkit itself;
838
DEBUG_USER — user’s debug messages;
839
DEBUG_WARN — warnings (typically, produced by toolkit itself);
840
DEBUG_FAIL — messages about failures (typically, produced by toolkit itself).
841
The most “important” level is DEBUG_FAIL, then DEBUG_WARN, etc. DEBUG_USER is the only one level for user’s messages.
842
Debug print setting up
843
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.
844
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).
845
Example:
846
#include <hw/model.hpp>
847
using namespace cpptesk::hw;
848
...
849
// reference model constructor
850
MyModel::MyModel() {
851
    // print messages with failures only,
852
    // switch on message coloring
853
    CPPTESK_SET_DEBUG_LEVEL(DEBUG_FAIL, true);
854
    // [FAIL] Error message style.
855
    CPPTESK_SET_DEBUG_STYLE(DEBUG_FAIL, BLACK, RED, RED, BLACK);
856
}