Jump to content

sheridp@umich.edu

Members
  • Content Count

    29
  • Joined

  • Last visited

1 Follower

About sheridp@umich.edu

  • Rank
    Member

Recent Profile Visitors

481 profile views
  1. Sorry for the delay, I just saw this reply. My use case is in modeling a CPU (at a pretty high, task level) using an SC_THREAD. What the CPU does is cycle through its list of tasks which involves sending and receiving messages to other components (let's call it slaveA & slaveB). However, if the CPU makes it through its whole list of tasks and has accomplished no useful work (e.g. it is polling slaves A & B, finding them not ready), then I need the CPU to sleep until either is ready. This is to help speed up the simulation (each cycle through the tasks involves multiple wait statements for small time increments if there's no useful work to do--I could just accumulate the time in loose fashion, but there are other reasons not to). Rather than having to know apriori about slaveA and slaveB's wakeup events, I have a pointer to slaveA's event returned in the message after a call to b_transport. Originally, I had collected these events in an sc_event_or_list, and if the CPU made i through its list of tasks without accomplishing work, it would wait on them. However, I realized that if, while checking slaveB, slaveA notified its wakeup event, I would miss it and the CPU would wait when it should go back and check slaveA again, and might even deadlock if nothing wakes the CPU up after that. Instead, what I wanted to do was have a method that would set a flag to tell the CPU to keep cycling. If, after polling slaveA and finding it was busy, I would modify the method's sensitivity to include the event returned by slaveA. Because next_trigger is a protected method, however, I cannot access it from withing the sc_thread of the CPU. What I settled on was similar to this, but instead of modifying a single method's sensitivity, I spawn new instances of the flag-setting method immediately after I receive the event pointer (before yielding so that I cannot miss slaveA's notification).
  2. This is exactly what I want to do, but next_trigger(sc_event_or_list&) is protected within sc_method_process.
  3. Is is possible to modify an sc_method_process's dynamic sensitivity from outside the method itself? While I can call next_trigger when the method is running, it would be preferable to add event sensitivity from another method/thread. If not, one work workaround I came up with is the following: sc_core::sc_event_or_list dynamic_sensitivity; sc_core::sc_event sensitivity_change_event; SC_METHOD(Change_Me_Method); sensitive << sensitivity_change_event; SC_THREAD(Changer_Thread); void Change_Me_Method(){ if(!sensitivity_change_event.triggered()){ //Do stuff } next_trigger(dynamic_sensitivity | sensitivity_change_event); } sc_core::sc_event new_event; void Changer_Thread(){ dynamic_sensitivity |= new_event; sensitivity_change_event.notify(); } Wondering if there is a cleaner solution.
  4. Eyck, Not to quibble, but I disagree with that interpretation. You're right I don't have hierarchical binding, and by the first sentence, I should register a transport method. However, the second sentence says that if I don't register one, a runtime error will be generated if and only if the corresponding method is called, which in my code, it isn't. I think this becomes even more problematic if I had configured the socket to be SC_ZERO_OR_MORE_BOUND, in which case it's even more likely that I might not register a transport method if I intend not to connect the socket. I can definitely understand that perhaps my interpretation relies too heavily on the second sentence, but I'd say the spec could probably be made more clear in that regard. Let me know your thoughts.
  5. I ran into an issue using multi_passthrough_target_sockets: It is required that register at least one transport method (b_transport or nb_transport_fw) or you'll get the following error: This is in contrast to the spec section 16.1.4.4, section l: It's not really a big problem (why would you ever not register at least one?), but it is something I ran into during development, as I was checking my hierarchical binding structure, but had not yet created my transport methods. The error message is particularly confusing, because the target_socket is bound, and the runtime error is thrown after elaboration, an not when the corresponding method is called. The following code will reproduce the error: #include <systemc.h> #include <tlm.h> #include <tlm_utils/multi_passthrough_target_socket.h> #include <tlm_utils/multi_passthrough_initiator_socket.h> class Container : sc_module { public: tlm_utils::multi_passthrough_target_socket<Container, 1, tlm::tlm_base_protocol_types, 0, SC_ZERO_OR_MORE_BOUND> target_socket; tlm_utils::multi_passthrough_initiator_socket<Container, 1, tlm::tlm_base_protocol_types, 0, SC_ZERO_OR_MORE_BOUND> initiator_socket; Container(sc_module_name name) { initiator_socket.bind(target_socket); //If both lines are line is commented, an error is generated // target_socket.register_b_transport(this, &Container::b_transport); // target_socket.register_nb_transport_fw( this, &Container::nb_transport_fw); } void b_transport( int id, tlm::tlm_generic_payload& trans, sc_time& delay ) { } tlm::tlm_sync_enum nb_transport_fw(int id, tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_time& delay){ } }; int sc_main(int argc, char *argv[]) { Container c("container"); sc_start(); return 0; }
  6. Hi Philipp, Thanks for your response. You are right, I think the spec is clear on that point. I think I had some confusion regarding the default flags on the compiler, but, as you pointed out, that is beyond the scope of the SystemC spec.
  7. The following Dockerfile will reproduce the problem: FROM alpine:3.9 as builder RUN apk add --no-cache build-base linux-headers WORKDIR /opt FROM builder as builder_systemc COPY systemc-2.3.3.gz /opt RUN mkdir /opt/systemc_src && \ tar -xf systemc-2.3.3.gz -C /opt/systemc_src --strip-components=1 && \ cd /opt/systemc_src && ./configure --prefix /opt/systemc-2.3.3 --enable-debug CXXFLAGS="-DSC_CPLUSPLUS=201703L" && \ make -j$(nproc) && \ make install Which results in the following error: CXX kernel/sc_simcontext.lo In file included from kernel/sc_simcontext.cpp:57: ../../src/sysc/utils/sc_string_view.h:62:29: error: 'string_view' in namespace 'std' does not name a type typedef SC_STRING_VIEW_NS_::string_view sc_string_view; ^~~~~~~~~~~ It looks like the following is related: #if SC_CPLUSPLUS >= 201402L && defined(__has_include) # if SC_CPLUSPLUS > 201402L && __has_include(<string_view>) /* since C++17 */ # define SC_STRING_VIEW_NS_ std # include <string_view> /* available in Library Fundamentals, ISO/IEC TS 19568:2015 */ # elif __has_include(<experimental/string_view>) # define SC_STRING_VIEW_NS_ std::experimental # include <experimental/string_view> # endif #else // TODO: other ways to detect availability of std::(experimental::)string_view? #endif I'm guessing that defining SC_CPLUSPLUS did not cause the -std=c++17 flag to be passed to the compiler, because <string_view> contains the following: #if __cplusplus >= 201703L Update: Modifying the ./configure command to: ./configure --prefix /opt/systemc-2.3.3 --enable-debug CXXFLAGS="-DSC_CPLUSPLUS=201703L -std=c++17" solves the problem. It might be worthwhile mentioning this in the INSTALL notes.
  8. Hi Mathieu, I know this post is over 5 years old, but did you ever find something like this?
  9. Hook, Yes, this is correct. The initiator calls nb_transport_fw in the target with a delay of 10ns timing annotation. In order to respect the timing annotation, the target placed the transaction into a payload_event_queue (PEQ) and it will emerge from the PEQ after 10ns (this is done by calling peq_with_get.notify(trans, delay) where the delay argument is what was passed into nb_transport_fw). Similarly at time = 125ns, the target calls nb_transport_bw to the initiator with a delay of 10ns. The initiator does the same thing--puts the transaction into its own PEQ with a delay of 10ns.
  10. Is it just that it is inappropriate to try to model at this high level of abstraction--like locking a bus without an explicit arbiter--using AT?
  11. Basically, what I'm interested in is a multi-producer, multi-consumer model over a shared bus. When not using TLM, I would implement it as follows: class top : sc_module { sc_mutex bus; producer p1("p1", bus); producer p2("p2", bus); consumer c1("c1"); consumer c2("c2"); p1.port(c1.port); p2.port(c2.port); }; class producer : sc_module { public: sc_mutex& bus; sc_fifo_out<transaction_object*> port; producer(const sc_core::sc_module_name &name_, sc_mutex& bus_) : bus(bus_){ SC_THREAD(thread); } void thread(){ while(true){ wait(production_time, SC_US); auto trans* = new transaction_object(); bus.lock(); //ensure exclusive access to the bus wait(transmission_time, SC_SEC); port.write(trans); //potentially block if the consumer thread is full; if we don't want to block access to the bus the whole time, we could wait on free space in the consumer fifo before locking the bus. bus.unlock(); } } } class consumer : sc_module { public: sc_core::sc_export<sc_fifo<transaction_object*>> port; sc_fifo<transaction_object*> fifo; consumer(const sc_core::sc_module_name &name_){ SC_THREAD(thread); port(fifo); } void thread(){ while(true){ auto trans = fifo.read(); wait(consumption_time, SC_SEC); } } } * Please note, I didn't try to compile the above code and I'm sure there are some syntax bugs; in addition to the obvious memory leak. This works great, and I think it's easy to understand, but (1) it doesn't follow TLM2.0 standards and (2) I think it might be significantly slower than TLM2.0 AT style. The problem I'm having is just that TLM2.0 AT style is just so counter-intuitive for me with callbacks, phases, and timing annotations. Further, I agree with the advice given by David Black on this forum that SC_THREADs are much more intuitive to understand than SC_METHODs, but I don't see how to implement AT style in a straightforward manner using SC_THREADs. A good example, is the SimpleBusAT (given in systemc-2.3.2/examples/tlm/common/include/models/SimpleBusAT.h) -- this looks far more complex than using an sc_mutex and sc_fifo, but I'm wondering if there is a simple design pattern for AT to follow that could help ease model development.
  12. If a third party model is designed to take a tlm_generic_payload, and you derive from tlm_generic_payload, then it should handle your transaction object correctly, ignoring any additional fields that may be defined on the object. If a target wants to make use of those additional fields, then it could dynamic_cast the tlm_generic_payload* to your derived type* (using C++ RTTI to ensure that it actually has a derived_type object) . I understand that the standard was instead developed around extensions, but I'm wondering what was the motivation for going in this direction.
  13. Does anyone know of any open source approximately timed TLM2.0 models? While there a few examples included in the SystemC download, I am looking for examples of real hardware models to get a better understanding of how model implementers actually use the base protocol (SC_METHOD vs SC_THREAD; 1, 2 or 4 phase, timing annotation, peq_with_get vs peq_with_cb_and_phase, etc.).
  14. Section 14.2 of the IEEE STD 1666-2011 states I am wondering why the extension mechanism is preferred since you could simple ignore the additional fields provided in a derived class.
×
×
  • Create New...