Jump to content

Bryan

Members
  • Posts

    11
  • Joined

  • Last visited

Bryan's Achievements

Member

Member (1/2)

0

Reputation

  1. @David Black I will look into this and attempt to learn. Since I have the model working now, it may be a significant change to go through and update to that newer style. However, if I have to make significant changes for some reason, it could make sense to do so. Thank you again.
  2. Thanx @David Black. While my pseudocode above did not show it, I do check the return value of the nb_read() function in my full code before attempting to use the pointer. Or so I intended... Now I get to fall on my sword. Here is pseudocode of what I was actually doing: // In consumer function MyClass* pOtherItem=NULL; if (fifo.nb_read(pOtherItem)) { // process the data available at pOtherItem } delete pOtherItem; The problem was the delete statement needed to be inside of the if protection. It was my intention for that, but I accidentally closed the if before the delete. And unfortunately the debugging dumps I added didn't catch that. This is the second time I have hit an issue when replacing read() with nb_read(). It turns out that this time it was definitely my fault as shown above. The last time I could not determine the reason for the seg-fault. I was likely too quick to blame the nb_read() based on that. A few hours after posting for help above, I finally found the unprotected delete after adding many more debugging dumps to my code. Thank you again for the help though! And I will look into replacing my NULL pointers as suggested.
  3. I have googled and searched this forum, but I cannot find a hint yet to tell me what I'm doing wrong here. It is likely my lack of depth on handling references vs. pointers, but I haven't found a combination which will work. In my model, I dynamically allocate an instance of a custom class in a producer function and write the pointer of that instance into an sc_fifo. In my consumer function, I have been using the sc_fifo_in_if read() function to pop the FIFO entry into a local variable (which is declared as a pointer to my custom class). The read() function is working just fine. I am creating a new model for which I've found that using an nb_read() would work better (and a follow-on nb_write(), but I cannot get that far). But when I attempt to run this code, I run into a seg-fault as soon as I call the nb_read() function. I don't know if there is a C++ limitation or perhaps my need to cast my pointer variable, but since the nb_read() function is utilizing a reference for the variable, I haven't been able to make any casting work. Here is very simplistic pseudo-code of what I want to do: class MyClass { // define my class }; sc_fifo<MyClass*> fifo; // in producer function MyClass* pItem = new MyClass(); fifo.write(pItem); // In consumer function MyClass* pOtherItem=NULL; pOtherItem = fifo.read(); // works fine fifo.nb_read(pOtherItem); // seg-fault I am doing this ultimately because the MyClass item is relatively large, thus copying those around through my model causes a performance hit. Passing around only a pointer to that item (and dynamically creating / destroying it as needed) allows faster runtime. Am I missing something simple? Am I trying to do something not possible? Am I getting lucky (ie: not doing something correctly) when I just use the blocking read() function? Appreciate any guidance here!
  4. @Eyck Thank you very much not only for the quick reply but also the great information. I do have a followup question. You state that I use a method in example 3 vs. a thread in example 2. In my spawn options I did not define the process as a method. And given that the read() function is a blocking function, I believe that the process_fifo_in process is actually a thread. Can you please clarify if I am incorrect? Regardless of that, I was able to make both suggestion 1 and and suggestion 3 work. Is there a preference for spawning the processes in before_end_of_elaboration vs. end_of_elaboration?
  5. Apologies for the poorly worded Title... I am experiencing an odd (to me) issue when constructing a model in which I have a hierarchy more than 1 level deep. ie: I have an sc_module instantiated within another sc_module, and I am attempting to bind an sc_fifo_in (also an out, but I've simplified to a single port for a testcase) from a testbench through the first sc_module to a second. The lowest-level module within the hierarchy has no static process defined by the constructor but instead spawns dynamic processes only which process the fifo. I can make this code work by either: defining a static process and not using the dynamic process (not ideal for my actual application as I have multiple of these to spawn) only have a single level of hierarchy such that I'm not passing the sc_fifo_in port through an sc_module to the second I created 3 examples on EDA Playground rather than posting 70+ lines of code here. If anyone prefers to see the code here instead, I'm happy to paste it. Here is the first example which works (only a single hierarchy level and using a dynamic process only): Working example Here is a second example which works (two levels of hierarchy and uses a static process only): Working example Here is the second example which fails (two levels of hierarchy and uses a dynamic process only): Failing example I have been trying to determine what I am doing wrong all day, and I have drastically simplified my actual code down to this very simple (not terribly interesting) example. In the Failing case, SystemC reports error E112 - port is not bound (I am building with SystemC 2.3.4). I assumed that there was an issue with not having a static process in my BottomHier module and only having a dynamic process, but when I remove the TopHier level as in my first Working Example above, the code compiles and binds ok. And the second example demonstrates that I can successfully pass an sc_fifo_in port through 2 sc_modules without issue. Is there some limitation I am experiencing when attempting to pass the sc_fifo_in through the TopHier module and binding it to the BottomHier module related to the use of a dynamic process? I simply want TopHier to be a pass-through in this example. I appreciate any advice here.
  6. David, Your recommendation was helpful on the -fstack-usage recommendation (that is the correct option). It uncovered a handful (~4) large stack consumers which were statically allocating. One being the top-level testbench itself as I didn't dynamically create it in my sc_main function. I reduced each of those down to more reasonable sizes. The challenge left is the sheer number of processes that I generate as I commented prior. Even with this cleanup, I still require the larger stack size compilation of systemc. One example: In one module, the call to before_end_of_elaboration reports 624 bytes of static allocation. That function was a much larger reporter before I improved it. The large consumer in that function is the spawning of 32 dynamic processes, so the spawn_options (which I now dynamically create rather than statically previously). That particular process is repeated 4096 times in my full model, so alone it accounts for ~2.55MB of static allocation. I believe that is my largest single static consumer with the next one being ~850kB in total. To your 1 types of storage: 1 - I have very few constants that I use across the model (< 50) 2 - I have no global variables (unless SystemC itself creates them), and no static variables 3 - I have converted everything which is obvious to me to convert to dynamic allocations. The pointers themselves still require storage though, and I believe that is a significant portion or my reported stack usage 4 - Plenty of these. I have 17 functions which report > 128 bytes of static allocation, most are smaller but repeated many times. Do you, or anyone else, know if online (or in print) resources which discuss optimizing a large model like this for run-time execution? That would be a future step for me. I have converted some threads to methods, and I have used some dynamic processes as well. I pass pointers or references where I know how to do so. I cannot help but wonder if there is a way to improve my performance with the sheer number of sc_fifo instances which exist in my model. It would take me a while to summarize the number. Thanx again for your assistance. (btw, I have taken your Duolos SystemC & TLM courses before, so we have had conversations during those - about a year ago...)
  7. David, You may be correct in that I may not be handling my variables correctly (I am not a highly experienced C++ user). I have in the past attempted to use sc_vectors to pass signals and fifo interfaces across modules of my design, but I ran into challenges with those. I abandoned the sc_vectors and replaced them with multidimensional arrays of ports. I am building a model of a design which has a multiple layers of hierarchy, each layer assembles modules with their own indexing. At the top, I have multidimensional arrays which are 4-dimensions. That felt beyond my ability when it came to creating the vectors, and the math gets a bit complicated when determining index positions within the vectors for binding. But to make certain I have terminology correct... I do not create new arrays within my SC_THREADs or SC_METHODs. I do define arrays in my class objects. Those consist of either ports (sc_in / sc_out), fifo interfaces, or multidimensional arrays of fifo pointers (I dynamically create the fifos when running the constructor). The total number of fifos I use within the design is quite large for data movement. So while this is not video application, it is a very large scale machine which I am modeling. Regarding the number of processes... I can calculate the number of SC_THREADs which I am launching. That is ~20,000. I have converted some threads to methods where it was straightforward to do so based on other suggestions. But in addition to the SC_THREADs, I also spawn a number of dynamic processes as well. That number is quite large at ~132,000. (I think my math adding those up is correct) If there is a mechanism to report the number of active threads from within my model, I'm happy to do that. The model does continue to run now with my logic corrections which I still see the W518. It's not fast by any means, but it does generate cycles.
  8. After more research, I found some information on the default stack size for threads in the systemc kernel. I discovered the ability to override the default stack size when compiling during the install. So I bumped it up about 4x of the default size. Now I still get the W518 warning, but my simulation actually begins! It hits a different issue which is my own fault, so I shall debug and correct. But the increased default stack size has allowed me to move forward. Should I be concerned about the W518 warning, or can it be ignored since the sim has begun executing?
  9. Ameya and David, Thank you both for the replies. Following up on my problem, it turns out I had a combination of issues which compounded to make this harder to find. The change to my parameters which made it appear that the issue was stack size related was a partial red-herring. I just happened to be crossing a threshold where the compile wasn't hitting a seg fault. Ultimately I had 2 issues: In one of the many for loops I use to construct my design, I had a "<=" in the condition test which should have been just a "<" Once resolved, I DID in fact still need to increase my stack size to avoid a seg fault in sc_main. After many iterations, I have the design elaborating cleanly now. Unfortunately, I've hit a new problem that I'm even less equipped to resolve. Again soliciting advice on where I go from here. I have used setrlimit to set the stack size both very large and smaller, and it does not change this behavior. I did reduce the size of some of the parameters of my design, and it will go further before it hits a seg-fault: Warning: (W518) stack setup failed: unsuccessful stack protection ignored: Cannot allocate memory, address=0x, enable=true In file: ../../../src/sysc/kernel/sc_cor_qt.cpp:172 Error: (E518) stack setup failed: failed to allocate stack memory In file: ../../../src/sysc/kernel/sc_cor_qt.cpp:273 When I shrink the parameters, I still get the Warning above but execution will continue. Then I received a seg-fault after it starts a brief execution: Warning: (W518) stack setup failed: unsuccessful stack protection ignored: Cannot allocate memory, address=0x, enable=true In file: ../../../src/sysc/kernel/sc_cor_qt.cpp:172 reset <snip of output> Segmentation fault (core dumped) I can turn off some work to see if I get past the seg-fault of the second message, but I'm uncertain what to do to address the stack setup error of the first messages. Advice or thoughts on where to look?
  10. I have a model of a large system which I am attempting to compile / simulate but am hitting a seg fault during elaboration. The model is parameterizable, and to some extent I can cause the seg fault to occur at different times during the elaboration by changing the parameters. I have done the obvious things I can find regarding suggestions... ulimit returns "unlimited", and I have varied my available memory (this is running in a VM) up to 32GB with no change. I have run the same model on a different system with the same result. The VM is Ubuntu while the other system is a RedHat production system. I am using SystemC version 2.3.3 on one and 2.3.4 on the other. And I'm compiling with c++17 flags set. I launched the executable with gdb and did a backtrace. I'm not an application debugger, so the output doesn't tell me just other than it's in the bowels of SystemC libraries (which I expected). I'll paste the output below. I've added a series of cout calls in the code to determine where the fail is happening also. Each time is it in the middle of a series of binds which are at different points of a loop. It's not near an extreme, and I am relatively confident in my indexing (although that could be an issue). The fact that the exact fail point moves leads me to believe that is not the issue. One final thing I tried was dumping the output of the getrlimit command to see if my stack was limited. It reports an enormous number, which I believe corresponds to my ulimit report of unlimited. I'm uncertain where to go next. I accept that I'm trying to build a large model, but it's hard to believe it is that large. All of my allocation of module hierarchy is dynamic, and my calls to new are not the fail points... Any advice on next debugging steps, or insight into potential limits of the libraries would be appreciated. Here is the gdb dump if it is informative for anyone... Program received signal SIGSEGV, Segmentation fault. 0x000055555557656f in sc_core::sc_port_b<sc_core::sc_signal_inout_if<bool> >::bind (this=0x555555a9a548, interface_=...) at /opt/systemc-2.3.4//include/sysc/communication/sc_port.h:286 286 { base_type::bind( interface_ ); } (gdb) bt #0 0x000055555557656f in sc_core::sc_port_b<sc_core::sc_signal_inout_if<bool> >::bind (this=0x555555a9a548, interface_=...) at /opt/systemc-2.3.4//include/sysc/communication/sc_port.h:286 #1 0x0000555555578586 in sc_core::sc_port_b<sc_core::sc_signal_inout_if<bool> >::operator() (this=0x555555a9a548, interface_=...) at /opt/systemc-2.3.4//include/sysc/communication/sc_port.h:289 #2 0x0000555555574dfa in Dut<Payload_t, CheckerPkt_t>::Dut (this=0x7fffffe5c7f0, _name=..., _cfg_info=..., _box_id=0) at ./include/dut.h:86 #3 0x000055555556f436 in sc_main (argc=1, argv=0x55555560ed10) at src/main.cpp:25 #4 0x00007ffff7e7ab76 in sc_elab_and_sim () from /opt/systemc-2.3.4//lib-linux64/libsystemc-2.3.4.so #5 0x00007ffff78a80b3 in __libc_start_main (main=0x7ffff7e720f0 <main>, argc=1, argv=0x7fffffffdfa8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdf98) at ../csu/libc-start.c:308 #6 0x000055555556f2ae in _start ()
  11. Hello all, I am building a SystemC model for a project and running into a wall attempting to utilize a sc_vector of sc_vectors for connecting ports. My project is modeling hardware behavior of a design in which I have a few levels of hierarchy, and as I move up the hierarchy, I am assembling a vector from individual signals. At the top of the hierarchy, I need to bind a vector from the middle hierarchy into a vector of vectors at the top. I have created an ultra-simplified testcase of this which demonstrates the issue I run into. I compile cleanly (with SystemC 2.3.4), but my runtime output fails with the following output. If it matters, I am compiling in a Linux environment with with g++ version 8.3.0. SystemC 2.3.4-Accellera --- Feb 9 2023 17:55:01 Warning: (W807) sc_vector::bind called with empty range: target `tophier.midhier0.test_vec_mid' (sc_vector) empty destination range given In file: ../../../src/sysc/utils/sc_vector.cpp:119 Warning: (W807) sc_vector::bind called with empty range: target `tophier.midhier1.test_vec_mid' (sc_vector) empty destination range given In file: ../../../src/sysc/utils/sc_vector.cpp:119 Warning: (W807) sc_vector::bind called with empty range: target `tophier.midhier2.test_vec_mid' (sc_vector) empty destination range given In file: ../../../src/sysc/utils/sc_vector.cpp:119 Warning: (W807) sc_vector::bind called with empty range: target `tophier.midhier3.test_vec_mid' (sc_vector) empty destination range given In file: ../../../src/sysc/utils/sc_vector.cpp:119 Starting simulation... Error: (E109) complete binding failed: port not bound: port 'tophier.midhier3.test_vec_mid_3' (sc_out) In file: ../../../src/sysc/communication/sc_port.cpp:235 I do not profess to be very experienced with C++ / SystemC in general, but I have created a few SystemC projects (and am quite experienced as a digital design engineer). I have used regular sc_vectors in the past with success, but I haven't tried to create a vector of vectors. There may be a better way to do this. A quick description of my testcase: at the bottom-hierarchy, I create a simple 1-bit signal (sig). at the middle-hierarchy, I instantiate multiple bottom-hierarchy modules and want to create a vector of the sig signals into test_vec_mid. at the top-hierarchy, I instantiate multiple middle-hierarchy modules and then want to assemble a 2-dimensional array (vector) of the test_vec_mid signals. In my actual design, I will use that 2D array to redistribute the bits from the vector. Below I will paste my code segment, and if easier, here is a link to the EDAPlayground version of the code. It gives the same errors I see in my system. Link to testcase One more note - I would prefer to use a bool for the datatype at the bottom-hierarchy, but the sc_vector assembly at the top gives a different error. The bool type doesn't have some method the vector assembly is looking for, so I moved to the sc_bv<1>. If there is an easy solution to that, I would be all ears. Finally, I am compiling with -DSC_INCLUDE_DYNAMIC_PROCESSES which was necessary based on the extensive Googling I have done before creating this testcase and posting here (my first post). Thanx to anyone who can offer a solution to this for me! #include <systemc> using namespace sc_core; using namespace sc_dt; #include <iostream> using namespace std; typedef sc_bv<1> BaseType; struct BottomHier : sc_module { public: sc_in<bool> clk{"clk"}; sc_out<BaseType> sig{"sig"}; BottomHier(sc_module_name name) : sc_module(name) { SC_HAS_PROCESS(BottomHier); SC_THREAD(do_work); sensitive << clk.pos(); } void do_work() { sig.write(0); while (1) { sig.write(rand() % 2); wait(); } } }; struct MidHier : sc_module { public: sc_in<bool> clk{"clk"}; sc_vector<sc_out<BaseType > > test_vec_mid; BottomHier* bottomhier[4]; MidHier(sc_module_name name) : sc_module(name), test_vec_mid("test_vec_mid", 4) { for (uint i=0; i<4; i++) { string str = "bottomhier" + to_string(i); bottomhier[i] = new BottomHier(str.c_str()); bottomhier[i]->clk(clk); bottomhier[i]->sig(test_vec_mid[i]); } } }; struct TopHier : sc_module { sc_clock clk{"clk", 10, SC_NS}; sc_vector<sc_vector<sc_signal<BaseType > > > test_vec; static sc_vector< sc_signal< BaseType > >* element_vector_creator(size_t size, const char* name, size_t) { return new sc_vector< sc_signal< BaseType > >( name, size ); } MidHier* midhier[4]; TopHier(sc_module_name name) : sc_module(name), test_vec("test_vec", 4) { for (uint i=0; i<4; i++) { string str = "midhier" + to_string(i); midhier[i] = new MidHier(str.c_str()); midhier[i]->clk(clk); midhier[i]->test_vec_mid(test_vec[i]); } } }; int sc_main(int argc, char *argv[]) { TopHier tophier("tophier"); cout << endl << "Starting simulation..." << endl << endl; sc_start(200, SC_NS); cout << endl << "Simulation complete..." << endl; return 0; }
×
×
  • Create New...