sc_vector.cpp revision 12855:588919e0e4aa
1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20// sc_vector.cpp -- test for 21// 22// Original Author: John Aynsley, Doulos, Inc. 23// 24// MODIFICATION LOG - modifiers, enter your name, affiliation, date and 25// 26// $Log: sc_vector.cpp,v $ 27// Revision 1.3 2011/07/24 16:04:12 acg 28// Philipp A. Hartmann: remove assert() that does not test the correct thing. 29// 30// Revision 1.2 2011/05/08 19:18:46 acg 31// Andy Goodrich: remove extraneous + prefixes from git diff. 32// 33 34// sc_vector 35 36#define SC_INCLUDE_DYNAMIC_PROCESSES 37#include <systemc> 38#include <cstring> 39 40using namespace sc_core; 41using std::cout; 42using std::endl; 43using std::string; 44 45struct Sub: sc_module 46{ 47 sc_inout<int> p; 48 49 Sub(sc_module_name) 50 { 51 SC_THREAD(T); 52 } 53 54 void T() 55 { 56 for (;;) 57 { 58 wait(p.default_event()); 59 } 60 } 61 62 SC_HAS_PROCESS(Sub); 63}; 64 65 66struct my_module: sc_module 67{ 68 my_module(sc_module_name n, string weird_arg ) 69 { 70 sc_assert( weird_arg == "The Creator" || weird_arg == "WeIrD_aRg" ); 71 } 72}; 73 74 75struct my_object: sc_object 76{ 77 my_object() : sc_object() {} 78 my_object(const char* c) : sc_object(c) {} 79}; 80 81 82struct i_f: virtual sc_interface 83{ 84 virtual void method() = 0; 85}; 86 87 88struct Initiator: sc_module 89{ 90 sc_vector<sc_port<i_f> > ports; 91 92 Initiator(sc_module_name) 93 : ports("ports", 4) 94 { 95 SC_THREAD(T); 96 } 97 98 void T() 99 { 100 for (unsigned int i = 0; i < ports.size(); i++) // Use method size() with vector 101 { 102 wait(10, SC_NS); 103 ports[i]->method(); // Use operator[] with vector 104 } 105 } 106 SC_HAS_PROCESS(Initiator); 107}; 108 109 110struct Initiator1: sc_module 111{ 112 sc_port<i_f> port; 113 114 Initiator1(sc_module_name) 115 : port("port") 116 { 117 SC_THREAD(T); 118 } 119 120 void T() 121 { 122 wait(10, SC_NS); 123 port->method(); 124 } 125 SC_HAS_PROCESS(Initiator1); 126}; 127 128 129struct Target: public sc_module, private i_f 130{ 131 sc_export<i_f> xp; 132 133 Target(sc_module_name) 134 : xp("xp") 135 { 136 xp.bind( *this ); 137 } 138 139 virtual void method() { 140 cout << "Called method() in " << name() << " at " << sc_time_stamp() << endl; 141 } 142}; 143 144 145typedef sc_vector<sc_inout<int> > port_type; 146 147struct M: sc_module 148{ 149 port_type ports; // Vector-of-ports 150 151 sc_vector<Sub> kids; // Vector-of-modules, each with a port p 152 sc_vector<Sub> kids2; 153 sc_vector<sc_signal<int> > sigs2; 154 sc_vector<sc_signal<int> > sigs3; 155 156 int dim; 157 158 Initiator* initiator; 159 sc_vector<Target> targets; 160 161 sc_vector<Initiator1> initiator_vec; 162 sc_vector<Target> target_vec; 163 164 165 sc_vector<my_module> my_vec_of_modules; 166 167 struct my_module_creator 168 { 169 my_module_creator( string arg ) : weird_arg(arg) {} 170 171 my_module* operator() (const char* name, size_t) 172 { 173 return new my_module(name, weird_arg ); 174 } 175 string weird_arg; 176 }; 177 178 sc_vector<my_module> my_vec_of_modules2; 179 180 // If creator is not a function object, it could be a function 181 my_module* my_module_creator_func( const char* name, size_t i ) 182 { 183 creator_func_called = true; 184 return new my_module( name, "WeIrD_aRg" ); 185 } 186 187 bool creator_func_called; 188 189 190 M(sc_module_name _name, int N) 191 : ports("ports", N) 192 , kids("kids") // Construct the vector with name seed "kids" 193 , kids2("kids2", 8) 194 , sigs2("sigs2", 4) 195 , sigs3("sigs3", 4) 196 , dim(N) 197 , targets("targets", N) 198 , initiator_vec("initiator_vec", N) 199 , target_vec("target_vec", N) 200 , my_vec_of_modules("my_vec_of_modules") 201 , creator_func_called(false) 202 { 203 //vec.init(N); // Alternative initialization (instead of passing N to ctor) 204 kids.init(N); 205 206 sc_assert( ports.size() == static_cast<unsigned int>(N) ); 207 sc_assert( kids.size() == static_cast<unsigned int>(N) ); 208 209 // Using vector view to create vector-of-ports 210 sc_assemble_vector(kids, &Sub::p).bind( ports ); 211 212 for (unsigned int i = 0; i < kids.size(); i++) 213 { 214 sc_assert( kids[i].p.get_interface() == ports[i].get_interface() ); 215 } 216 217 initiator = new Initiator("initiator"); 218 219 // Using vector view to create vector-of-exports 220 initiator->ports.bind( sc_assemble_vector(targets, &Target::xp) ); 221 222 // Double whammy 223 sc_assemble_vector(initiator_vec, &Initiator1::port).bind( sc_assemble_vector(target_vec, &Target::xp) ); 224 225 // sc_vector_view has no public constructors, though it is copyable 226 sc_vector_assembly< Initiator1, sc_port<i_f> > assembly = sc_assemble_vector(initiator_vec, &Initiator1::port); 227 228 sc_assert( &*(assembly.begin()) == &(*initiator_vec.begin()).port ); 229 // sc_assert( &*(assembly.end()) == &(*initiator_vec.end()).port ); 230 sc_assert( assembly.size() == initiator_vec.size() ); 231 for (unsigned int i = 0; i < assembly.size(); i++) 232 { 233 sc_assert( &assembly[i] == &initiator_vec[i].port ); 234 sc_assert( &assembly.at(i) == &initiator_vec[i].port ); 235 } 236 237 std::vector<sc_object*> elements; 238 239 // sc_vector_view (aka sc_vector_assembly) acts as a proxy for sc_vector 240 // It has begin() end() size() operator[] bind() etc 241 242 elements = assembly.get_elements(); 243 for ( unsigned i = 0; i < elements.size(); i++ ) 244 if ( elements[i] ) 245 sc_assert( elements[i] == &initiator_vec[i].port ); 246 247 elements = ports.get_elements(); 248 for ( unsigned i = 0; i < elements.size(); i++ ) 249 if ( elements[i] ) 250 sc_assert( elements[i] == &ports[i] ); 251 252 elements = sc_assemble_vector(initiator_vec, &Initiator1::port).get_elements(); 253 for ( unsigned i = 0; i < elements.size(); i++ ) 254 if ( elements[i] ) 255 sc_assert( elements[i] == &initiator_vec[i].port ); 256 257 // Additional method to support a vector iterator as an offset 258 sc_assemble_vector(kids2, &Sub::p).bind( sigs2.begin(), sigs2.end(), kids2.begin()); 259 sc_assemble_vector(kids2, &Sub::p).bind( sigs3.begin(), sigs3.end(), kids2.begin() + 4 ); 260 261 // Construct elements of sc_vector, passing through ctor arguments to user-defined sc_module 262 my_vec_of_modules.init(N, my_module_creator("The Creator")); 263 264 // Alternatively, instead of a function object pass in a function 265 my_vec_of_modules2.init(N, sc_bind( &M::my_module_creator_func, this, sc_unnamed::_1, sc_unnamed::_2 ) ); 266 267 // Well-formedness check on creator function call 268 my_module_creator foo("The Creator"); 269 const char* nm = "foo"; 270 unsigned int idx = 0; 271 my_module* next = foo( (const char*)nm, (sc_vector<my_module>::size_type)idx ); 272 char buf[80]; 273 strcpy(buf, this->name()); 274 strcat(buf, ".foo"); 275 sc_assert( strcmp(next->name(), buf) == 0 ); 276 delete next; 277 278 SC_THREAD(T); 279 } 280 281 void T() 282 { 283 int j = 0; 284 for (int i = 0; i < 10; i++) 285 { 286 wait(10, SC_NS); 287 ports[i % dim].write((j++) % 10); // Use operator[] with vector 288 } 289 } 290 291 SC_HAS_PROCESS(M); 292}; 293 294struct Top: sc_module 295{ 296 sc_vector<sc_signal<int> > sigs; // Vector-of-signals 297 sc_vector<sc_signal<int> > more_sigs; // Vector-of-signals 298 sc_vector<sc_signal<int> > hi_sigs; // Vector-of-signals 299 sc_vector<sc_signal<int> > lo_sigs; // Vector-of-signals 300 301 M *m1, *m2, *m3; 302 303 Top(sc_module_name _name) 304 : sigs("sigs", 4) 305 , more_sigs("more_sigs", 4) 306 , hi_sigs("hi_sigs", 2) 307 , lo_sigs("lo_sigs", 2) 308 { 309 m1 = new M("m1", 4); 310 m2 = new M("m2", 4); 311 m3 = new M("m3", 4); 312 313 for (int i = 0; i < 4; i++) 314 m1->ports[i].bind( sigs[i] ); // Using operator[] with a vector 315 316 port_type::iterator it = m2->ports.bind( more_sigs ); // Vector-to-vector bind 317 sc_assert( (it - m2->ports.begin()) == 4 ); 318 319 // Bind upper half of ports vector to hi_sigs 320 it = m3->ports.bind( hi_sigs.begin(), hi_sigs.end() ); 321 sc_assert( (it - m3->ports.begin()) == 2 ); 322 323 // Bind lower half of ports vector to lo_sigs 324 it = m3->ports.bind( lo_sigs.begin(), lo_sigs.end(), it); 325 sc_assert( (it - m3->ports.begin()) == 4 ); 326 327 SC_THREAD(T); 328 SC_THREAD(T2); 329 } 330 331 void T() 332 { 333 sc_event_or_list list; 334 for (int i = 0; i < 4; i++) 335 list |= sigs[i].default_event(); 336 for (;;) 337 { 338 wait(list); 339 cout << "Top:" << sigs[0] << sigs[1] << sigs[2] << sigs[3] << endl; 340 } 341 } 342 343 344 void T2() 345 { 346 wait(10, SC_US); 347 348 // Create sc_vector during simulation 349 sc_vector<my_object> vec_obj("vec_obj", 4); 350 sc_assert( vec_obj.size() == 4 ); 351 for (unsigned int i = 0; i < vec_obj.size(); i++) 352 cout << "vec_obj[" << i << "].name() = " << vec_obj[i].name() << endl; 353 354 sc_object* proc = sc_get_current_process_handle().get_process_object(); 355 std::vector<sc_object*> children = proc->get_child_objects(); 356 357 sc_assert( children.size() == 5 ); // sc_vector itself + 4 X my_object 358 } 359 360 SC_HAS_PROCESS(Top); 361}; 362 363 364int sc_main(int argc, char* argv[]) 365{ 366 Top top("top"); 367 368 std::vector<sc_object*> children = top.get_child_objects(); 369 sc_assert( children.size() == 21 ); // sc_vectors themselves are sc_objects 370 371 sc_start(); 372 373 sc_assert( top.m1->creator_func_called ); 374 sc_assert( top.m2->creator_func_called ); 375 sc_assert( top.m3->creator_func_called ); 376 377 cout << endl << "Success" << endl; 378 return 0; 379} 380 381