// -------------------------------------------------------------- // // We could use print() (from the scv_extensions utility interface) // in place of this function. However, the interest in this function // is not so much what it does, but to demonstrate how to access // functions within classes from higher levels in the program. // void packet::dump(void) const { const scv_extensions<packet> p = scv_get_const_extensions(*this); cout << " " << p.ptype.get_enum_string(p.ptype); cout << " " << source; cout << " " << destination << endl; }
void print_fields(const T& data) { // need a copy of the extension that persists until the end const scv_extensions<T> ext = scv_get_const_extensions(data); // print values in the fields int size = ext.get_num_fields(); if (size) { cout << "Printing field values..." << endl; for (int i=0; i<size; ++i) { const scv_extensions_if * field = ext.get_field(i); if (field->is_integer()) cout << "field \"" << field->get_name() << "\" has value " << field->get_integer() << "." << endl; } } }
// ---------------------------------------- // example usage // // what the user writing a testbench would manipulate // their composite types. // ---------------------------------------- sctop::sctop(sc_module_name name) : sc_module(name) { // tb_startup(); // ---------------------------------------- // static extension (does not require extra storage space in a packet) // ---------------------------------------- packet_t p; // Define the characteristics for this structure, then make sure introspection agrees int numFields = 4; std::string fieldNames[] = { "packet_type", "src", "dest", "payload" }; int fieldValues[] = {0, 0, 1, 2}; int errorCount = 0; // Initialize the fields p.packet_type = fieldValues[0]; p.src = fieldValues[1]; p.dest = fieldValues[2]; p.payload = fieldValues[3]; // Check introspection functions const scv_extensions<packet_t> ext = scv_get_const_extensions(p); int size = ext.get_num_fields(); if (size != numFields) { errorCount++; cout << TBS_ERROR << "Number of fields is " << size << ", should be " << numFields << endl; } else { cout << TBS_INFO << "Number of fields is " << size << endl; } if (size > 0 && size <= numFields) { for (int i=0; i<size; ++i) { const scv_extensions_if * field = ext.get_field(i); if (field == NULL) { errorCount++; cout << TBS_ERROR << "Field " << i << " not found" << endl; } else if (fieldNames[i] != field->get_name()) { errorCount++; cout << TBS_ERROR << "Field " << i << " should have name " << fieldNames[i] << ", instead has name " << field->get_name() << endl; } else if (!field->is_integer()) { errorCount++; cout << TBS_ERROR << "Expected " << fieldNames[i] << " to be of type integer" << endl; } else { if (field->get_integer() != fieldValues[i]) { errorCount++; cout << TBS_ERROR << "Expected value " << fieldValues[i] << " for field " << fieldNames[i] << " found to instead be " << field->get_integer() << endl; } else { cout << TBS_INFO << "Field " << i << " okay" << endl; } } } } // ---------------------------------------- // dynamic extension (allow attachment of callbacks, // uninitialized values, constraints, etc.) // // - require the use of scv_smart_ptr template. // ---------------------------------------- // randomization (direct) (VWG R3d, Rb1) scv_smart_ptr<packet_t> pp; scv_shared_ptr<scv_random> g(new scv_random("gen", RND_SEED)); pp->set_random(g); // // Check introspection functions // fieldValues[0] = 17; fieldValues[1] = 34; fieldValues[2] = 63; fieldValues[3] = -13; pp->packet_type = fieldValues[0]; pp->src = fieldValues[1]; pp->dest = fieldValues[2]; pp->payload = fieldValues[3]; scv_extensions_if *ppExt = pp.get_extensions_ptr(); size = ppExt->get_num_fields(); if (size != numFields) { errorCount++; cout << TBS_ERROR << "Number of fields is " << size << ", should be " << numFields << endl; } else { cout << TBS_INFO << "Number of fields is " << size << endl; } if (size > 0 && size <= numFields) { for (int i=0; i<size; ++i) { const scv_extensions_if * field = ppExt->get_field(i); if (field == NULL) { errorCount++; cout << TBS_ERROR << "Field " << i << " not found" << endl; } else if (fieldNames[i] != field->get_name()) { errorCount++; cout << TBS_ERROR << "Field " << i << " should have name " << fieldNames[i] << ", instead has name " << field->get_name() << endl; } else if (!field->is_integer()) { errorCount++; cout << TBS_ERROR << "Expected " << fieldNames[i] << " to be of type integer" << endl; } else { if (field->get_integer() != fieldValues[i]) { errorCount++; cout << TBS_ERROR << "Expected value " << fieldValues[i] << " for field " << fieldNames[i] << " found to instead be " << field->get_integer() << endl; } else { cout << TBS_INFO << "Field " << i << " okay" << endl; } } } } // // Check uninitialize, initialize and next // cout << TBS_INFO << "Check if maintains initial value across consecutive accesses" << endl; fieldValues[0] = pp->packet_type; fieldValues[1] = pp->src; fieldValues[2] = pp->dest; fieldValues[3] = pp->payload; if (fieldValues[0] != pp->packet_type || fieldValues[1] != pp->src || fieldValues[2] != pp->dest || fieldValues[3] != pp->payload ) { errorCount++; cout << TBS_ERROR << "Value(s) changed across consecutive accesses" << endl; } else { cout << TBS_INFO << "Values maintained across consecutive accesses" << endl; } cout << TBS_INFO << "Make sure they change values after a next" << endl; pp->next(); int newFieldValues[4]; newFieldValues[0] = pp->packet_type; newFieldValues[1] = pp->src; newFieldValues[2] = pp->dest; newFieldValues[3] = pp->payload; if (fieldValues[0] == newFieldValues[0] || fieldValues[1] == newFieldValues[1] || fieldValues[2] == newFieldValues[2] || fieldValues[3] == newFieldValues[3]) { errorCount++; cout << TBS_ERROR << "Value(s) did not change after next" << endl; } else { cout << TBS_INFO << "Values changed after next" << endl; } cout << TBS_INFO << "Check if maintains next value across multiple consecutive accesses" << endl; fieldValues[0] = pp->packet_type; fieldValues[1] = pp->src; fieldValues[2] = pp->dest; fieldValues[3] = pp->payload; if (newFieldValues[0] != pp->packet_type || newFieldValues[1] != pp->src || newFieldValues[2] != pp->dest || newFieldValues[3] != pp->payload ) { errorCount++; cout << TBS_ERROR << "Value(s) changed across consecutive accesses" << endl; } else { cout << TBS_INFO << "Values maintained across consecutive accesses" << endl; } cout << TBS_INFO << "Check if maintains value across spurious initialize" << endl; fieldValues[0] = pp->packet_type; fieldValues[1] = pp->src; fieldValues[2] = pp->dest; fieldValues[3] = pp->payload; pp->initialize(); if (fieldValues[0] != pp->packet_type || fieldValues[1] != pp->src || fieldValues[2] != pp->dest || fieldValues[3] != pp->payload ) { errorCount++; cout << TBS_ERROR << "Value(s) changed across spurious initialize" << endl; } else { cout << TBS_INFO << "Values maintained across spurious initialize" << endl; } cout << TBS_INFO << "Check behavior after uninitialize" << endl; pp->uninitialize(); if (fieldValues[0] == (newFieldValues[0] = pp->packet_type) || fieldValues[1] == (newFieldValues[1] = pp->src) || fieldValues[2] == (newFieldValues[2] = pp->dest) || fieldValues[3] == (newFieldValues[3] = pp->payload)) { errorCount++; cout << TBS_ERROR << "Value(s) didn't change across uninitialize" << endl; } else { cout << TBS_INFO << "Values changed across uninitialize" << endl; } cout << TBS_INFO << "Check behavior after 2nd access after uninitialize" << endl; if (newFieldValues[0] != pp->packet_type || newFieldValues[1] != pp->src || newFieldValues[2] != pp->dest || newFieldValues[3] != pp->payload ) { errorCount++; cout << TBS_ERROR << "Value(s) changed after 2nd access after uninitialize" << endl; } else { cout << TBS_INFO << "Values maintained after 2nd access after uninitialize" << endl; } cout << TBS_INFO << "Check behavior after spurious uninitialize" << endl; pp->uninitialize(); pp->uninitialize(); if (fieldValues[0] == (newFieldValues[0] = pp->packet_type) || fieldValues[1] == (newFieldValues[1] = pp->src) || fieldValues[2] == (newFieldValues[2] = pp->dest) || fieldValues[3] == (newFieldValues[3] = pp->payload)) { errorCount++; cout << TBS_ERROR << "Value(s) didn't change across uninitialize" << endl; } else { cout << TBS_INFO << "Values changed across uninitialize" << endl; } cout << TBS_INFO << "Check behavior after 2nd access after spurious uninitialize" << endl; if (newFieldValues[0] != pp->packet_type || newFieldValues[1] != pp->src || newFieldValues[2] != pp->dest || newFieldValues[3] != pp->payload ) { errorCount++; cout << TBS_ERROR << "Value(s) changed after 2nd access after uninitialize" << endl; } else { cout << TBS_INFO << "Values maintained after 2nd access after uninitialize" << endl; } // // Repeat the above checks, but this time only change 1st and 3rd fields // cout << TBS_INFO << "Repeat above checks, but only changing 1st and 3rd fields" << endl; cout << TBS_INFO << "Make sure they change values after a next" << endl; fieldValues[0] = pp->packet_type; fieldValues[1] = pp->src; fieldValues[2] = pp->dest; fieldValues[3] = pp->payload; pp->packet_type.next(); pp->dest.next(); if (fieldValues[0] == (newFieldValues[0] = pp->packet_type) || fieldValues[1] != (newFieldValues[1] = pp->src) || fieldValues[2] == (newFieldValues[2] = pp->dest) || fieldValues[3] != (newFieldValues[3] = pp->payload)) { errorCount++; cout << TBS_ERROR << "Value did not change properly after next" << endl; } else { cout << TBS_INFO << "Values changed properly after next" << endl; } cout << TBS_INFO << "Check if maintains next value across multiple consecutive accesses" << endl; fieldValues[0] = pp->packet_type; fieldValues[1] = pp->src; fieldValues[2] = pp->dest; fieldValues[3] = pp->payload; if (newFieldValues[0] != pp->packet_type || newFieldValues[1] != pp->src || newFieldValues[2] != pp->dest || newFieldValues[3] != pp->payload ) { errorCount++; cout << TBS_ERROR << "Value(s) changed across consecutive accesses" << endl; } else { cout << TBS_INFO << "Values maintained across consecutive accesses" << endl; } cout << TBS_INFO << "Check if maintains value across spurious initialize" << endl; fieldValues[0] = pp->packet_type; fieldValues[1] = pp->src; fieldValues[2] = pp->dest; fieldValues[3] = pp->payload; pp->packet_type.initialize(); pp->dest.initialize(); if (fieldValues[0] != pp->packet_type || fieldValues[1] != pp->src || fieldValues[2] != pp->dest || fieldValues[3] != pp->payload ) { errorCount++; cout << TBS_ERROR << "Value(s) changed across spurious initialize" << endl; } else { cout << TBS_INFO << "Values maintained across spurious initialize" << endl; } cout << TBS_INFO << "Check behavior after uninitialize" << endl; pp->packet_type.uninitialize(); pp->dest.uninitialize(); if (fieldValues[0] == (newFieldValues[0] = pp->packet_type) || fieldValues[1] != (newFieldValues[1] = pp->src) || fieldValues[2] == (newFieldValues[2] = pp->dest) || fieldValues[3] != (newFieldValues[3] = pp->payload)) { errorCount++; cout << TBS_ERROR << "Value(s) didn't change properly across uninitialize" << endl; } else { cout << TBS_INFO << "Values changed properly across uninitialize" << endl; } cout << TBS_INFO << "Check behavior after 2nd access after uninitialize" << endl; if (newFieldValues[0] != pp->packet_type || newFieldValues[1] != pp->src || newFieldValues[2] != pp->dest || newFieldValues[3] != pp->payload ) { errorCount++; cout << TBS_ERROR << "Value(s) changed after 2nd access after uninitialize" << endl; } else { cout << TBS_INFO << "Values maintained after 2nd access after uninitialize" << endl; } cout << TBS_INFO << "Check behavior after spurious uninitialize" << endl; pp->packet_type.uninitialize(); pp->dest.uninitialize(); pp->packet_type.uninitialize(); pp->dest.uninitialize(); if (fieldValues[0] == (newFieldValues[0] = pp->packet_type) || fieldValues[1] != (newFieldValues[1] = pp->src) || fieldValues[2] == (newFieldValues[2] = pp->dest) || fieldValues[3] != (newFieldValues[3] = pp->payload)) { errorCount++; cout << TBS_ERROR << "Value(s) didn't change properly across uninitialize" << endl; } else { cout << TBS_INFO << "Values changed properly across uninitialize" << endl; } cout << TBS_INFO << "Check behavior after 2nd access after spurious uninitialize" << endl; if (newFieldValues[0] != pp->packet_type || newFieldValues[1] != pp->src || newFieldValues[2] != pp->dest || newFieldValues[3] != pp->payload ) { errorCount++; cout << TBS_ERROR << "Value(s) changed improperly after 2nd access after uninitialize" << endl; } else { cout << TBS_INFO << "Values properly maintained after 2nd access after uninitialize" << endl; } // // Repeat the above checks, but this time only change 2nd and 4th fields // cout << TBS_INFO << "Repeat above checks, but only changing 1st and 3rd fields" << endl; cout << TBS_INFO << "Make sure they change values after a next" << endl; fieldValues[0] = pp->packet_type; fieldValues[1] = pp->src; fieldValues[2] = pp->dest; fieldValues[3] = pp->payload; pp->src.next(); pp->payload.next(); if (fieldValues[0] != (newFieldValues[0] = pp->packet_type) || fieldValues[1] == (newFieldValues[1] = pp->src) || fieldValues[2] != (newFieldValues[2] = pp->dest) || fieldValues[3] == (newFieldValues[3] = pp->payload)) { errorCount++; cout << TBS_ERROR << "Value did not change properly after next" << endl; } else { cout << TBS_INFO << "Values changed properly after next" << endl; } cout << TBS_INFO << "Check if maintains next value across multiple consecutive accesses" << endl; fieldValues[0] = pp->packet_type; fieldValues[1] = pp->src; fieldValues[2] = pp->dest; fieldValues[3] = pp->payload; if (newFieldValues[0] != pp->packet_type || newFieldValues[1] != pp->src || newFieldValues[2] != pp->dest || newFieldValues[3] != pp->payload ) { errorCount++; cout << TBS_ERROR << "Value(s) changed across consecutive accesses" << endl; } else { cout << TBS_INFO << "Values maintained across consecutive accesses" << endl; } cout << TBS_INFO << "Check if maintains value across spurious initialize" << endl; fieldValues[0] = pp->packet_type; fieldValues[1] = pp->src; fieldValues[2] = pp->dest; fieldValues[3] = pp->payload; pp->src.initialize(); pp->payload.initialize(); if (fieldValues[0] != pp->packet_type || fieldValues[1] != pp->src || fieldValues[2] != pp->dest || fieldValues[3] != pp->payload ) { errorCount++; cout << TBS_ERROR << "Value(s) changed across spurious initialize" << endl; } else { cout << TBS_INFO << "Values maintained across spurious initialize" << endl; } cout << TBS_INFO << "Check behavior after uninitialize" << endl; pp->src.uninitialize(); pp->payload.uninitialize(); if (fieldValues[0] != (newFieldValues[0] = pp->packet_type) || fieldValues[1] == (newFieldValues[1] = pp->src) || fieldValues[2] != (newFieldValues[2] = pp->dest) || fieldValues[3] == (newFieldValues[3] = pp->payload)) { errorCount++; cout << TBS_ERROR << "Value(s) didn't change properly across uninitialize" << endl; } else { cout << TBS_INFO << "Values changed properly across uninitialize" << endl; } cout << TBS_INFO << "Check behavior after 2nd access after uninitialize" << endl; if (newFieldValues[0] != pp->packet_type || newFieldValues[1] != pp->src || newFieldValues[2] != pp->dest || newFieldValues[3] != pp->payload ) { errorCount++; cout << TBS_ERROR << "Value(s) changed after 2nd access after uninitialize" << endl; } else { cout << TBS_INFO << "Values maintained after 2nd access after uninitialize" << endl; } cout << TBS_INFO << "Check behavior after spurious uninitialize" << endl; pp->src.uninitialize(); pp->payload.uninitialize(); pp->src.uninitialize(); pp->payload.uninitialize(); if (fieldValues[0] != (newFieldValues[0] = pp->packet_type) || fieldValues[1] == (newFieldValues[1] = pp->src) || fieldValues[2] != (newFieldValues[2] = pp->dest) || fieldValues[3] == (newFieldValues[3] = pp->payload)) { errorCount++; cout << TBS_ERROR << "Value(s) didn't change properly across uninitialize" << endl; } else { cout << TBS_INFO << "Values changed properly across uninitialize" << endl; } cout << TBS_INFO << "Check behavior after 2nd access after spurious uninitialize" << endl; if (newFieldValues[0] != pp->packet_type || newFieldValues[1] != pp->src || newFieldValues[2] != pp->dest || newFieldValues[3] != pp->payload ) { errorCount++; cout << TBS_ERROR << "Value(s) changed improperly after 2nd access after uninitialize" << endl; } else { cout << TBS_INFO << "Values properly maintained after 2nd access after uninitialize" << endl; } if (errorCount != 0) { cout << TBS_FAIL << "Encountered " << errorCount << " errors\n"; } else { cout << TBS_SUCCESS << endl; } }
void print_number_of_fields(const T& data) { cout << "number of fields : " << scv_get_const_extensions(data).get_num_fields() << endl; }