0% found this document useful (0 votes)
40 views66 pages

Lecture 5

The document discusses SystemC, an open-source C++ library used for hardware-software co-specification of embedded systems. It provides an overview of SystemC and how it allows modeling of both hardware and software components within a single language to facilitate co-design. Key features discussed include modules, ports, signals, processes, and various data types supported.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
40 views66 pages

Lecture 5

The document discusses SystemC, an open-source C++ library used for hardware-software co-specification of embedded systems. It provides an overview of SystemC and how it allows modeling of both hardware and software components within a single language to facilitate co-design. Key features discussed include modules, ports, signals, processes, and various data types supported.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 66

SystemC: Co-specification and

Embedded System Modeling

Overview:
 Hardware-Software Co-Specification
 SystemC and Co-specification
 Introduction to SystemC for Co-specification
 A SystemC Primer
Hardware-Software Codesign
Co-design of Embedded Systems consists of the
following parts:
 Co-Specification
Developing system specification that describes hardware,
software modules and relationship between the hardware
and software
 Co-Synthesis
Automatic and semi-automatic design of hardware and
software modules to meet the specification
 Co-Simulation and Co-verification
Simultaneous simulation of hardware and software
HW/SW Co-Specification

• Model the Embedded system functionality from


an abstract level.
• No concept of hardware or software yet.
• Common environment
SystemC: based on C++.
• Specification is analyzed to generate a task
graph representation of the system
functionality.
Co-Specification
• A system design language is needed to describe the
functionality of both software and hardware.
• The system is first defined without making any
assumptions about the implementation.

• A number of ways to define new specification


standards grouped in three categories:

 SystemC An open source library in C++ that provides a modeling


platform for systems with hardware and software components.
SystemC for Co-specification
Open SystemC Initiative (OSCI) 1999 by EDA venders
including Synopsys, ARM, CoWare, Fujitsu, etc.
 A C++ based modeling environment containing a
class library and a standard ANSI C++ compiler.
 SystemC provides a C++ based modeling platform for
exchange and co-design of system-level intellectual
property (SoC-IP) models.
 SystemC is not an extension to C++
SystemC 1.0 and 2.1, 2.2 and 2.3 versions
It has a new C++ class library
SystemC Library Classes
SystemC classes enable the user to
• Define modules and processes
• Add inter-process/module communication through ports
and signals.
Modules/processes can handle a multitude of data types:
Ranging from bits to bit-vectors, standard C++ types to
user define types like structures
Modules and processes also introduce timing, concurrency
and reactive behavior.
• Using SystemC requires knowledge of C/C++
SystemC 2.0 Language Architecture
SystemC 2.0 Language Architecture
• All of SystemC builds on C++
• Upper layers are cleanly built on top of the lower layers
• The SystemC core language provides a minimal set of
modeling constructs for structural description, concurrency,
communication, and synchronization.
• Data types are separate from the core language and user-
defined data types are fully supported.
• Commonly used communication mechanisms such as
signals and FIFOs can be built on top of the core language.
The MOCs can also be built on top of the core language.
• If desired, lower layers can be used without needing the
upper layers.
SystemC Benefits
SystemC 2.x allows the following tasks to be
performed within a single language:
• Complex system specifications can be developed and simulated
• System specifications can be refined to mixed software and
hardware implementations
• Hardware implementations can be accurately modeled at all the
levels.
• Complex data types can be easily modeled, and a flexible fixed-
point numeric type is supported
• The extensive knowledge, infrastructure and code base built
around C and C++ can be leveraged
SystemC for Co-Specification
Multiple abstraction levels:
 SystemC supports untimed models at different levels of
abstraction,
• ranging from high-level functional models to detailed clock
cycle accurate RTL models.
Communication protocols:
 SystemC provides multi-level communication semantics
that enable you to describe the system I/O protocols at
different levels of abstraction.
Waveform tracing:
 SystemC supports tracing of waveforms in VCD, WIF, and
ISDB formats.
SystemC Development Environment
SystemC Features
Rich set of data types:
 to support multiple design domains and abstraction levels.
• The fixed precision data types allow for fast simulation,
• Arbitrary precision types can be used for computations with large numbers.
• the fixed-point data types can be used for DSP applications.
Variety of port and signal types:
 To support modeling at different levels of abstraction, from the
functional to the RTL.
Clocks:
 SystemC has the notion of clocks (as special signals).
 Multiple clocks, with arbitrary phase relationship, are supported.
Cycle-based simulation:
 SystemC includes an ultra light-weight cycle-based simulation
kernel that allows high-speed simulation.
SystemC Data types
• SystemC supports:
 all C/C++ native types
 plus specific SystemC types

• SystemC types:
 Types for systems modeling
 2 values (‘0’,’1’)
 4 values (‘0’,’1’,’Z’,’X’)
 Arbitrary size integer (Signed/Unsigned)
 Fixed point types
SC_Logic, SC_int types
SC_Logic: More general than bool, 4 values :
(‘0’ (false), ‘1’ (true), ‘X’ (undefined) , ‘Z’(high-impedance) )
Assignment like bool
my_logic = ‘0’;
my_logic = ‘Z’;
Operators like bool but Simulation time bigger than bool
Declaration
sc_logic my_logic;

Fixed precision Integer: Used when arithmetic operations


need fixed size arithmetic operands
• INT can be converted in UINT and vice-versa
• 1-64 bits integer in SystemC
sc_int<n> -- signed integer with n-bits
sc_uint<n> -- unsigned integer with n-bits
Other SystemC types
Bit Vector
sc_bv<n>
2-valued vector (0/1)
Not used in arithmetics operations
Faster simulation than sc_lv
Logic Vector
sc_lv<n>
Vector of the 4-valued sc_logic type
Assignment operator (=)
my_vector = “XZ01”
Conversion between vector and integer (int or uint)
Assignment between sc_bv and sc_lv
Additional Operators:
Reduction -- and_reduction() or_reduction() xor_ reduction()
Conversion -- to_string()
SystemC Data types
Type Description
sc_logic Simple bit with 4 values(0/1/X/Z)
sc_int Signed Integer from 1-64 bits
sc_uint Unsigned Integer from 1-64 bits
sc_bigint Arbitrary size signed integer
sc_biguint Arbitrary size unsigned integer
sc_bv Arbitrary size 2-values vector
sc_lv Arbitrary size 4-values vector
sc_fixed templated signed fixed point
sc_ufixed templated unsigned fixed point
sc_fix untemplated signed fixed point
sc_ufix untemplated unsigned fixed point
SystemC types
Operators of fixed precision types

Bitwise ~ & | ^ >> <<


Arithmetics + - * / %
Assignement = += -= *= /= %= &= |= ^=
Equality == !=
Relational < <= > >=
Auto-Inc/Dec ++ --
Bit selection [x] e.g. mybit = myint[7]
Part select range() e.g. myrange = myint.range(7,4)
Concatenation (,) e.g. intc = (inta, intb);
Usage of SystemC types
sc_bit y, sc_bv<8> x;
y = x[6];

sc_bv<16> x, sc_bv<8> y;
y = x.range(0,7);

sc_bv<64> databus, sc_logic result;


result = databus.or_reduce();

sc_lv<32> bus2;
cout << “bus = “ << bus2.to_string();
SystemC Specific Features
• Modules:
 A class called a module: A hierarchical entity that can
have other modules or processes contained in it.
• Ports:
 Modules have ports through which they connect to other
modules.
 Single-direction and bidirectional ports.
• Signals:
 SystemC supports resolved and unresolved signals.
• Processes:
 used to describe functionality.
 contained inside modules.
Modules
The basic building block in SystemC to partition a design.
• Modules are similar to „entity“ in VHDL
• Modules allow designers to hide internal data
representation and algorithms from other modules.
Declaration
 Using the macro SC_MODULE
SC_MODULE(modulename) {
 Using typical C++ struct or class declaration:
struct modulename : sc_module {
Elements:
Ports, local signals, local data, other modules,
processes, and constructors
SystemC Constructor
Constructor: Each module should include a constructor that
identifies processes as methods using the SC_METHOD macro.
SC_METHOD ( funct ) ; Identifies the function or process funct
Methods are called similar to C++ as:
function_type module_name::function_name(data_type var_name) { … }

• SC_METHOD process is triggered by events and executes all the


statements in it before returning control to the SystemC kernel.
• A Method needs to be made sensitive to some internal or external
signal. e.g. sensitive_pos << clock or sensitive_neg << clock
• Process and threads get executed automatically in the constrcutor
even if an event in sensitivity list does not occur. To prevent this
un-intentional execution, dont_initialize() function is used.
SystemC Module
SC_MODULE(module_name) {
// Ports declaration
// Signals declaration
// Module constructor : SC_CTOR
// Process constructors and sensibility list
// SC_METHOD
// Sub-Modules creation and port mappings
// Signals initialization
}
module
process
process

module module
Signals and Ports
Ports of a module are the external interfaces that pass information to
and from a module.
sc_inout<data_type> port_name;
• Create an input-output port of ‘data_type’ with name
‘port_name’.
• sc_in and sc_out create input and output ports respectively.
Signals are used to connect module ports allowing modules to
communicate.
sc_signal<data_type> sig_name ;
• Create a signal of type ‘data_type’ and name it ‘sig_name’.
• hardware module has its own input and output ports to which
these signals are mapped or bound.
For example:
in_tmp = in.read( );
out.write(out_temp);
2-to-1 Mux Modules
Module constructor – SC_CTOR is Similar to an
“architecture“ in VHDL
SC_MODULE( Mux21 ) {
sc_in< sc_uint<8> > in1;
sc_in< sc_uint<8> > in2;
sc_in< bool > selection;
sc_out< sc_uint<8> > out;

void MuxImplement( void );


SC_CTOR( Mux21 ) {
SC_METHOD( MuxImplement );
sensitive << selection;
sensitive << in1;
sensitive << in2;
}
}
SystemC Counter Code
struct counter : sc_module { // the counter module
sc_inout<int> in; // the input/output port of int type
sc_in<bool> clk; // Boolean input port for clock
void counter_fn(); // counter module function
SC_CTOR( counter ) {
SC_METHOD( counter_fn ); // declare the counter_fn as a method
dont_initialize(); // don’t run it at first execution
sensitive_pos << clk; // make it sensitive to +ve clock edge
}
}

// software block that check/reset the counter value, part of sc_main


void check_for_10(int *counted) {
if (*counted == 10) {
printf(“Max count (10) reached ... Reset count to Zero\n");
*counted = 0;
}
}
BCD Counter Example Main Code
void check_for_10(int *counted);
int sc_main(int argc, char *argv[ ]) {
sc_signal<int> counting; // the signal for the counting variable
sc_clock clock("clock",20, 0.5); // clock period = 20 duty cycle = 50%
int counted; // internal variable, to store the value in counting signal
counting.write(0); // reset the counting signal to zero at start
counter COUNT("counter"); // call counter module
COUNT.in(counting); // map the ports by name
COUNT.clk(clock); // map the ports by name
for (unsigned char i = 0; i < 21; i++) {
counted = counting.read(); // copy the signal onto the variable
check_for_10(&counted); // call the software block & check for 10
counting.write(counted); // copy the variable onto the signal
sc_start(20); // run the clock for one period
} return 0;
}
Counter Main Code with Tracing
int sc_main(int argc, char *argv[ ]) {
sc_signal<int> counting; // the signal for the counting variable
sc_clock clock("clock", 20, 0.5); // clock; time period = 20 duty cycle = 50%
int counted; // internal variable, to stores the value in counting signal
// create the trace- file by the name of "counter_tracefile.vcd“
sc_trace_file *tf = sc_create_vcd_trace_file("counter_tracefile");
// trace the clock and the counting signals
sc_trace(tf, clock.signal(), "clock");
sc_trace(tf, counting, "counting");
counting.write(0); // reset the counting signal to zero at start
counter COUNT("counter"); // call counter module. COUNT is just a temp var
COUNT.in(counting); // map the ports by name
COUNT.clk(clock); // map the ports by name
for (unsigned char i = 0; i < 21; i++) {
…..
}
sc_close_vcd_trace_file(tf); // close the tracefile
return 0;
}
SystemC Counter Module
#include "systemc.h"
#define COUNTER
struct counter : sc_module { // the counter module
sc_inout<int> in; // the input/output port of int type
sc_in<bool> clk; // Boolean input port for clock
void counter_fn(); // counter module function
SC_CTOR( counter ) { // counter constructor
SC_METHOD( counter_fn ); // declare the counter_fn as a method
dont_initialize(); // don’t run it at first execution
sensitive_pos << clk; // make it sensitive to +ve clock edge
}
};
void counter :: counter_fn() {
in.write(in.read() + 1);
printf("in=%d\n", in.read());
}
Module Instantiation
• Instantiate module
Module_type Inst_module (“label”);
• Instantiate module as a pointer
Module_type *pInst_module;
// Instantiate at the module constructor SC_CTOR
pInst_module = new module_type (“label”);

Inst_module.a(s);
Inst_module.b(c);
Inst_module.q(q);
pInst_module -> a(s);
pInst_module -> b(c);
pInst_module -> q(q);
Sub-module Connections
Signals
sc_signal<type > q, s, c;
 Positional Connection
 Named Connection
Named and Positional Connections
SC_MODULE(filter) {
// Sub-modules: “components
sample *s1;
coeff *c1;
mult *m1;
sc_signal<sc_uint <32> > q,s,c;
// Constructor :“architecture”
SC_CTOR(filter) {
//Sub-modules instantiation/mapping
s1 = new sample (“s1”);
s1->din(q); // named mapping
s1->dout(s);
c1 = new coeff(“c1”);
c1->out(c); // named mapping
m1 = new mult (“m1”);
(*m1)(s, c, q)//positional mapping
}
}
Communication and
Synchronization
• SystemC 2.0 and higher has general-purpose
• Channel
 A mechanism for communication and synchronization
 They implement one or more interfaces
• Interface
 Specify a set of access methods to the channel
But it does not implement those methods
• Event
 Flexible, low-level synchronization primitive
 Used to construct other forms of synchronization
Communication and
Synchronization
Interfaces
Module1 Module2

Channel

Events

Ports to Interfaces
Interfaces
 Interface is purely functional and does not provide the
implementation of the methods.
• Interface only provides the method's signature.
 Interfaces are bound to ports.
• They define what can be done through a particular port.

 The implementation is done


inside a channel.
Channels
 Channel implements an interface
• It must implement all of its defined methods.
 Channel are used for communication between processes inside
of modules and between modules.
 Inside of a module a process may directly access a channel.
 If a channel is connected to a port of a module, the process
accesses the channel through the port.
Channels
Channels
Two types of Channels: Primitive and Hierarchical
 Primitive Channels:
• They have no visible structure and no processes
• Theye cannot directly access other primitive channels.
o sc_signal
o sc_signal_rv
o sc_fifo
o sc_mutex
o sc_semaphore
o sc_buffer
 Hierarchical Channels:
• These are modules themselves,
• may contain processes, other modules etc.
• may directly access other hierarchical channels.
Channel Usage
Use Primitive Channels:
• when you need to use the request-update semantics.
• when channels are atomic and cannot reasonably be
chopped into smaller pieces.
• when speed is absolutely crucial.
 Using primitive channels can often reduce the number of delta
cycles.
• when it doesn't make any sense i.e. trying to build a
channel out of processes and other channels such as a
semaphore or a mutex.
Use Hierarchical Channels:
• when you would want to be able to explore the underlying
structure,
• when channels contain processes or ports,
• when channels contain other channels.
A Communication Modeling
FIFO Example
Write Interface
Producer Consumer

FIFO

Read Interface

Problem definition: FIFO communication channel with blocking read and write operation
Source available in SystemC installation, under “examples\systemc” subdirectory
Processes
Processes are functions identified to the SystemC kernel
and called if a signal of the sensitivity list changes.
• Processes implement the funcionality of modules.
• Similar to C++ functions or methods
Three types of Processes: Methods, Threads and Cthreads
 Methods : When activated, executes and returns
SC_METHOD(process_name)
 Threads: can be suspended and reactivated
- wait( ) -> suspends
- one sensitivity list event -> activates
SC_THREAD(process_name)
 Cthreads: are activated by the clock pulse
SC_CTHREAD(process_name, clock value);
Processes
Type SC_METHOD SC_THREAD SC_CTHREAD
Activates Event in sensit. list Event in sensit. List Clock pulse
Exec.
Suspends NO YES YES
Exec.
Infinite Loop NO YES YES
suspended/ N.D. wait() wait()
reactivated wait_until()
by
Constructor SC_METHOD(call_back); SC_THREAD(call_back); SC_CTHREAD(
& sensitive(signals); sensitive(signals); call_back,
Sensibility sensitive_pos(signals); sensitive_pos(signals); clock.pos() );
definition sensitive_neg(signals); sensitive_neg(signals); SC_CTHREAD(
call_back,
clock.neg());
Sensitivity List of a Process
• sensitive with the ( ) operator
Takes a single port or signal as argument
sensitive(s1);sensitive(s2);sensitive(s3)
• sensitive with the stream notation
Takes an arbitrary number of arguments
sensitive << s1 << s2 << s3;
• sensitive_pos with either ( ) or << operator
Defines sensitivity to positive edge of Boolean signal or clock
sensitive_pos << clk;
• sensitive_neg with either ( ) or << operator
Defines sensitivity to negative edge of Boolean signal or clock
sensitive_neg << clk;
Multiple Process Example
SC_MODULE(ram) {
sc_in<int> addr;
sc_in<int> datain;
sc_in<bool> rwb;
sc_out<int> dout;
int memdata[64];
// local memory storage
int i;
void ramread(); // process-1
void ramwrite();// process-2
SC_CTOR(ram){
SC_METHOD(ramread);
sensitive << addr << rwb;
SC_METHOD(ramwrite);
sensitive << addr << datain << rwb;
for (i=0; i++; i<64) {
memdata[i] = 0;
} }
};
Thread Process and wait() function
 wait( ) may be used in both SC_THREAD and SC_CTHREAD
processes but not in SC_METHOD process block
 wait( ) suspends execution of the process until the process is
invoked again
 wait(<pos_int>) may be used to wait for a certain number of
cycles (SC_CTHREAD only)

In Synchronous process (SC_CTHREAD)


• Statements before the wait( ) are executed in one cycle
• Statements after the wait( ) executed in the next cycle

In Asynchronous process (SC_THREAD)


• Statements before the wait( ) are executed in the last event
• Statements after the wait( ) are executed in the next event
Thread Process and wait() function
void do_count() {
while(1) {
if(reset) {
value = 0;
}
else if (count) {
value++;
q.write(value);
}
wait(); // wait till next event !
}
}
Example Code
void wait_example:: my_thread_process(void)
{
wait(10, SC_NS);
cout << "Now at " << sc_time_stamp() << endl;
sc_time t_DELAY(2, SC_MS);
t_DELAY *= 2;
cout << "Delaying " << t_DELAY<< endl;
wait(t_DELAY);
cout << "Now at " << sc_time_stamp()<< endl;
}
OUTPUT
Thread Example
SC_MODULE(my_module) {
sc_in<bool> id;
sc_in<bool> clock;
sc_in<sc_uint<3> > in_a;
sc_in<sc_uint<3> > in_b; Thread Implementation
sc_out<sc_uint<3> >
out_c;
void my_thread(); //my_module.cpp
void my_module::
SC_CTOR(my_module){ my_thread(){
SC_THREAD(my_thread); while(true){
sensitive << clock.pos(); if (id.read())
} out_c.write(in_a.read());
}; else
out_c.write(in_b.read());
wait();
}
};
CThread
 Almost identical to SC_THREAD, but implements
“clocked threads”
 Sensitive only to one edge of one and only one
clock
 It is not triggered if inputs other than the clock
change

• Models the behavior of unregistered inputs and


registered outputs
• Useful for high level simulations, where the clock is
used as the only synchronization device
• Adds wait_until( ) and watching( ) semantics for easy
deployment.
Counter Example
SC_MODULE(countsub)
in1
{ sum
sc_in<double> in1; in2 adder
sc_in<double> in2; subtractor diff
sc_out<double> sum; clk
sc_out<double> diff;
sc_in<bool> clk;
void addsub();
// addsub method
// Constructor: void countsub::addsub()
SC_CTOR(countsub) {
{ double a;
// declare addsub as SC_METHOD double b;
SC_METHOD(addsub);
a = in1.read();
// make it sensitive to
// positive clock b = in2.read();
sensitive_pos << clk; sum.write(a+b);
} diff.write(a-b);
}; };
sc_main()
The top level is a special function called sc_main.
• It is in a file named main.cpp or main.c
• sc_main() is called by SystemC and is the entry point for
your code.
• The execution of sc_main() until the sc_start()
function is called.
int sc_main (int argc, char *argv []) {
// body of function
sc_start(arg) ;
return 0 ;
}
• sc_start(arg) has an optional argument:
It specifies the number of time units to simulate.
If it is a null argument the simulation will run forever.
Clocks
• Special object
• How to create ?
sc_clock clock_name ( “clock_label”, period,
duty_ratio, offset, initial_value );
• Clock connection
f1.clk( clk_signal ); //where f1 is a module
• Clock example:
sc_clock clock1 ("clock1", 20, 0.5, 2, true);

2 12 22 32 42
sc_time
sc_time data type to measure time. Time is expressed in two parts:
a numeric magnitude and a time unit e.g. SC_MS, SC_NS,
SC_PS, SC_SEC, etc.
sc_time t(20, SC_NS);
//var t of type sc_time with value of 20ns

More Examples:
sc_time t_PERIOD(5, SC_NS) ;
sc_time t_TIMEOUT (100, SC_MS) ;
sc_time t_MEASURE, t_CURRENT, t_LAST_CLOCK;
t_MEASURE = (t_CURRENT-t_LAST_CLOCK) ;
if (t_MEASURE > t_HOLD) { error ("Setup violated") }
Time representation in SystemC
Set Time Resolution:
sc_set_time_resolution (10, SC_PS) ;
 Any time value smaller than this is rounded off
 default; 1 Peco-Second
sc_time t2(3.1416, SC_NS); // t2 gets 3140 PSEC
To Control Simulation:
sc_start( ) ;
sc_stop( ) ;
To Report Time Information:
sc_time_stamp( ) // returns the current simulation time
cout << sc_time_stamp( ) << endl ;
sc_simulation_time( )
Returns a value of type double with the current simulation
time in the current default time unit
sc_event
Event
 Something that happens at a specific point in time.
 Has no value or duration
sc_event:
 A class to model an event
• Can be triggered and caught.
Important
(the source of a few coding errors):
 Events have no duration  you must be watching to
catch it
• If an event occurs, and no processes are waiting to
catch it, the event goes unnoticed.
sc_event
You can perform only two actions with an
sc_event:
 wait for it
• wait(ev1)
• SC_THREAD(my_thread_proc);
• sensitive << ev_1; // or
• sensitive(ev_1)
 cause it to occur
notify(ev1)
Common misunderstanding:
 if (event1) do_something
• Events have no value
• You can test a Boolean that is set by the process that caused an
event;
• However, it is problematic to clear it properly.
notify( )
To Trigger an Event:
event_name.notify(args);
event_name.notify_delayed(args);
notify(args, event_name);
Immediate Notification:
causes processes which are sensitive to the event to be made
ready to run in the current evaluate phase of the current
delta-cycle.
Delayed Notification:
causes processes which are sensitive to the event to be made
ready to run in the evaluate phase of the next delta-cycle.
Timed Notification:
causes processes which are sensitive to the event to be made
ready to run at a specified time in the future.
notify( ) Examples
sc_event my_event ; // event
sc_time t_zero (0, SC_NS) ; // variable t_zero of type sc_time
sc_time t(10, SC_MS) ; // variable t of type sc_time

Immediate
my_event.notify();
notify(my_event); // current delta cycle
Delayed
my_event.notify_delayed();
my_event.notify(t_zero);
notify(t_zero, my_event); // next delta cycle
Timed
my_event.notify(t);
notify(t, my_event);
my_event.notify_delayed(t); // 10 ms delay
cancel ( )
Cancels pending notifications for an event.
• It is supported for delayed and timed notifications.
• not supported for immediate notifications.
Given:
sc_event a, b, c; // events
sc_time t_zero (0,SC_NS); // variable t_zero of type sc_time
sc_time t(10, SC_MS); // variable t of type sc_time

a.notify(); // current delta cycle
notify(t_zero, b); // next delta cycle
notify(t, c); // 10 ms delay
Cancel of Event Notification:
a.cancel(); // Error! Can't cancel immediate notification
b.cancel(); // cancel notification on event b
c.cancel(); // cancel notification on event c
SC_MODULE(missing_event) {
SC_CTOR(missing_event) { Problem with
SC_THREAD(B_thread); // ordered
SC_THREAD(A_thread); // to cause events
SC_THREAD(C_thread); // problems
}
void A_thread( ) {
a_event.notify( ) ; // immediate!
cout << "A sent a_event!" << endl;
}
void B_thread() {
wait(a_event) ;
cout << "B got a_event!" << endl;
}
If wait(a_event) is issued after
void C_thread() {
the immediate notification
wait(a_event) ;
a_event.notify( )
cout << "C got a_event!" << endl;
Then B_thread and C_thread
}
can wait for ever.
sc_event a_event;
Unless a_avent is issued again.
}
Properly Ordered Events
SC_MODULE(ordered_events) { void B_thread() {
SC_CTOR(ordered_events) { while (true) {
SC_THREAD(B_thread); b_event.notify(SC_ZERO_TIME);
SC_THREAD(A_thread); cout << "B sent b_event!" << endl;
SC_THREAD(C_thread); wait(a_event);
// ordered to cause problems cout << "B got a_event!" << endl;
} } // endwhile
}
void A_thread() { void C_thread() {
while (true) { while (true) {
a_event.notify(SC_ZERO_TIME); c_event.notify(SC_ZERO_TIME);
cout << "A sent a_event!" << endl; cout << "C sent c_event!" << endl;
wait(c_event); wait(b_event);
cout << "A got c_event!" << endl; cout << "C got b_event!" << endl;
} // endwhile } // endwhile
} }
sc_event a_event, b_event, c_event;
};
Time & Execution Interaction

Simulated
Execution
Activity
wait( ) and watching( )
Legacy SystemC code for Clocked Thread
wait(N); // delay N clock edges
wait_until (delay_expr); // until expr true @ clock

Same as
For (i=0; i!=N; i++)
wait( ) ; //similar as wait(N)
do wait ( ) while (!expr) ; // same as
// wait_until(delay_expr)
Previous versions of SystemC also included other
constructs to watch signals such as watching(),
Traffic Light Controller
Highway
 Normally has a green light.
Sensor:
 A car on the East-West side road triggers N
the sensor
• The highway light: green => yellow => red,
• Side road light: red => green.
SystemC Model:
S
 Uses two different time delays:
• green to yellow delay >= yellow to red delay
(to represent the way that a real traffic light works).
Traffic Controller Example
// traff.h
#include "systemc.h“

SC_MODULE(traff) {
// Constructor
// input ports SC_CTOR(traff) {
sc_in<bool> roadsensor; SC_THREAD(control_lights);
sc_in<bool> clock; // Thread
sensitive << roadsensor;
// output ports sensitive << clock.pos();
sc_out<bool> NSred; }
sc_out<bool> NSyellow; };
sc_out<bool> NSgreen;
sc_out<bool> EWred;
sc_out<bool> EWyellow;
sc_out<bool> EWgreen;
void control_lights();
int i;
Traffic Controller Example
// traff.cpp
#include "traff.h"
void traff::control_lights() {
NSred = false;
NSyellow = false;
NSgreen = true;
EWred = true;
EWyellow = false; NSgreen = false; // times up for EW green
EWgreen = false; NSyellow = false; // set EW to yellow
while (true) { NSred = true;
while (roadsensor == false) EWgreen = false;
wait(); EWyellow = true;
NSgreen = false;// road sensor triggered EWred = false;
NSyellow = true; // set NS to yellow for (i=0; i<5; i++)
NSred = false; // times up for EW yellow
for (i=0; i<5; i++) wait();
wait(); NSgreen = true; // set EW to red
NSgreen = false; // yellow interval over NSyellow = false; // set NS to green
NSyellow = false; // set NS to red NSred = false;
NSred = true; // set EW to green EWgreen = false;
EWgreen = true; EWyellow = false;
EWyellow = false; EWred = true;
EWred = false; for (i=0; i<50; i++) // wait one more long
for (i= 0; i<50; i++) wait(); // interval before allowing
wait(); // a sensor again
}
}
References

• System Design with SystemC, by T. Grotker, S.


Liao, G. Martin and S. Swan, Kluwer Academic
2002.

• A SystemC Primer, by J. Bhasker Second Edition


2004, 2002 PDF exists.

• SystemC: From the Ground Up, by D.C. Black, J.


Donovan, B. Bunton and A. Keist 2nd edition 2010.

You might also like