Jump to content

Eyck

Members
  • Posts

    355
  • Joined

  • Last visited

  • Days Won

    87

Everything posted by Eyck

  1. You are readfing the port in the construcotr. At this time the port has no connection to a signal and you get the error message. You migth move this part to either end_of_elaboration() or start_of_simulation() or drop it at all.
  2. Can you prove the example on edaplayground? This would allow to help with reasonable time.
  3. The problem is that the pointer is not initialized. So : A *extA{nullptr}; req->get_extension(ext); // tlm::tlm_generic_payload *req is the declaration if (extA == nullptr) { do ActionX } else { do ActionY } should do the trick. BTW , a better soultion would be: auto* extA = req->get_extension<A>(); if (extA == nullptr) { do ActionX } else { do ActionY } or even more concise: if (auto* extA = req->get_extension<A>()) { do ActionY } else { do ActionX }
  4. Your design has several issues and flaws. The issues are: In ALU you assign a value to opc_out in the constructor. At that point the port does not have a signal attached. You need to move this assignement into subtract: void subtract() { out_sub = 0; if (Opmode == '0') out_sub = in1 - in2; } You do not connect Opmode to a signal in Datapath Aside of that these are the flaws I see: you should name your signals and port. This helps to debig things. Using C++11 (which all actuall compilers use by default) you can do it like this which does not give to much overhead: class ALU : public sc_module { public: sc_in <int> in1{"in1"}, in2{"in2"}; sc_out <int> out_sub{"out_sub"}; sc_in < sc_logic > Opmode{"Opmode"}; sc_out <sc_logic> equal{"equal"}, greater{"greater"}; There is no need to create modules dynamically except you want to do this in before_end_of_elaboation(). This eases readability and enures consistent memory management and destructor calls. Dont do multiple declarations and assignements in the same line. Although C/C++ permits I highly recommend to avoid: void Controller::next_state_gen() { switch (P_state) { case idle: a_sel = SC_LOGIC_0, b_sel = SC_LOGIC_0, ld_a = SC_LOGIC_0, ld_b = SC_LOGIC_0, ld_GCD = SC_LOGIC_0; It makes reading and understanding your code difficult. And code is much more read than written.
  5. SInce the question is already 4 years old I guess there will be now answer. If you need something like the fair mutex you might have a look at the scc::ordered_semaphore which can also be used as a mutex (with a value of one). At https://github.com/Minres/SystemC-Components/blob/main/src/sysc/scc you will find a complete implementation.
  6. Why not use constructor prameters? Another option would be cci_params. Via the broker they can be given a value before they are created. So you can use them in contructor bodies....
  7. You need to implement a method or a thread being sensitive on the clock. Something like: SC_MODULE(test) { sc_core::sc_in<bool> clk_i{"clk_i"}; sc_core::sc_ou<bool> out_o{"out_o"}; SC_CTOR(test) { SC_THREAD(run); } void run(){ while(true) { wait(clk_i.posedge_event()); out_o.write(!out_o.read()); } } };
  8. You can find a complete implementation of a memory here: https://github.com/Minres/SystemC-Components/blob/main/src/components/scc/memory.h or here: https://git.minres.com/SystemC/PySysC-SC/src/branch/master/components/target.cpp The latter has also a toplevel: https://git.minres.com/SystemC/PySysC-SC/src/branch/master/top/ BR
  9. Well, t_socket[i] is a pointer. So with o_tb[i]->bind(m_abc->t_socket[i]); you are calling bind with a pointer. There is no such function defined. I would suggest to refrain from using raw pointers and C-style arrays as they harm more than helping you. I coded up an example at https://www.edaplayground.com/x/MTTy If you are going to build up a really big design then you should use a std::unique_ptr with std::make_unique in your sc_main function only. This way all design elements will be instantiated using a single new call...
  10. the simple_target_socket_tagged does tell the callback which socket called the callback not which initiator. So you need to have a target socket for each of your peripherals. A use example of tagged sockets can be found at https://www.doulos.com/httpswwwdouloscomknowhow/systemc/tlm-20/tutorial-3-routing-methods-through-interconnect-components/ where simple_initiator_socket_:tagged is used for the router. The use of simple_target_socket_tagged is similar.
  11. TGC is 'The Good Core' family of RISC-V cores of MINRES Technolgis GmbH. The VP-Vibes organization at Github is for any project related to Virtual Prototypes. So the SystemC-Components library comes with SystemC utilities, components like register and generic bus targets as well as on-chip interconnect protocol definitions. The VPV-Peripherals provides peripherals which can be used in building VPs while the TGC-VP assembles all these components into a VP. Parts of the VP, in detail the ISS and its infrastructure, is being used as reference model to verify the RTL implementation(s). For this we use an insturction stream generator and a response checker (see also here).
  12. tri-state logic is not synthesizable. But if you use a 2-bit vector where one bit shows activity and one bit the value this can be synthesized... But it doubles the number af wires and depending on the gate logic the size of the logic. This may be wroked around by designing a custom cell for the standard cell library. After it is characterized the cell might be used by the synthesizer.
  13. Yes, you are writing 2 elements into the fifo in the same evaluation phase. This results in a single notification of the data wrtitten event. The returned value tells you if the write was succesfull or not. How to react on that depends on your model. At least you have to try it again at a later time (e.g. when the fifo has room for the new element). The delta cycle does not change. But I guess you mean when does the function return. For this you can consult the LRM. But in short: nb_write returns immediately, it is non-blockin (or nb). Therefore you can use it in an SC_METHOD. write is blocking which means internally wait is called and it returns once the element has been placed in the fifo. Therefor write can only be used in SC_THREAD since the call to wait() is not allowed in SC_METHOD.
  14. There are quite few more RISC-V ISS/VPs, all based on SystemC. E.g.: ETISS of TU München (https://github.com/VP-Vibes/etiss) TGC-VP of MINRES (https://github.com/VP-Vibes/TGC-VP)
  15. There are no SystemC specific profiling tools freely available. So either you use tools of well-know EDA vendors or used gprof, valgrind, ptrace, or alike to profile your simulation. Unfortunately they are not aware of sc_threads (or coroutines) so some creativity is needed to interpret the results. I would also put some emphasis on memory allocation and managment. If the footprint gets larger caches need to be more often flushed and this cost quite some time.
  16. The simplest solution would be to pass a pointer (or reference) to OS_Task or the TCB with task_create() and task_end(). A forward declaration alogn with the OS_API class should be sufficient. I don't know your requirements but it seems to me that your use of sc_module is sub-optimal for the purpose of modeling OS tasks. The reason is simple: you cannot create or delete sc_module after the elaboration phase. And OS tasks tend to be dynamic... So sc_object and sc_spawn might be a better solution. I assume that task_create() and task_end() always surround the behavior of a task. So why not move them into the OS_Task itself? If you pass then the TCB as pointer or by reference you could encapsulate the entire stuff of task handling in the OS_task class...
  17. I took your eample and pasted it at https://www.edaplayground.com/x/EtqQ From there is works without any hassle. You seem to have anything different in your code base than posted here.
  18. C++17 supports the inline static syntax (see https://en.cppreference.com/w/cpp/language/static). So you need to have a C++17 capable compiler and specify the language level accordingly. In C++14 this is not supported....
  19. tlm_fifo provides a blocking read called get() as well as an event to use: ok_to_get(). To block the writer you can use ok_to_put() which is triggered when the fifo is read.
  20. I had a look onto your code and it has several flaws: your condion variable not protected against spurious and lost wakeups you use one global condition variable for all threads. This is bad design... your simulation runs out of events. Since the SC kernel does not see any events during the start of your thread(s), it simply shuts down the simulation. So before your thread is alive there is no simulation at all diamond problem with multiple inheritance: ThreadSafeEvent inherits of sc_prim_channel and ThreadSafeEventIf where both inherit of sc_interface. So at least ThreadSafeEventIf needs to ingerit virtual. Instead of dealing with pthreads you should use std::thread and friends. This eases your life quite a lot an makes things easier Based on your example I created a working example at https://www.edaplayground.com/x/Nn9e using C++11. Make sure that in the field 'Compile Options' the option '-pthread' is given as well as c++11 or c++14 is selected
  21. Neither is the case. Between putting an element into the fifo and the element becoming available is at least a delta cycle. And this is by design as in hardware it takes some time for values to propagate. sc_core::sc_fifo exposes the same behavior. If you need immediate update you can use ordinary C++ containers like std::dequeue...
  22. But if you look into fir_const.h you see: coefs[0] = -6; coefs[1] = -4; coefs[2] = 13; coefs[3] = 16; coefs[4] = -18; coefs[5] = -41; coefs[6] = 23; coefs[7] = 154; coefs[8] = 222; coefs[9] = 154; coefs[10] = 23; coefs[11] = -41; coefs[12] = -18; coefs[13] = 16; coefs[14] = 13; coefs[15] = -4; which is just assignement, not declaration. coefs is declared as member variable of module fir: SC_MODULE(fir) { sc_in<bool> reset; sc_in<bool> input_valid; sc_in<int> sample; sc_out<bool> output_data_ready; sc_out<int> result; sc_in_clk CLK; sc_int<9> coefs[16]; SC_CTOR(fir) { SC_CTHREAD(entry, CLK.pos()); reset_signal_is(reset,true); #include "fir_const.h" } void entry(); }; In your code you declare and initialize a local variable: void ex::entry(){ double angles[...] = {...}; .... } which shadows your class member angels. As soon as the funtion ex::entry() finishes the local variable angels get destroyed. What you can do is just assigning it e.g.: void ex::entry(){ angles = {...}; .... } which is similar to the fir example you quated. As I mentioned earlier, you should make yourself familiar with variable life times and visibility.
  23. Did you install teh SCV? It is a separate library from SystemC...
  24. That's why it always better to use an unnamed enum as shown in the edaplayground example. This is typesafe and allows the compiler to check things.
  25. You are declaring angles local in the body of the constructor. Once this finishes they are destroyed as they are stack allocated. You are running into undefined behavior. This is basic C++, lifetime of variables. You need to declare angles as member of the class/SC_MODULE and only assign in teh constructor
×
×
  • Create New...