Dr.
Zhonghai Lu
KTH Royal Institute of Technology
C++ Basics
SystemC
Introduction
and Get
Started
Modules
and
Processes
Concurrency
and Time
Channels
and
Interfaces
Transaction
Level
Modeling
KTH IL2452 System Design Languages
SystemC
Data Types
and
Debugging
SystemC
Summary
Aim
Understand communication concepts in SystemC
and know how to use it for design
Content
Primitive channels and interfaces
How to use primitive channels?
How to design my own channels?
Ports (used by modules to access channels)
Hierarchical channels
How to design and use my own hierarchical
channels?
KTH IL2452 System Design Languages
Concept
for communication
Channel categories
Primitive channels
Hierarchical channels
KTH IL2452 System Design Languages
In SystemC, channels model communication enabling
the ESL design concepts.
Separate communication from computation while
offering interface.
Refine communication while keeping the interfaces
untouched.
Fast simulation using function calls for communication.
An example
CPU
ASIC
Abstract Bus
MEM
KTH IL2452 System Design Languages
Arbiter
I/O
An interface is declared as a set of methods (pure virtual
functions), like APIs (Application Programming Interfaces) for
hardware and software.
An interface is an abstract base class of the channel.
A channel implements an interface.
A module calls interface methods via a port. Note that, within in
a module, accessing a channel can be done without using ports.
The port definition specifies the type of interface required by the
module in order to access the channel.
Interface
KTH IL2452 System Design Languages
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_buffer<>
sc_fifo<>
sc_mutex, sc_semaphore
To
understand the built-in primitive
channels, we need to know their associated
events and ports altogether.
7
KTH IL2452 System Design Languages
Primitive channel
Event
Port
sc_signal<T>
sc_buffer<T>
change in value
write()
sc_in, sc_out, sc_inout
sc_fifo<T>
write() or read()
sc_fifo_in, sc_fifo_out
sc_mutex
sc_semaphore
sc_signal vs. sc_buffer
sc_buffer is derived from sc_signal, and thus shares all the
same methods and specialized port types.
They differ in what constitutes an event. For sc_signal, an
event is a change in the value of the signal; With sc_buffer,
every call to the write() method causes an event, whether or
not the value of the sc_buffer changes.
sc_signal for modeling hardware wire or bus
(sc_signal_resolved), sc_buffer for modeling data flow where
each new input data will be sampled irrespective of if it is the
same or different from the previous sample.
KTH IL2452 System Design Languages
Primitive channel
Event
Port
sc_signal<T>
sc_buffer<T>
change in value
write()
sc_in, sc_out, sc_inout
sc_fifo<T>
write() or read()
sc_fifo_in, sc_fifo_out
sc_mutex
sc_semaphore
sc_fifo
is a first-in-first-out buffer, widely
used in untimed functional modeling.
sc_mutex vs. sc_semaphore
Used to synchronzize accesses to shared
resources.
Sc_mutex is for a single shared resource while
sc_semaphore is more general, used for multiple
shared resources.
Modeling operating systems and software.
KTH IL2452 System Design Languages
Template class
Interface methods
Bounded FIFO with a
default depth 16,
minimum depth 1
Infinite FIFO defined in
tlm::tlm_fifo
Nonblocking read and
write
Blocking read and
write
Specialized ports for
accessing SC_FIFO,
without using ->
operator
sc_fifo<T> fifo(fifo, 5)
bool fifo.nb_read(T&); //false if empty
bool fifo.nb_write(const T&); //false if full
void fifo.read(T&); //wait if empty
void fifo.write(const T&); //wait if full
sc_fifo_out<int> fifo_out; //for write
sc_fifo_in<int> fifo_in; //for read
sc_fifo_in<T> is equivalent to sc_port<sc_fifo_in_if<T>, 0> >
KTH IL2452 System Design Languages
10
SC_MODULE (Producer) {
sc_fifo_out<int> fifo_out;
.
fifo_out.write(data);
.
};
Top
SC_MODULE (Consumer) {
sc_fifo_in<int> fifo_in;
.
fifo_in.read(data);
Specialized port
.
};
. operator
sc_fifo
Producer
Consumer
SC_MODULE (Top) {
Producer p;
Consumer c;
sc_fifo<int> fifo;
SC_CTOR(Top): p(p), c(c), fifo(fifo,5){
p.fifo_out(fifo);
c.fifo_in(fifo);
.
};
KTH IL2452 System Design Languages
Step1:
11
Declare an abstract interface class
derived from sc_interface
Virtual inheritance to allow multiple inheritance
Pure virtual functions because it is mandatory for
users to supply the implementation
Example: Queue
class queue_write_if : virtual public sc_interface {
public: virtual void write (int c) = 0;};
class queue_read_if : virtual public sc_interface {
public: virtual int read () = 0;};
class queue_if : public queue_write_if, public queue_read_if { };
KTH IL2452 System Design Languages
12
Declare the queue class as
our own channel
#include queue_if.h
The interface class is
declared but does nothing.
It is the channels
responsibility to override
the pure virtual methods
and describe functionality.
Derived from sc_object.
Since the queue channel is
neither a hierarchical nor a
primitive channel, it is
recommended that such
channels are at least derived
from sc_object so that they
own attributes such as a
hierarchical name and a
position in the module
hierarchy.
sc_object is the base class for
all objects in the module
hierarchy.
class Queue : public queue_if, public sc_object {
public:
Queue(char *_nm, int _size): sc_object(_nm),
size(_size) {
data = new int[size];
w=r=n=0;
}
private:
int* data;
int size, w, r, n;
};
13
KTH IL2452 System Design Languages
Class sc_object is
the base class for
all objects in the
module hierarchy.
sc_module
+kind
get_child_objects
w: write pointer
r: read pointer
n: number of data
in the queue
void write(int c);
int read();
sc_object
+name
+kind
get_child_objects
get_parent_objects
sc_prim_channel
+kind
KTH IL2452 System Design Languages
sc_port_base
sc_process*
+kind
+kind
+get_child_objects
14
Define interface methods
With the same interface
declaration, definitions
may be different.
#include queue_if.h
void Queue :: write(int c) {
if (n < size) {
n++;
data[w++] = c;
if (w == size) w = 0;
}
};
int Queue::read(){
int c = 0;
if (n > 0) {
n--;
c = data[r++];
if (r == size) r = 0;
}
return c;
}
15
KTH IL2452 System Design Languages
We
write a module to
test the functionality
of the channel.
use port-less channel
access, i.e. access the
channel without
declaring ports.
Port-less channel access
KTH IL2452 System Design Languages
class Test : public sc_module {
public:
Queue queue;
SC_CTOR(Test): queue(queue, 10){
SC_THREAD(testing);
}
void testing(){
for(int i=0; i<10; i++)
queue.write(i);
for(int i=0; i<10; i++)
std::cout << queue.read();
}
};
16
Class sc_port, a class template with three parameters, is
the base class for all ports in SystemC.
Interface type
The max. number of channels to which the port may be bound
(0 means no limit, default is 1).
Port binding policy (optional) with respect to unbounded ports.
sc_port<my_interface, N, policy> if1, if2, ;
Port definitions can use the class sc_port directly or use a
port specialization, which is a class dervied from sc_port,
for example, sc_in, sc_fifo_in.
template <class T>
class sc_in : public sc_port<sc_signal_in_if<T>, 1> { };
template<class T>
class sc_fifo_in : public sc_port<sc_fifo_in_if<T>, 0> { };
17
KTH IL2452 System Design Languages
Channel: interface + implementation
Module uses ports to access the channel interface
Required interface: sif
Module
Offered interface: sif
Process
channel
sc_port<sif> port;
port->method();
Inherit sc_module if
hierarchical channel
struct channel: sif, sc_object {
void method() { }
};
struct sif: virtual sc_interface {
virtual void method() = 0;};
The port is declared with interface sif, so a process may call the method method()
through the port.
Note that the port is typed using the name of the interface, not the channel. Thus, any
channel that implements the interface sif may be bound to the port.
KTH IL2452 System Design Languages
18
Define interface-typed ports
Define a process to call an interface method
Through the typed port out, call the write() method offered by
a queue_write_if. Which channel (queue) to use is decided by
the Port-to-Channel binding.
queue_write_if queue_read_if
Top
Producer
Consumer
queue
SC_MODULE(Producer){
public:
sc_port<queue_write_if> out;
void write_chan();
void Producer :: write_chan(){
for(int i=0; i<10; i++)
out -> write(i);
}
SC_CTOR(Producer){
SC_THREAD(write_chan); }
};
Interface method call (IMC)
Overloaded operator ->
19
KTH IL2452 System Design Languages
The syntax for binding sc_port instances to channels is the
same as we would use for one of the standard signal ports,
like binding sc_in, sc_out ports to sc_signals.
queue_write_if queue_read_if
Top
Producer
Consumer
out
queue
SC_MODULE(Top){
Queue queue;
Producer producer;
Consumer consumer;
SC_CTROR(Top):queue(queue, 5){
producer.out(queue);
consumer.in(queue);
}
in
Channel instance
Module instance
Port to channel binding
};
KTH IL2452 System Design Languages
20
Besides
functional methods, one can add
debug facilities to an interface.
For example, add a dump() method that writes
out the content of the queue at a time instance.
class queue_debug_if : virtual public sc_interface {
public:
virtual void dump const() = 0;
};
class Queue : public queue_if, public queue_debug_if, public sc_object {
public:
void write(int c);
int read();
void dump() const;
};
KTH IL2452 System Design Languages
21
Different
from primitive channels,
hierarchical channels are modules which may
have ports and sub-modules.
Used to model complex communication, such
as network on chip.
The distinction between module and channel
becomes fuzzy because of hierarchial
channels, but any channel must have well
defined interfaces.
KTH IL2452 System Design Languages
22
Define the channel interface
Implement the channel
Port creation: Create ports (interface-typed) at
the user module
1.
2.
3.
eg. sc_port<queue_write_if> out;
The user module uses the interface method call
eg. out->write(i);
Port-to-Channel binding: Bind ports of the user
module to the channel instance
4.
Example: A stack channel
Define a write and a read interface, using
nonblocking method.
KTH IL2452 System Design Languages
23
Define
a write and a read interface, using
nonblocking method.
#ifndef STACK_IF_H
#define STACK_IF_H
#include <systemc>
class stack_write_if : virtual public sc_interface {
public:
virtual bool nb_write(char) = 0; //write a character
virtual void reset()=0;
//empty the stack
};
class stack_read_if : virtual public sc_interface {
public:
virtual bool nb_read(char&) = 0; //read a character
};
#endif
KTH IL2452 System Design Languages
24
The
stack channel implements the methods.
#ifndef STACK.H
#define STACK.H
#include <systemc>
#include stack.h
class stack : pubic sc_module, public stack_read_if, stack_write_if {
private:
char data[100];
int top; //top of the stack
public:
stack(sc_module_nm nm) : sc_module(nm), top(0){ }
bool nb_write(char c) {
if (top<100) { data[top++] = c; return true;}
return false; }
void reset(){ top = 0;}
bool nb_read(char& c){
if (top > 0) { c = data[--top]; return true;}
return false;}
};
#endif
KTH IL2452 System Design Languages
25
To use the stack, it must be instantiated. We use
again a producer and a consumer.
#ifndef PRODUCER.H
#define PRODUCER.H
#include <systemc>
#include stack_if.h
class producer : pubic sc_module {
public:
sc_port<stack_write_if> out; //declare a port that interfaces to the stack
sc_in<bool> clock;
void write_stack(){
int i=0; char* TestString=Hello world;
while true {
wait(); //wait for clock edge
if (out->nb_write(TestString[i]) //write to the stack via the port calling nb_write() method
cout << Write stack << TestString[i] << at << sc_time_stamp() <<endl;
i=(i+1)%32;}}
SC_CTOR(producer){
SC_THREAD(write_stack);
sensitive << clock.pos(); }
#endif
KTH IL2452 System Design Languages
26
#include systemc.h
#include producer.h
#include consumer.h
#include stack.h
int sc_main(int argc, char* argv[]){
sc_clock ClkFast(ClkFast, 100, SC_NS);
sc_clock ClkSlow(ClkSlow, 50, SC_NS);
stack Stack1(Stack 1);
producer P1(Producer 1);
P1.out(Stack1);
P1.clock(ClkFast);
consumer C1(Consumer 1);
C1.in(Stack1);
C1.clock(ClkSlow);
sc_start(5000, SC_NS);
return 0;
}
KTH IL2452 System Design Languages
Processes
27
communicate with channels
Channels inside the module: directly calling the
channel methods (port-less access)
Channels outside the module: indirectly calling
via port(s) of the module
Create Interface-typed port
Use interface method call
KTH IL2452 System Design Languages
28
SystemC concepts in C++
Interfaces
Channels
Class implementation of interfaces
Ports
Abstract class
Template class sc_port<IF>
Specialized ports: sc_in<>, sc_out<>, sc_fifo_in<>, sc_fifo_out<>
Channels
Primitive channels: sc_signal, sc_fifo, sc_buffer.
Hierarchical channels are essentially modules but with interfaces
We can follow well-defined steps to build own channels with
appropriate interfaces.
Homework:
Try the example of creating own channel Queue.
KTH IL2452 System Design Languages
29
TLM
whitepaper Transaction Level Modeling
in SystemC by Rose, Swan et al.
Download TLM-1.0 package for TLM
examples.
KTH IL2452 System Design Languages
30
www.systemc.org,
www.accelera.org
www.doulos.com
SystemC:
From the Ground Up by D. C. Black,
J. Donovan, B. Bunton, and A. Keist.
System Design with SystemC by T. Grtker, S.
Liao, G. Martin, and S. Swan
Others
KTH IL2452 System Design Languages
31