Jump to content

Eyck

Members
  • Posts

    356
  • Joined

  • Last visited

  • Days Won

    87

Everything posted by Eyck

  1. Your do_sum() is sensistive to A_val_in and B_val_in which means wati() finishes as soon as A_val_in or B_val_in gets data. Then you read the data using blocking read. This means the function waits until data in the fifo is available anyways. Your loop could be simplified as void sum::do_sum() { while(true) { unsigned int Sint = A_val_in.read() + B_val_in.read(); S_val_out.write(Sint); sum_finished.notify(SC_ZERO_TIME); } } and you don't need a sensitivity list at all. This can be done also in a non-blocking way: void sum::do_sum() { unsigned int A_val=0, B_val=0; while(true) { wait(A_val_in.data_written_event() && B_val_in.data_written_event()); // this creates an sc_event_and_list if(A_val_in.nb_read(A_val) && B_val_in.nb_read(B_val)){ unsigned int Sint = A_val + B_val; S_val_out.write(Sint); sum_finished.notify(SC_ZERO_TIME); } } } You may also remove the sum_finished event since fifos provide a data_written event (part of the sc_fifo_nonblocking_in_if).
  2. No, a bool does not provide events. More over of A is true for a longer time how often should the thread be activated? I guess what you need is a clock.
  3. You also need to change the order of sc_start and trace file creation: sc_trace_file *tf=sc_create_vcd_trace_file("trace"); tf->set_time_unit(1,SC_NS); sc_trace(tf,A,"A"); sc_trace(tf,B,"B"); sc_trace(tf,O,"O"); sc_start(SC_ZERO_TIME); Afaik the kernel will not add traces once the simulation passed end of elaboration (which happens with the very first call of sc_start())
  4. If you use #include with angle brackets the current directory is not part of the include search path. So either you use #include "andh2.h" or add the current directory to the list of include directories of the compiler invocation
  5. A SC_METHOD being sensitive to a positive edge of a clock is not a latch rather a register. It is the same than in (System)Verilog or VHDL. Moreover a sc_signal is not a queue at all. Writes in the same delta cylce superseed earlier writes in the same delta cycle. A signal in SystemC is similar to a wire or reg in Verilog or a signal in VHDL. Maybe you should revisit your understanding of RTL description and its logics. There are many ways how to implement things. You may write a lot of different modules what brings a lot of overhead. Usually you implement a pipeline as a set of processes (SC_METHODS or even SC_THREADS) communicating via sc_signals or sc_fifos.
  6. Actually this is a Virtualizer specific question so you are better up contacting SNPS directly or try their SolvNet. But if you have missing symbols during link you miss to specify a library. How to solve this is a question to SNPS.
  7. Well, if Stage1 should hold the value of 2 until Stage2 is able to process it then Stage2 need to tell Stage1 that is busy with the value before. In your example Stage2 read (consumed) already the value 2 so that Stage1 can provide the next value (3). This is what you see in the simulation: Stage2 tells Stage1 that it is busy processing the value of 2 so Stage 1 holds the next value (3) until Stage2 is ready. Actually the implementation and behavior is correct.
  8. I'm not aware of any example so I will no be able to answer your question. But I do not see your problem. You would do it as it is done in hardware. Each stage is providing a ready signal indicating to the stage before that it can take inputs. And now the preceeding stage updates its outputs only if the ready signal of the next stage is active.
  9. Due to the METHOD your derived clock switches in the second delta cycle. One way I can think of is 'gating' the primary clock as well: #include "systemc.h" SC_MODULE(ClockPropagater) { sc_in<bool> clk{"clk"}; sc_out<bool> p_clk1{"p_clk1"}, p_clk2{"p_clk2"}; // Clock gating can be potentially added. void Propagate() { p_clk1 = clk; p_clk2 = clk;} SC_CTOR(ClockPropagater) { SC_METHOD(Propagate); sensitive << clk; } }; SC_MODULE(outputer) { sc_in<bool> clk; sc_out<int> c_out; void writer() { for (int i = 0; i < 5; ++i) { cout << "Write " << this->name() << " " << i << endl; c_out.write(i); wait(); } exit(0); } SC_CTOR(outputer) { SC_CTHREAD(writer, clk.pos()); } }; SC_MODULE(reader) { sc_in<bool> clk; sc_in<int> c_in; void read() { while (true) { cout << "Run " << this->name() << " " << this->c_in.read() << endl; wait(); } } SC_CTOR(reader) { SC_CTHREAD(read, clk.pos()); } }; int sc_main(int argc, char* argv[]) { sc_clock TestClk("TestClock", 10, SC_NS,0.5); sc_signal<bool> ck1, ck2; sc_signal<int> sig; ClockPropagater cp{"clock_propagater"}; cp.clk(TestClk); cp.p_clk1(ck1); cp.p_clk2(ck2); outputer o{"output"}; o.clk(ck1); o.c_out(sig); reader r{"reader_propagated_clk"}; r.clk(ck2); r.c_in(sig); reader r1{"reader_raw_clk"}; r1.clk(ck1); r1.c_in(sig); sc_start(); // run forever return 0; }
  10. Do you have an error message or stacktrace (gdb)? 'simulation [...] crashes suddenly' is very generic and can have manifold root causes... Where do you execute the code? You can only create sc_object based elements during elaboration. But if PortElement is a plain C++ class I have no idea why it fails...
  11. I guess your problem stem from a particular implementation detail in SystemC: if you have an inheritance hierarchy you should declare all constructor parameters as ' my_module( sc_core::sc_module_name const& nm). For the leaf module can leave it as 'MyModule(sc_core::sc_module_name nm)'. In the second case a copy of the module name is created which manipulates the hierarchy stack of the kernel. I assume this way you srew up your design. It is save to always pass the sc_module_name by const reference in the constructors. This would makeup for a good rule in a modleing guideline
  12. Well, sc_fifo is not TLM. For your example the basic question is: what is the protocol on fifo_out? Should it be clock-based? Valid-Ready signaling? So your queastion and example is too generic and broad. If you are looking for an example to translate from TLM2.0 to pin level of an Amba AHB protocol you may have a look here: https://git.minres.com/SystemC/SystemC-Components/src/branch/master/incl/tlm/ahb/bfm and https://git.minres.com/SystemC/SystemC-Components/src/branch/master/src/tlm_ahb_bfm_initiator.cpp as well as https://git.minres.com/SystemC/SystemC-Components/src/branch/master/src/tlm_ahb_bfm_target.cpp. They implement TLM2.0 to pin and pin to TLM2.0
  13. AFAIK the first version should properly instantitate. Maybe you mess up within the constructor ... Since this is not really source code it is hard to tell any further. Maybe you can provide a silghtly mor concrete example e.g. on https://www.edaplayground.com/
  14. Basically yes but just add_attribute is not enough. From the top of my head: you need to declare in your sc_module: sc_core::sc_attribute<A*> attr{"attr", nullptr}; sc_core::sc_in<bool> pin{"pin"}; in the constructor of your sc_module you need to add the attribute to the sc_object/sc_port: pin.add_attribute(attr); via attr.value = new A(); you can assign a value. This way the attribute can be found e.g. via the SystemC object tree (sc_core::sc_get_top_level_objects() ). Alternatives depend of your goal. One option would be to use CCI, esp. cci_param. But again, it depends what you want to achieve...
  15. SCV does not contain an the respective overloads for scv_introspection and _scv_distribution. Therefore there is afaik no way to simply randomize a vector. As a workaround you might use the randomization for plain C-style arrays.
  16. Just to add 2 cents to @David Black proposal: If the instantiation is exepensive you could fork() (https://en.wikipedia.org/wiki/Fork_(system_call)) your programm after instantiating the design. Basically you create a new OS process as copy of the current one and here you can continue the simulation. But in essence it is the same approach as David described.
  17. My point was more of a generic nature and more related to modeling guidelines. If your initiator/test_producer has many signals some of them might belong 'logically' together as they are written at the same time. E.g in AHB you have HADDR, HTRANS, HBURST, HWRITE, etc. Instead of declaring them as sc_out<sc_dt::sc_logic> xxx or alike: sc_out<sc_dt::sc_lv<32>> HADDR; sc_out<sc_dt::sc_lv<4>> HTRANS; sc_out<sc_dt::sc_logic> HWRITE; . . . it would make sense to do it this way: struct ahb_req { sc_dt::sc_lv<32> HADDR; sc_dt::sc_lv<4> HTRANS; sc_dt::sc_logic HWRITE; . . . }; sc_out<ahb_req> ahb_out; In the first case you have basically 3 signals/events to observe and deal with. In the latter one you only have 1 event. If you cannot refactor the the producer than doing so just for the receiver is point less. But if you have the option to refactor the initiator then I would recommend to do it in this or a similar way.
  18. You cannot call sc_main directly from main(). main() comes with the SystemC reference implementation (SystemC simulator) and initailizes the simulation kernel. You miss that in your main function, you migh tlook it up at https://github.com/accellera-official/systemc/blob/master/src/sysc/kernel/sc_main.cpp and https://github.com/accellera-official/systemc/blob/master/src/sysc/kernel/sc_main_main.cpp Despite that, you cannot call your sc_main twice. The simulation kernel in the reference implementation is not re-entrant. Thus the LRM states in section 4.3.4.2 Function sc_start: in the sequence you described you would call sc_start() after sc_stop() has been called
  19. You cannot bind an output port to an input port. Ultimately each port must bind to a signal either hierarchically (this is where port to port binding can is used) or directly. So you need to define signal for each of the test_module output ports and bind the sc_out and sc_inout ports to it. 2 remarks: you should use sc_in instead of sc_inout to indicate the purpose clearly sc_out is just a child of sc_inout to reduce the number of output ports (and hence signal) you might want to group signals logically belonging together into structs. Those can be used as data typs of signals and ports. This reduces the number of signals and events and increases simulation speed.
  20. You may check section 14.12 Data length attribute and '14.15 Streaming width attribute' in the LRM. The first says: while the second states in paragraph 😄
  21. AFAICS you don't increment the index i in the while loop. But your code is way to complex.: std::ifstream ifs("TEXT.txt"); if(ifs.is_open()){ int buf = 0; for (int i = 0; i < MEM_DEPTH; i++) { ifs >> buf; buff_1[i]=buf } } ifs.close(); should replace everything from fopen() until fclose(). And you should avoid using macros, they will bite you. '#define MEM_DEPTH 20' should become 'const size_t MEM_DEPTH=20;'.
  22. Not directly. You need to bind Out to a vector of signals of type bool and create a method being sensitive to all signals in the vector. This method then does the conversion and drives the ALUout signal.
  23. Actually there might be a more versatile approach using Python as 'wrapper' and glue for SystemC. There was last year a paper at DVCon Europe about PySysC: http://events.dvcon.org/events/proceedings.aspx?id=278--2 (the repo can be found here: https://git.minres.com/SystemC/PySysC) This allows to use wxWidget, gtk, or QT to interact with the SystemC simulation (the paper shows some prototype I wrote for internal use).
  24. SCML is not open-source and if you look at section 1 of the LICENSE file the folks already violate the license by providing the source code. So you are left with 2 options... For simple busses you can go with the TLM2.0 base protocol which works fairly well. SCC supports non-blocking accesses at the registers and memories so you are left to get or write some interconnect component. AFAIK there are no bus implementations available as open-source to be used out of the box. But you are invited to contribute e.g. to the SCC (you may contact me directly via github).
  25. That is a typo as the method() function shows. it Should read sc_out<sc_uint<2> >
×
×
  • Create New...