Jump to content

Roman Popov

  • Posts

  • Joined

  • Last visited

  • Days Won


Reputation Activity

  1. Like
    Roman Popov got a reaction from Supernova in Range of port mapping from outer to inner module input port   
    A well known SystemC problem.  Unfortunately you will have to create SC_METHOD that will divide your ins port into multiple signals on range basis.
  2. Like
    Roman Popov got a reaction from AnandRamesh in Newbie sc_signal<class T> creation problem   
    you can pass reg_file constructor parameter as second parameter to sc_signal constructor:
    For example:
    sc_signal<reg_file> tmr_regs {"tmr_regs", number_of_regs}; However your code won't compile anyway, because sc_signal requires operator =, operator <<, operator == and sc_trace method to be defined in user-defined data type. Check here for example:
    Also, please note that your modeling style is not common in SystemC world. For regfile modeling you should probably
    create a dedicated SC_MODULE (reg_file)  or use array of sc_signals directly :   sc_signal<sc_uint<8>> tmr_regs[REG_NUMS]; //You can also use sc_vector for that purpose.
  3. Like
    Roman Popov got a reaction from susharma in Skipping this library for "sccom-link"   
    Hello, I think you should ask Mentor support directly.
  4. Like
    Roman Popov got a reaction from maehne in Microsoft Visual Studio Community 2015   
    We are facing this too. Hope to see VS2015 support soon. There are issues with modern C++ support in VS2013.
  5. Like
    Roman Popov got a reaction from maehne in Problems with SystemC syntax, improvment request   
    This is my plan.
    My plan is opposite: if this sort of syntax will be helpful for users, commercial vendors will probably support it in existing systemc synthesis tools.
    Speaking about SystemC "language" complexity: this is indeed the case with current SystemC. Because of that most HW designers prefer Verilog/SystemVerilog.
    But features I've presented are about reducing SystemC syntax complexity, not about further complication.  So code will be more compact, less verbose and error-prone.
    Personally I find one good thing about HW design in SystemC: If I will lose my job in semiconductor industry, I can find another one as C++ programmer    Something I couldn't do if I were a SystemVerilog programmer.
  6. Like
    Roman Popov got a reaction from maehne in sc_port get_interface() method   
    Check following member functions described in IEEE1666-2011
    5.12.8 Member functions for bound ports and port-to-port binding size operator-> operator[]   Looks like everything should be bound before end_of_elaboration callback
    You can also look into reference SystemC implementation source code to get the details.
  7. Like
    Roman Popov got a reaction from maehne in Merging sc_int and sc_bigint   
    It seems like it makes sense to merge sc_*int and sc_big*int types.
    Wide buses are all around in modern systems. For example 64 bytes is common size of cache line. 
    I do not see a good reason to keep two types for representing types with user-defined size.
    For example in Verilog I have single common type for all cases:
    bit [31:0] address; bit [511:0] data; But in SystemC I will have to use different types:
    sc_uint<32> address; sc_biguint<512> data; Specializing sc_uint depending on size will not break compatibility with existing Systemc 2.3 code .
    constexpr bool is_biguint(unsigned x) { return x > 64; } template<int n, bool isbig = is_biguint(n)> struct sc_uint {}; template<int n> struct sc_uint <n, true>: public sc_unsigned { }; template<int n> struct sc_uint <n, false>: public sc_uint_base { };  
  8. Like
    Roman Popov got a reaction from maehne in Problems with SystemC syntax, improvment request   
    If we combine expression templates and in-place initialization, enhanced C++11 syntax can look something like that:
    SC_MODULE(demo_mod) {     sc_in<int> a_in{"a_in"};     // second optional parameter is assignment expression     sc_out<sc_int<8>> b_out{"b_out", a_in + c_sig};     // constant zero output     sc_out<int> zero_out{"zero_out", 0};     sc_signal<sc_uint<4>> c_sig{"c_sig"};     // some bus port     amba::apb_slave apb_in{"apb_in"};     // sencond optional paramteter to sc_module_name is binding function     some_module inst_name {{"inst_name", [&]() {         inst_name.in0(a_in);         inst_name.apb_in(apb_in); // bus binding         inst_name.in1(10); // bind to constant         inst_name.out0(); // unconnected by design     }}};     sc_signal<sc_uint<8>> d_sig{"d_sig"};     SC_CTOR(demo_mod) {         // assignment         d_sig.assign( (c_sig , c_sig) - 10 );         SC_THREAD(test_thread);     }     sc_signal<sc_uint<8>> e_sig{"e_sig"};     void test_thread() {         int var = 12;         // wait for expression         wait( c_sig[0] && (a_in == 12) );         // evaluates expression         e_sig = a_in + b_out.range(3,0) + d_sig + 12;         sc_stop();     } };
  9. Like
    Roman Popov got a reaction from maehne in Problems with SystemC syntax, improvment request   
    One more powerful feature of Verilog are implicit signals and methods.
    Consider following example:
    logic          clk; logic [7:0]   addr; logic          write_en; logic          slave0_irq; logic          slave1_irq; master master0 (     .clk(clk),     .addr(addr),     .write_en(write_en),     .interrupt_vec( {slave1_irq, slave0_irq} ) ); slave slave0 (     .clk(clk),     .addr(addr[6:0]),     .write_en(write_en && addr[7] == 0 ),     .interrupt(slave0_irq)     ); slave slave1 (     .clk(clk),     .addr(addr[6:0]),     .write_en(write_en && addr[7] == 1 ),     .interrupt(slave1_irq)     ); In Verilog I can bind port to signal sub-range without explicitly defining additional signal and creating a method to extract sub-range:
    .addr(addr[6:0]), SystemC:
    sc_signal<sc_bv<7> > subaddr{"subsignal"}; ... void extract_subrange_method() { subaddr = addr.read().range(6,0); } ... SC_METHOD(extract_subrange_method); sensitive << addr; ... slave0.addr(subaddr); About 7 LOC in SystemC vs 1 LOC in Verilog. 
    Verilog allows to merge multiple signals into one:
    .interrupt_vec( {slave1_irq, slave0_irq} ) Or even more complex expressions :
    .write_en(write_en && addr[7] == 1 ), So if I rewrite whole module from Verilog to SystemC I will get about 150-200 LOC vs 35 LOC in original Verilog file. 
    SystemC desperately needs similar syntax if it wants to grow as HDL.  Mixing Verilog and SystemC is not an option: in general I have HLS-style and RTL-style code in same module.   So we either need an HLS for Verilog, or facelift for SystemC. 
    It feels like it is possible to implement such type of binding at library level, without creating additional "SystemC preporcessor".
    Because we bind sc_ports to sc_signals (not to primitive types (char, int)) it is possible to improve those classes to support this type of syntax.
    For example we can apply expression templates over sc_signals:
    So expression like this:
    write_en && addr[7] == 1
    over sc_signals will return some class sc_expression that will contain both:
    recursive function to compute expression list of sc_signals that will go into sensitivity list Next, during port binding create anonymous sc_signal with the same type as port.  And spawn a method that will assign this signal a value computed by expression template.
  10. Like
    Roman Popov got a reaction from maehne in Problems with SystemC syntax, improvment request   
    Some syntax to create methods/threads out of constructor body would be helpful too. For example by creating classes sc_thread and sc_method.
    imagine something like
    SC_MODULE (foo) { SC_CTOR(foo); // sc_method ( sensitivity_list , process_handle ) sc_method  sum_method ( {a,b,c} , [&]() {          sum = a + b + c;     } }; void diff_method_body(); sc_method  diff_method ( {x,y} , diff_method_body ); }; void foo::diff_method_body() { diff = x - y; }
  11. Like
    Roman Popov got a reaction from maehne in Problems with SystemC syntax, improvment request   
    One more thing to consider is positional port binding using initializer list.
    While I never use this feature, I think it can be implemented in some better way.  
    Looks like there is a limitation of maximum 64 ports with current sc_module : 
    void operator () ( const sc_bind_proxy& p001, const sc_bind_proxy& p002 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p003 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p062 = SC_BIND_PROXY_NIL, ... const sc_bind_proxy& p063 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p064 = SC_BIND_PROXY_NIL ); };
  12. Like
    Roman Popov got a reaction from maehne in Problems with SystemC syntax, improvment request   
    There is a problem with implementation of in-place binding I've suggested in previous post: it does not respects the fact that signals may not be constructed by the time biding function is executed.
    So it is better to delay binding until everything is constructed. Here is better implementation:
     struct my_sc_module : public sc_module {    typedef std::function<void()> bind_func_t;     bind_func_t bf;     my_sc_module( bind_func_t bind_func ) : bf(bind_func)  {}     void before_end_of_elaboration() override {         if (bf) bf();     } }; #define SC_MODULE(user_module_name)                                           \     struct user_module_name : my_sc_module #define SC_CTOR(user_module_name)                                             \     typedef user_module_name SC_CURRENT_USER_MODULE;                          \     user_module_name( ::sc_core::sc_module_name , bind_func_t bind_func = 0) : my_sc_module(bind_func) SC_MODULE(adder) {     SC_CTOR(adder) {         SC_METHOD(add_method);         sensitive << a << b;     }     void add_method() { sum = a + b; }     sc_in<uint8_t> a{"a"}, b{"b"};     sc_out<sc_uint<9> > sum{"sum"}; }; SC_MODULE(adder_test) {     sc_signal<uint8_t> *a;     adder add_inst{"add_inst", [&]() {         add_inst.a(*a);         add_inst.b(;         add_inst.sum(sum);     } };     SC_CTOR(adder_test) {         a = new sc_signal<uint8_t>("a");         SC_THREAD(test_thread);     }     void test_thread() {         a->write(11);         b = 31;         wait(1, SC_PS);         cout << sum.read() << endl;         sc_stop();     }     sc_signal<uint8_t> b{"b"};     sc_signal<sc_uint<9>> sum{"sum"}; }; int sc_main(int, char**){     adder_test test("test");     sc_start();     return 0; }
  13. Like
    Roman Popov got a reaction from maehne in Problems with SystemC syntax, improvment request   
    Is any facelift planned for next SystemC release (2.4 or 3.0)?
    I want to share some feedback , from synthesizable SystemC designer prospective. 
    Recently I’ve done a lot of synthesizable SystemC coding for HLS (High level synthesis tools). I really enjoy the power of synthesizable stateful threads (SC_THREADS), it helps a lot in converting algorithmic C++ code into RTL.  TLM abstraction of synthesizable bus interfaces works well too.
    However, If you look at low level syntax details, SystemC code looks really ugly comparing to Verilog.  Consider a simple example:
    module adder ( input [7:0] a, b, output [8:0] res ); assign res = a + b; endmodule module adder_test; reg [7:0] a, b; wire [8:0] res; adder adder_isnt( .a(a), .b(, .res(res) ); initial begin a = 11; b = 31; #1; $display("%d",res); end endmodule If I rewrite in SystemC it would be:
      #include <systemc.h> SC_MODULE(adder) { sc_in<uint8_t> a, b; sc_out<sc_uint<9> > sum; SC_CTOR(adder) : a{"a"} , b{"b"} , sum{"sum"} { SC_METHOD(add_method); sensitive << a << b; } void add_method() { sum = a + b; } }; SC_MODULE(adder_test) { sc_signal<uint8_t> a, b; sc_signal<sc_uint<9>> sum; adder add_inst; SC_CTOR(adder_test) : a("a") , b("b") , sum("sum") , add_inst("add_inst") { add_inst.a(a); add_inst.b(; add_inst.sum(sum); SC_THREAD(test_thread); } void test_thread() { a = 11; b = 31; wait(1, SC_PS); cout << sum.read() << endl; sc_stop(); } }; Main problem is not that SystemC code has more charaters/LOCs, but that semantically related statements are distributed across source file.
    Take for example adder instantiation:
    First we have to declare member variable:
      adder add_inst; Next we need to initialize its name:
      : add_inst("add_inst") And finally bind its ports:
    add_inst.a(a); add_inst.b(; add_inst.sum(sum); Because of this syntactic problem it is very hard to read SystemC code when you have a lot of signals and modules instantiated.  
    Same problem with SC_METHOD and SC_THREAD:
    You have to define method in one part of code, and declare it as a SC_METHOD/SC_THREAD in another.  I often forgot to put this SC_THREAD macro and my simulations do not work.
    Forgetting sc_module_name initialization is even more common (but does not do that much damage).
    So there are two problems with SystemC syntax:
    Code hard to read. Easy to forget something.  
    I hope this will be fixed soon.  If I start to think about it , I see two possible options:
    Option 1: Preprocessing
      First solution would be creating some SystemC preprocessor. It's not that uncommon idea in C++ world.  For example widely used Qt Framework (http://www.qt.io/) uses it’s own preprocessor. Some EDA SystemC tools use it too: Forte Cynthesizer used preprocessor to extract uArch constraints from some vendor predefined Macros,  I think Cadence Stratus inherited this HLS Macro idea too (have not tried it yet).

    The obvious argument against this would be breaking C++ tools compatibility (for example C++ IDE front-ends). But it’s not always the case: Qt and HLS preprocessors do not break C++ syntax,  syntactically valid SystemC code will stay a valid C++ code.
    But some C++ static analysis tools may break: for example, if we generate body of sc_module constructors in preprocessor, than we will have some “unreachable” code, “unused” methods detected in human-written code.

    Second argument against preprocessor is that user will need to integrate additional step into C++ build process. Sometimes it hurts, many users do not like to write custom build steps.

    Main benefit in preprocessing is that it solves all the problems. It would be even possible to automatically generate sensitivity lists for SC_METHODS (in that case it it would be very smart Clang-based preprocessor), highly desired.
      Option 2:  Improve SystemC library
      Many things can be done simply by improving SystemC library.  In that case we will be limited by C++ meta-programming capabilities.

    Ultimate solution to sc_object naming will be C++ reflection:
    But my bet it would not be standardized in next five years or so. Probably some EDA or semiconductor company can devote some resources to make it happen sooner?

    Many things are better out-of-the box in C++11,
    For example in-class initializers:
    sc_signal<uint8_t>     a{"a"}, b{"b"}; sc_signal<sc_uint<9>>  sum{"sum"}; I use it now in all of my SystemC verification code.  Unfortunately not yet supported by HLS tool I use.

    David Black proposed solution for assign
    Same idea with lambda can be applied to every SC_METHODS/SC_THREAD processes.  

    Binding instance ports can be implemented in the same place where instance defined.
    Consider for example passing “bind” lambda using in-class initializer:
      #define SC_CTOR(user_module_name)                                           \   typedef std::function<void(user_module_name& self)> bind_func_t;          \   typedef user_module_name SC_CURRENT_USER_MODULE;                          \   user_module_name( ::sc_core::sc_module_name, bind_func_t bindf= 0)        \   { if (bindf) { bindf(*this); } #define BIND_INST(module_type) \   [&](module_type& i) Summing all together improved SystemC can probably look like:
    SC_MODULE(adder) {       sc_in<uint8_t>       a{"a"}, b{"b"};       sc_out<sc_uint<9> >  sum{"sum"};       SC_CTOR(adder) { ASSIGN( a|b, sum = a + b; );       } }; SC_MODULE(adder_test) {       sc_signal<uint8_t>     a{"a"}, b{"b"};       sc_signal<sc_uint<9>>  sum{"sum"};       adder add_inst{"add_inst", BIND_INST(adder) {               i.a(a);               i.b(;               i.sum(sum);           }};       SC_CTOR(adder_test) {                     SC_THREAD_LAMBDA(test_thread) {            a = 11; b = 31;            wait(1, SC_PS);            cout << sum.read() << endl;            sc_stop(); }       } };  
  14. Like
    Roman Popov got a reaction from Tedy in Dynamic communication path in SystemC/TLM   
    You can do this with pointer to port or using sc_vector;
    for example:
    SC_MODULE (test_mod) { sc_in<unsigned>  *data_port; ... SC_CTOR(test_mod) { if (create_data_port) data_port = new sc_in<unsigned> ("port_name"); } }
  15. Like
    Roman Popov got a reaction from apfitch in Problem with the case statement   
    Hello kihtrak,
    In your source code you don't assign any value to bin.   Please provide a minimal simulation source code to reproduce your problem. Otherwise nobody can help you.
  16. Like
    Roman Popov reacted to aheimberger in SystemC 2.3 Pretty-Printer   
    Hey Guys,
    I don't know if you know about GDB Pretty-Printer. GDB Pretty-Print let you print your debug output in a legible way. I tried to write the Pretty-Printers analyzing the SystemC 2.3 implementation and I was learning how the information is stored within the SystemC implementation. You will find the Pretty-Printer under following link. 
    On Github you will find instructions about installing the Pretty-Printer and a verification python file. Hope this Pretty-Printer helps you and does not cause to many problems. I were also able to use them within Eclipse.
    Cheers Andy

  • Create New...