Jump to content

sheridp@umich.edu

Members
  • Content Count

    26
  • Joined

  • Last visited

1 Follower

About sheridp@umich.edu

  • Rank
    Member

Recent Profile Visitors

421 profile views
  1. 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.
  2. 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; }
  3. 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.
  4. 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.
  5. Hi Mathieu, I know this post is over 5 years old, but did you ever find something like this?
  6. 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.
  7. 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?
  8. 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.
  9. 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.
  10. 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.).
  11. 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.
  12. Hi Philipp, Sure. Can you point me in the direction of the official SystemC repo (I currently just downloaded the source from http://accellera.org/downloads/standards/systemc). I found the following: https://github.com/systemc/systemc-2.3 , which looks official, but it's not version 2.3.2. On the other hand, I found https://github.com/avidan-efody/systemc-2.3.2, but it looks unofficial. If there is no official repo that includes 2.3.2, I can just create one from the downloaded source. Thanks, Patrick
  13. Actually, even if you're just modeling hardware, you might want to use sc_spawn in the case that you have a run-time configurable number of hardware blocks. SC_THREADS have to be declared at compile time.
  14. Hi Sumit, I think when you are just modeling hardware with fixed modules, there probably isn't a whole lot of uses for sc_spawn (I'm sure others could find some uses). However, in my models, I do a lot of modeling of firmware state machines at a pretty high level of abstraction (ie. I'm writing models before any firmware is available, so the models are not using something like instruction set simulators). In these models, a command is received and then a number of different actions are taken in sequence throughout the lifetime of the command, sometimes waiting on hardware or other threads, etc.). The easiest way to model this is as an sc_thread: void run(Command received_command) { do_x(received_command); wait(10, SC_US); do_y(received_command); mutex.lock(); do_z(received_command); mutex.unlock(); ... } The thing is, at compile time, I have no idea how many commands I'll receive, this depends on run-time inputs to the model. So I typically have a fixed module using SC_THREAD receiving the commands, but then for each command it receives, it kicks off a run using sc_spawn. SC_THREAD(receiver); void receiver() { while(true) { auto command = fifo.read(); sc_spawn(sc_bind(&run, command)); } }
×
×
  • Create New...