Sunteți pe pagina 1din 58

Embedded Systems

Design

Lecture: SystemC
SystemC
What is it?
SystemC
A C++ library
#include <systemc.h>
Library is a set of C++ classes and
macros for event-driven simulation
Transaction Level Modeling (TLM) (aka Behavioural)

Developed to support system level


design for modeling, verification, and
simulation of hardware/software
systems
SystemC
With SystemC, designers can simulate
concurrent processes
Prototype using techniques similar to
Verilog and VHDL, but with the
programmability of a C language
i.e. Notion that C++ = easy, RTL = harder
SystemC
Lets model a D flip flop (register)
D Flip Flop

BACK TO VHDL....
SystemC
Lets model a D flip flop (register)
SystemC
Lets model a D flip flop (register)

Dedicated HW Unit Acts as your CPU


-Executes SW
SystemC
Lets model a D flip flop (register)

Offload data intensive phases of the


application (write) to HW
Then read back results to main (CPU)
SystemC
Lets model a D flip flop (register)
#include "systemc.h"
SC_MODULE(dff) {
sc_in<bool > clk;
sc_in<bool > din;
sc_out<bool > dout;

void p1() {
dout.write(din.read());
}

SC_CTOR(dff) {
SC_METHOD(p1);
sensitive << clk.pos();
}
};
SystemC
Lets model a D flip flop (register)
#include "systemc.h"
SC_MODULE(dff) {
sc_in<bool > clk;
sc_in<bool > din;
sc_out<bool > dout;

void p1() {
dout.write(din.read());
}

SC_CTOR(dff) {
SC_METHOD(p1);
Ports sensitive << clk.pos();
}
};
SystemC
Lets model a D flip flop (register)
#include "systemc.h"
SC_MODULE(dff) {
sc_in<bool > clk;
sc_in<bool > din;
sc_out<bool > dout;

void p1() {
dout.write(din.read());
}

SC_CTOR(dff) {
SC_METHOD(p1);
dont_initialize();
sensitive << clk.pos();
}
};
SystemC
Lets model a D flip flop (register) w/ enable
#include <systemc.h> Flipflop.h
#include "flipflop.h"
Flipflop.cpp
SC_MODULE(flipflop) {
sc_in<bool > clk; sc_int<3> data;
sc_in<bool> enable;
sc_in<sc_uint<3> > din; void flipflop :: ff_method() {
cout << "Enable = " << enable.read() <<", output = ";
sc_out<sc_uint<3> > dout;
if(enable.read() == 1){
void ff_method(); data = din.read();
dout.write(din.read());
SC_CTOR(flipflop) { }
SC_METHOD(ff_method); cout << data.to_string(SC_BIN) << endl;
dont_initialize(); }
sensitive << clk.pos();
}
};
SystemC
Lets model a D flip flop (register)

Done with the HW unit


Whats next?
SystemC
#include <systemc.h>
#include "flipflop.h"

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

return 0;
}
SystemC
#include <systemc.h>
#include "flipflop.h"

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

sc_signal<sc_uint<3> > data_in, data_out; //signals for binding


sc_signal<bool> en;
sc_clock clk("clk",10,SC_NS,0.5); //Create a clock signal

flipflop DUT("flipflop"); //Create Device Under Test


DUT.din(data_in); // Connect/map the ports to signals
DUT.dout(data_out);
DUT.clk(clk);
DUT.enable(en);

Signals
return 0;
}
SystemC
int sc_main(int argc, char* argv[]){

...
sc_clock clk("clk",10,SC_NS,0.5); //Create a clock signal

flipflop DUT("flipflop"); //Create Device Under Test


...
// Create wave file and trace the signals executing
tf = sc_create_vcd_trace_file("trace_file");
tf->set_time_unit(1, SC_NS);
sc_trace(tf, clk, "clk");
sc_trace(tf, en, "enable");
sc_trace(tf, data_in, "data_in");
sc_trace(tf, data_out, "data_out");

en.write(0); //initialize
data_in.write(0);
sc_start(9, SC_NS);
...
sc_close_vcd_trace_file(tf);
return 0;
}
SystemC
int sc_main(int argc, char* argv[]){

...
sc_clock clk("clk",10,SC_NS,0.5); //Create a clock signal

flipflop DUT("flipflop"); //Create Device Under Test


...
// Create wave file and trace the signals executing
tf = sc_create_vcd_trace_file("trace_file");
tf->set_time_unit(1, SC_NS);
sc_trace(tf, clk, "clk");
sc_trace(tf, en, "enable");
sc_trace(tf, data_in, "data_in");
sc_trace(tf, data_out, "data_out");

en.write(0); //initialize
data_in.write(0);
sc_start(9, SC_NS);
...
sc_close_vcd_trace_file(tf);
return 0;
}
SystemC
Makefile used to compile C/C++ projects and are
extremely useful when it is necessary to include several
source, header or library files to create your executable

CC=/usr/bin/g++
ARCH := $(shell arch)
SYSTEMC_HOME=/usr/local/SystemC-2.3.0
.... Makefile
PROGRAM = flipflop.x
SRCS = flipflop.cpp sc_main.cpp
OBJS = flipflop.o sc_main.o
....
SystemC
Lets model a D flip flop (register) w/ enable
#include <systemc.h> Flipflop.h
#include "flipflop.h"
Flipflop.cpp
SC_MODULE(flipflop) {
sc_in<bool > clk; sc_int<3> data;
sc_in<bool> enable;
sc_in<sc_uint<3> > din; void flipflop :: ff_method() {
cout << "Enable = " << enable.read() <<", output = ";
sc_out<sc_uint<3> > dout;
if(enable.read() == 1){
void ff_method(); data = din.read();
dout.write(din.read());
SC_CTOR(flipflop) { }
SC_METHOD(ff_method); cout << data.to_string(SC_BIN) << endl;
dont_initialize(); }
sensitive << clk.pos();
}
};
SystemC I/O Port Types
VHDL Port SystemC Port SystemC Notes
in sc_in
out sc_out Behaves like a VHDL buffer port
inout sc_inout
buffer sc_inout
SystemC Data Types
VHDL Type SystemC Type SystemC Notes
bit sc_bit Use native C++ bool type instead
bit_vector sc_bv Faster in simulation than sc_lv
Only support 4 types, 'X','Z','0'
std_ulogic sc_logic
and '1'
Only support 4 types, 'X','Z','0'
std_ulogic_vector sc_lv
and '1'
Resolution function for 'X','Z','0'
std_logic sc_logic_resolved
and '1'
Resolution function for 'X','Z','0'
std_logic_vector sc_signal_rv
and '1'
boolean bool recommended instead of sc_bit
int size is platform dependent, use
integer int
sizeof(int)
N bits signed/unsigned integer
integer sc_int<N>/sc_uint<N>
vector (N <=64)
arbitrary length signed/unsigned
integer sc_bigint<M>/sc_biguint<M>
integer vector
Native C/C++ 32bits floating point
float float
number
SystemC Data Types
VHDL Type SystemC Type SystemC Notes
bit sc_bit Use native C++ bool type instead
bit_vector sc_bv Faster in simulation than sc_lv
Only support 4 types, 'X','Z','0'
std_ulogic sc_logic
and '1'
Only support 4 types, 'X','Z','0'
std_ulogic_vector sc_lv
and '1'
Resolution function for 'X','Z','0'
std_logic sc_logic_resolved
and '1'
Resolution function for 'X','Z','0'
std_logic_vector sc_signal_rv
and '1'
boolean bool recommended instead of sc_bit
int size is platform dependent, use
integer int
sizeof(int)
N bits signed/unsigned integer
integer sc_int<N>/sc_uint<N>
vector (N <=64)
arbitrary length signed/unsigned
integer sc_bigint<M>/sc_biguint<M>
integer vector
Native C/C++ 32bits floating point
float float
number

sc_logic and sc_lv are unresolved types, only support the 4 signal types
Rule of Thumb Use C++ native types as much as possible. If you dont need
x and z then use: std_logic = <bool>, std_logic_vector = sc_int and sc_uint
SystemC I/O Port Types
VHDL Port SystemC Port SystemC Notes
in sc_in
out sc_out Behaves like a VHDL buffer port
inout sc_inout
buffer sc_inout

- PC counter example
-VHDL vs SystemC
VHDL and SystemC

PC COUNTER EXAMPLE
dont_initialize()
Flipflop.h
#include <systemc.h> #include "flipflop.h" Flipflop.cpp
SC_MODULE(flipflop) { sc_int<3> data;
sc_in<bool > clk;
sc_in<bool> enable; void flipflop :: ff_method() {
sc_in<sc_uint<3> > din; cout << "Enable = " << enable.read() <<", output = ";
sc_out<sc_uint<3> > dout; if(enable.read() == 1){
data = din.read();
void ff_method(); dout.write(din.read());
}
SC_CTOR(flipflop) { cout << data.to_string(SC_BIN) << endl;
SC_METHOD(ff_method); }
dont_initialize();
sensitive << clk.pos();
}
};
sc_start()
int sc_main(int argc, char* argv[]){

...
sc_clock clk("clk",10,SC_NS,0.5); //Create a clock signal

flipflop DUT("flipflop"); //Create Device Under Test


...
// Create wave file and trace the signals executing
tf = sc_create_vcd_trace_file("trace_file");
tf->set_time_unit(1, SC_NS);
sc_trace(tf, clk, "clk");
sc_trace(tf, en, "enable");
......

en.write(0); //initialize
data_in.write(0);
sc_start(9, SC_NS);

en.write(1); //enable and input


data_in.write(7);
sc_start(10, SC_NS);
...
return 0;
}
sc_start()
int sc_main(int argc, char* argv[]){

...
sc_clock clk("clk",10,SC_NS,0.5); //Create a clock signal

flipflop DUT("flipflop"); //Create Device Under Test


...
// Create wave file and trace the signals executing
tf = sc_create_vcd_trace_file("trace_file");
tf->set_time_unit(1, SC_NS);
sc_trace(tf, clk, "clk");
-SystemC scheduler calls each
sc_trace(tf, en, "enable");
......
process at t=0 (when executable
started)
en.write(0); //initialize -independent of any events
data_in.write(0);
sc_start(9, SC_NS);

en.write(1); //enable and input


data_in.write(7);
sc_start(10, SC_NS);
...
return 0;
}
dont_initialize()

Simple D flip flop with dont_initialize() invoked


dont_initialize()

without dont_initialize()
Clock Generation
sc_clock clock_name(clockLabel, period,
duty_ratio, offset, initial_value);

sc_clock clk("clk", 10, SC_NS, 0.5); //Create a clock signal


Clock Generation
sc_clock clk("clk",10,SC_NS,0.5); //Create a clock signal
...
en.write(0); //initialize
data_in.write(0);
sc_start(9, SC_NS);

en.write(1); //enable and input


data_in.write(7);
sc_start(10, SC_NS);
Clock Generation
sc_signal<bool> clk2 //Create a clock signal

clk2.write(1); // convert the clock to high


sc_start(10, SC_NS); // run for 10 ns
clk2.write(0); // start the clock as low
sc_start(10, SC_NS); // run for 10 ns
Clock Generation
sc_start(10, SC_PS); // run for 10 picosecond.
//SC_FS, SC_PS, SC_NS, SC_US, SC_MS, SC_SEC
sc_start(); // run until sc_stop()
sc_start(-1); // run until sc_stop()
sc_start(0); // run for 1 delta cycle!

sc_stop = stop simulation


Initializing Ports
ENTITY Test IS
port (count : out std_logic_vector(7 downto 0):=X"AA";
zero : out std_logic:='1');
END Test;

SC_MODULE(test) {

sc_inout<sc_lv<8> > count=0xAA;


sc_out<sc_logic > zero='1';
.....

SC_CTOR(test_ctor){
....
}
}
Initializing Ports
ENTITY Test IS
port (count : out std_logic_vector(7 downto 0):=X"AA";
zero : out std_logic:='1');
END Test;

SC_MODULE(test) {

sc_inout<sc_lv<8> > count=0xAA;


sc_out<sc_logic > zero='1';
.....

SC_CTOR(test_ctor){
....
}
}
Initializing Ports
ENTITY Test IS
port (count : out std_logic_vector(7 downto 0):=X"AA";
zero : out std_logic:='1');
END Test;
SC_MODULE(test) {
sc_inout<sc_lv<8> > count;
sc_out<sc_logic > zero;

SC_CTOR(count) {
...
count.initialize(0xAA);
zero.initialize('1');
...
}
};
Bit Select & Concatenation
-Rotation, shifting, swaps etc
VHDL
port (din : in std_logic_vector(7 downto 0);
dout1 : out std_logic_vector(7 downto 0);
dout2 : out std_logic_vector(7 downto 0));

Architecture
dout1 <= din(0) & din(7 downto 1); -- ROR
dout2 <= din(3 downto 0) & din(7 downto 4); -- Swap Nibble

SystemC
din(7,1) => Range or multiple term concatenation
din[0] => Bit select concatenation
Bit Select & Concatenation
-Rotation, shifting, swaps etc
VHDL
port (din : in std_logic_vector(7 downto 0);
dout1 : out std_logic_vector(7 downto 0);
dout2 : out std_logic_vector(7 downto 0));

Architecture
dout1 <= din(0) & din(7 downto 1); -- ROR
dout2 <= din(3 downto 0) & din(7 downto 4); -- Swap Nibble

SystemC
din(7,1) => Range or multiple term concatenation
din[0] => Bit select concatenation

?
Bit Select & Concatenation
-Rotation, shifting, swaps etc
VHDL
port (din : in std_logic_vector(7 downto 0);
dout1 : out std_logic_vector(7 downto 0);
dout2 : out std_logic_vector(7 downto 0));

Architecture
dout1 <= din(0) & din(7 downto 1); -- ROR
dout2 <= din(3 downto 0) & din(7 downto 4); -- Swap Nibble

SystemC
sc_in<sc_uint<8> > din;
sc_out<sc_uint<8> > dout1;
sc_out<sc_uint<8> > dout2;

dout1.write( ( din.read()[0] , din.read()(7,1) ) );


dout2.write( ( din.read()(3,0) , din.read()(7,4) ) ) ;
Processes
SystemC supports 3 types of processes:
SC_METHOD
SC_THREAD
SC_CTHREAD
Processes
SC_METHOD process executed
whenever an event on the sensitivity list
occurs
Processes
SC_METHOD process executed
whenever an event on the sensitivity list
occurs
SC_THREAD process that is only
called once by SystemCs scheduler
Processes
SC_THREAD process that is only
called once by SystemCs scheduler
Uses a wait() statement to suspend the
process, where control is then given back
to the scheduler
Process will return and execute statement
after wait() when an event on the
sensitivity list occurs
Processes
SC_METHOD SC_THREAD
#include "systemc.h"

SC_MODULE(dff) {
sc_in<bool > clk;
sc_in<bool > din;
sc_out<bool > dout;

void p1() {
dout.write(din.read());
}

SC_CTOR(dff) {
SC_METHOD(p1);
sensitive << clk.pos();
}
};
Processes
SC_METHOD SC_THREAD
#include "systemc.h" #include "systemc.h"

SC_MODULE(dff) { SC_MODULE(dff) {
sc_in<bool > clk; sc_in<bool > clk;
sc_in<bool > din; sc_in<bool > din;
sc_out<bool > dout; sc_out<bool > dout;

void p1() { void p1() {


dout.write(din.read()); while(true) { // Infinite loop
} wait(); // Note Position!
dout.write(din.read());
SC_CTOR(dff) { }
SC_METHOD(p1); }
sensitive << clk.pos();
} SC_CTOR(dff) {
}; SC_THREAD(p1); // call p1 only once
sensitive << clk.pos();
}
};
Processes SC_METHOD simulates faster than SC_THREAD

SC_METHOD SC_THREAD
#include "systemc.h" #include "systemc.h"

SC_MODULE(dff) { SC_MODULE(dff) {
sc_in<bool > clk; sc_in<bool > clk;
sc_in<bool > din; sc_in<bool > din;
sc_out<bool > dout; sc_out<bool > dout;

void p1() { void p1() {


dout.write(din.read()); while(true) { // Infinite loop
} wait(); // Note Position!
dout.write(din.read());
SC_CTOR(dff) { }
SC_METHOD(p1); }
sensitive << clk.pos();
} SC_CTOR(dff) {
}; SC_THREAD(p1); // call p1 only once
sensitive << clk.pos();
}
};
dont_initialize() with SC_THREAD
SC_CTOR(dff) { void p1() {
SC_THREAD(p1); while(true) {
// call p1 only once wait();
dont_initialize();
// don't call p1 at time 0
dout.write(din.read());
sensitive << clk.pos(); }
} }
dont_initialize() with SC_THREAD
SC_CTOR(dff) { void p1() {
SC_THREAD(p1); while(true) {
// call p1 only once dout.write(din.read());
dont_initialize();
// don't call p1 at time 0 wait();
sensitive << clk.pos(); }
} }
dont_initialize() with SC_THREAD
SC_CTOR(dff) { void p1() {
SC_THREAD(p1); while(true) {
// call p1 only once dout.write(din.read());
dont_initialize();
// don't call p1 at time 0 wait();
sensitive << clk.pos(); }
} }
SC_CTHREAD
SC_CTHREAD(process_name, clock_value){..}
Instead of being activated by sensitivity
list signals, this process is activated by a
clock pulse
i.e. Statements before wait() will be executed
in one cycle
Statements after wait() executed in the next
cycle
RTL and Hierarchy
RTL and Hierarchy

-Port map to instantiate other modules


within an entity
-Bind signals to ports
SystemC and Hierarchy

Declare constructors and instantiate other


modules in current SC_MODULE
SystemC and Hierarchy
#include "dff.h"

SC_MODULE(shiftreg) {
sc_in<bool > clk;
sc_in<bool > reset;
sc_in<bool > din;
sc_out<bool > dout;

sc_signal<bool > q1_s,q2_s,q3_s;

dff dff1; // Instantiate FF


dff dff2;
dff dff3;
dff dff4;

SC_CTOR(shiftreg) : dff1("dff1"),
dff2("dff2"), dff3("dff3"), dff4("dff4")
{
dff1.clk(clk);
dff1.reset(reset);
dff1.din(din);
dff1.dout(q1_s);

dff2.clk(clk);
dff2.reset(reset);
dff2.din(q1_s);
dff2.dout(q2_s);

....
}
};
Multiplier Accelerator
HDL Versus SystemC
SystemC
Simulates at the behavioural level
In comparison to ANSI C, designer may
support:
Multiple concurrent processes
Hierarchical designs, modules, and their
communications at the transaction level
Event-driven simulation
HDL Versus SystemC
What cant SystemC do for our SoC
designs?
And what does HDL/RTL provide for our
designs in comparison?

S-ar putea să vă placă și