Jump to content

David Black

  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by David Black

  1. If your question on UVM is whether the repository is open to modifications, the answer is no. The UVM proof of concept library is carefully managed by Accellera as part of the standard's development. I cannot answer the question about test suites.
  2. David Black

    Log File Parsing

    Surprisingly, to me at least, a perl script I wrote in 1997 still appears to be popular. You can find it here: <https://github.com/dcblack/logscan/blob/master/README.md>.
  3. SystemC's implementation code is not generally an area we discuss except in the extremely rare instance we find a bug. Please read IEEE-1666 standards document (freely available via accellera.org). The behavior is correct.
  4. David Black

    Initial value port

    [Sorry for delay. For some reason I was not notified of your reply.] The point of my challenge was that you would not initialize the FIFO beyond allowing to come up empty. At least I have never see a FIFO that would be pre-filled. At start_of_simulation, you can initialize all you want as long as you can do everything within a single delta cycle. Hence you can write signals and fffos. Effectively, start_of_simulation is when activity is allowed to start happening.
  5. Based on the question, it seems to me that you need to take a class in C++. Anyhow, of course you cannot execute an object file. You need a fully linked executable. Files ending in .o are not executable because they do not contain fully resolved code. Linking is part of the process of compilation. If your code compiled, I expect there is another file either with no extension or perhaps with .x or .exe. In any event, you definitely should not ever have to add the execute privilege (chmod +x). In fact, that was a bold and dangerous move on your part.
  6. dynamic_cast to sc_module* would only give you access to methods of sc_module that were overridden in A. fun() and function() are not part of sc_module.
  7. David Black

    How can I implement SC_FORK JOIN_ANY /SC_FORK JOIN_NONE

    Read up on sc_spawn and sc_process_handle. Basically, you can do something like: // Example of fork-join any std::vector<sc_process_handle> process_handles; process_handles.push_back( sc_spawn( [&](){ ... } ); //< repeat as needed ... sc_event_or_list terminated_events; for( auto& ph : process_handles ) { terminated_events |= ph.terminated_event(); } wait( terminated_events ); //< wait for any process to exit for( auto& ph : process_handles ) { ph.kill(); } // Example of fork-join none (void)spawn( [&](){ ... } ); //< repeat as needed ...
  8. David Black

    sc_fifo with multiple readers (or writers)

    To answer the question of a fifo multiple writers and one reader, I would suggest either of two approaches: Create a module with a vector of inputs (1 per writer) and the sc_fifo output. A simple method process can then arbitrate and facilitate placing incoming data onto the output. This has the advantage of allowing a custom arbitration scheme Create an internal std::queue and limit access with a mutex (sc_mutex might work). Since the queue doesn't have a limitation, it will be up to you to manage maximum depth issues. Downside is that arbitration is managed by the mutex and may not be ideal. For a fifo with multiple readers, you probably need a manager to decide arbitrate requests, which is similar to 1 above.
  9. David Black

    sc_fifo with multiple readers (or writers)

    In general, your design would not work because reading a real hardware FIFO takes time and readers would get entangled. How would you manage that? Second, you are not using the correct methodology to connect up your FIFO, which is why you don't see the error. SystemC expects you to connect modules to channels using ports. Skipping the hierarchy and connecting consumers using pointers is incorrect. Instead, you consumer should replace your my_fifo pointer with a fifo port. You have two choices: sc_port< sc_fifo_in_if<int> my_fifo_port; or sc_fifo_in<int> my_fifo_port; The syntax to access the fifo will be my_fifo_port->read(). Next you will need to attempt to connect the port to the fifo during construction in your producer with: for( int i=0...4 ) consumer.port.bind( my_fifo ); When you run you will encounter an error during elaboration (construction) that you already have a connection and fifo ports don't allow more than one binding.
  10. Note: This is somewhat of an expert question. I am considering how best to probe a SystemC design to determine connectivity. My goal is to be able to automatically determine how ports are connected at end-of-elaboration or later. My first inclination was to do something like: std::cout << "Connection from " << myport.name() << " to " << myport->name() << std::endl; Just to be clear, myport.name() provides the path to the port itself; whereas, myport->name() should provide the path to the channel that the port is connected to. However the above requires all channels and interfaces to implement the method name(), which is not currently the case. The implementation would simply be: const char* Channel::name( void ) const { return sc_object::name(); } I am first looking to see if anybody has a current solution that does not require modification of the standard. I don't think it exists, but I could be overlooking something.
  11. David Black

    Automation for probing port connectivity

    Actually, I was very close to the solution you provided, and it provides some of the solution. The hierarchical is not a problem for my needs. I am having problems getting my TLM sockets to report properly. I only need the initiator sockets. Thank you.
  12. David Black

    simple socket

    I would suggest that those for-loops need a better bound and should be coded: sc_assert( objA->initiator_socket.size() >= objB->target_socket.size() && objB->target_socket.size() > 0 ); for( int i=0;i<objA->initiator_socket.size(); ++i ) { objA->initiator_socket[i].bind(objB->target_socket[i]); } Coding rule: NEVER use a literal constant when a reasonable alternative is possible. Even when "in a hurry", you will not be disappointed if you use this rule.
  13. David Black

    Drive SCModel from a C-Shell

    I would suggest that putting anything other than instantiation of a top level module is inappropriate. You should create a top level module with a thread to contain your behavior. As you are interested in communicating with SystemC from outside the simulator (i.e. from the shell), then you need to use thread-safe techniques. SystemC is not thread-safe without special precautions. You have two choices in this regard: Use polling inside your thread and use appropriate interprocess communications mechanisms (don't forget to use a mutex). Create a primitive channel using async_request_update and appropriate interprocess communications mechanisms to capture the data from outside. Neither approach is trivial.
  14. David Black

    Initial value port

    The 'initialize(T)' method is a leftover from SystemC 1.0 circa 1999, when SystemC had not yet properly abstracted the port/channel concept. At that point in time, there was a stronger emphasis on making SystemC look like Verilog or VHDL. The 'initialize(T)' method is only present on the 'sc_out<T>' and 'sc_inout<T>' port classes, as part of their partial template specialization. The 'initialize(T)' method is not generally available to 'sc_port<>'. I usually don't mention it because then the reader gets the wrong impression that 'initialize(T)' should be present everywhere. In fact, it is only useful for RTL aspects. Certainly, this is not part of TLM. Since SystemC is more about abstraction and modeling, I avoid it. It is straightforward to override start_of_simulation. @TRANGIt is important for you to understand this distinction. I realize that the specification may say that "port is initialized to zero" or some such, but the concept of port in the specification is quite different than the concept of port in SystemC. If you don't understand this, you will hobble your understanding of SystemC. So there are three ways in SystemC of modeling what the specification says regarding an output pin on a hardware design. Depend on the underlying datatype's initial value to initialize the signal (not very flexible) If using the specialized ports (sc_out and sc_inout only), call the initialize(T) method. Write to the port during start_of_simulation, which is the most general and powerful approach. Challenge: How would you initialize an sc_fifo< float > connected to an sc_fifo< float > channel with four values? #include <systemc> #include <list> #include <iostream> using namespace sc_core; using namespace std; SC_MODULE( Source ) { sc_fifo_out< float > send_port; SC_CTOR( Source ) { SC_THREAD( source_thread ); } void source_thread( void ) { wait( 10, SC_NS ); send_port->write( 99.7 ); wait( 10, SC_NS ); std::cout << "Finished" << std::endl; sc_stop(); } // How to initialize output to contain following initial values? // { 4.2, -8.3e9, 0.0, 3.14 } // Do not add this to the thread. Instead, ensure that it happens before any thread executes. } }; SC_MODULE( Sink ) { sc_fifo_in< float > receive_port; SC_CTOR( Sink ) { SC_THREAD( sink_thread ); }; void sink_thread( void ) { for(;;) { std::cout << "Received " << setw(12) << receive_port->read() << " at " << sc_time_stamp() << std::endl; } } }; SC_MODULE( Top ) { // Constructor SC_CTOR( Top ) { m_source.send_port .bind( m_fifo ); m_sink.receive_port.bind( m_fifo ); } // Local modules Source m_source { "source" }; Sink m_sink { "sink" }; // Local channels sc_fifo< float > m_fifo; }; int sc_main( int argc, char* argv[] ) { Top top { "top" }; sc_start(); return 0; } Key concepts: SystemC is a modeling language mapped on top of C++. SystemC ports are not signals or pins. sc_in<T>, sc_out<T> and sc_inout<T> are partial template specializations of sc_port<T> on the respective sc_signal<T> interface classes. For historic reasons (SystemC 1.0), there are extra methods added to these specializations including initialize(T), read(), and write(T) that can later confuse novice SystemC programmers.
  15. David Black

    Initial value port

    Ports do not hold values. Ports are simply references to channels. Ports provide a means to access a channel. sc_signal is simply a type of channel. This particular channel supports several methods including read() and write(), which are used to obtain (get) and alter (set) the state (attribute) of the channel. You can use these methods signal directly: type value; //< local storage ... signal.write( value ); ... value = signal.read(); Or if the channel is located outside your module, you should access the methods via port connections thus: output->write( value ); ... value = input->read(); Because the connectivity is not fully established until after elaboration is completed, you generally cannot provide an initial value during construction of an external channel from inside a module. Also, the signal method takes advantage of the update phase of the simulator and should only be accessed at start of simulation. Therefore, the proper way to initialize a "port" is to write to the corresponding signal a the start of simulation by overriding the so-called callback method start_of_simulation(): SC_MODULE( MyModule ) { ... void start_of_simulation( void ) override; }; Implementation: void MyModule::start_of_simulation( void ) { output->write( initial_value ); }
  16. David Black

    Array of ports

    @Eyck With one input, you only need to be sensitive to the single input port. @Khushi Since it's an sc_signal<>, you might even consider embedding the signal vector inside the module and then providing an sc_vector<sc_export<sc_signal_in_if<bool>>,16> to make it easier for your subscribers.
  17. David Black

    Array when declare port for model

    SC_NAMED is not part of IEEE 1666:2011, but rather a newly introduced (SystemC PoC 2.3.2) convenience macro looking for feedback and possible inclusion in the next version of the standard.
  18. David Black

    Array when declare port for model

    The proper SystemC notion of a port is very different from VHDL or Verilog. Ports are really a very fancy type of pointer used to direct method calls to channels. Note that channels are not signals or wires. Channels are classes that provide public methods to communicate safely between SystemC processes. The sc_core::sc_int<T> port is actually a partial template specialization for the proper SystemC port, sc_core::sc_port<T>. Ports are always bound to SystemC interfaces. A slightly more complete way of expressing this would be: using namespace sc_core; sc_port< sc_signal_in_if <bool> inA; // Port for connecting to a signal channel capable of communicating a single boolean value. Please note that you don't really initialize ports in the sense of assigning an initial value, because ports do not carry values. You do initialize ports in the sense of C++ construction and subsequent binding of ports to channels. SystemC ports have up to three template parameters (although the interface is normally the only one needed) and normally a single optional constructor argument (the sc_object instance name). If very much of the wording I've chosen above is foreign to you, then you probably don't have enough C++ programming background yet. Before tackling SystemC you need to be proficient at C++ (not C). None of your three attempted examples appear correct, but I infer that you may be interested in a port for communicating five bits over an sc_signal channel. This would be done in SystemC as follows: sc_in<sc_int<5>> inB1; or sc_port< sc_signal_in_if<sc_int<5>>> inB2; Note that the following would not work: sc_in<bool> inC[5]; // Attempt to create an array of 5 ports for 5 different sc_signal<bool> connections This is due to the unfortunate manner that array elements are constructed, and SystemC's requirement that component objects must be constructed with unique instance names. I don't have time to go deeper, andI suggest you either get a good book on SystemC or take a formal class. If you don't have a solid grasp of C++, please be certain to get educated on that as well.
  19. You would need to write a wrapper class with debug aids builtin. A sketch might be: struct debug_mutex : sc_core::sc_mutex { void lock( void ) override { auto requester = sc_core::sc_get_current_process_handle(); INFO( DEBUG, "Attempting lock of mutex " << uint_ptr_t(this) << " from " << requester.name() " at " << sc_time_stamp() ); this->sc_mutex::lock(); locked = true; locker = requester.name(); time = sc_time_stamp(); changed.notify(); } void unlock( void ) override { auto requester = sc_core::sc_get_current_process_handle(); this->sc_mutex::unlock(); time = sc_time_stamp(); locked = false; locker = ""; changed.notify(); } // Attributes bool locked{ false }; sc_event changed; sc_time time; string locker; }; I have not tested above. NOTE: I have a macro INFO that issues an appropriate SC_REPORT_INFO_VERB with the above indicated syntax. Replace with your own. Never use std::cout or std::cerr if coding SystemC.
  20. David Black

    SystemC 2.3.3 fail "make check" in MacOS

    I installed on High Sierra myself and now on Mojave without incident. At the risk of a lot of data, perhaps we need to see examples/sysc/test-suite.log?
  21. David Black

    SystemC 2.3.3 fail "make check" in MacOS

    You need to provide more information: - OS name and version (e.g. Ubuntu 18.04) - Compiler name and version (e.g. GCC 7.1)
  22. David Black

    libsystemc-2.3.3.so cannot open shared object file

    Please show results of: ls -l $SYSTEMC_HOME/lib-linux64/
  23. David Black


    This appears to be homework for school. I suggest you try reframing your request.
  24. David Black

    Benchmarking RTL simulation with SystemC

    Is it really the size of the primitive, or the size of the data in play that's the issue? Also, if you could relocate the data to in close proximity to one another, then the caching would be potentially more efficient since it is the cache line size and utilization that has a large impact on performance. Perhaps a redesign of primitives would change this for RTL; although, it might take some serious rethink to make it work. If construction of sc_signal<bool> invoked some pooling and data aggregation. I would bet a saavy C++ programmer could improve this. For what it's worth, I have had some ideas that might make gate-level sims possible in SystemC too.
  25. David Black

    Temporal Decoupling

    One trick to making temporal decoupling work is that if you have shared resources (i.e. shared memory between two initiators), you will need to do synchronization on demand for reads to the shared areas. To be clear, just because a target is accessible from two initiators does not mean it is shared. For example, in many SMP systems there might be a 32MB memory visible to two processors; however, the design of the software may only intercommunicate using a designated "shared" region of 2MB by agreement. Each processor might have its own "private" 15M region that is off-limits to the other processor by design intent. Suppose we call the processors A and B. If they stick to their private regions of memory, no problems happen; however, if processor A attempts to read a section of the shared memory to obtain information provided by processor B, then synchronization of local time is necessary. This is because processor A might be temporally ahead of the time for processor B, which ends up writing to the area A is interested just prior to A's reading it. Unless they synchronize, processor A won't see the new value from processor B. For some software systems this might not be a problem, but there are times when synchronization is demanded to ensure correct operation. So success in using temporal decoupling requires full system hardware and software knowledge.