Track 3: ESL and SystemC
The Definitive Guide to SystemC:
    The SystemC Language
    David C Black, Doulos
Track 3: The Definitive Guide to SystemC
The SystemC Language
        Introduction to SystemC
              Overview and background
              Central concepts
              The SystemC World
              Use cases and benefits
        Core Concepts and Syntax
        Bus Modeling
        Odds and Ends
                                           2
What is SystemC?
    System-level modeling language
          Network of communicating processes (c.f. HDL)
          Supports heterogeneous models-of-computation
          Models hardware and software
    C++ class library
          Open source proof-of-concept simulator
          Owned by Accellera Systems Initiative
                                                Communicating
                                                processes
                                                                    3
Features of SystemC
       Modules          (structure)
       Ports            (structure)
       Processes        (computation, concurrency)
       Channels         (communication)
       Interfaces       (communication refinement)
       Events           (time, scheduling, synchronization)
       Data types       (hardware, fixed point)
                 Port                   Interface
    Module                                                Module
    Process
                              Channel                     Process
                                                                    4
Modules and Channels
      Module                                                      Module
      Process                         Channel                     Process
 Functionality /      Separated!      Communication /
 Computation                             Protocol
Architecture of SystemC
                               User Applications
               SystemC
                                                        Other Model
              Verification          TLM Library
                                                         Libraries
              Library SCV
                               Primitive Channels
                      (signal, buffer, fifo, mutex, semaphore)
                   Core Language
             (module, port, process,                Data Types
            channel, interface, event)
                                   C++ Language
                                                                            6
Typical Use Case: Virtual Platform
 Multiple software stacks
                 Software                                           Software
   CPU          ROM         RAM     DMA                   DSP         ROM      RAM
                                             Bridge
 Interrupt      Timer        I/O    Bridge              Interrupt     Timer    A/D
 Multiple buses and bridges
                                                                               TLM-2.0
                        Memory                         Custom
          I/O                       RAM      DMA                      D/A
                        interface                     peripheral
 Digital and analog hardware IP blocks
                                                                                         10
Track 3: The Definitive Guide to SystemC
The SystemC Language
             Introduction to SystemC
             Core Concepts and Syntax
                    Data
                    Modules and connectivity
                    Processes & Events
                    Channels and Interfaces
                    Ports
             Bus Modeling
             Odds and Ends
                                                                                         14
SystemC Data Types
In namespace sc_dt::
  Template           Base class          Description
  sc_int<W>          sc_int_base         Signed integer, W < 65
  sc_uint<W>         sc_uint_base        Unsigned integer, W < 65
  sc_bigint<W>       sc_signed           Arbitrary precision signed integer
  sc_biguint<W>      sc_unsigned         Arbitrary precision unsigned integer
                                         (intermediate results unbounded)
  sc_logic                               4-valued logic: '0' '1' 'X' 'Z'
  sc_bv<W>           sc_bv_base          Bool vector
  sc_lv<W>           sc_lv_base          Logic vector
  sc_fixed<>         sc_fix              Signed fixed point number
  sc_ufixed<>        sc_ufix             Unsigned fixed point number
                                                                                           15
Limited Precision Integer sc_int
         int           i;
         sc_int<8> j;
         i = 0x123;
         sc_assert( i == 0x123 );
         j = 0x123;                                                  Truncated to 8 bits
         sc_assert( j == 0x23 );
         sc_assert( j[0] == 1 );                                        Bit select
         sc_assert( j.range(7,4) == 0x2 );                             Part select
         sc_assert( concat(j,j) == 0x2323 );                        Concatenation
   Other useful operators: arithmetic, relational, bitwise, reduction, assignment
   length() to_int() to_string() implicit-conversion-to-64-bit-int
                                                                                           16
Logic and Vector Types
  sc_logic and sc_lv<W>
        Values SC_LOGIC_0, SC_LOGIC_1, SC_LOGIC_X, SC_LOGIC_Z
        Initial value is SC_LOGIC_X
  No arithmetic operators
   sc_logic R, S;                 sc_int<4>      n = "0b1010";
   R = '1';                       bool        boo = n[3];
   S = 'Z';                       sc_lv<4>      lv = "01XZ";
   S = S & R;                     sc_assert( lv[0] == 'Z' );
                                  n += lv.to_int();
                                  cout << n.to_string(SC_HEX);
                                                                       17
Fixed Point Types
        sc_fixed <wl, iwl, q_mode, o_mode, n_bits> a;
        sc_ufixed<wl, iwl, q_mode, o_mode, n_bits> b;
        sc_fix    c(wl, iwl, q_mode, o_mode, n_bits);
        sc_ufix d(wl, iwl, q_mode, o_mode, n_bits);
   Word length                - number of stored bits - no limit
   Integer word length        - number of bits before binary point
   Quantization mode          - behavior when insufficient precision
   Overflow mode              - behavior when result too big
   Number of saturated bits   - used with wrap overflow modes
     Compiler flag -DSC_INCLUDE_FX
                                                                       18
Data Summary
             C++                   SystemC           SystemC       SystemC
 Unsigned    unsigned int          sc_bv, sc_lv      sc_uint       sc_biguint
 Signed      int                                     sc_int        sc_bigint
 Precision   Host-dependent        Limited           Limited       Unlimited
                                   precision         precision     precision
 Operators   C++ operators         No arithmetic     Full set of   Full set of
                                   operators         operators     operators
 Speed       Fastest               Faster            Slower        Slowest
                                                                                 19
Modules
                                       Module
                       Module                          Module
                                      Channel
                       Process        Channel          Process
                       Ports
                       Instances
                             - connection
                               Channels
                                Processes
                                  of other
                                        - communication
                                          -to
                                           modules
                                            computation
                                              external
                                                    - hierarchy
                                                       channels
                                                                                 20
SC_MODULE
               #include "systemc.h"
 Class         SC_MODULE(Mult)
               {
                    sc_in<int>    a;
 Ports              sc_in<int>    b;
                    sc_out<int> f;
                    void action() { f = a * b; }
 Constructor        SC_CTOR(Mult)
                    {
                        SC_METHOD(action);         Process
                          sensitive << a << b;
                    }
               };
                                                             21
SC_MODULE or sc_module?
  Equivalent       SC_MODULE(Name)
  :                {
                     ...
                   };
                   struct Name: sc_module
                   {
                     ...
                   };
                   class Name: public sc_module
                   {
                   public:
                     ...
                   };
                                                             22
Separate Header File
      // mult.h
      #include "systemc.h"
                                                    // mult.cpp
      SC_MODULE(Mult)
                                                    #include "mult.h"
      {
           sc_in<int>    a;                         void Mult::action()
           sc_in<int>    b;                         {
                                                      f = a * b;
           sc_out<int> f;                           }
           void action();
           SC_CTOR(Mult)
           {
               SC_METHOD(action);
                                                  Define constructor in .cpp?
                 sensitive << a << b;
                                                  Yes - explained later
           }
      };
                                                                                23
The Test Bench
Top
                                        testclk
                              asig
                                                       fsig
                                         Mult
               Stim                                                   Mon
                              bsig      f=a*b
           Module               Port                  Channel
                                                                                25
Top Level Module
                       #include   "systemc.h"
                       #include   "stim.h"
   Header files        #include   "mult.h"
                       #include   "mon.h"
                       SC_MODULE(Top)
                       {
                           sc_signal<int> asig, bsig, fsig;
      Channels
                           sc_clock testclk;
                           Stim stim1;
      Modules              Mult uut;
                           Mon mon1;
                           ...
                       }
                                                                              26
Module Instantiation
            SC_MODULE(Top)
            {
              sc_signal<int> asig, bsig, fsig;
                sc_clock testclk;
                Stim stim1;
                Mult uut;
                Mon mon1;
                                     Name of data member
                SC_CTOR(Top)
                : testclk("testclk", 10, SC_NS),
                  stim1("stim1"),
                  uut ("uut"),
                  mon1 ("mon1")
                {
                  ...
                }            String name of instance (constructor argument)
            }
                                                                              27
Port Binding
              SC_CTOR(Top)
              : testclk("testclk", 10, SC_NS),
                stim1("stim1"),
                uut("uut"),
                mon1("mon1")
              {
                stim1.a(asig);
                stim1.b(bsig);
                stim1.clk(testclk);
                  uut.a(asig);
                  uut.b(bsig);
                  uut.f(fsig);         Alternative function
                  mon1.a.bind(asig);
                  mon1.b.bind(bsig);
                  mon1.f.bind(fsig);
                  mon1.clk.bind(testclk);
              }
            Port name                Channel name
                                                                               28
sc_main
    sc_main is the entry point to a SystemC application
        #include "systemc.h"
        #include "top.h"
                                                          Called from main()
        int sc_main(int argc, char* argv[])
        {
            Top top("top");                 Instantiate one top-level module
            sc_start();                     End elaboration, run simulation
            return 0;
        }
                                                                               29
Namespaces
 #include "systemc.h"           Old header - global namespace
 SC_MODULE(Mod)
 {
   sc_in<bool> clk;
   sc_out<int> out;
  ... cout << endl;
 #include "systemc"            New header     #include "systemc"
                                              using namespace sc_core;
 SC_MODULE(Mod)                               using namespace sc_dt;
 {                                            using std::cout;
   sc_core::sc_in<bool> clk;                  using std::endl;
   sc_core::sc_out<int> out;
                                              SC_MODULE(Mod) {
  ... std::cout << std::endl;                   sc_in<bool> clk;
                                                sc_out<int> out;
                                                ... cout << endl;         31
                                                                               31
Summary of Files
                    systemc.h
        stim.h                     mult.h                       mon.h
        stim.cpp                   mult.cpp                     mon.cpp
                    #include
                                     top.h
         main.cpp
                                                                               32
Compilation and Simulation
                                    C++ Development
                                                                       .cpp
  SystemC         Pre-compiled        Environment
                                                                 .h           User's
class libraries     headers?           Text Editor                            source
      .cpp                                                                     files
.h
                                        Compiler
                                                                          Makefile
                                         Linker                 make
                  Pre-compiled
                     library
                                      Executable
 prompt> make
 prompt> run.x
                                       Debugger
 prompt> ddd run.x
                                                                                       33
Kinds of Process
             Processes
                  Must be within a module (not in a function)
                  A module may contain many processes
             Three different kinds of process
                  Methods            SC_METHOD
                  Threads            SC_THREAD
                  Clocked threads    SC_CTHREAD         (for synthesis)
             Processes can be static or dynamic
                                                                                       34
SC_METHOD Example
 #include <systemc.h>                         template<class T>
                                              void Register<T>::entry()
 template<class T>                            {
 SC_MODULE(Register)                            if (reset)
 {                                                q = 0; // promotion
   sc_in<bool> clk, reset;                      else if (clk.posedge())
   sc_in<T>    d;                                 q = d;
   sc_out<T>   q;                             }
     void entry();                              SC_METHODs execute in zero
                                                time
   SC_CTOR(Register)
                                                SC_METHODs cannot be
   {                                            suspended
     SC_METHOD(entry);
       sensitive << reset;                      SC_METHODs should not
       sensitive << clk.pos();
                                                contain infinite loops
   }
 };
                                                                              35
SC_THREAD Example
#include "systemc.h"                       #include "stim.h"
SC_MODULE(Stim)                            void Stim::stimulus()
{                                          {
  sc_in<bool> Clk;                           wait();
  sc_out<int> A;                             A = 100;
  sc_out<int> B;                             B = 200;
                                             wait();         for Clk edge
     void stimulus();                        A = -10;
                                             B = 23;
     SC_CTOR(Stim)                           wait();
     {                                       A = 25;
       SC_THREAD(stimulus);                  B = -3;
         sensitive << Clk.pos();             wait();
     }                                       sc_stop();     Stop simulation
};                                         }
     More general and powerful than an SC_METHOD
     Simulation may be slightly slower than an SC_METHOD
     Called once only: hence often contains an infinite loop
                                                                              36
SC_HAS_PROCESS
    #include "systemc.h"
    class Counter: public sc_module
    {
    public:
      sc_in<bool> clock, reset;
      sc_out<int> q;
                                                       Constructor arguments
     Counter(sc_module_name _nm, int _mod)
     : sc_module(_nm), count(0) , modulus(_mod)
     {
       SC_HAS_PROCESS(Counter);
                                               Needed if there's a process
         SC_METHOD(do_count);
                                                and not using SC_CTOR
           sensitive << clock.pos();
     }
    private:
      void do_count();
      int       count;
      int const modulus;
    };
                                                                               37
Dynamic Sensitivity
   SC_CTOR(Module)
   {
     SC_THREAD(thread);
       sensitive << a << b;        Static sensitivity list
   }
   void thread()
   {
     for (;;)
     {
       wait();                         Wait for event on a or b
       ...
       wait(10, SC_NS);                Wait for 10ns
       ...                                                     ignore a or b
       wait(e);                    Wait for event e
       ...
     }
   }
                                                                               38
sc_event and Synchronization
  SC_MODULE(Test)
  {                        Shared variable
     int data;
     sc_event e;
     SC_CTOR(Test)
     {                                   Primitive synchronization object
       SC_THREAD(producer);
       SC_THREAD(consumer);
     }
     void producer()
     {
       wait(1, SC_NS);
       for (data = 0; data < 10; data++) {
         e.notify();
         wait(1, SC_NS);                  Schedule event immediately
       }
     }
     void consumer()
     {                                    Resume when event occurs
       for (;;) {
         wait(e);
         cout << "Received " << data << endl;
       }
     }
  };
                                                                            39
sc_time
   Simulation time is a 64-bit unsigned integer
   Time resolution is programmable - must be power of 10 x fs
   Resolution can be set once only, before use and before simulation
   Default time resolution is 1 ps
  enum sc_time_unit {SC_FS, SC_PS, SC_NS, SC_US, SC_MS, SC_SEC};
  sc_time(double, sc_time_unit);          Constructor
  void     sc_set_time_resolution(double, sc_time_unit);
  sc_time sc_get_time_resolution();
  const sc_time& sc_time_stamp();          Get current simulation time
                                                                            40
 sc_clock
                                     sc_time                  sc_time
       sc_clock clk("clk",            period, 0.4, firstedge, true);
       sc_clock clk("clk", 10, SC_NS, 0.4, 12, SC_NS, true);
                                                 Duty cycle             1st edge rising
   0                           12        16              22        26             32
                  ("clock_N", 1, SC_NS, 0.5,                  0, SC_NS, true);
       Defaults
                                              Avoid clocks altogether for fast models!
                                                                                          41
 Elaboration / Simulation Callbacks
                              Instantiation
Elaboration                     sc_start()
                                                        before_end_of_elaboration()
                                                        end_of_elaboration()
                                                        start_of_simulation()
                                                           Every process without
                          Initialization Phase
                                                          dont_intialize() runs once
Simulation
                                Scheduler
                  sc_stop()
                                  Done
                                                        end_of_simulation()
                                                                                          44
Overriding the Callbacks
                                    SC_MODULE(Test)
  Called for each                   {
                                      SC_CTOR(Test) {}
       Module
                                         void   before_end_of_elaboration(){...}
       Primitive channel                 void   end_of_elaboration()       {...}
                                         void   start_of_simulation()      {...}
       Port                              void   end_of_simulation()        {...}
                                    };
       Export
  Do nothing by default
  before_end_of_elaboration() may perform instantiation and port binding
  In PoC simulator, end_of_simulation() only called after sc_stop()
                                                                                                      45
The Scheduler in Detail
                               sc_start()
                                                Initialization
   Runnable processes {R}                        Evaluation                  request_update()
                               notify()                 {R} empty
                                                                               Update requests {U}
sensitive
                           notify(0)              Update
                                                        {U} empty
     Delta notifications {D}                Empty {D} into {R}
                                                        {R} empty
                                                                 {T} empty
                       notify(>0)                                                         sc_stop()
                                                Advance time
    Timed notifications {T}                    All at current
                                                                                   Done
                                            time from {T} into
                                                     {R}                                              46
Kinds of Channel
        Primitive channels
             Implement one or more interfaces
             Derived from sc_prim_channel
             Have access to the update phase of the scheduler
             Examples - sc_signal, sc_signal_resolved, sc_fifo
        Hierarchical channels
             Implement one or more interfaces
             Derived from sc_module
             Can instantiate ports, processes and modules
        Minimal channels - implement one or more interfaces
                                                                                    47
Built-in Primitive Channels
     Channel                    Interfaces              Events
     sc_signal<T>               sc_signal_in_if<T>      value_changed_event()
                                sc_signal_inout_if<T>
     sc_buffer<T>               Same as sc_signal       On every write()
     sc_signal_resolved         Same as                 Same a sc_signal
     sc_signal_rv<W>            sc_signal<sc_logic>
     sc_clock                   Same as sc_signal<bool> posedge & negedge
     sc_fifo<T>                 sc_fifo_in_if<T>        data_written_event()
                                sc_fifo_out_if<T>       data_read_event()
     sc_mutex                   sc_mutex_if             n/a
     sc_semaphore               sc_semaphore_if         n/a
     sc_event_queue             n/a                     Every notify() invocation
                                                                                    48
Interface Method Call
                   Port            Interface              Port-less access
    Module
                                          Channel              Process
    Process
              Required interface               Implements the interface
     An interface declares of a set of methods (pure virtual functions)
     An interface is an abstract base class of the channel
     A channel implements one or more interfaces (c.f. Java)
     A module calls interface methods via a port
                                                                             49
Declare the Interface
                           Important
  #include "systemc"
  class queue_if : virtual public sc_core::sc_interface
  {
  public:
     virtual void write(char c) = 0;
     virtual char read() = 0;
  };
                                                                             50
Queue Channel Implementation
 #include "queue_if.h"
 class Queue : public queue_if, public sc_core::sc_object
 {
 public:
     Queue(char* nm, int _sz)
     : sc_core::sc_object(nm), sz(_sz)
     { data = new char[sz]; w = r = n = 0; }
     void write(char c);
     char read();                     Implements interface methods
 private:
     char* data;
     int sz, w, r, n;
 };
                                                                           51
Understanding Ports
                 Port    Required interface    Provided interface
      Module
                                               Channel
      Process
                sc_port<i_f> p;                   struct Chan: i_f,
                                                               sc_module
                                                  {
 p->method();                                       void method() {...}
                                                  };
                           struct i_f: virtual sc_interface
                           {
                              virtual void method() = 0;
                           };
                                                                           52
Queue Ports
 class Producer : public sc_core::sc_module
 {
 public:
   sc_core::sc_port<queue_write_if> out;
      void do_writes();
      SC_CTOR(Producer)
      {
        SC_THREAD(do_writes);
      }
 };
                                    queue_write_if     queue_read_if
                             Producer                              Consumer
                                                Channel
                                                                              53
Calling Methods via Ports
        #include <systemc>
        #include "producer.h"
        using namespace sc_core;
        void Producer::do_writes()
        {
          std::string txt = "Hallo World.";
          for (int i = 0; i < txt.size(); i++)
          {
            wait(SC_ZERO_TIME);
                out->write(txt[i]);
            }
        }
      Note: -> overloaded      Interface Method Call
                                                                              54
Why Ports?
              Ports allow modules to be independent of their environment
              Ports support elaboration-time checks (register_port,
              end_of_elaboration)
              Ports can have data members and member functions
                  Producer                                       Consumer
                                         Channel
                                                                                           55
Exports
                      Port               Channel              Port
           Producer                                                   Consumer
                               write()               read()
                                         Queue
                                         Module
           Port                Export                Export              Port
Producer                                                                        Consumer
                     write()                                  read()
                                          Queue
                                         Channel
Producer                                                                        Consumer
                     write()                                  read()
                                          Queue
                                                                                           56