diff options
Diffstat (limited to 'src/systemc/tests/systemc/1666-2011-compliance/sc_vector/sc_vector.cpp')
-rw-r--r-- | src/systemc/tests/systemc/1666-2011-compliance/sc_vector/sc_vector.cpp | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/src/systemc/tests/systemc/1666-2011-compliance/sc_vector/sc_vector.cpp b/src/systemc/tests/systemc/1666-2011-compliance/sc_vector/sc_vector.cpp new file mode 100644 index 000000000..21628e93d --- /dev/null +++ b/src/systemc/tests/systemc/1666-2011-compliance/sc_vector/sc_vector.cpp @@ -0,0 +1,380 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +// sc_vector.cpp -- test for +// +// Original Author: John Aynsley, Doulos, Inc. +// +// MODIFICATION LOG - modifiers, enter your name, affiliation, date and +// +// $Log: sc_vector.cpp,v $ +// Revision 1.3 2011/07/24 16:04:12 acg +// Philipp A. Hartmann: remove assert() that does not test the correct thing. +// +// Revision 1.2 2011/05/08 19:18:46 acg +// Andy Goodrich: remove extraneous + prefixes from git diff. +// + +// sc_vector + +#define SC_INCLUDE_DYNAMIC_PROCESSES +#include <systemc> +#include <cstring> + +using namespace sc_core; +using std::cout; +using std::endl; +using std::string; + +struct Sub: sc_module +{ + sc_inout<int> p; + + Sub(sc_module_name) + { + SC_THREAD(T); + } + + void T() + { + for (;;) + { + wait(p.default_event()); + } + } + + SC_HAS_PROCESS(Sub); +}; + + +struct my_module: sc_module +{ + my_module(sc_module_name n, string weird_arg ) + { + sc_assert( weird_arg == "The Creator" || weird_arg == "WeIrD_aRg" ); + } +}; + + +struct my_object: sc_object +{ + my_object() : sc_object() {} + my_object(const char* c) : sc_object(c) {} +}; + + +struct i_f: virtual sc_interface +{ + virtual void method() = 0; +}; + + +struct Initiator: sc_module +{ + sc_vector<sc_port<i_f> > ports; + + Initiator(sc_module_name) + : ports("ports", 4) + { + SC_THREAD(T); + } + + void T() + { + for (unsigned int i = 0; i < ports.size(); i++) // Use method size() with vector + { + wait(10, SC_NS); + ports[i]->method(); // Use operator[] with vector + } + } + SC_HAS_PROCESS(Initiator); +}; + + +struct Initiator1: sc_module +{ + sc_port<i_f> port; + + Initiator1(sc_module_name) + : port("port") + { + SC_THREAD(T); + } + + void T() + { + wait(10, SC_NS); + port->method(); + } + SC_HAS_PROCESS(Initiator1); +}; + + +struct Target: public sc_module, private i_f +{ + sc_export<i_f> xp; + + Target(sc_module_name) + : xp("xp") + { + xp.bind( *this ); + } + + virtual void method() { + cout << "Called method() in " << name() << " at " << sc_time_stamp() << endl; + } +}; + + +typedef sc_vector<sc_inout<int> > port_type; + +struct M: sc_module +{ + port_type ports; // Vector-of-ports + + sc_vector<Sub> kids; // Vector-of-modules, each with a port p + sc_vector<Sub> kids2; + sc_vector<sc_signal<int> > sigs2; + sc_vector<sc_signal<int> > sigs3; + + int dim; + + Initiator* initiator; + sc_vector<Target> targets; + + sc_vector<Initiator1> initiator_vec; + sc_vector<Target> target_vec; + + + sc_vector<my_module> my_vec_of_modules; + + struct my_module_creator + { + my_module_creator( string arg ) : weird_arg(arg) {} + + my_module* operator() (const char* name, size_t) + { + return new my_module(name, weird_arg ); + } + string weird_arg; + }; + + sc_vector<my_module> my_vec_of_modules2; + + // If creator is not a function object, it could be a function + my_module* my_module_creator_func( const char* name, size_t i ) + { + creator_func_called = true; + return new my_module( name, "WeIrD_aRg" ); + } + + bool creator_func_called; + + + M(sc_module_name _name, int N) + : ports("ports", N) + , kids("kids") // Construct the vector with name seed "kids" + , kids2("kids2", 8) + , sigs2("sigs2", 4) + , sigs3("sigs3", 4) + , dim(N) + , targets("targets", N) + , initiator_vec("initiator_vec", N) + , target_vec("target_vec", N) + , my_vec_of_modules("my_vec_of_modules") + , creator_func_called(false) + { + //vec.init(N); // Alternative initialization (instead of passing N to ctor) + kids.init(N); + + sc_assert( ports.size() == static_cast<unsigned int>(N) ); + sc_assert( kids.size() == static_cast<unsigned int>(N) ); + + // Using vector view to create vector-of-ports + sc_assemble_vector(kids, &Sub::p).bind( ports ); + + for (unsigned int i = 0; i < kids.size(); i++) + { + sc_assert( kids[i].p.get_interface() == ports[i].get_interface() ); + } + + initiator = new Initiator("initiator"); + + // Using vector view to create vector-of-exports + initiator->ports.bind( sc_assemble_vector(targets, &Target::xp) ); + + // Double whammy + sc_assemble_vector(initiator_vec, &Initiator1::port).bind( sc_assemble_vector(target_vec, &Target::xp) ); + + // sc_vector_view has no public constructors, though it is copyable + sc_vector_assembly< Initiator1, sc_port<i_f> > assembly = sc_assemble_vector(initiator_vec, &Initiator1::port); + + sc_assert( &*(assembly.begin()) == &(*initiator_vec.begin()).port ); + // sc_assert( &*(assembly.end()) == &(*initiator_vec.end()).port ); + sc_assert( assembly.size() == initiator_vec.size() ); + for (unsigned int i = 0; i < assembly.size(); i++) + { + sc_assert( &assembly[i] == &initiator_vec[i].port ); + sc_assert( &assembly.at(i) == &initiator_vec[i].port ); + } + + std::vector<sc_object*> elements; + + // sc_vector_view (aka sc_vector_assembly) acts as a proxy for sc_vector + // It has begin() end() size() operator[] bind() etc + + elements = assembly.get_elements(); + for ( unsigned i = 0; i < elements.size(); i++ ) + if ( elements[i] ) + sc_assert( elements[i] == &initiator_vec[i].port ); + + elements = ports.get_elements(); + for ( unsigned i = 0; i < elements.size(); i++ ) + if ( elements[i] ) + sc_assert( elements[i] == &ports[i] ); + + elements = sc_assemble_vector(initiator_vec, &Initiator1::port).get_elements(); + for ( unsigned i = 0; i < elements.size(); i++ ) + if ( elements[i] ) + sc_assert( elements[i] == &initiator_vec[i].port ); + + // Additional method to support a vector iterator as an offset + sc_assemble_vector(kids2, &Sub::p).bind( sigs2.begin(), sigs2.end(), kids2.begin()); + sc_assemble_vector(kids2, &Sub::p).bind( sigs3.begin(), sigs3.end(), kids2.begin() + 4 ); + + // Construct elements of sc_vector, passing through ctor arguments to user-defined sc_module + my_vec_of_modules.init(N, my_module_creator("The Creator")); + + // Alternatively, instead of a function object pass in a function + my_vec_of_modules2.init(N, sc_bind( &M::my_module_creator_func, this, sc_unnamed::_1, sc_unnamed::_2 ) ); + + // Well-formedness check on creator function call + my_module_creator foo("The Creator"); + const char* nm = "foo"; + unsigned int idx = 0; + my_module* next = foo( (const char*)nm, (sc_vector<my_module>::size_type)idx ); + char buf[80]; + strcpy(buf, this->name()); + strcat(buf, ".foo"); + sc_assert( strcmp(next->name(), buf) == 0 ); + delete next; + + SC_THREAD(T); + } + + void T() + { + int j = 0; + for (int i = 0; i < 10; i++) + { + wait(10, SC_NS); + ports[i % dim].write((j++) % 10); // Use operator[] with vector + } + } + + SC_HAS_PROCESS(M); +}; + +struct Top: sc_module +{ + sc_vector<sc_signal<int> > sigs; // Vector-of-signals + sc_vector<sc_signal<int> > more_sigs; // Vector-of-signals + sc_vector<sc_signal<int> > hi_sigs; // Vector-of-signals + sc_vector<sc_signal<int> > lo_sigs; // Vector-of-signals + + M *m1, *m2, *m3; + + Top(sc_module_name _name) + : sigs("sigs", 4) + , more_sigs("more_sigs", 4) + , hi_sigs("hi_sigs", 2) + , lo_sigs("lo_sigs", 2) + { + m1 = new M("m1", 4); + m2 = new M("m2", 4); + m3 = new M("m3", 4); + + for (int i = 0; i < 4; i++) + m1->ports[i].bind( sigs[i] ); // Using operator[] with a vector + + port_type::iterator it = m2->ports.bind( more_sigs ); // Vector-to-vector bind + sc_assert( (it - m2->ports.begin()) == 4 ); + + // Bind upper half of ports vector to hi_sigs + it = m3->ports.bind( hi_sigs.begin(), hi_sigs.end() ); + sc_assert( (it - m3->ports.begin()) == 2 ); + + // Bind lower half of ports vector to lo_sigs + it = m3->ports.bind( lo_sigs.begin(), lo_sigs.end(), it); + sc_assert( (it - m3->ports.begin()) == 4 ); + + SC_THREAD(T); + SC_THREAD(T2); + } + + void T() + { + sc_event_or_list list; + for (int i = 0; i < 4; i++) + list |= sigs[i].default_event(); + for (;;) + { + wait(list); + cout << "Top:" << sigs[0] << sigs[1] << sigs[2] << sigs[3] << endl; + } + } + + + void T2() + { + wait(10, SC_US); + + // Create sc_vector during simulation + sc_vector<my_object> vec_obj("vec_obj", 4); + sc_assert( vec_obj.size() == 4 ); + for (unsigned int i = 0; i < vec_obj.size(); i++) + cout << "vec_obj[" << i << "].name() = " << vec_obj[i].name() << endl; + + sc_object* proc = sc_get_current_process_handle().get_process_object(); + std::vector<sc_object*> children = proc->get_child_objects(); + + sc_assert( children.size() == 5 ); // sc_vector itself + 4 X my_object + } + + SC_HAS_PROCESS(Top); +}; + + +int sc_main(int argc, char* argv[]) +{ + Top top("top"); + + std::vector<sc_object*> children = top.get_child_objects(); + sc_assert( children.size() == 21 ); // sc_vectors themselves are sc_objects + + sc_start(); + + sc_assert( top.m1->creator_func_called ); + sc_assert( top.m2->creator_func_called ); + sc_assert( top.m3->creator_func_called ); + + cout << endl << "Success" << endl; + return 0; +} + |