0% found this document useful (0 votes)
15 views

SystemC-n-BehaviorCoding_Fall2021_Section4_SystemC

Uploaded by

Hua-Chien Chang
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views

SystemC-n-BehaviorCoding_Fall2021_Section4_SystemC

Uploaded by

Hua-Chien Chang
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 123

+

SystemC, Behavior Coding


and Modeling
蘇培陞 博士
Alan P. Su, Ph.D.
[email protected], [email protected]
+ 2

Contents

 Chapter 1 SystemC Overview


 Chapter 2 Module, Signal, Port & Blockingness
 Chapter 3 Processes, Interface & Channel
 Chapter 4 Data Types
 Chapter 5 Fixed Point Types
+
3

Drag picture to plac

Section 4
SystemC 2.3, IEEE 1666-2011

Drag picture to plac


+ 4

Class Objectives

 Learn how to code in SystemC


 Understand
the SystemC simulation
mechanism, thus understand how to verify a
SystemC design
 Familiar with SystemC basic data types
 Levelsof abstraction: system level,
transaction level, cycle-accurate, behavior
level and RTL
 Using High Level Synthesis
+ 5

Accellera Systems Initiative

 Accellerais an independent not-for-profit


standard organization. It is the home of
Verilog, SystemVerilog & SystemC. Among
which SystemC is an open source standard
for system-level design
 Where is Accellera
 http://www.accellera.org/home/

 Until November 2018


the latest version is SystemC 2.3.3 (IEEE 1666-2011 including TLM
2.0)
http://www.accellera.org/downloads/standards/syst
emc
+
Drag picture to placeholder or click ico
6

Not “English as
Second Language”
Drag picture to plac

Chapter 1
SystemC Overview
+ 7

SystemC Overview

▶ The dream to realize the unison of HW/SW designing languages. A


unified design environment.
▶ Version 1: it is just another HDL, not much to do with system-level
designing
▶ Version 2: with the adding of channel, now it is a serious system-
level language
▶ Version 2.1: adding some programming language features and
simulation semantics, e.g. sc_spawn, before_end_of_elaboration,
etc.
▶ IEEE approved OSCI SystemC 2.1 as the IEEE 1666 Standard on
12/12/2005
▶ SystemC 2.2 is some enhancements and bug fixes of 2.1
▶ IEEE 1666-2011, aka SystemC 2.3, adding TLM 2.0 and some
process control syntax
+ 8

SystemC Overview

▶Isa C++ class library and a methodology that


one can use to effectively create cycle-
accurate models of functions, hardware
architecture, and interfaces of the SoC and
system-level designs.
▶One can use SystemC and standard C++
development tools to create a system-level
model, quickly simulate to validate and
optimize the design, explore various
algorithms, and provide the hardware and
software development team with an
executable specification of the system.
+ 9

SystemC Highlights
▶ Modules: component
▶ Processes: functions, SC_THREAD & SC_METHOD
▶ Ports: I/O ports
▶ Signals: wires
▶ Rich set of port and signal types
▶ Rich set of data types
▶ Clocks

▶ Cycle-based simulation: ultra light-weight and fast


▶ Multiple abstraction levels
▶ Communication protocols: channel & interface
▶ Debugging support: runtime error checking
▶ Waveform tracing: VCD, WIF and ISDB formats
+Traditional System Design Methodology 10

C, C++ Done
System-level Modeling

Verilog/VHDL

Simulation &
Refine
Analysis
Simulation

Results
Synthesis

To tape out, test and


product delivery
+ 11

SystemC 2.3 Language


Architecture
Methodology-Specific Layered Libraries
Verification Library,
Libraries
Master/Slave Library, etc. TLM 2.0 Library, etc.

Primitive Channels
Signal, Mutex, Semaphore, FIFO, etc.

Core Language Data Types


Modules 4-valued Logic Type
Ports 4-valued Logic Vectors
Interfaces Bits and Bit Vectors
Channels Arbitrary Precision Integers
Fixed-Point Types

Event-Driven Simulation
Events, Processes

C++ Language Standards


+ 12

SystemC & C++

▶ SystemCis a set of C++ class definitions and a


methodology for using these classes.
▶ C++class definition means systemc.h and the
matching library.
▶ Methodology means the use of simulation kernel and
modeling.
▶ Youcan use all of the C++ syntax, semantics, run
time library, STL and such.
▶ However, you need to follow SystemC methodology
closely to make sure the simulation executes correctly.
+ 13

SystemC & HDL

▶SystemC is a Hardware Description Language


(HDL) from system-level down to gate level.
▶Modules written in traditional HDLs like Verilog
and VHDL can be translated into SystemC, but
not vise versa. Reason: Verilog and VHDL do
not support transaction-level.
▶SystemVerilog is Verilog plus assertion, which
is an idea borrowed from programming
languages. And SystemC supports assertion as
well through the C++ syntax and semantics.
+ 14

SystemVerilog vs. SystemC

▶SystemVerilog is Verilog plus verification


(assertion).
▶The above statement is not fair, but it is the
truth now.
▶SystemVerilog and SystemC work together to
complete the design platform from system-
level to gate-level.
▶SystemC deals with whatever above RTL.
▶SystemVerilog deals with RTL and below.
+ 15

SystemC Myth I
+ 16
Methodology

SystemC Myth II

▶ It
is a language to unify the design environment,
SW and HW. A unified design environment.
▶ Well, this is a dream in the academy. In industry,
this is a long way to go and as of today,
SystemC is not the answer. Notice, SystemC is
an HDL, it itself does not support software
performance measure mechanism.
▶ Will the day that a unified design language be
realized? We just don’t know. But new
developments called Model Based Design and
Software Defined Hardware are in discussion.
+ 17

Note 2

SystemC does not


model software.
It is an HDL.
Period.
+ 18

Note 3

SystemC does not


run faster, higher
abstraction level
does.
+ 19

System-Level Language

▶To be categorized as a system-level


language, the simulation SPEED is the key.
▶The simulation speed should take no
1,000 time slower than the real HW. In
another word, 1 second of HW execution
time equals 16 minutes and 40 seconds
simulation time
▶To achieve this kind of performance, the
system is best modeled in transaction
level, e.g., token based
+
Drag picture to placeholder or click ico
20

Not “English as
Second Language”
Drag picture to plac

Chapter 2
Module, Port, Signal & Blockingness
+ 21

Modules

A module is the basic structural building block


in SystemC, the same as Verilog “module”. It
may contain
 Ports for communication
 Data members
 Channel members
 Processes
 Member functions not registered as processes
 Instances of other modules
+ 22

Module Structure
 Derived from class sc_module:
class my_module : public sc_module { … };
 A more commonly used way:
SC_MODULE (module_name) {
// ports, sc_export, data members, member functions
// processes, etc.
SC_CTOR(module_name) { // constructur
// body of constructor
// process registration, sensitivity lists
// module instantiations, port binding etc.
}
}; // do not forget this final ;
 SC_MODULE is a macro:
#define SC_MODULE(user_module_name) \
struct user_module_name : sc_module
+ 23

Ports

 sc_in<data_type>; //input port


 sc_out<data_type>; //output port
 sc_inout<data_type>; //in/out port
 If
data_type is a type with size
declaration, a space is needed before
the closing bracket, e.g.
sc_in<sc_uint<10> >;
Note: if C++11 is used, i.e. –std=c++11, no space needed
+ 24

Light Weight Port Binding

 Using HW port-to-port binding is not


intuitive at system-level and slow.
Starting 2.1 SC_EXPORT is supported for
light weight binding.
 Vastlyused in the TLM library. People say
at transaction level SC_EXPORT must be
used.
 Thepurpose is to speed up the
simulation.
+ 25

Signal (1)

 Is
a un-directional wire when connects
to ports
 Theflow of data is determined by the
ports a signal connects to
 Example:

sc_signal<sc_uint<32> > w1;


Note: at least a space is needed here.
But if C++11 is used, i.e. –std=c++11, no space needed
+ 26

Signal (2)

 Non-blocking descriptor
 Example:

sc_signal<sc_uint<32> > reg1;


reg1 = 3;
+ 27

Blocking & Non-blocking

 Anassignment statement has two sides,


Right-Hand-Side (LHS) and Left-Hand-Side
(LHS)
 A = 5 + 3;

 Evaluate: the execution of the RHS expression


 5+3⇒8

 Update: update the LHS expression


 A⇐8
+ 28

Blocking

 Evaluate and update immediately and in one


step/statement

// a == 3, b == 4, c == 5
b = a; // b is now 3
c = b; // c is now 3
a = c; // a is 3, again
+ 29

Non-blocking

 Two steps: Evaluate first and immediately, and update


occurs when all evaluations at current time step are
completed

// a == 3, b == 4, c == 5
b = a; // b is still 4
c = b; // c is still 5
a = c; // a is still 3
wait();
// b is updated as 3
// c is updated as 4
// a is updated as 5
+ 30

Blocking example

sc_uint<8> ary[8] = {1,2,3,4,5,6,7,8};


for (i=0; i<7; i++)
ary[i+1] = ary[i]; // blocking
// all elements in ary have
// the same value, 1
+ 31

Non-blocking exampe

sc_signal<sc_uint<8> > ary[8];


ary[0] = 1;
ary[1] = 2;

ary[7] = 8;

for (i=0; i<7; i++)


ary[i+1] = ary[i]; // non-blocking
// ary[] becomes a shift register
+ 32

Note

 When using reference C codes downloaded


from the Internet, say H.264 codes, notice
that all these codes are in SW mindset. Which
means, all assignments are blocking
+ 33

Port & Signal Connection

 Named Mapping
#include “systemc.h”
#include “mult.h”
#include “coeff.h”
#include “sample.h”
c1
SC_MODULE(filter) {
sample *s1;
coeff *c1;
mult *m1;
sc_signal<sc_uint<32> > q, s, c;
s1 m1
SC_CTOR(filter) {
s1 = new sample(“s1”);
s1->din ( q );
s1->dout ( s );
c1 = new coeff(“c1”);
c1->out ( c );
m1 = new mult(“m1”);
m1->a ( s );
m1->b ( c );
m1->q ( q );
}
};
+ 34

Port & Signal Connection –


Cont.
 Positional Mapping is no longer supported in 2.2

#include “systemc.h”
#include “mult.h”
#include “coeff.h”
c1
#include “sample.h”
SC_MODULE(filter) {
sample *s1;
coeff *c1;
mult *m1; s1 m1
sc_signal<sc_uint<32> > q, s, c;
SC_CTOR(filter) {
s1 = new sample(“s1”);
(*s1) ( q,s ); // 2.2 illegal
c1 = new coeff(“c1”);
(*c1) ( c ); // 2.2 illegal
m1 = new mult(“m1”);
(*m1) ( s, c, q ); // 2.2 illegal
}
};
+ 35

Process First Look

 Processes are the basic unit of execution within


SystemC. Processes are called to emulate the behavior
of the target device or system.
 The real work of a module is performed in processes.
 Processes are functions that are identified to the
SystemC kernel and called/activated whenever signals
these processes are sensitive to.
 These statements are executed sequentially until the
end of the process, or being suspended by a wait()
statement.
 SC_METHOD, SC_THREAD, SC_CTHREAD
+ 36

Module Example

#include “systemc.h”

SC_MODULE(timer) {
sc_in<bool> start; // ports
sc_out<bool> timeout;
sc_in<bool> clock;

int count; // data and function members


void runtimer();

SC_CTOR(timer) { // constructor
SC_THREAD(runtimer);
sensitive << clock.pos() // sensitivity list
<< start;
count = 0;
}
}; // do not forget the final semi-column
§ sensitive_pos and sensitive_neg are deprecated in 2.2
+ 37

A Module Implementation
// timer.cpp
#include “timer.h”

void timer::runtimer() {
while(1) {
if (start.read()) {
cout << “Timer: timer start detected “ << endl;
count = 5;
timeout.write(0);
} else {
if (count == 0) {
timeout.write(1);
} else {
count--;
timeout.write(0);
}
}
wait();
}
}
+ 38

Clock

 Synopsis
class sc_clock : public sc_signal_in_if<bool>,
public sc_module
{
public:
sc_clock();
explicit sc_clock( sc_module_name name_ );
sc_clock( sc_module_name name_,
const sc_time& period_,
double duty_cycle_ = 0.5,
const sc_time& start_time_ = SC_ZERO_TIME,
bool pos_edge_first = true);

};

 Example:
sc_time clkPrd(20, SC_NS), clkDly(2, SC_NS);
sc_clock clock1(“clock1”, clkPrd, 0.50, clkDly, true);
+
A Simple Example

39
+ 40

Specification

Data
M S
Application/ Data Data Application/
Stimuli
transmit receiver Sink
S M
Acknowledge
+ 41

C/C++ Model
frame data; //global data frame storage for Channel
void transmit(void) { //transmits frames to Channel
int framenum; // sequence number for framces
frams s; // Local frame
packet buffer; // Buffer to hold intermediate data
event_t event; // Event to trigger actions in transmit

framenum = 1; // Initialize sequence numbers


get_data_fromApp(&buffer); // Get initial data from Application
while (true) { // Runs forever
s.info = buffer; // Put data into frame to be sent
s.seq = framenum; // Set sequence number of frame
send_data_toChannel(&s); // Pass frame to Channel to be sent
start_timer(s.seq); // Start timer to wait for acknowledge
// If timer times out packet was lost
wait_for_event(&event); // Wait for events from channel and timer
if (event == new_frame) { // Got a new frame
get_data_fromChannel(s) // Read frame
if (s.ack == framenum) { // Did we get the correct acknowledge
get_data_fromApp(&buffer); // Yes, get more data
inc(framenum); // Increase framenum
}
}
}
}
+ 42

C/C++ Model - Cont.

void receiver(void) { // Gets frames from channel


int framenum; // Scratchpad frame number
frame r,s; // Temp frames to save information
event_t event; // Event to cause actions in receiver

framenum = 1; // Start framenum at 1


while (true) { // Runs forever
wait_for_event(&event); // Wait for data from Channel
if (event == new_frame) { // A new frame has arrived
get_data_fromChannel( r ); // Get the data from the Channel
if (r.seq == framenum) { // Is this the frame we expected
send_data_toApp(&r.info); // Yes, then send data to application
inc(framenum); // Get ready for the next frame
}
s.ack = framenum – 1; // Send back an acknowledge that frame was
received
send_data_toChannel(&s); // Send acknowledge
}
}
}
+ 43

SystemC Model

timer

Data
M S

transmit bus receiver display


S M

Acknowledge
+ 44

SystemC Model – packet


// pakcet.h file friend bool
#ifndef PACKETINC operator == ( const packet_type& a, const packet_type& b ) {
#define PACKETINC return ( a.info == b.info &&
#include "systemc.h" a.seq == b.seq &&
class packet_type { a.retry == b.retry );
public: }
long info; friend ostream&
int seq; operator << ( ostream& os, const packet_type& a )
int retry; {
a.print( os );
packet_type() return os;
: info(0), seq(0), retry(0) {} }
packet_type( long info_, int seq_, int retry_ ) };
: info(info_), seq(seq_), retry(retry_) {} extern void sc_trace(sc_trace_file *tf,
packet_type( const packet_type& a ) const packet_type& v,
: info( a.info ), seq(a.seq), retry(a.retry) {} const std::string& name);
~packet_type() {} #endif

packet_type& operator = ( const packet_type& a ) {


info = a.info; // packet.cpp file
seq = a.seq; #include “packet.h”
retry = a.retry;
return *this; void sc_trace(sc_trace_file *tf, const packet_type& v,
} const sc_string& NAME) {
void print( ostream& os ) const { sc_trace(tf, v.info, NAME + “.info”);
os << info << ", " << seq << ", " << retry << endl; sc_trace(tf, v.seq, NAME + “.seq”);
} sc_trace(tf, v.retry, NAME + “.retry”);
}
+ 45

SystemC Model – transmit


// transmit.h // transmit.cpp
#include “packet.h” #include “transmit.h”
int transmit::get_data_fromApp() {
SC_MODULE (transmit) { int result;
sc_in<packet_type> tpackin; result = rand();
sc_in<bool> timeout; cout << “Generate: Sending Data Value = “ << result << “\
sc_out<packet_type> tpackout; n”;
sc_inout<bool> start_timer; return result;
sc_in<bool> clock; }
void transmit::send_data() {
int buffer; if (timeout) {
int framenum; s.info = buffer;
packet_type packin, tpackold; s.seq = framenum;
packet_type s; s.retry = retry;
retry++;
int retry;
tpackout = s;
bool start;
start_timer = true;
cout << “Transmit:Sending packet no. “ <<
void send_data(); s.seq << endl;
int get_data_fromApp(); } else {
packin = tpackin;
// Constructor if (!(packin == tpackold)) {
SC_CTOR(transmit) { if (packin.seq == framenum) {
SC_METHOD(send_data); buffer = get_data_fromApp();
sensitive << timeout; framenum++;
sensitive << clock.pos(); retry = 0;
framenum = 1; }
retry = 0; tpackold = tpackin;
start = false; s.info = buffer;
buffer = get_data_fromApp(); s.seq = framenum;
} s.retry = retry;
}; retry++;
tpackout = s;
start_timer = true;
cout << “Transmit:Sending packet no. “ <<
s.seq << endl;
} } }
+ 46

SystemC Model – noisybus

// noisybus.h // noisybus.cpp
#include “packet.h” #include “noisybus.h”

void noisybus::receive_data() {
SC_MODULE (noisybus) {
int i;
sc_in<packet_type> tpackin;
packin = tpackin;
sc_in<packet_type> rpackin; cout << “Noisybus: Received packet seq no. = “ << packin.seq <<
sc_out<packet_type> tpackout; endl;
sc_out<packet_type> rpackout; i = rand();
packout = packin;
packet_type packin; cout << “Noisybus: Random number = “ << i << endl;
if ((i > 1000) && (i < 5000)) {
packet_type packout;
packout.seq = 0;
packet_type ackin;
}
packet_type ackout; rpackout = packout;
}
void receive_data();
void send_ack(); void noisybus::send_ack() {
// Constructor int i;
SC_CTOR(noisybus) { ackin = rpackin;
SC_METHOD(receive_data); cout << “Noisybus: Received Ack for packet = “ << ackin.seq <<
endl;
sensitive << tpackin; i = rand();
ackout = ackin;
SC_METHOD(send_ack); if ((i > 10) && (i < 500)) {
sensitive << rpackin; ackout.seq = 0;
} }
}; tpackout = ackout;
}
+ 47

SystemC Model – receiver

// receiver.h // receiver.cpp
#include “packet.h” #include “receiver.h”

SC_MODULE(receiver) {
void receiver::receive_data() {
sc_in<packet_type> rpackin;
sc_out<packet_type> rpackout; packin = rpackin;
sc_out<long> dout; if (packin == packold) return;
sc_in<bool> rclk; cout << “Receiver: got packet no. = “ <<
packin.seq << endl;
int framenum; if (packin.seq == framenum) {
packet_type packin, packold; dout = packin.info;
packet_type s; framenum++;
int retry; retry++;
s.retry = retry;
void receive_data();
s.seq = framenum – 1;
//Constructor rpackout = s;
SC_CTOR(receiver) { }
SC_METHOD(receive_data); packold = packin;
sensitive << rclk.pos(); }
framenum = 1;
retry = 1;
}
};
+ 48

SystemC Model – timer

// timer.h // timer.cpp
#include “systemc.h” #include “timer.h”

SC_MODULE(timer) { void timer::runtimer() {


sc_in<bool> start; while(true) {
if (start) {
sc_out<bool> timeout;
cout << “Timer: start detected “
sc_in<bool> clock; << endl;
count = 5;
int count; timeout = false;
} else {
void runtimer(); if (count > 0) {
count--;
// Constructor timeout = false;
SC_CTOR(timer) { } else {
SC_THREAD(runtimer); timeout = true;
sensitive << clock.pos(); }
sensitive << start; }
wait();
count = 0;
}
}
}
};
+ 49

SystemC Model – display

// display.h // display.cpp
#include “packet.h” #include “display.h”

SC_MODULE(display) { void display::print_data() {


sc_in<long> din; cout << “Display: Data value received,
Data = “ << din << endl;
}
void print_data();
// Constructor
SC_CTOR(display) {
SC_METHOD(print_data);
sensitive << din;
}
};
+ 50

SystemC Model – main


// main.cpp receiver r1(“receiver”); // receiver instantiation
#include “packet.h” r1.rpackin(PACKET4); // connect to noisybus
#include “timer.h” r1.rpackout(PACKET3); // connect to noisybus
#include “transmit.h” r1.dout(DOUT); // port to signal binding
#include “noisybus.h” r1.rclk(RCLK); // clocking
#include “receiver.h”
#include “display.h” display d1(“display”);// display instantiation
d1 << DOUT; // signal to port connection
int sc_main(int argc, char* argv[]) {
sc_signal<packet_type> PACKET1, PACKET2,
PACKET3, PACKET4; timer tm1(“timer”); // timer instantiation
sc_signal<long> DOUT; tm1 << START << TIMEOUT << CLOCK.signal();
sc_signal<bool> TIMEOUT, START; // signal to port connections
sc_clock CLOCK(“clock”, 20); // transmit clock
sc_clock RCLK(“rclk”, 15); // receiver clock // tracing:
// trace file creation, with VCD type output
transmit t1(“transimit”); // transmit instantiation sc_trace_file *tf = sc_create_vcd_trace_file(“simplex”);
t1.tpackin(PACKET2); // port to signal binding // External signals
t1.timeout(TIMEOUT); sc_trace(tf, CLOCK.signal(), “clock”);
t1.tpackout(PACKET1); sc_trace(tf, TIMEOUT, “timeout”);
t1.start_timer(START); sc_trace(tf, START, “start”);
t1.clock(CLOCK); // clocking
sc_trace(tf, PACKET1, “packet1”);
noisybus n1(“noisybus”); // noisybus instantiation sc_trace(tf, PACKET2, “packet2”);
n1.tpackin(PACKET1); // connect to transmit sc_trace(tf, PACKET3, “packet3”);
n1.rpackin(PACKET3); // port to signal binding sc_trace(tf, PACKET4, “packet4”);
n1.tpackout(PACKET2); // connect to transmit sc_trace(tf, DOUT, “dout”);
n1.rpackout(PACKET4); // port to signal binding
sc_start(10000); // simulate for 10000 time
steps
// default is ps

sc_close_vcd_trace_file(tf);

return(0);
}
+
Drag picture to placeholder or click ico
51

Not “English as
Second Language”
Drag picture to plac

Chapter 3
Processes, Interface & Channel
+ 52

Basics

 Ina typical programming language, processes


are executed sequentially as control is
transferred from one process to another to
perform the desired function.
 Processes are not hierarchical, so no process
can call another process directly. Processes
can call methods and functions that are not
processes.
 Processes have sensitivity lists. The process is
called, or activated, whenever any values in
the sensitivity lists are changed.
+ 53

Basics – Cont.

 However, hardware components and devices (including


wires) are executed in parallel.
 To mimic the hardware behavior, at each time period,
or on the trigger of an event, ready processes are
called to simulate the behavior at that moment, till
before next time period (end of the process,) or till it
hits a wait().
+ 54

Method

 SC_METHOD
 Method is just SystemC ways of saying
function, or subroutine. Therefore, it inherits
the behavior of a function.
 A process is called to execute and returns the
execution back to the calling mechanism
when completed.
 A locally declared variable is not permanent.
Meaning, the value of a local variable is no
longer valid after the end of a method.
+ 55

Thread

SC_THREAD

 Threadis a process that always alive. Unlike


method, its local variables are alive throughout
the simulation.
 Thread can be suspended and reactivated. A
thread can contain wait() statements that
suspend the process until an event occurs on one
of the signals the process is sensitive to.
 Thread is not supported in the OSCI Synthesizable
Subset
+ 56

Clocked Thread

SC_CTHREAD
 Clocked thread is a special case of a thread process. A
clocked thread is only sensitive to one edge of a clock
cycle (positive or negative).
 Clocked thread is used to clearly describe reset
behavior by using

reset_signal_is()
async_reset_signal_is()
 The use of wait() is the same as in SC_THREAD.
+ 57

Clocked Thread Example - IIR

// IIR.h #include “IIR.h”


SC_MODULE(IIR) void IIR::iir()
{
{
// reset
sc_in<sc_uint<32> > input; mid = 0;
sc_out<sc_uint<32> > output; mid1 = 0;
sc_in<bool> enable; mid2 = 0;
sc_in<sc_clock> clk; a1 = 354; a2 = 1799;
b1 = 573; b2 = 1254;
// computation
void iir(); while (1) {
sc_uint<32> x, y; wait();
sc_signal<sc_uint<32> > mid, x = input.read();
mid1, y = mid + a2 * mid1 + b2 * mid2;
mid2; mid = x + a1 * mid1 + b1 * mid2;
mid2 = mid1;
sc_uint<32> a1, a2, b1, b2;
mid1 = mid;
SC_CTOR(IIR) { output.write(y);
SC_CTHREAD(iir, clk.pos()); }
reset_signal_is(enable, false); }
}
};
+
SC_HAS_PROCESS
 Used when you like to create a constructor with more
parameters than just defined by SC_METHOD, SC_THREAD
and SC_CTHREAD
 Another way to put it, SC_HAS_PROCESS is the
constructor creator
 If you have the module implemented in one file,
i.e. .cpp, then you can place SC_HAS_PROCESS before the
constructor
 If you have the module implemented in separated .h
and .cpp files, then place SC_HAS_PROCESS inside the
constructor
 No matter what, having the SC_HAS_PROCESS inside the
constructor works best
+
SC_HAS_PROCESS Example (1)
ram.h
#include <systemc.h>
SC_MODULE(RAM) {
sc_in<bool>. clock;
sc_in<bool>. rw;
sc_in<sc_uint<32> > addr;
sc_inout<sc_uint<32> > data;

void ram_proc();

RAM(sc_module_name name_, unsigned int size_=64) :


sc_module(name_), size(size_) {
The extended parameter
SC_HAS_PROCESS(RAM);
SC_CTHREAD(ram_proc, clock.pos());
reset_signal_is(reset, false);

memory = new sc_uint<32> [size];


}
private:
sc_uint<32>* memory;
const unsigned int size;
}
+
SC_HAS_PROCESS Example (2)
ram.cpp
#ifndef RAM_MODULE
#define RAM_MODULE

#include “ram.h”

void RAM::ram_proc() {
for (int i = 0; i < size; i++)
memory[i] = 0x0;
while(true) {
wait();
unsigned int haddr = addr.read();
assert(haddr < size);
if (rw) {
data = memory[haddr];
} else {
memory[haddr] = data.read();
}
}
}
#endif
+
SC_HAS_PROCESS Example (3)
main.cpp

#include “ram.h”

int sc_main (int argc, char* argv[]) {



RAM ram64(“ram64”);
RAM ram1024(“ram1024”, 1024);
… The extended parameter
}
#endif
+ 62

Dynamic Process

 Starting 2.1, SC_SPAWN is supported


 Dynamic process means a component is materialized
only when used. This is a programming skill to speed
up the simulation performance.
 The concept of dynamic process is not HW oriented.
+ 63

sc_main()

int sc_main(int argc, char* argv[]) {


sc_fifo<int> s1(10); // fifo of depth 10
sc_fifo<int> s2(10);
sc_fifo<int> s3(10);
stimgen stime(“stime”); // stimgen module
stim(s1, s2); // binding
adder add(“add”); // adder module
add(s1, s2, s3); // binding
monitor mon(“mom”); // monitor module
mon.re(s3); // binding
sc_start(); // run indefinitely
return 0;
}
+
Execution Semantics

64
+ 65

Simulating Parallelism
250 ps 250 ps 250 ps

a a a

mult c mult c mult c

b b b
1.Input to b is 1.Inputs to mult are 1.Input to signal c is
changed changed changed
2.Triggered signal b to 2.Triggered mult to 2.Triggered signal c to
compute the change compute the change compute the change
3.Input to a is 3.Inputs to signals a, b 3.Inputs to signals a, b
changed and c are not and mult are not
4.Triggered signal a to changed changed
compute the change 4.No execution to a, b 4.No execution to a, b
5.Inputs to mult and and c and mult
signal c are not
changed
6.No execution to mult
and c
+ 66

Execution Semantics

An event based simulator. Events


occur at a given simulation time.
main() is part of the SystemC
library. It calls sc_main()
Elaboration: The execution of the
sc_main() from the start to the
first invocation of sc_start().
+ 67

Simulation Semantics

 Thescheduler controls the timing and order of


process execution, handles event notifications
and manages updates to channels.
 Thescheduler supports the notion of delta-
cycle, which consists of an evaluate phase and
update phase.
 Processes are non-preemptive, meaning for a
thread process, codes between two wait() will
execute without any other process interruption
and a method process completes its execution
without interrupted by another process.
+ 68

Initialization Phase

 the first step in the simulator scheduler. Each method


process is executed once during initialization and each
thread process is executed until a wait statement is
encountered.
 To turn off initialization for a particular process, call
dont_initialize() after the SC_METHOD, SC_THREAD or
SC_CTHREAD process declarations inside a module
constructor.
 The order of processes’ execution is unspecified.
However, the execution order between processes is
determined. This only means every two simulation runs
to the same code always have the same execution
ordering to yield identical results.
+ 69

Synchronization – Bus
Arbitration
evaluate
evaluate AArequests
checks BBBreads
requests
checks evaluate
evaluate
busgrant from
busgrant
memory
update update

A YESNO B
request_update
request_update read
checkGrant
grant-ID
evaluate
B update
C
Cycle:
0
1
read write
memory
evaluate update
D
+ 70

Simulation Functions

 Startingthe simulation: sc_start() is


called in sc_main() to start the scheduler
 Stopping the simulation: sc_stop() is called
to stop the scheduler and return control
back to the sc_main(). In this case the
simulation cannot be continued anymore.
 Obtaining
current simulation time:
sc_time_stamp() & sc_simulation_time()
+ 71

Time

 Data type sc_time


 Time unit:
 enum sc_time_unit {
SC_FS = 0, // femtosecond
SC_PS, // picosecond
SC_NS, // nanosecond
SC_US // microsecond
SC_MS, // millisecond
SC_SEC // sec };
 sc_time t(123, SC_NS); // t = 123 nanoseconds
+ 72

Time Resolution

 The time resolution is the smallest amount of time that


can be represented by all sc_time objects in a SystemC
simulation. The default value for the time resolution is 1
picosecond.
 A user may set the time resolution to some other value
by calling the sc_set_time_resolution(). This
function, if called, must be called before any sc_time
objects are constructed.
 A user may ascertain the current time resolution by
calling the sc_get_time_resolution().
 Any time smaller than the time resolution will be
rounded off, using round-to-nearest.
+ 73

Time Unit

 Time unit is to specify the period of one simulation


step. It is larger or equal to time resolution. The default
time unit is 1 nanosecond.
 Call sc_set_default_time_unit() to set default time
unit:
 sc_set_default_time_unit(10, SC_MS);

 Time values may sometimes be specified with a


numeric value without time unit:
 sc_start(1000); // run for 1000 time units
+ 74

Events

 An event is an object and its synopsis is:


class sc_event {
public:
sc_event();
~sc_event();
void cancel();
void notify();
void notify( const sc_time& );
void notify( double, sc_time_unit );
sc_event_or_list& operator | (const sc_event& ) const;
sc_event_and_list& operator & (const sc_event& ) const;
private:
sc_event (const sc_event&);
sc_event& operator = ( const sc_event& );
}
+ 75

Events – Cont.

 An sc_event instance determines when and whether a


process execution is triggered or resumed.
 The sc_event provides basic synchronization for
processes. Event notification causes the kernel to call a
method process, or to resume a thread process that is
sensitive to the event.
 The event keeps a list of processes that are sensitive to
occurrences of the event.
 The owner of an event, a process or a channel, is
responsible to report change to the event. However, it is
the event to keep the list of what processes the
scheduler should trigger or resume on this event.
+ 76

Event – Cont.

A, B & C: Processes
B D: Channel
D
A
C

Event Notify B Notify C


+ 77

Event – Cont.

3 ways to notify an event:


 Immediate: the event is triggered in the current
evaluation phase of the current delta-cycle; notify()
 Delta-cycle delayed: the event will be triggered during
the evaluate phase of the next delta-cycle; notify(0,
SC_NS) or notify(SC_ZERO_TIME)
 Timed: the event will be triggered at the specified time in
the future; notify(10, SC_NS)
sc_event my_event;
sc_time t(10, SC_NS); // a 10ns time interval
my_event.notify(); // immediate
my_event.notify(0); // delta-cycle delayed
my_event.notify(t); // notification in 10ns
+ 78

Multiple Event Notification

 Earlier notification will always override one scheduled to occur


later, and an immediate notification is always earlier than any
delta-cycle delayed or timed notification.
 Notice a potential non-deterministic situation:
Process A{ Process B { Process C {
my_event.notify() my_event.notify(0); wait(my_event);
; } }
}

 If A first then B, C will be executed at both current and next


delta-cycle.
 However, if B first then A, C will execute once only at the
current delta-cycle
+ 79

Canceling Event Notifications

 A pending delayed event notification may be


canceled using cancel(). However
immediate event cannot be canceled.
sc_event a, b, c;
sc_time t(10, SC_MS);
a.notify();
b.notify(0);
c.notify(t);

a.cancel(); // Error!
b.cancel(); // Canceled!
c.cancel(); // Canceled!
+ 80

Multiple Pending Events

 Whilesc_event() can only allow a


single pending event,
sc_event_queue() can handle multiple
pending events.
+
Interface and Channel
The basic modeling elements of inter-module
communication are interface, port and channel

81
+ 82

Interface
 Aninterface defines the set of access
functions (methods) of a channel. It
specifies the name, parameters and
return type of functions but does not
have the implementation details.
 sc_fifo_in_if
 sc_fifo_out_if
 sc_mutex_if
 sc_semaphore_if
 sc_signal_in_if
 sc_signal_inout_if
+ 83

Channel
 A channel implements the interface functions. Channel
provides the communication between methods or
within a module provides the communication between
processes.
 Channel may implement one or more interfaces
 Different channels may implement the same interface
in different ways
 sc_buffer
 sc_fifo
 sc_mutex
 sc_semaphore
 sc_signal
 sc_signal_resolved
 sc_signal_rv
+
Drag picture to placeholder or click ico
84

Not “English as
Second Language”
Drag picture to plac

Chapter 4
Data Types
+ 85

sc_bit

 2 value single bit type


 ‘0’ (false) and ‘1’ (true)

sc_bit operators
Bitwise & (and) | (or) ^ (xor) ~ (not)

Assignment = &= |= ^=
Equality == !=

 a = a & b; a &= b;
 a = a | b; a |= b;
+ 86

sc_logic

 4 value single bit type


 ‘0’ (false), ‘1’ (true), ‘X’ (unknown), ‘Z’ (high-
impedance)
sc_logic operators

Bitwise & (and) | (or) ^ (xor) ~ (not)

Assignment = &= |= ^=
Equality == !=

x = ‘1’; x = ‘Z’;
x ^= y; x != y;
+ 87

sc_int & sc_uint


1 to 64 bit fixed precision signed/unsigned integer type
Fixed precision integer operators
Bitwise ~ & | ^ >> <<
Arithmetic + - * / %
Assignment = += -= *= /= %= &= |= ^=
Equality == !=
Relational < <= > >=
Autoincrement ++
Autodecrement --
Bit Select [x]
Part Select range()
Concatenation (,)

mybit = myint[7]; myrange = myint.range(7,4);


intc = (inta, intb);
+ 88

sc_bigint & sc_biguint


Arbitrary size signed/unsigned integer type
Fixed precision integer operators
Bitwise ~ & | ^ >> <<
Arithmetic + - * / %
Assignment = += -= *= /= %= &= |= ^=
Equality == !=
Relational < <= > >=
Autoincrement ++
Autodecrement --
Bit Select [x]
Part Select range()
Concatenation (,)

sc_biguint<128> b1; sc_biguint<64> b2; sc_biguint<150> b3;


b3 = b1*b2; // 42 bits will be truncated before assign into b3
+ 89

sc_bv
Arbitrary sized 2 value vector type
Fixed precision integer operators
Bitwise ~ & | ^ >> <<
Assignment = &= |= ^=
Equality == !=
Bit Select [x]
Part Select range()
Concatenation (,)
Reduction and_reduce() or_reduce() xor_reduce()
sc_bv<64> databus;
sc_logic result;
result = databus.or_reduce();
// or_reduce returns the result of ORing all bits in databus
// and_reduce(), or_reduce() and xor_reduce() return bool value
+ 90

sc_lv

Arbitrary sized 4 value vector type


Fixed precision integer operators
Bitwise ~ & | ^ >> <<
Assignment = &= |= ^=
Equality == !=
Bit Select [x]
Part Select range()
Concatenation (,)
Reduction and_reduce() or_reduce() xor_reduce()

sc_lv<16> bus1;
bus1 = “ZZZZZZZZZZZZZZZZ”;
// this string like assignment also works for sc_bv
+
Drag picture to placeholder or click ico
91

Not “English as
Second Language”
Drag picture to plac

Chapter 5
Fixed Point Types
+ 92

Fixed Point Types Basics

 Total word length (wl): the total number of bits. Word


length must be greater than 0.
 Integer word length (iwl): the integer fraction bit
length. iwl can be positive or negative and can be
larger than wl.
 xxx.xx : wl = 5, iwl = 3
 .ssxxxxx : wl = 5, iwl = -2
 xxxxx00 : wl = 5, iwl = 7

 For above examples, notice carefully the position of the


decimal point
+ 93

Quantization Mode
 How to handle the situation when the result of
an operation generates more precision in the
LSB than is available as specified by wl and
iwl. For example, a division, 1/3.
Quantization Mode Name
Round to plus infinity SC_RND
Round to zero SC_RND_ZERO
Round to minus infinity SC_RND_MIN_INF
Round to infinity SC_RND_INF
Convergent round SC_RND_CONV
Truncate SC_TRN
Truncate to zero SC_TRN_ZERO
+ 94

SC_RND
 Round the value to the closest representable number
by adding the MSB of the removed bits to the
remaining bits. ( 二進位之四捨五入 )
 01001.010[10100] → 01001.011
+ 95

SC_RND Examples

sc_fixed<4, 2> x;
sc_fixed<3, 2, SC_RND> y;
x = 1.25; // 1.25 = 01.01
y = x; // 01.0[1] → 01.1 = 1.5

x = -1.25 // -1.25 = 10.11 (01.01 2’s


complement)
y = x; // 10.1[1] → 11.0 = -1
+ 96

SC_RND_ZERO
 Performs SC_RND if the two nearest representable
numbers are not an equal distance apart, otherwise
round to zero is performed.
 x.x is not of equal distance. .xx or xx. Are of equal
distance
 When round to zero, for a positive number redundant
bits are deleted, and for a negative number SC_RND is
performed.
+ 97

SC_RND_MIN_INF
 Performs SC_RND if the two nearest
representable numbers are not an equal
distance apart, otherwise round to minus
infinity is performed.
 Minus infinity: omitting the redundant bits on
the LSB side.
+ 98

SC_RND_INF
 Performs SC_RND if the two nearest representable
numbers are not an equal distance apart, otherwise
round to plus infinity is performed.
 Plus infinity: for positive numbers perform SC_RND. For
negative numbers eliminate the redundant bits.
+ 99

SC_RND_CONV
 Performs SC_RND if the two nearest representable
numbers are not an equal distance apart, otherwise
checks the LSB of the remaining bits. If the LSB is 1
then round towards plus infinity. If the LSB is 0 then
round towards minus infinity.

sc_fixed<4, 2> x;
sc_fixed<3, 2, SC_RND> y;
x = .75; // .75 = 00.11
y = x; // 01.0 = 1
+ 100

SC_TRN
 Default mode. The redundant bits are always deleted.
Other ways of saying is it always rounds towards minus
infinity.
+ 101

SC_TRN_ZERO
 Performs truncate to positive numbers.
 Performs SC_RND to negative numbers.
+ 102

Overflow Mode
 Overflow: when the result of an operation generated more
bits on the MSB side than are available for representation.
 Overflow mode is specified by the o_mode and n_bits
parameters to a fixed point data type, it has two major
modes, saturate and wrap-around.
 MIN is the smallest negative number that can be
represented.
 MAX is the largest positive number that can be represented.
Overflow Mode Name
Saturate SC_SAT
Saturate to zero SC_SAT_ZERO
Symmetrical saturate SC_SAT_SYM
Wrap-around SC_WRAP
Sign magnitude wrap-around SC_WRAP_SM
+ 103

SC_SAT
 Convertsthe value to MAX for an overflow and
MIN for an underflow.
+ 104

SC_SAT Examples

sc_fixed<4,4> x;
sc_fixed<3,3,SC_TRN,SC_SAT> y;
x = 6; // 0110, with a sign bit
y = x; // 011 = 3, remember the sign bit

x= -5; // 1011
y = x; // 100 = -4
+ 105

SC_SAT_ZERO
 Sets the result to 0 for any value that is outside the
representable range of the fixed point data type.
+ 106

SC_SAT_SYM
 In 2’s complement notation there is one more
negative representation than positive. Sometimes it is
desirable to have the same positive and negative
numbers of representations. SC_SAT_SYM generates
MAX and negative overflow generates –MAX for signed
numbers.
+ 107

Wrap-around

 When overflow occurs, this operation wraps around the


overflowed value from MAX to MIN. The unsigned case is
similar to the way a counter would work in hardware.
 There are two different cases within the wrap-around
operation: n_bits parameter set to 0 or is greater than
0. The n_bits parameter sets the number of bits to be
wrapped around.
+ 108

SC_WRAP, nbits = 0
 The default overflow mode.
 Any MSB bits outside the range of the target type are
deleted.
+ 109

SC_WRAP, n_bits > 0

 n_bits MSB bits are to be saturated. The sign bit is


retained. The bits that are not saturated are
maintained.
+ 110

SC_WRAP_SM, n_bits = 0

 Deletes any MSB bits that are outside the result work
length.
 Sign bit is set to the value of the LSB of deleted bits.
+ 111

SC_WRAP_SM, n_bits > 0


 A sign magnitude wrap is performed and n_bits MSB
bits will be saturated.
 The first n_bits MSB bits are saturated to MAX for
positive numbers and to MIN for negative numbers.
+ 112

sc_fixed & sc_ufixed

 Need to
 #include <sysc/datatypes/fx/sc_fixed.h> // for sc_fixed
 #include <sysc/datatypes/fx/sc_ufixed.h> // for sc_ufixed
 using namespace sc_dt;
 Templated & static signed/unsigned fixed point data types
 Declaration Syntax:
sc_fixed <wl, iwl [,q_mode [, o_mode [, n_bits]]]>
var_name([init_val][,cast_switch]);
cast_switch : SC_ON, SC_OFF
 Examples
sc_ufixed<16, 1, SC_RND_CONV, SC_SAT_SYM, 1> a(1.5);
+ 113

sc_fixed_fast & sc_ufixed_fast

 Need to
 #include <sysc/datatypes/fx/sc_fixed.h> // within sc_fixed
 #include <sysc/datatypes/fx/sc_ufixed.h> // within sc_ufixed
 using namespace sc_dt;
 Mantissa limited to 53 bits. Templated & static signed/unsigned
fixed point data types
 Declaration Syntax:
sc_fixed_fast <wl, iwl [,q_mode [, o_mode [, n_bits]]]>
var_name([init_val][,cast_switch]);
cast_switch : SC_ON, SC_OFF
 Examples
sc_ufixed<16, 1, SC_RND_CONV, SC_SAT_SYM, 1> a(1.5);
+ 114

sc_fix & sc_ufix


 Need to
 #include <sysc/datatypes/fx/sc_fix.h> // for sc_fix
 #include <sysc/datatypes/fx/sc_ufix.h> // for sc_ufix
 using namespace sc_dt;
 Untemplated signed/unsigned fixed point data types.
Dynamic type settings.
 syntax:
sc_fix var_name([init_val][,wl,iwl]
[,q_mode,o_mode[,n_bits]] [,cast_switch]);
sc_fix var_name([init_val,]type_params
[,cast_switch]);
 Example

sc_ufix a(16, 1, SC_RND_CONV,SC_SAT_SYM, 1);


+ 115

Dynamic Fixed-Point Type


Settings
 Helpexplore different wl, iwl, quantization
and overflow settings.
 sc_fxtype_params
 data members
 wl: word length
 iwl: integer word length
 q_mode: quantization mode
 o_mode: overflow mode
 n_bits: saturated bits
 some others
 Reading/writing individual data members
 .wl() .iwl() .q_mode() .o_mode()

Codesign of Embedded Systems Winter-Spring 2001


+ 116

Dynamic Fixed-Point Type


Settings (cont’d)
 Example
sc_fxtype_params my_fx_type(8,4,SC_RND,SC_SAT);
sc_fix my_fx(my_fx_type);
my_fx = 10.2;
for (int i – 1; i < 10; i++) {
my_fx_type.wl(my_fx_type.wl()+i);
my_fx_type.iwl(my_fx_type.iwl()+i);
// Only my_fx_type is changed
// my_fx wl and iwl remain the same
sc_fix my_fx2(my_fx_type); // my_fx2 has new type settings
my_fx2 = my_fx;
cout << “my_fx2 = “ << my_fx2.to_string(SC_BIN) << endl;
}
Codesign of Embedded Systems Winter-Spring 2001
+ 117

sc_fix_fast & sc_ufix_fast


 Need to
 #include <sysc/datatypes/fx/sc_fix.h> // within sc_fix
 #include <sysc/datatypes/fx/sc_ufix.h> // within sc_ufix
 using namespace sc_dt;
 Mantissa limited to 53 bits. Untemplated signed/unsigned
fixed point data types. Dynamic type settings
 syntax:
sc_fix var_name([init_val][,wl,iwl]
[,q_mode,o_mode[,n_bits]] [,cast_switch]);
sc_fix var_name([init_val,]type_params
[,cast_switch]);
 Example

sc_ufix a(16, 1, SC_RND_CONV,SC_SAT_SYM, 1);


+ 118

Useful State Information

 Status member functions


 is_neg()
 is_zero()
 overflow_flag()
 quantization_flag()

sc_fixed<10,2> my_var;
if (my_var.is_zero())
...

Codesign of Embedded Systems Winter-Spring 2001


+ 119

Conversion To String

 Conversion member function


 to_string(number_representation, format)

 Available number representations


 SC_DEC (is the default)
 SC_BIN SC_BIN_US SC_BIN_SM
 SC_OCT SC_OCT_US SC_OCT_SM
 SC_HEX SC_HEX_US SC_HEX_SM
 SC_CSD

 Available formats
 SC_F - Fixed Notation (is the default)
 SC_E - Scientific Notation

sc_fixed<10,5> my_var;
cout << my_var.to_string(SC_BIN, SC_E);

Codesign of Embedded Systems Winter-Spring 2001


+ 120

Type Casting

 Done during initialization and/or assignment (if


required)
 Type casting operations
1. Quantization
2. Overflow handling
(sign-extension and/or zero filling is done wherever necessary)

 Can be turned ON or OFF, using


 Current Context
 Parameter during fix-point data declaration
 SC_ON, SC_OFF
sc_ufixed<16,16> d(SC_OFF);

Codesign of Embedded Systems Winter-Spring 2001


+ 121

Type Casting (cont’d)

 TurningCasting off will turn off fixed-


point handling of the operand
 Itwill be treated as a large float
 Bit-accurate behavior of the operand will not
be available

Codesign of Embedded Systems Winter-Spring 2001


+ 122

Arrays of Fixed-Point Data

 Static fixed-point data types


 sc_fixed<10,5> a[8];
 Only CAST Switch is determined by current
Context
 The same for all Static fixed-point types

 Dynamic fixed-point data types


 sc_fix a[8];
 Default constructor is called.
 Default values are taken from current context

Codesign of Embedded Systems Winter-Spring 2001


+
End of 4th Section
Thanks to you all!

123

You might also like