Jump to content

Eyck

Members
  • Posts

    356
  • Joined

  • Last visited

  • Days Won

    87

Everything posted by Eyck

  1. It depends on what level of abstraction you want to use to model AXI4. For LT level multi-socket should be ok. But to model at AT level you are better off using an sc_vector of sockets as each socket has its own timing and state. But I'm wondering: why would you want to use multi passthrough sockets? What gainusing them would you expect?
  2. Actually there is nothing to change in the conan package. You just need to tell conan to use C++17 and it will fetch (or build) the respective package. The command line oiption to do so is '--settings compiler.cppstd=17'. If you use cmake to create your build system I highly recommend to use conan version 1.59 and conan.cmake from https://github.com/conan-io/cmake-conan/tree/v0.16.1
  3. This is an issue in 2.3.3, see also here: https://github.com/accellera-official/systemc/issues/24 And yes, to my knowledge there is no propagation of the setting to user code. Therefore e.g. the conan package explicitly sets the cmake option to OFF.
  4. You should use the cmake based approach to install SystemC, it is going to become the default in the future anyways. But beware, default settings have slightly changed, see https://github.com/accellera-official/systemc/issues/24 But you should raise an issue at github...
  5. transport_dbg is similar to b_transport but without timing and the target is not allowed to call wait (similar to nb_transport_*). It is used to do debugg accesses, e.g. when using a target debugger in a virtual platform. Accesses via transport_dbg shoul be transparrent to the simulation itself. E.g. the simulation should behave the same way no matter if a register is read via transport_dbg or not.
  6. A TLM2.0 socket consist of 2 parts: the port connecting to another socket and an export exposing interfaces to be connected to a port. If you use SC_ZERO_OR_MORE_BOUND this only changes the port part which is fine since you don't want to connect to a target socket. But the export needs to have an bw interface implementation. For an initiator module this should not be a problem as the it needs to bind a bw interface. For a hierarchical port you may bind a dummy implementation of the bw interface.
  7. Please be aware: cxxabi.h is a GCC specific implementation and will quite likely not work with MSVC or Clang
  8. If you stay in C++ this is the only solution. But by modifying the SystemC kernel you loose standards compatibility. If you can switch to python there is PySysC (https://github.com/accellera-official/PySysC) which allows to inspect data types at runtime.
  9. acquire/release only deal with the payload and the extensions, not with the data array. And it works only if ypu use a tlm memory manager. An example can be seen at https://github.com/Minres/SystemC-Components/blob/develop/examples/axi-axi/sc_main.cpp#L58
  10. AFAIK there is nothing out-of-the-box. Basically you need to embedd an interpreter and provide it with some function to be called by the script. Easy to embed would be Lua, Python or Tcl. In all these cases you need to write the code to integrate the interpreter with the SC kernel. Since SystemC is C++ this is not overly complicated (done that several times) For Python the is another option: use PySysC to construct and run your model. It allows to execute Python code as part of the model. Latest updates you may find here as it is under active development.
  11. Wrt. to you first question there is a clear 'it depends'. If you have an array of sc_objects (basically SystemC named things like modules, ports, signals, channels, and alike as well as sc_vector) you should use sc_vector. Otherwise stick with STL container types. Wrt. your second question: your example is correct but your interpretation not: SystemC executes as mayn as needed delta cycles at the same time stamp. So the read_oldvalue() and the write() function are evaluated in the first delta cycle of the current time stamp. Then the signals are written and the event is notified so that read_newvalue() is evaluated in the second delta cycle at the current time stamp. Between the 2 delta cycles the SystemC kernel runs the update phase so that signals get their new values. Therefore read_newvalues() will read the new values as it is scheduled after the update phase. I seriously recommend to read the LRM, some text book (e.g. @David Blacks 'SystemC from the ground up') or take some (online) tutorials like https://fpgatutorial.com/systemc-scheduler/ or https://learnsystemc.com/
  12. Actually you are right, sc_spawn_options default is SC_THREAD. For spawning there is no preference or even difference. But for your ports there is a difference: only in end_of_elaboration ports are completely bound and you can access the events of the associated channel. If you do this in before_end_of_elaboration() you will run into the same problems you had initially Pls. check also the LRM wrt this.
  13. SystemC guarantees sequential execution of threads so that no expicit syncronization mechanisms are needed. Please consult the LRM for further information. SystemC does not guarantee any particular order of execution of threads so reading and writing from different SC processes to native datatypes may give surprising results e.g. if both processes are sensitive to the same event. In this case you should use a signal or any other primitive channel which uses a defered updatre scheme (e.g. sc_fifo).
  14. This is basic C++, you need to dereference the pointer: Initiator->socket(*(MODULE->socket)); Using raw pointer and new is discouraged, yyou should use std::unique_ptr. My advise is to spend some time in getting more familiar with modern C++
  15. You try to make the invocation of functions sequential by abusing delta cycles. This usually leads to bad simulation performance. To ensure deterministic simulation there is the concept of primitive channels or signals (which is an implementation of a primitive channel). I would do an implementation similar to the following (untested): SC_MODULE(timing) { sc_in_clk clk; sc_core::sc_vector<sc_core::sc_signal<my_struct>>> my_array{"my_array", 10}; int index = 0; void write() { std::array<int, 4> write_data; write_data.fill(index); my_array[index % 10].write(my_struct(index % 2, write_data)); index++; } void read_oldvalue() { for (int idx = 0; idx < 10; idx++) { cout << my_array[idx]; } cout << endl; } void read_newvalue() { for (int idx = 0; idx < 10; idx++) { cout << my_array[idx]; } cout << endl; } SC_CTOR(timing) { SC_METHOD(write); dont_initialize(); sensitive<<clk.pos(); SC_MEHTOD(read_oldvalue); sensitive<<clk.pos(); SC_METHOD(read_newvalue); for(auto& s: my_value) sensitive<<s; } }; This simplifies your design and read_newvalue() is only called if something changes. Since you did not write about your intend I cannot judge I cannot judge if this makes sense. Another option would be to instantiate a sc_event being triggered by the write function and make the read_newvalue() sensitive to this event.
  16. The root cause of the problem is the following: in your constructor your are trying to call a function of the sc_fifo_in_if which is not yet bound when having a hierarchical binding. Why is then example 2 woring? There is a difference in your example 2 (working with static process) and 3 (non-working): you use a thread in example 2 and a methoid in example 3. To react on the event in example 3 you need to access the interface during construction (where it is not being bound) while in example 2 the thread accesses the port during simulation (where the port is bound. I see 3 options: use sc_fifo_in::data_written() which returns an sc_event_finder instead of an event (this would be the correct way) use a dynamic thread instead of a dynamic method spawn your method in the end_of_elaboration() call, port are then bound
  17. In both cases there is no difference. The operator=() is overloaded with read() adn write() respectively. So you can use both notions interchangably. I personally tend to use read() and write() since this expresses my intend.
  18. You might use sc_signal<std:vector<T>> sc_vector<sc_signal<T>>
  19. SystemC has no comcept of blocking or non-blocking assignments. If you write to a signal you write to the signal immediatly and the result becomes visible in the next delta cycle. So you parts like Y_copy = Y.read(); ACC.range(7,4) = Y_copy.range(3,0); Accumulator.write(ACC); are correct. You may shortern this to ACC.range(7,4) = Y.read().range(3,0); Accumulator.write(ACC); So you may have an issue in other parts of your code.
  20. Here you use one particular implementation of SystemC. If you switch to another simulator (e.g. a commercial one) this might look completely different. The events in your example occur at the same time: notified by eq at time 15 ns, old sigvalue is 0 ... notified by clk.pos, will notify eq in 10ns, now is 15 ns
  21. Looks like you pass a temporary to the SystemC kernel so that the sc_module and the method does not exist anymore when the kernel wants to invoke it.
  22. First: using the code feature of the forum makes things more readable. In your constructor you declared time() already as SC_THREAD now you need to surround your code with an endless loop: void time() { static sc_time time; static int temp = 0; static int flag = 0; while(true) { //<=== the endless loop to not leave the thread wait(e1); //<=== waiting for the even to trigger behavior if ((time != SC_ZERO_TIME) && (timer_cntrl & 1 << 0)) { int temp = time.to_default_time_units() + mLastUpdate; int time_delay = temp - NowTime; e1.notify(time_delay, SC_NS); time = SC_ZERO_TIME; } else if (timer_cntrl & 1 << 0) { switch (temp) { case 0: next_trigger(20 * (timer_cmp + flag), SC_NS); temp = 1; break; case 1: if (timer_cntrl & 1 << 1) { intr0 = 1; timer_intr_status |= 1 << 0; e2.notify(20, SC_NS); } next_trigger(20 * (255 - timer_cmp), SC_NS); temp = 2; break; case 2: if (timer_cntrl & 1 << 2) { intr1 = 1; timer_intr_status |= 1 << 1; e3.notify(20, SC_NS); } next_trigger(0, SC_NS); temp = 0; flag = 1; break; } } else { time = sc_time_stamp(); } } } This can be found in any SystemC book or lecture material.
  23. AFAIK there is no actual blog post or tutorial on setting uo VSCode with the reference implementation An option to start with SystemC would be to use a cmake based SystemC project. I created on some time ago, it can be found at https://github.com/Minres/SystemC-Quickstart Then you might import this project into VSCode as described e.g. her: https://www.pragmaticlinux.com/2021/07/import-a-cmake-project-into-visual-studio-code/ I'm not aware a a list of commercial SystemC simulators, you might have to use a search engine of your choice....
  24. If you qant to trigger on both edges you just need to use value_changed(). You get the warning since you are creating a thread with the same method for 2 different sensitivity lists. Since the method name is used to create the thread object you get a warning when creating the second thread object. You may ignore it (and actually it is possible to switch this message off) but the better way is to use the value_changed event finder.
  25. The behavior can be found in the vm_* classes, e.g. in https://github.com/Minres/DBT-RISE-RISCV/blob/master/src/vm/interp/vm_rv32imac.cpp The idea idea here is that the childs of arch_if encapsulate the architectural state of the processor while the iss::interp::vm_base<> derived classes implement the behavior. The combination of the 2 forms a processor. This processor is then extended with functionality by using mixins (riscv_hart_msu_vp is a mixin providing the privileged ISA stuff of RISC-V).
×
×
  • Create New...