Jump to content

David Black

Members
  • Content Count

    313
  • Joined

  • Last visited

  • Days Won

    67

Everything posted by David Black

  1. What do you see under /usr/local/systemc2.3.1/lib-linux64? In other words, what does the following reveal: ls -l /usr/local/systemc2.3.1/lib-linux64
  2. David Black

    Functional coverage- VCS

    This is a tools issue and not a UVM topic per se. This forum focuses on UVM issues. Your problem probably needs to be discussed on a Synopsys forum (not Accellera). That said, I believe vcs writes to log and database files located in the same directory where the tool was launched. So you should create separate directories for each run. This will likely require some simple (not necessarily trivial) scripting automation. vcs may also have some switches to help redirect file outputs. I recommend RTFM at a minimum.
  3. David Black

    Temporal Decoupling

    I believe it would be fair to say that there are no universally accepted best practices, and the system design will dictate much of the implementation. In the case of shared memory, the target would need to have some idea that the memory of interest is shared. So you would need somewhere in the system to have a mapping. It might be the entire device, or a memory map might exist as a configurable object. When the target receives a read request for shared memory, it would then synchronize in order to be certain that any writes from the past are completed in other initiators. Depending on your design, you might be able to reduce the number of synchronizations if you can know apriori the nature of the sharing. E.g. if a block of memory was shared using a mutex, then synchronization might be limited to the mutex with the assumption that if you own the mutex, then the block is not written to by other initiators. This of course has some risks in the face of software defects.
  4. David Black

    how can i know which event triggered a process?

    Responding to Phillip: I'm guessing this is coming up for the next update of the standard and is currently under consideration. I guess I need to find more time to get synced up to the latest additions since 2.3.
  5. Don't know how I missed that issue...
  6. If you will read the SystemC standard, you will see that Initators are required to set the response initially to TLM_INCOMPLETE_RESPONSE. Targets are obliged to change this to either TLM_OK_RESPONSE or one of the valid error returns. Seems your downstream targets never saw the transaction. Perhaps the address decoding (in the interconnect) went wrong. You are obliged to set the command, address, data pointer, data length, streaming width, byte enable pointer, DMI hint and response. I suggest RTFM, then debug the interconnect andr targets for a receipt.
  7. Port requires a pointer towards the object containing implementations of methods specified in the interface. Export provides the very pointer that port needs. Port goes from caller towards callee. Export goes from callee towards caller. Pseudo-graphically: // +----------------------------------------------------------------------------------+ // |struct Top : sc_module { | // | | // | initiator.p1.bind( target.x1 ); | // | | // | Initiator initiator{"orgin"}; Target target{"target"}; | // | +------------------------------------+ +--------------------------------------+ | // | |struct Initiator : sc_module { | |struct Target : sc_module { | | // | | | | | | // | | sc_port<IF> p1{"p1"}; | | sc_export<IF> x1{"x1"}; | | // | | caller.p0.bind( p1 ); | | x1.bind( callee.x0 ); | | // | | | | | | // | | Caller caller{"caller"}; | | Callee callee{"callee"}; | | // | | +----------------------------+ | | +------------------------------+ | | // | | |struct Caller : sc_module { | | | |struct Callee : sc_module, IF | | | // | | | | | | | | | | // | | | sc_port<IF> p0{"p0"}; | | | | sc_export<IF> x0{"x0"}; | | | // | | | SC_THREAD(thread1); | | | | Data m_data; | | | // | | | | | | | x0.bind(*this); | | | // | | | | | | | | | | // | | | .------------------. | | | | .----------------------. | | | // | | | | void thread1() | | | | | | void xfer( data& d ) | | | | // | | | | { | | | | | | { | | | | // | | | | p0->xfer( v ); | [p0]->[p1]->[x1]->[x0] | // Save/load d | | | | // | | | | } | | | | | | auto t = d; | | | | // | | | | | | | | | | d = m_data; | | | | // | | | | | | | | | | // Transform t | | | | // | | | | | | | | | | m_data = t; | | | | // | | | | | | | | | | } | | | | // | | | '------------------' | | | | '----------------------' | | | // | | | | | | | | | | // | | |}; | | | | | | | // | | +----------------------------+ | | +------------------------------+ | | // | | | | | | // | |}; | |}; | | // | +------------------------------------+ +--------------------------------------+ | // | | // |}; | // +----------------------------------------------------------------------------------+
  8. There is no rule stating that you must use the quantum keeper. Design your own.
  9. If you are calculating the timing of the transfer, it makes a difference as to how much data is received in a single clock. 8-bytes on a byte-wide interface is eight times slower than a 64-bit interface. It's all about modeling. For Loosely-Timed models, it may not make as much difference since time is less important. It also has application when considering endianess.
  10. Assumption: TLM means TLM 2.0 Each system has at least one initiator (presumably the CPU). Initiators cannot talk directly to one another because that would be like saying function f1() can somehow cause function f2() to call f1() and interchange information. It just doesn't work. However, f1() can deposit data in an agreed upon shared data location, and f2() can then interrogate that memory location. Furthermore, in SystemC, the call of f1() can also invoke an sc_event to wake up the other process from sleep. There is a danger to be aware of depending on how the information is transferred. If the information is exchanged atomically, there is not problem, and this is easy to accomplish in SystemC modeling since it is currently a cooperative multi-tasking environment. However, if your channels simulate timewise transfer of data, then you may need to include a SystemC mutex. A trivial way of ensuring synchronization would be to simply use an sc_fifo or a tlm_fifo in the target object. Suggestion: Learn SystemC core concepts before learning TLM-2.0.
  11. David Black

    how can i know which event triggered a process?

    Simple answer: there really is no straightforward way to do this. Of course if you wanted to get into the internals of the SystemC implementation, it is possible; however, that completely violates the standard. As to why this is not allowed: performance. The desire to have efficiency overrides the desire for corner cases such as yours. How can you work around this? Several possible approaches, but here one I would use: Create a new event class that adds tracking and an API to access it. This is easy to do if you know your C++ and SystemC well enough. Trivial outline of concept:: static const sc_core::sc_process_handle NONEXISTANT; struct Tracked_Event { void notify( void ); // sets m_process_handle and notifies m_event void notify( sc_core::sc_time delay ); // same except waits for delay sc_process_handle get_trigger( void ) { return m_process_handle; } void clear( void ) { m_process_handle = NONEXISTANT; }; private: sc_core::sc_event m_event; sc_core::sc_processhandle m_process_handle; }; struct Event_array { Event_array( int depth ); void wait( void ); // clears all m_process on entry, then waits for an m_event Tracked_event operator[]( int ); sc_vector<sc_core::sc_process_handle> get_trigger_list( void ); private: sc_vector<Tracked_Event> m_event_array; sc_core::uint64 m_delta_count; };
  12. David Black

    How to reset a thread in SystemC

    SC_THREADs are simply threads that are sensitive to a clock. Instead of wait(10ns), you wait(2), which means to "wait 2 clocks". Does not work for SC_METHOD though (no equivalent).
  13. In LT with Temporal Delay, the initiators maintain a local variable (sometimes with the aid of the Quantum Keeper) that represents time. Although time is not as important, we don't want to throw it completely away. So each initiator keeps a variable that represents how far ahead of the simulator's notion of time it has progressed. You can represent execution of instructions by simply adding a time value to that variable. Targets want to know the current simulated (not simulator) time so they can respond appropriately. For example, a timer definitely needs a notion of time in order to timeout. So initiators pass their local notion of the "current time" to the target. If a target wants to represent the notion of a time change, it can add to that delay, which will be reflected in the initiator since the b_transport call passes it by reference. LT models don't completely avoid sc_core::wait(), but they do try to minimize it because context switches affect performance. Adding to a local variable doesn't have as much of a hit.
  14. I think there are a few more options, but first, you need to acutely aware of the issue of OS thread safety. The SystemC kernel is not generally thread-safe unless you use async_request_update(), and a queue. I've done this several times. That said you have several options: Place software inside a SystemC SC_THREAD and provide convenience methods to initiate TLM transport calls. This is the simplest SystemC approach, but does not allow for modeling the actual CPU planned to be used and hence timing is not very accurate. This has the fastest performance from the SystemC point of view. Place the software on a development board that has the target CPU and some type of communications to the machine where you will run SystemC. I generally use TCP/IP sockets. Replace the driver with a special socket call passing packets to to a remote machine and receiving back the response. On the SystemC side, create an OS thread to receive the socket and inject the message into SystemC via the async_request_update call and an unbounded STL queue or FIFO of some type. A TLM 1.0 FIFO might do. A receiving thread can then pass the data into the SystemC simulation and return the result. This is somewhat more overhead, but allows for a more accurate target CPU. Obtain an ISS (Instruction Set Simulator) for the target processor and interface it to SystemC. This varies in complexity. You might look at existing models or talk with vendors such as Cadence or Mentor. Or perhaps your CPU vendor (e.g. Arm has some very nice models). As @Eyck suggested QEMU, DBT-RISE´╗┐-RISCV´╗┐. Also Gem5 (Google it).
  15. David Black

    How to reset a thread in SystemC

    Use SystemC 2.3 is your only easy option. I would expect much help from others to recreate what has already been done. You could also recast threads into cthreads (which has always worked).
  16. David Black

    Count number of SC_THREAD and/or SC_METHOD

    Caveat: That is the number of statically allocated processes. It does not account for dynamic threads or processes (i.e. sc_spawn'ed), which would be more difficult to track. Mind you, it is pretty complete and most likely static is what you are after.
  17. David Black

    Log File Parsing

    Just a few short thoughts: 1. If using SystemC or UVM, you should use restrict messages to the respective SC_REPORT_* or `uvm_report_* macros. These have standardized output formats, which makes them easier to use. 2. If using SystemVerilog without UVM, then use $info, $error, etc. for similar reasons 3. At the end of a simulation, you can detect how many errors etc. and use a return code. If would also suggest always printing a summary of the run (e.g. how many warnings and erros), and ALWAYS show one of two messages at the end: PASSED or FAILED. Makes life easier. My reason for the original logscan tool was situations where you don't have control over the error messages (e.g. certain EDA tools output).
  18. David Black

    Verifying Verification Components

    @kilroy369 I had forgotten that one. Much better suggestion. Same basic idea.
  19. David Black

    Verifying Verification Components

    I would do something I've previously done with SystemC (where uvm_error hails from). Basically, replaced the report handler with my own intercept to recategorize errors. Then added a mechanism to register "expected" errors, warnings, fatals. Prior to a point where an error was going to be injected, I would issue something like: begin_expect_error( "packet failure", 2 ); inject_error( ... ); wait_for_appropriate_time_or_event(); end_expect_error( "packet failure" ); If the report handler sees up to two errors, I would change the message severity to INFO and count off the expected error. At the end_expect_error call, I would check that exactly the number of expected errors occurred or consider it an error. Also, have to consider the possibility of the end_ call never happening.
  20. 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.
  21. 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>.
  22. 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.
  23. 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.
  24. 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.
  25. 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.
×