Jump to content

David Black

Members
  • Content Count

    476
  • Joined

  • Last visited

  • Days Won

    105

Reputation Activity

  1. Like
    David Black got a reaction from student4K in Running "Hello SystemC": assertion `m_references_n != 0' failed   
    Code itself looks fine. I ran the above on EDAplayground without problem.
    I also ran on MacOS 10.15.7 (Catalina) with Apple clang++ 12.0 (LLVM )
    Here is a link to where I ran it: https://edaplayground.com/x/V25h
    SystemC 2.3.3-Accellera --- Sep 21 2020 10:55:34
    g++ 7.5
    Using C++ standard 201402
    Ubuntu 18.04
    You might consider upgrading g++ (4.8 is pretty old). I use g++ 9.3 normally.
  2. Like
    David Black got a reaction from Pratik Parvati in Problem with immediate notification of event   
    SystemC is a discrete event driven simulator using an approach similar to Verilog, SystemVerilog and VHDL.The coding approach assumes cooperative multitasking. This is very time efficient and more importantly simplifies the modeling aspect if you really understand it, and makes it easier to interoperate with other simulators.
    Immediate notification is a unique feature of SystemC that works for some models, but not all. The reasoning behind it is simple efficiency. Delayed notification (i.e., SC_ZERO_TIME) is the safest approach if you are not certain that other processes are designed to work with immediate notification. Both potentially (likely) result in additional delta cycles.
    I have an old presentation (with code) that graphically single steps the simulator to make its behavior easier to understand under https://github.com/dcblack/SystemC-Engine/.
  3. Thanks
    David Black got a reaction from plafratt in TLM2.0 preempt last request   
    @plafrattTLM2 is built to allow any protocols you like. The "base protocol" was deemed sufficient for most needs; however, TLM2 was designed specifically to allow alternatives. Furthermore, the standard provides mechanisms to keep the cost of adapters/bridges between protocols simulation efficient.
    [Plug - ignore if you like] The Doulos course on TLM 2.0 <https://www.doulos.com/training/systemc-tlm-20/systemc-modeling-using-tlm-20-online/> investigates the base protocol and then builds up to a module describing custom protocols.
     
  4. Like
    David Black reacted to Eyck in TLM2.0 preempt last request   
    Actually the usual bus protocols allow to send larger number of requests and the interconnect is allowed to answer them 'out of order' (e.g. AMBA AXI or CHI). But you are free to define you onw protocol and its own rules. The LRM states exactly how to do this. One example can be found at  https://github.com/Arteris-IP/tlm2-interfaces which defines the extensions and phases for the AXI/ACE and the CHI protocol.
  5. Like
    David Black got a reaction from KiranK in what are the major differences between sc_port and sc_export?   
    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; | | | | // | | | | | | | | | | } | | | | // | | | '------------------' | | | | '----------------------' | | | // | | | | | | | | | | // | | |}; | | | | | | | // | | +----------------------------+ | | +------------------------------+ | | // | | | | | | // | |}; | |}; | | // | +------------------------------------+ +--------------------------------------+ | // | | // |}; | // +----------------------------------------------------------------------------------+  
  6. Thanks
    David Black got a reaction from gabriel123 in How to create a vector of fifos and add new fifos values depending on an input?   
    SystemC FIFO's represent hardware and as such may only be created during construction of a model. After elaboration closes, you are not allowed to add more fifos. None of your code examples above are complete, so it is fairly hard to give you a complete answer. Perhaps you could put your design on https://edaplayground.com and share a link with us.
    For details on phases of SystemC (e.g. elaboration) see IEEE-1666-2011.pdf, which you can obtain through Accellera.org.
     
  7. Like
    David Black reacted to AmeyaVS in Looking for SystemC tutor   
    Hello @berry_runner,
    Regarding a dedicated training look here: https://www.doulos.com/training/
    But as a starter in this, I would recommend getting to know following in no particular order:
    C++11/14/17: Useful for writing concise and clean code. SystemC from Ground Up 2nd Edition by @David Black. https://github.com/dcblack/SCFTGU_BOOK/ Look into the examples directory in SystemC sources. https://github.com/accellera-official/systemc/tree/master/examples Look into publicly released projects on Github: https://github.com/topics/systemc  Follow similar discussions in this forums: If you still have queries you can post in the forum for community support.
    Hope this helps.
    Regards,
    Ameya Vikram Singh
  8. Thanks
    David Black got a reaction from Nithin in Difference between sc_fifo_in and sc_fifo   
    sc_fifo<T> is a channel representing hardware FIFO behavior.
    sc_fifo_in<T> is a specialized port used to access an sc_fifo channel. Almost identical to sc_port<sc_fifo_in_if<T>>
    Suggestion: Read the freely available SystemC standards document (IEEE-1666-2011) or obtain a book on SystemC. It's all very clear there.
     
  9. Like
    David Black got a reaction from maehne in sc_inout class   
    Nothing wrong. Your output will be available after the delta cycle completes. You can view the new value in the next delta cycle.
    The problem for you conceptually is that you think 'S_val_out = expression' is a blocking statement. In other words, you expect the value to be transferred to the current value of S_val_out at the end of the assignment. Actually what is happening is akin to:
    S_val_out->write( A_val_in->read() +B_val_in->read() );  External to your sum class object, the S_val_out is bound to a channel sc_signal<T>, where the write() method is implemented. The write method does something like this:
    template<typename T> class sc_signal : sc_signal_in_if<T>, sc_signal_inout_if<T> { void write( T value ) { next_val = value; request_notify(); } T read() { return curr_val; } void notify() { curr_val = next_val; } }; SystemC will call notify at the end of the delta cycle after all other processes in the current delta cycle have completed their work.
    You could force code displaying the sum into the next delta cycle with:
    wait(SC_ZERO_TIME); but that could theoretically affect the other wait depending on how the inputs are being driven and cause you to miss updates.
  10. Like
    David Black got a reaction from omaima in Eclipse Windows with SystemC 2.3.0   
    @omaima RTFM please. It's all in the README and related files. Better yet, signup and take a class from somebody.
  11. Thanks
    David Black got a reaction from Abdelrahman in set sc_core::sc_in<bool>   
    Let me start by observing that you probably don't want to initialize an input port. After all, inputs observe information from outside the module. So I will assume you mean an output port. If need be, you could change to use an sc_inout<T> port, but you might create a nasty race condition.
    The cleanest and most general approach is to write to the port during the start_of_simulation phase. How? Just create a override method, void sc_start_of_simulation(void), in your module.
    SC_MODULE( Example ) { sc_out<bool> oport{"oport"}; sc_signal<int> local_sig{"local_sig"}; void sc_start_of_simulation( void ) { oport->write( false ); // initialize an external signal via a port local_sig.write( 42 ); // initialize an internal signal } ... the rest of your module ... };  
    One other thing, I need to clear up a misconception: SystemC ports do not have a value despite the unfortunate presence of the overloaded operator=. The value that you are thinking comes from the port, actually comes from the channel it is connected to. In the case of sc_in<T> and sc_out<T>, the channels are specifically sc_signal<T>. Also, a channel itself is not data. Channels are vehicles for communication and synchronization. When you write to an sc_signal, you are depositing a value into an internal buffer, the future value buffer. When you read from an sc_signal, you are obtaining the value from another buffer, the current value. How and when the future value gets copied to the current value, is the subject of a deeper idea.
    For sc_signal channels, there used to be special method, init, but that is not standard. It is also the case that a constructor exists in the Proof-of-Concept implementation with a second constructor argument for initialization; however, this is also not yet standardized. So I would avoid either of these approaches.
     
  12. Like
    David Black got a reaction from maehne in Clock Gating in SystemC?   
    Three thoughts might be helpful for you to consider:
    You could of course use next_trigger() in SC_METHOD:
    SC_MODULE(HARD_WAY) { sc_in<bool> clock, clock_enabled; SC_CTOR(HARD_WAY) { SC_METHOD(gated_method); sensitive << clock; ... } ... void gated_method(void) { if ( clock_enabled and clock.posedge() ) { // Normal operations } else { // Wait until clock is re-enabled next_trigger( not clock_enabled ); } } The better way is to use sc_process_handle::disable() and enable()
    #define SC_INCLUDE_DYNAMIC_PROCESSES #include <systemc> #include <vector> using namespace sc_core; std::vector<sc_process_handle> gated; //< collect processes needing gating SC_MODULE(EASY_WAY) { sc_in<bool> clock; SC_CTOR(EASY_WAY) { SC_METHOD(gated_method); sensitive << clock; gated.push_back(sc_get_current_process_handle()); ... } void gated_method(void) { // Normal operations } ... }; // Process controlling gating void control thread(void) { ... if ( turn_off_clock ) { for( auto& process : gated ) process.disable(); } if ( turn_on_clock ) { for( auto& process : gated ) process.enable(); } ... } Above approach works on all static SystemC process types. Dynamic processes might escape.
    A more comprehensive and easier approach could be done if your gated processes are all submodules of a containing module. In that case, you skip the registration issue, because you can simply do a hierarchical search to collect the list of processes that need to be disabled or enabled at the time of power down/up. This approach will also capture dynamic processes.
     
     
  13. Like
    David Black reacted to Eyck in Issue while calling sc_main multiple times from main   
    Just to add 2 cents to @David Black proposal: If the instantiation is exepensive you could fork() (https://en.wikipedia.org/wiki/Fork_(system_call)) your programm after instantiating the design. Basically you create a new OS process as copy of the current one and here you can continue the simulation. But in essence it is the same approach as David described.
  14. Like
    David Black reacted to maehne in Issue while calling sc_main multiple times from main   
    The primary reason is that the SystemC Proof-of-Concept (PoC) implementation uses some global data structures, which get constructed during elaboration, which are not fully cleaned up when sc_stop() is called. These data structures are only freed by the OS when the application quits. There have been some efforts improve the PoC implementation in this area, but these are currently stalled. Unfortunately, partially due to bad code examples, bad habits, and laziness, many SystemC models also not cleanly deallocate their dynamically allocated resources, as they still use manual resource allocation using the new operator, but never release that memory using delete as they don't implement a destructor out of laziness. Since the general availability of smart pointers in C++'11, especially std::unique_ptr<T>,  managing cleanly dynamic memory management has become much more convenient and there is no justification anymore to write such dirty code. However, there is a lot of legacy code out there making a bad example and hardware engineers often lack a formal education in C++ instead learning the language basically on the job. This will only resolve slowly over time. 
    @David Black's suggestion to launch your multiple simulations from a separate process implemented using your favourite scripting language or even in C++, is the easiest workaround for the above problems.
  15. Like
    David Black got a reaction from KiranK in Does anyone knows what different between systemC and systemC TLM?   
    SystemC TLM is a part of the SystemC standard (both parts TLM1 and TLM2). True, it is an newer addition, but it is never-the-less part of the standard.
     
    TLM1 was the first attempt to standardize an API, which worked, but it didn't address the needs of the SystemC community as well as had been hoped. TLM2 standardizes a methodology to model address mapped bus communications and the associated API. It allows for easier exchange of IP blocks for simulation.
     
    TLM emphasizes that "ports" are not just wiring connection points, but rather a nexus for higher levels of communication. TLM2 has "sockets", which are really just glorified SystemC port combinations (sc_port & sc_export). TLM2 also standardizes some concepts (even if not stringently) of different styles of transaction level modeling (sometimes called coding styles). For instance, "loosely-timed" (LT) represents "execute as fast as possible while maintaining register functional accuracy"; whereas, "approximately-timed" (AT) means "provide sufficient timing detail to allow bus-level timing analysis[1]". AT does not simulate as quickly as LT because it has to provide extra details and timing behavior.
     
    Note 1: Not necessarily the same as clock cycle accuracy.
     
    On the other hand, the SystemC core provides the fundamental mechanisms that allow for design encapsulation (sc_module), event-driven simulation (sc_event and wait()), processes (SC_THREAD, SC_METHOD), a notion of simulated time (sc_time) and channels (sc_interface, sc_prim_channel, sc_channel). Channels are one of the most important features and enable abstraction of safe interprocess communications. SystemC also provides the minor addition of hardware datatypes (sc_logic<>, sc_int<>, sc_fixed<>, etc). It also provides primitive communications channels such as sc_signal<> and sc_fifo<>. Thus, the SystemC core provides the foundation needed to implement TLM.
     
    Sadly in some sense, SystemC provides a number of simplifications for writing RTL even though it is fundamentally not the strong point of the simulator. To some degree these simplifications are an holdover from SystemC 1.0 for backwards compatibility. I said sad because the simplifications have encouraged many to think of SystemC as an appropriate vehicle for writing RTL code, but then get frustrated at the lack of performance (for RTL). SystemVerilog and VHDL are much better suited for that task. The RTL aspect of SystemC is good in making it easier to interface SystemC to the other languages for co-simulation.
  16. Like
    David Black got a reaction from Nitin_S in Issue while calling sc_main multiple times from main   
    @Eyck is correct. It would be a major rewrite of SystemC to allow this. If you are trying to launch multiple simulations (sequentially) perhaps with different parameters, you need to do that from a script. If you are super insistent you have to do it under C++, you could try the following:
    // Compile your main SystemC as run.exe and place it in the same directory as this program int main(void) { int errors = 0; errors |= system("./run.exe -option 1"); errors |= system("./run.exe -option 2"); return errors; } Or just use your favorite script language (bash, perl, zsh, csh, python) to do the equivalent. You can store results in files and read configuration data from files. It's just C++.
    If you want to rewrite the main.cpp from the library, feel free to do so, but you still won't be able to reset SystemC's internal data structures without invoke a completely new process.
  17. Like
    David Black reacted to Eyck in Binding sc_out type of ports to sc_port<sc_signal_inout_if<T>,N> type of multiports failed   
    You cannot bind an output port to an input port. Ultimately each port must bind to a signal either hierarchically (this is where port to port binding can is used) or directly.
    So you need to define signal for each of the test_module output ports and bind the sc_out and sc_inout ports to it.
    2 remarks:
    you should use sc_in instead of sc_inout to indicate the purpose clearly sc_out is just a child of sc_inout to reduce the number of output ports (and hence signal) you might want to group signals logically belonging together into structs. Those can be used as data typs of signals and ports. This reduces the number of signals and events and increases simulation speed.
  18. Like
    David Black got a reaction from maehne in How can I identify which port has changed value when using a multiport   
    First, you have an error in your example corrected below:
    for(int i=0;i<prt_input.size();i++) sensitive << prt_input[i]->value_changed_event(); } Second, you can use a recent addition to SystemC (if using version 2.3.3 or later) using the new sc_event::triggered() method, which returns true if the event happened in the immediately preceding delta-cycle. You would simply apply this to the default_event() method present in most channels. A less general approach could also be used with sc_signal channel, which has always provided the event() method for the same effect, but won't work on other channels. Of course you can apply this to any method returning events of other types (e.g. sc_fifo_in_if::data_written_event()). This can also be used with SC_THREADs with the sc_event_or_list.
    I illustrate the more general approach on EDAplayground here: https://edaplayground.com/x/4kgB
  19. Like
    David Black got a reaction from maehne in About AT   
    Approximately-Timed (AT) models provide decent timing accuracy for modeling purposes. Common use cases include architectural analysis (cost vs performance). AT models are used to understand the effects of interconnect and bus protocols on overall performance.
    Loosely-Timed (LT) models provide for simulation performance (i.e. fast), but often use techniques that sacrifice modeled timing accuracy. The intent is for use in software development on virtual platforms. Techniques used include Temporal De-coupling coupled a notion of a Quantum, and Direct Memory Interface. LT models usually try to minimize calls to wait() due to overhead of context switching. Fast models almost never use sc_clock (slows simulation).
    Both modeling styles (AT & LT) should be register accurate and functionally correct. Both include timing, but obviously the degree of accuracy differs greatly.
    Standards compliant models will provide both modeling styles in a single design; although; it is often the case that early modeling starts with one or the other and later adds the missing style. Generally, b_transport functions provide the LT coding style, and nb_transport_* methods provide the AT coding style.
    Neither should be as accurate as RTL because that would require adding so much code overhead that you might as well write RTL and skip SystemC. Clock cycle accurate models are generally inappropriate. Cycle-Approximate or Cycle-Count Accurate modeling is a better description of AT models.
    [As an employee of Doulos Ltd, I teach courses on SystemC modeling with TLM-2.0. You might find that taking an on-line class from us is beneficial. https://www.doulos.com]
  20. Like
    David Black got a reaction from maehne in About AT   
    TLM (Transaction Level Modeling) is focused on communication (interconnection) of SystemC models. So your question is slightly irrelevant. From what you indicate, I would say that AT modeling style would accomplish what you are interested in. Sockets are an almost essential aspect of  TLM as they simplify modeling and can provide information about the transaction.
    As to what metrics you can get, that is up to you. SystemC is not a prepacked set of subroutines, nor is it a narrowly focused on one type of analysis. SystemC is a methodology using C++ to model any variety of ideas using an event driven simulation core (provided). You provide the code to stimulate and assess the information. It is common to obtain things such as bus bandwidth and utilization, but there are no primitives provided to do this on its own.
    Important: You need to be well versed in C++ to effectively use SystemC. Far too many folks approach SystemC thinking it will be a panacea and only requires C.
    There are companies that provide commercial tools on top of SystemC to help with modeling. I will not comment on their utility, but obviously they have some value or they would not be around for long. There are also consulting companies that specialize in SystemC. Learn more on the main Accellera website (https://www.accellera.com). My employer (and thus myself) focuses on the training/educational aspect.
  21. Like
    David Black got a reaction from maehne in SC_METHOD Dynamic sensitivity modification outside the process   
    Silly me, I was quite mistaken in my simple solution (and it only took me a few minutes after posting to realize it); however, this exercise reminded me of a 2011 feature: reset. This works for SC_METHOD processes, but is inconvenient for SC_THREADs. I enjoyed working the puzzle.
    You can see a full working example here: https://www.edaplayground.com/x/39QM
    Outline:
    When registering your SC_METHOD process capture the process handle and specify dont_initialize(). At the start of your method implementation, check for the trigger state of reset_event and return immediately if triggered. To reset static sensitivity, simply issue reset on the process. Include a comment that you are simply interrupting. Note 1: This assumes you are using a version of SystemC 2.3.3 or later. If using 2.3, you will need to add a bool flag that is set at the time of invoking reset and cleared inside the process upon detection.
    Note 2: You could also use reset_signal_is(); however, that would require adding deassertion and would be messier in my opinion.
    An alternate and less intrusive method would be to simply add an interrupt event into the sc_event_or_list every time you change sensitivity:
    next_trigger(some_event | interrupt_event); next_trigger(time_delay, interrupt_event); Unfortunately, this doesn't work for sc_event_and_list; however, you can synthesize that situation with another process. I will leave that for you to figure out.
  22. Like
    David Black reacted to Eyck in How to open and read TEXT file in systemC   
    AFAICS you don't increment the index i in the while loop.
    But your code is way to complex.:
    std::ifstream ifs("TEXT.txt"); if(ifs.is_open()){ int buf = 0; for (int i = 0; i < MEM_DEPTH; i++) { ifs >> buf; buff_1[i]=buf } } ifs.close(); should replace everything from fopen() until fclose(). And you should avoid using macros, they will bite you. '#define MEM_DEPTH 20' should become 'const size_t MEM_DEPTH=20;'.
     
  23. Like
    David Black got a reaction from tahirsengine in A weird question about UVM   
    UVM is all about reuse. Reuse has several different aspects:
    Reuse of an engineers knowledge -- those experienced with UVM can usually jump onto an existing or new UVM project with very little ramp time. I have seen some verification environments using their own methodology that literally took months for new engineers to come up to speed on. Mind you misuse of UVM can lead to the same conclusion if you don't stay within the standard itself. Reuse of verification components -- means you can reuse a UVM environment without editing a single line of code provided by that environment. This is huge. It is possible to purchase UVM components that test standard interfaces (e.g., 1G Ethernet) and not have to create the code yourself. It still requires the expertise to plug the component into your environment, but it is relatively easy to do. UVM also means application of a tried and tested methodology rather than role your own.
    Downsides to UVM include:
    UVM is fairly complex and to get the most out of it generally requires training UVM is fairly large as a body of code and has a lot of boilerplate code Bottom-line: You don't have to use UVM to verify your code, but if your designs are large enough, it seem crazy not to adopt it. You can hire employees and contractors that know how to do leverage UVM and purchase components to shorten your design task. For small/tiny designs, it may not make sense.
  24. Like
    David Black got a reaction from Nimesh in Determining change in signals   
    module who_changed_first(input a, b, start); always @(posedge start) begin byte changed; WATCHERS: fork @a changed = "a"; @b changed = "b"; join_any disable WATCHERS; //< prevent others from overwriting case (changed) "a": work_1; "b": work_2; endcase end Assumes SystemVerilog. If Verilog you will need to add .
    See https://edaplayground.com/x/2NXz for example code.
  25. Like
    David Black reacted to Eyck in Module that convert an sc_vector input into sc_signal   
    Sure. Just add a method reading all bool sc_in and write to the output. You need to make it sensitive to all inputs Something like:
    SC_MODULE(conv){ sc_vector<sc_in<bool> > input{"input"}; sc_out<bool> ouput{"ouput"}; SC_CTOR(conv){ SC_HAS_PROCESS(conv); SC_METHOD(method); for(auto& in: input){ sensitive<<in; } } void method(){ unsigned res = input[1]?2:0+input[0]?1:0; output=res; } };  
×
×
  • Create New...