112855Sgabeblack@google.com/*****************************************************************************
212855Sgabeblack@google.com
312855Sgabeblack@google.com  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
412855Sgabeblack@google.com  more contributor license agreements.  See the NOTICE file distributed
512855Sgabeblack@google.com  with this work for additional information regarding copyright ownership.
612855Sgabeblack@google.com  Accellera licenses this file to you under the Apache License, Version 2.0
712855Sgabeblack@google.com  (the "License"); you may not use this file except in compliance with the
812855Sgabeblack@google.com  License.  You may obtain a copy of the License at
912855Sgabeblack@google.com
1012855Sgabeblack@google.com    http://www.apache.org/licenses/LICENSE-2.0
1112855Sgabeblack@google.com
1212855Sgabeblack@google.com  Unless required by applicable law or agreed to in writing, software
1312855Sgabeblack@google.com  distributed under the License is distributed on an "AS IS" BASIS,
1412855Sgabeblack@google.com  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1512855Sgabeblack@google.com  implied.  See the License for the specific language governing
1612855Sgabeblack@google.com  permissions and limitations under the License.
1712855Sgabeblack@google.com
1812855Sgabeblack@google.com *****************************************************************************/
1912855Sgabeblack@google.com
2012855Sgabeblack@google.com// sc_vector.cpp -- test for
2112855Sgabeblack@google.com//
2212855Sgabeblack@google.com//  Original Author: John Aynsley, Doulos, Inc.
2312855Sgabeblack@google.com//
2412855Sgabeblack@google.com// MODIFICATION LOG - modifiers, enter your name, affiliation, date and
2512855Sgabeblack@google.com//
2612855Sgabeblack@google.com// $Log: sc_vector.cpp,v $
2712855Sgabeblack@google.com// Revision 1.3  2011/07/24 16:04:12  acg
2812855Sgabeblack@google.com//  Philipp A. Hartmann: remove assert() that does not test the correct thing.
2912855Sgabeblack@google.com//
3012855Sgabeblack@google.com// Revision 1.2  2011/05/08 19:18:46  acg
3112855Sgabeblack@google.com//  Andy Goodrich: remove extraneous + prefixes from git diff.
3212855Sgabeblack@google.com//
3312855Sgabeblack@google.com
3412855Sgabeblack@google.com// sc_vector
3512855Sgabeblack@google.com
3612855Sgabeblack@google.com#define SC_INCLUDE_DYNAMIC_PROCESSES
3712855Sgabeblack@google.com#include <systemc>
3812855Sgabeblack@google.com#include <cstring>
3912855Sgabeblack@google.com
4012855Sgabeblack@google.comusing namespace sc_core;
4112855Sgabeblack@google.comusing std::cout;
4212855Sgabeblack@google.comusing std::endl;
4312855Sgabeblack@google.comusing std::string;
4412855Sgabeblack@google.com
4512855Sgabeblack@google.comstruct Sub: sc_module
4612855Sgabeblack@google.com{
4712855Sgabeblack@google.com  sc_inout<int> p;
4812855Sgabeblack@google.com
4912855Sgabeblack@google.com  Sub(sc_module_name)
5012855Sgabeblack@google.com  {
5112855Sgabeblack@google.com    SC_THREAD(T);
5212855Sgabeblack@google.com  }
5312855Sgabeblack@google.com
5412855Sgabeblack@google.com  void T()
5512855Sgabeblack@google.com  {
5612855Sgabeblack@google.com    for (;;)
5712855Sgabeblack@google.com    {
5812855Sgabeblack@google.com      wait(p.default_event());
5912855Sgabeblack@google.com    }
6012855Sgabeblack@google.com  }
6112855Sgabeblack@google.com
6212855Sgabeblack@google.com  SC_HAS_PROCESS(Sub);
6312855Sgabeblack@google.com};
6412855Sgabeblack@google.com
6512855Sgabeblack@google.com
6612855Sgabeblack@google.comstruct my_module: sc_module
6712855Sgabeblack@google.com{
6812855Sgabeblack@google.com  my_module(sc_module_name n, string weird_arg )
6912855Sgabeblack@google.com  {
7012855Sgabeblack@google.com    sc_assert( weird_arg == "The Creator" || weird_arg == "WeIrD_aRg" );
7112855Sgabeblack@google.com  }
7212855Sgabeblack@google.com};
7312855Sgabeblack@google.com
7412855Sgabeblack@google.com
7512855Sgabeblack@google.comstruct my_object: sc_object
7612855Sgabeblack@google.com{
7712855Sgabeblack@google.com  my_object()              : sc_object()  {}
7812855Sgabeblack@google.com  my_object(const char* c) : sc_object(c) {}
7912855Sgabeblack@google.com};
8012855Sgabeblack@google.com
8112855Sgabeblack@google.com
8212855Sgabeblack@google.comstruct i_f: virtual sc_interface
8312855Sgabeblack@google.com{
8412855Sgabeblack@google.com  virtual void method() = 0;
8512855Sgabeblack@google.com};
8612855Sgabeblack@google.com
8712855Sgabeblack@google.com
8812855Sgabeblack@google.comstruct Initiator: sc_module
8912855Sgabeblack@google.com{
9012855Sgabeblack@google.com  sc_vector<sc_port<i_f> > ports;
9112855Sgabeblack@google.com
9212855Sgabeblack@google.com  Initiator(sc_module_name)
9312855Sgabeblack@google.com  : ports("ports", 4)
9412855Sgabeblack@google.com  {
9512855Sgabeblack@google.com    SC_THREAD(T);
9612855Sgabeblack@google.com  }
9712855Sgabeblack@google.com
9812855Sgabeblack@google.com  void T()
9912855Sgabeblack@google.com  {
10012855Sgabeblack@google.com    for (unsigned int i = 0; i < ports.size(); i++)  // Use method size() with vector
10112855Sgabeblack@google.com    {
10212855Sgabeblack@google.com      wait(10, SC_NS);
10312855Sgabeblack@google.com      ports[i]->method();  // Use operator[] with vector
10412855Sgabeblack@google.com    }
10512855Sgabeblack@google.com  }
10612855Sgabeblack@google.com  SC_HAS_PROCESS(Initiator);
10712855Sgabeblack@google.com};
10812855Sgabeblack@google.com
10912855Sgabeblack@google.com
11012855Sgabeblack@google.comstruct Initiator1: sc_module
11112855Sgabeblack@google.com{
11212855Sgabeblack@google.com  sc_port<i_f> port;
11312855Sgabeblack@google.com
11412855Sgabeblack@google.com  Initiator1(sc_module_name)
11512855Sgabeblack@google.com  : port("port")
11612855Sgabeblack@google.com  {
11712855Sgabeblack@google.com    SC_THREAD(T);
11812855Sgabeblack@google.com  }
11912855Sgabeblack@google.com
12012855Sgabeblack@google.com  void T()
12112855Sgabeblack@google.com  {
12212855Sgabeblack@google.com    wait(10, SC_NS);
12312855Sgabeblack@google.com    port->method();
12412855Sgabeblack@google.com  }
12512855Sgabeblack@google.com  SC_HAS_PROCESS(Initiator1);
12612855Sgabeblack@google.com};
12712855Sgabeblack@google.com
12812855Sgabeblack@google.com
12912855Sgabeblack@google.comstruct Target: public sc_module, private i_f
13012855Sgabeblack@google.com{
13112855Sgabeblack@google.com  sc_export<i_f> xp;
13212855Sgabeblack@google.com
13312855Sgabeblack@google.com  Target(sc_module_name)
13412855Sgabeblack@google.com  : xp("xp")
13512855Sgabeblack@google.com  {
13612855Sgabeblack@google.com    xp.bind( *this );
13712855Sgabeblack@google.com  }
13812855Sgabeblack@google.com
13912855Sgabeblack@google.com  virtual void method() {
14012855Sgabeblack@google.com    cout << "Called method() in " << name() << " at " << sc_time_stamp() << endl;
14112855Sgabeblack@google.com  }
14212855Sgabeblack@google.com};
14312855Sgabeblack@google.com
14412855Sgabeblack@google.com
14512855Sgabeblack@google.comtypedef sc_vector<sc_inout<int> > port_type;
14612855Sgabeblack@google.com
14712855Sgabeblack@google.comstruct M: sc_module
14812855Sgabeblack@google.com{
14912855Sgabeblack@google.com  port_type ports; // Vector-of-ports
15012855Sgabeblack@google.com
15112855Sgabeblack@google.com  sc_vector<Sub> kids; // Vector-of-modules, each with a port p
15212855Sgabeblack@google.com  sc_vector<Sub> kids2;
15312855Sgabeblack@google.com  sc_vector<sc_signal<int> > sigs2;
15412855Sgabeblack@google.com  sc_vector<sc_signal<int> > sigs3;
15512855Sgabeblack@google.com
15612855Sgabeblack@google.com  int dim;
15712855Sgabeblack@google.com
15812855Sgabeblack@google.com  Initiator*        initiator;
15912855Sgabeblack@google.com  sc_vector<Target> targets;
16012855Sgabeblack@google.com
16112855Sgabeblack@google.com  sc_vector<Initiator1> initiator_vec;
16212855Sgabeblack@google.com  sc_vector<Target>     target_vec;
16312855Sgabeblack@google.com
16412855Sgabeblack@google.com
16512855Sgabeblack@google.com  sc_vector<my_module> my_vec_of_modules;
16612855Sgabeblack@google.com
16712855Sgabeblack@google.com  struct my_module_creator
16812855Sgabeblack@google.com  {
16912855Sgabeblack@google.com    my_module_creator( string arg ) : weird_arg(arg) {}
17012855Sgabeblack@google.com
17112855Sgabeblack@google.com    my_module* operator() (const char* name, size_t)
17212855Sgabeblack@google.com    {
17312855Sgabeblack@google.com      return new my_module(name, weird_arg );
17412855Sgabeblack@google.com    }
17512855Sgabeblack@google.com    string weird_arg;
17612855Sgabeblack@google.com  };
17712855Sgabeblack@google.com
17812855Sgabeblack@google.com  sc_vector<my_module> my_vec_of_modules2;
17912855Sgabeblack@google.com
18012855Sgabeblack@google.com  // If creator is not a function object, it could be a function
18112855Sgabeblack@google.com  my_module* my_module_creator_func( const char* name, size_t i )
18212855Sgabeblack@google.com  {
18312855Sgabeblack@google.com    creator_func_called = true;
18412855Sgabeblack@google.com    return new my_module( name, "WeIrD_aRg" );
18512855Sgabeblack@google.com  }
18612855Sgabeblack@google.com
18712855Sgabeblack@google.com  bool creator_func_called;
18812855Sgabeblack@google.com
18912855Sgabeblack@google.com
19012855Sgabeblack@google.com  M(sc_module_name _name, int N)
19112855Sgabeblack@google.com  : ports("ports", N)
19212855Sgabeblack@google.com  , kids("kids")  // Construct the vector with name seed "kids"
19312855Sgabeblack@google.com  , kids2("kids2", 8)
19412855Sgabeblack@google.com  , sigs2("sigs2", 4)
19512855Sgabeblack@google.com  , sigs3("sigs3", 4)
19612855Sgabeblack@google.com  , dim(N)
19712855Sgabeblack@google.com  , targets("targets", N)
19812855Sgabeblack@google.com  , initiator_vec("initiator_vec", N)
19912855Sgabeblack@google.com  , target_vec("target_vec", N)
20012855Sgabeblack@google.com  , my_vec_of_modules("my_vec_of_modules")
20112855Sgabeblack@google.com  , creator_func_called(false)
20212855Sgabeblack@google.com  {
20312855Sgabeblack@google.com    //vec.init(N);  // Alternative initialization (instead of passing N to ctor)
20412855Sgabeblack@google.com    kids.init(N);
20512855Sgabeblack@google.com
20612855Sgabeblack@google.com    sc_assert( ports.size() == static_cast<unsigned int>(N) );
20712855Sgabeblack@google.com    sc_assert( kids.size()  == static_cast<unsigned int>(N) );
20812855Sgabeblack@google.com
20912855Sgabeblack@google.com    // Using vector view to create vector-of-ports
21012855Sgabeblack@google.com    sc_assemble_vector(kids, &Sub::p).bind( ports );
21112855Sgabeblack@google.com
21212855Sgabeblack@google.com    for (unsigned int i = 0; i < kids.size(); i++)
21312855Sgabeblack@google.com    {
21412855Sgabeblack@google.com      sc_assert( kids[i].p.get_interface() == ports[i].get_interface() );
21512855Sgabeblack@google.com    }
21612855Sgabeblack@google.com
21712855Sgabeblack@google.com    initiator = new Initiator("initiator");
21812855Sgabeblack@google.com
21912855Sgabeblack@google.com    // Using vector view to create vector-of-exports
22012855Sgabeblack@google.com    initiator->ports.bind( sc_assemble_vector(targets, &Target::xp) );
22112855Sgabeblack@google.com
22212855Sgabeblack@google.com    // Double whammy
22312855Sgabeblack@google.com    sc_assemble_vector(initiator_vec, &Initiator1::port).bind( sc_assemble_vector(target_vec, &Target::xp) );
22412855Sgabeblack@google.com
22512855Sgabeblack@google.com    // sc_vector_view has no public constructors, though it is copyable
22612855Sgabeblack@google.com    sc_vector_assembly< Initiator1, sc_port<i_f> > assembly = sc_assemble_vector(initiator_vec, &Initiator1::port);
22712855Sgabeblack@google.com
22812855Sgabeblack@google.com    sc_assert( &*(assembly.begin()) == &(*initiator_vec.begin()).port );
22912855Sgabeblack@google.com    // sc_assert( &*(assembly.end())   == &(*initiator_vec.end()).port );
23012855Sgabeblack@google.com    sc_assert( assembly.size()  == initiator_vec.size() );
23112855Sgabeblack@google.com    for (unsigned int i = 0; i < assembly.size(); i++)
23212855Sgabeblack@google.com    {
23312855Sgabeblack@google.com      sc_assert( &assembly[i]    == &initiator_vec[i].port );
23412855Sgabeblack@google.com      sc_assert( &assembly.at(i) == &initiator_vec[i].port );
23512855Sgabeblack@google.com    }
23612855Sgabeblack@google.com
23712855Sgabeblack@google.com    std::vector<sc_object*> elements;
23812855Sgabeblack@google.com
23912855Sgabeblack@google.com    // sc_vector_view (aka sc_vector_assembly) acts as a proxy for sc_vector
24012855Sgabeblack@google.com    // It has begin() end() size() operator[] bind() etc
24112855Sgabeblack@google.com
24212855Sgabeblack@google.com    elements = assembly.get_elements();
24312855Sgabeblack@google.com    for ( unsigned i = 0; i < elements.size(); i++ )
24412855Sgabeblack@google.com      if ( elements[i] )
24512855Sgabeblack@google.com        sc_assert( elements[i] == &initiator_vec[i].port );
24612855Sgabeblack@google.com
24712855Sgabeblack@google.com    elements = ports.get_elements();
24812855Sgabeblack@google.com    for ( unsigned i = 0; i < elements.size(); i++ )
24912855Sgabeblack@google.com      if ( elements[i] )
25012855Sgabeblack@google.com        sc_assert( elements[i] == &ports[i] );
25112855Sgabeblack@google.com
25212855Sgabeblack@google.com    elements = sc_assemble_vector(initiator_vec, &Initiator1::port).get_elements();
25312855Sgabeblack@google.com    for ( unsigned i = 0; i < elements.size(); i++ )
25412855Sgabeblack@google.com      if ( elements[i] )
25512855Sgabeblack@google.com        sc_assert( elements[i] == &initiator_vec[i].port );
25612855Sgabeblack@google.com
25712855Sgabeblack@google.com    // Additional method to support a vector iterator as an offset
25812855Sgabeblack@google.com    sc_assemble_vector(kids2, &Sub::p).bind( sigs2.begin(), sigs2.end(), kids2.begin());
25912855Sgabeblack@google.com    sc_assemble_vector(kids2, &Sub::p).bind( sigs3.begin(), sigs3.end(), kids2.begin() + 4 );
26012855Sgabeblack@google.com
26112855Sgabeblack@google.com    // Construct elements of sc_vector, passing through ctor arguments to user-defined sc_module
26212855Sgabeblack@google.com    my_vec_of_modules.init(N, my_module_creator("The Creator"));
26312855Sgabeblack@google.com
26412855Sgabeblack@google.com    // Alternatively, instead of a function object pass in a function
26512855Sgabeblack@google.com    my_vec_of_modules2.init(N, sc_bind( &M::my_module_creator_func, this, sc_unnamed::_1, sc_unnamed::_2 ) );
26612855Sgabeblack@google.com
26712855Sgabeblack@google.com    // Well-formedness check on creator function call
26812855Sgabeblack@google.com    my_module_creator foo("The Creator");
26912855Sgabeblack@google.com    const char* nm = "foo";
27012855Sgabeblack@google.com    unsigned int idx = 0;
27112855Sgabeblack@google.com    my_module* next = foo( (const char*)nm, (sc_vector<my_module>::size_type)idx );
27212855Sgabeblack@google.com    char buf[80];
27312855Sgabeblack@google.com    strcpy(buf, this->name());
27412855Sgabeblack@google.com    strcat(buf, ".foo");
27512855Sgabeblack@google.com    sc_assert( strcmp(next->name(), buf) == 0 );
27612855Sgabeblack@google.com    delete next;
27712855Sgabeblack@google.com
27812855Sgabeblack@google.com    SC_THREAD(T);
27912855Sgabeblack@google.com  }
28012855Sgabeblack@google.com
28112855Sgabeblack@google.com  void T()
28212855Sgabeblack@google.com  {
28312855Sgabeblack@google.com    int j = 0;
28412855Sgabeblack@google.com    for (int i = 0; i < 10; i++)
28512855Sgabeblack@google.com    {
28612855Sgabeblack@google.com      wait(10, SC_NS);
28712855Sgabeblack@google.com      ports[i % dim].write((j++) % 10);  // Use operator[] with vector
28812855Sgabeblack@google.com    }
28912855Sgabeblack@google.com  }
29012855Sgabeblack@google.com
29112855Sgabeblack@google.com  SC_HAS_PROCESS(M);
29212855Sgabeblack@google.com};
29312855Sgabeblack@google.com
29412855Sgabeblack@google.comstruct Top: sc_module
29512855Sgabeblack@google.com{
29612855Sgabeblack@google.com  sc_vector<sc_signal<int> > sigs; // Vector-of-signals
29712855Sgabeblack@google.com  sc_vector<sc_signal<int> > more_sigs; // Vector-of-signals
29812855Sgabeblack@google.com  sc_vector<sc_signal<int> > hi_sigs; // Vector-of-signals
29912855Sgabeblack@google.com  sc_vector<sc_signal<int> > lo_sigs; // Vector-of-signals
30012855Sgabeblack@google.com
30112855Sgabeblack@google.com  M *m1, *m2, *m3;
30212855Sgabeblack@google.com
30312855Sgabeblack@google.com  Top(sc_module_name _name)
30412855Sgabeblack@google.com  : sigs("sigs", 4)
30512855Sgabeblack@google.com  , more_sigs("more_sigs", 4)
30612855Sgabeblack@google.com  , hi_sigs("hi_sigs", 2)
30712855Sgabeblack@google.com  , lo_sigs("lo_sigs", 2)
30812855Sgabeblack@google.com  {
30912855Sgabeblack@google.com    m1 = new M("m1", 4);
31012855Sgabeblack@google.com    m2 = new M("m2", 4);
31112855Sgabeblack@google.com    m3 = new M("m3", 4);
31212855Sgabeblack@google.com
31312855Sgabeblack@google.com    for (int i = 0; i < 4; i++)
31412855Sgabeblack@google.com      m1->ports[i].bind( sigs[i] );  // Using operator[] with a vector
31512855Sgabeblack@google.com
31612855Sgabeblack@google.com    port_type::iterator it = m2->ports.bind( more_sigs ); // Vector-to-vector bind
31712855Sgabeblack@google.com    sc_assert( (it - m2->ports.begin()) == 4 );
31812855Sgabeblack@google.com
31912855Sgabeblack@google.com    // Bind upper half of ports vector to hi_sigs
32012855Sgabeblack@google.com    it = m3->ports.bind( hi_sigs.begin(), hi_sigs.end() );
32112855Sgabeblack@google.com    sc_assert( (it - m3->ports.begin()) == 2 );
32212855Sgabeblack@google.com
32312855Sgabeblack@google.com    // Bind lower half of ports vector to lo_sigs
32412855Sgabeblack@google.com    it = m3->ports.bind( lo_sigs.begin(), lo_sigs.end(), it);
32512855Sgabeblack@google.com    sc_assert( (it - m3->ports.begin()) == 4 );
32612855Sgabeblack@google.com
32712855Sgabeblack@google.com    SC_THREAD(T);
32812855Sgabeblack@google.com    SC_THREAD(T2);
32912855Sgabeblack@google.com  }
33012855Sgabeblack@google.com
33112855Sgabeblack@google.com  void T()
33212855Sgabeblack@google.com  {
33312855Sgabeblack@google.com    sc_event_or_list list;
33412855Sgabeblack@google.com    for (int i = 0; i < 4; i++)
33512855Sgabeblack@google.com      list |= sigs[i].default_event();
33612855Sgabeblack@google.com    for (;;)
33712855Sgabeblack@google.com    {
33812855Sgabeblack@google.com      wait(list);
33912855Sgabeblack@google.com      cout << "Top:" << sigs[0] << sigs[1] << sigs[2] << sigs[3] << endl;
34012855Sgabeblack@google.com    }
34112855Sgabeblack@google.com  }
34212855Sgabeblack@google.com
34312855Sgabeblack@google.com
34412855Sgabeblack@google.com  void T2()
34512855Sgabeblack@google.com  {
34612855Sgabeblack@google.com    wait(10, SC_US);
34712855Sgabeblack@google.com
34812855Sgabeblack@google.com    // Create sc_vector during simulation
34912855Sgabeblack@google.com    sc_vector<my_object> vec_obj("vec_obj", 4);
35012855Sgabeblack@google.com    sc_assert( vec_obj.size() == 4 );
35112855Sgabeblack@google.com    for (unsigned int i = 0; i < vec_obj.size(); i++)
35212855Sgabeblack@google.com      cout << "vec_obj[" << i << "].name() = " << vec_obj[i].name() << endl;
35312855Sgabeblack@google.com
35412855Sgabeblack@google.com    sc_object* proc = sc_get_current_process_handle().get_process_object();
35512855Sgabeblack@google.com    std::vector<sc_object*> children = proc->get_child_objects();
35612855Sgabeblack@google.com
35712855Sgabeblack@google.com    sc_assert( children.size() == 5 ); // sc_vector itself + 4 X my_object
35812855Sgabeblack@google.com  }
35912855Sgabeblack@google.com
36012855Sgabeblack@google.com  SC_HAS_PROCESS(Top);
36112855Sgabeblack@google.com};
36212855Sgabeblack@google.com
36312855Sgabeblack@google.com
36412855Sgabeblack@google.comint sc_main(int argc, char* argv[])
36512855Sgabeblack@google.com{
36612855Sgabeblack@google.com  Top top("top");
36712855Sgabeblack@google.com
36812855Sgabeblack@google.com  std::vector<sc_object*> children = top.get_child_objects();
36912855Sgabeblack@google.com  sc_assert( children.size() == 21 ); // sc_vectors themselves are sc_objects
37012855Sgabeblack@google.com
37112855Sgabeblack@google.com  sc_start();
37212855Sgabeblack@google.com
37312855Sgabeblack@google.com  sc_assert( top.m1->creator_func_called );
37412855Sgabeblack@google.com  sc_assert( top.m2->creator_func_called );
37512855Sgabeblack@google.com  sc_assert( top.m3->creator_func_called );
37612855Sgabeblack@google.com
37712855Sgabeblack@google.com  cout << endl << "Success" << endl;
37812855Sgabeblack@google.com  return 0;
37912855Sgabeblack@google.com}
38012855Sgabeblack@google.com
381