You are on page 1of 32

SystemC Quick Tutorial

Ando Ki adki@dynalith.com Dynalith Systems

Copyright 2005 by Ando Ki

Agenda and objectives


           SystemC design process Design in hardware point of view Design in SystemC point of view Design organization SystemC module, port, constructor, process SystemC module instantiation SystemC signal tracing SystemC top-level Compilation and running of SystemC program Viewing VCD waveform Compilation using make  This session presents a quick tutorial of SystemC to grasp how to model hardware and how to simulate it.

SystemC quick tutorial: 2

Copyright 2005 by Ando Ki

SystemC design process


Standard C++ development environment
header SystemC library C++ Compiler Loader Make Design source files in SystemC

SystemC class library and simulation kernel

a.out (run.x) Debugger

wave data (VCD)

Running the executable (a.out) means simulation.


SystemC quick tutorial: 3
Copyright 2005 by Ando Ki

Design in hardware point of view


enable address[31:0]

memory decoder
selected

 Hierarchy
memory, decode, and ram

 Signal lines
directions, type of driving, width

rdwr we data[15:0]

ram

   

Control and data Concurrency or parallelism Reactivity More such as clock, delay, and so on.

enable address[] rdwr we data[] READ WRITE

SystemC quick tutorial: 4

Copyright 2005 by Ando Ki

Design in SystemC point of view


memory memory
enable address  Hierarchy of blocks
module

decoder decoder
selected

 Signal lines
port signal

 Control and data


abstraction level

rdwr we data

ram ram

 Concurrency or parallelism
process

 Reactivity module process port signal


SystemC quick tutorial: 5
Copyright 2005 by Ando Ki

sensitivity list of process wait()

 more
clock

Design organization
 Design source code
Interface files: .h Implementation files: .cpp
and.h
#include .. SC_MODULE . { };

and.cpp
void and:: do_and() {

 Interface file (.h) describes


Port and data members of a module prototypes of member functions of a module

 Implementation file contains


The code for the member functions

In1 In2

Out

SystemC quick tutorial: 6

Copyright 2005 by Ando Ki

SystemC module
 Basic building blocks in SystemC
Modules are declared with the SystemC keyword SC_MODULE, which is actually a C macro equivalent to defining the module as a C++ class.

 Ports pass data to/from module


Ports represent physical pins on a hardware block
Interface file, e.g., and.h C macro
In1 In2 #include systemc.h SC_MODULE(AND) { sc_in<bool> In1; sc_in<bool> In2; sc_out<bool> Out;

SystemC header ports

Out

C++ constructor

SC_CTOR( AND) { } };
Copyright 2005 by Ando Ki

SystemC quick tutorial: 7

SystemC port of module


 Ports allow a module to access an interface
SystemC port is a means by which a module can call the method implemented by a SystemC channel.
#include systemc.h SC_MODULE(AND) { sc_port<sc_signal_in_if<bool> > In1; sc_port<sc_signal_in_if<bool> > In2; sc_port<sc_signal_out_if<bool> > Out; }; In1 In2 sc_signal_in_if channel
SystemC quick tutorial: 8
Copyright 2005 by Ando Ki

SystemC interface ports

Out

SystemC constructor of module


 Constructor registers process within the SystemC simulation kernel and also to define the sensitivity list of the process
#include systemc.h SC_MODULE(AND) { sc_in<bool> In1; sc_in<bool> In2; sc_out<bool> Out; void do_and(); SC_CTOR( AND) { SC_METHOD(do_and); sensitive << In1 << In2; } }; In1 In2 do_and() Out

C++ member function C++ constructor Macro to register a C++ function as a SystemC process Process sensitivity
(in this example, changes on the ports In1 and/or In2 will trigger execution of the process do_and().)

SystemC quick tutorial: 9

Copyright 2005 by Ando Ki

SystemC process of module


 Processes are pieces of code which execute sequentially (line-by-line) inside a module.  Process executes concurrently with other processes.

In1 In2

do_and()

Out

Include module header file


#include and.h

Function called when A or B change

void AND::do_and() { Out.write(In1.read() && In2.read()); }

Interface method calls

Logical and function


SystemC quick tutorial: 10
Copyright 2005 by Ando Ki

SystemC module in C++


Using SystemC macros
#include systemc.h SC_MODULE(AND) { sc_in<bool> In1; sc_in<bool> In2; sc_out<bool> Out; void do_and(); SC_CTOR( AND) { SC_METHOD(do_and); sensitive << In1 << In2; } };

C++ point of view


#include systemc.h Class AND : public sc_module { sc_port<sc_signal_in_if<bool> > In1; sc_port<sc_signal_in_if<bool> > In2; sc_port<sc_signal_out_if<bool> > Out; void do_and(); SC_HAS_PROCESS(AND); AND( sc_module_name string ) : sc_module(string) { SC_METHOD(do_and); sensitive << In1 << In2; } };

SystemC quick tutorial: 11

Copyright 2005 by Ando Ki

SystemC module: one more example

// xor.h #include systemc.h SC_MODULE(XOR) { sc_in<bool> In1; sc_in<bool> In2; sc_out<bool> Out; void do_xor(); SC_CTOR( XOR) { SC_METHOD(do_xor); sensitive << In1 << In2; } };

In1 In2

Out

// xor.cpp #include xor.h void XOR::do_xor() { bool tmp1, tmp2; tmp1 = In1.read(); tmp2 = In2.read(); if ((tmp1&&!tmp2)||(!tmp1&&tmp2)) Out.write(true); else Out.write(false); }
SystemC quick tutorial: 12
Copyright 2005 by Ando Ki

SystemC module instantiation


// half_adder.h #include and.h #include xor.h SC_MODULE(half_adder) { sc_in<bool> In1, In2; sc_out<bool> Sum, Carry; AND Uand; XOR Uxor; void do_half_adder(); Sum

In1 In2

Module instances C++ initializers

Carry

SC_CTOR( half_adder) : Uand(Uand), Uxor(Uxor) { Uand.In1(In1); Uand.In2(In2); Uand.Out(Carry); Uxor.In1(In1); Uxor.In2(In2); Uxor.Out(Sum); } };

Port connections

Note that there are no processes.


SystemC quick tutorial: 13
Copyright 2005 by Ando Ki

SystemC module: test stimulus


Out1 Out2

clk // stimulus.h #include systemc.h SC_MODULE(stimulus) { sc_in<bool> clk; sc_out<bool> Out1, Out2; void do_stimulus(); SC_CTOR( stimulus) { SC_METHOD(do_stimulus); sensitive << clk.pos(); } }; // stimulus.cpp #include stimulus.h void stimulus::do_stimulus() { Out1.write(random()&0x1); Out2.write(random()&0x1); }

Clock edge sensitive

SystemC quick tutorial: 14

Copyright 2005 by Ando Ki

SystemC signal tracing


 Tracing signal or data member of module
Step 1: create a trace file Step 2: register signals variables to be traced Step 3: close the trace file before returning from sc_main().

Create a trace file named wave.vcd.


sc_trace_file* vcd_tf = sc_create_vcd_trace_file(wave); Trace a signal object sc_trace(vcd_tf, signal_object, string); sc_trace(vcd_tf, some_module.signal_object, string); Trace a signal object in a sc_start(); sub-module sc_close_vcd_trace_file(vcd_tf); Close the trace file
SystemC quick tutorial: 15
Copyright 2005 by Ando Ki

SystemC top-level: sc_main (1/2)


 Every SystemC program must include sc_main() function
sc_main() is called once by the SystemC simulation kernel.

 Two major phases of execution of a SystemC program


Elaboration: module hierarchy is created, processes are registered Simulation
sc_start() marks the end of elaboration and the start of simulation Every process starts to execute at the start of simulation.

Sig_sum clock Sig_A Sig_B

Sig_carry

SystemC quick tutorial: 16

Copyright 2005 by Ando Ki

SystemC top-level: sc_main (2/2)


Clock creation: 10 nano second period
// main.cpp #include "half_adder.h" #include "stimulus.h" int sc_main(int argc, char* argv[]) { sc_clock clock("clock", 10, SC_NS); sc_signal<bool> Sig_A, Sig_B; sc_signal<bool> Sig_sum, Sig_carry; half_adder Uhalf_adder("Uhalf_adder"); Uhalf_adder.In1(Sig_A); Uhalf_adder.In2(Sig_B); Uhalf_adder.Sum(Sig_sum); Uhalf_adder.Carry(Sig_carry); stimulus Ustimulus("Ustimulus"); Ustimulus.clk(clock); Ustimulus.Out1(Sig_A); Ustimulus.Out2(Sig_B); } sc_trace_file* vcd_tf = sc_create_vcd_trace_file("wave"); sc_trace(vcd_tf, clock, "clock"); sc_trace(vcd_tf, Sig_A, "Sig_A"); sc_trace(vcd_tf, Sig_B, "Sig_B"); sc_trace(vcd_tf, Sig_sum, "Sig_sum"); sc_trace(vcd_tf, Sig_carry, "Sig_carry"); sc_start(100, SC_NS); sc_close_vcd_trace_file(vcd_tf); return(0);

Connecting signals Sub-module instantiation and port connection

Start simulation up to 100 nano second Trace file creation and trace registration
SystemC quick tutorial: 17
Copyright 2005 by Ando Ki

Compilation of SystemC program


and.cpp
void and:: do_and() { }

and.h
#include .. SC_MODULE . { };

stimulus.cpp stimulus.h
void stimulus:: do_stimulus() { } #include .. SC_MODULE . { };

xor.cpp
void xor:: do_xor() { }

xor.h
#include .. SC_MODULE . { };

half_adder.h
#include .. #include .. SC_MODULE . { };

main.cpp
#include .. #include .. int sc_main(..) }

GNU C++ compiler


g++ g++ g++ g++

Where SystemC header files reside Compiling each implementation files Final executable, i.e., SystemC simulator

-I/usr/local/SystemC/include -c and.cpp -I/usr/local/SystemC/include -c xor.cpp -I/usr/local/SystemC/include -c stimulus.cpp -I/usr/local/SystemC/include -c main.cpp run.x

g++ -L/usr/local/SystemC/lib-linux -o

and.o xor.o stimulus.o main.o -lsystemc

Where SystemC libraries reside


SystemC quick tutorial: 18
Copyright 2005 by Ando Ki

Running SystemC simulation


 The executable object is a complete SystemC simulator.  Running the executable object means simulation.
g++ -I/usr/local/SystemC/include -c and.cpp g++ -I/usr/local/SystemC/include -c xor.cpp g++ -I/usr/local/SystemC/include -c stimulus.cpp g++ -I/usr/local/SystemC/include -c main.cpp g++ -L/usr/local/SystemC/lib-linux -o run.x and.o xor.o stimulus.o main.o lsystemc ./run.x

Executable object Simulation

SystemC quick tutorial: 19

Copyright 2005 by Ando Ki

Viewing VCD waveform


 Run any VCD display utilities, such as GTKWave.

SystemC quick tutorial: 20

Copyright 2005 by Ando Ki

Compilation using make


 Use UNIX make command to determine automatically which pieces of a large program need to be recompiled, and issue the commands to recompile them.
Specify the platform which is using Specify where SystemC is installed Specify the SystemC libraries reside Specify the SystemC library All implementation files to be compiled Specify the name of executable Specify the rule how to compile Specify the rule how to link all objects

 make command automatically refers to Makefile or makefile.


# A sample Makefile for SystemC example TARGET_ARCH = linux SYSTEMC = /usr/local/SystemC INCDIR = -I$(SYSTEMC)/include LIBDIR = -L$(SYSTEMC)/lib-$(TARGET_ARCH) LIBS = -lsystemc CC = g++ CFLAGS = -c SRCS = and.cpp xor.cpp stimulus.cpp main.cpp OBJS = $(SRCS:.cpp=.o) EXE = run.x .SUFFIXES: .cpp .o .cpp.o: $(CC) $(CFLAGS) $(INCDIR) $< $(EXE): $(OBJS) $(CC) $(LIBDIR) -o $@ $(OBJS) $(LIBS)
Copyright 2005 by Ando Ki

SystemC quick tutorial: 21

All together

SystemC quick tutorial: 22

Copyright 2005 by Ando Ki

Example: half_adder
 This example follows the step explained before.
Step 1: go to your directory
[user@host] cd ~/codes/cpp_class/examples/half_adder [user@host] ls

Step 2: see the codes Step 3: compilation


Run make with Makefile, or Run RunMe.sh or RunMe.csh.

Step 4: run
Run run.x.

[user@host] cd ~/codes/cpp_class/examples/half_adder [user@host] cd ~/codes/cpp_class/examples/half_adder [user@host] ls [user@host] ls [user@host] ./RunMe.sh [user@host] ./RunMe.sh [user@host] run.x [user@host] run.x [user@host] [user@host]

SystemC quick tutorial: 23

Copyright 2005 by Ando Ki

Two examples and three labs


 Ex1: Simple adder example  Ex2: Simple counter example  Ex3: Simple memory example  Lab1: Simple calculator  Lab2: Simplex data protocol -- homework

SystemC quick tutorial: 24

Copyright 2005 by Ando Ki

Ex1: Simple adder example


 This example shows how to compile a SystemC program and how to see the results in waveform fashion.
Step 1: Go to your directory.
[user@host] cd codes/sc_tutorial/examples/adder [user@host] ls

Step Step Step Step

2: 3: 4: 5:

See the codes. Compile. Run. View the waveform.

SystemC quick tutorial: 25

Copyright 2005 by Ando Ki

Ex1: Simple adder - Structure


Block diagram
testbench testbench
op1 op2 sum A B SUM Adder Adder
testbench.cpp testbench.cpp testbench.h testbench.h adder.cpp adder.cpp adder.h adder.h

File hierarchy
systemc.h systemc.h

CLOCK

main.cpp main.cpp

clock clock
 Function: SUM = A + B;  Testbnech: stimulus & monitor & checking  Clock: generating clock signal
SystemC quick tutorial: 26

Makefile Makefile

Copyright 2005 by Ando Ki

Ex1: Simple adder sc_main


// main.cpp #include "adder.h" #include "testbench.h" int sc_main(int argc, char *argv[]) { sc_signal<int> op1, op2, sum; sc_set_time_resolution(1, SC_NS); // V2.0 sc_set_default_time_unit(1, SC_NS); sc_clock CLOCK("clock", 20, 0.5, 25, true); // make ADDER module with named connection adder ADDER("adder"); ADDER.A(op1); ADDER.B(op2); ADDER.SUM(sum); // make TESTBENCH module with positional connection testbench TESTER("tester"); TESTER(op1, op2, sum, CLOCK); // trace file creation sc_trace_file *tf = sc_create_vcd_trace_file("wave"); sc_trace(tf, CLOCK, "clock"); sc_trace(tf, op1, "A"); sc_trace(tf, op2, "B"); sc_trace(tf, sum, "SUM"); sc_start(100, SC_NS); return(0); }

main.cpp

SystemC quick tutorial: 27

Copyright 2005 by Ando Ki

Ex1: Simple adder testbench


testbench.h
// //header headerfor fortestbench testbench // testbench.h // testbench.h #include #include"systemc.h" "systemc.h" SC_MODULE(testbench) SC_MODULE(testbench){{ sc_out<int> sc_out<int>A, A,B; B; sc_in<int> C; sc_in<int> C; sc_in<bool> sc_in<bool>clock; clock; int inttmpA, tmpA,tmpB, tmpB,tmpC; tmpC; void voiddo_test(); do_test(); SC_CTOR(testbench) SC_CTOR(testbench){{ SC_THREAD(do_test); SC_THREAD(do_test); sensitive_pos(clock); sensitive_pos(clock); tmpA tmpA= =0; 0;tmpB tmpB= =100; 100; }} }; };

testbench.cpp
// //module modulefor fortestbench testbench // testbench.cpp // testbench.cpp #include #include"testbench.h" "testbench.h" void voidtestbench::do_test(void) testbench::do_test(void){{ while while(1) (1){{ A = tmpA; A = tmpA; B.write(tmpB); B.write(tmpB); wait(); wait(); tmpC tmpC= =C.read(); C.read(); if (tmpC if (tmpC!= !=(tmpA+tmpB)) (tmpA+tmpB)){{ fprintf(stderr, n", fprintf(stderr,"Error: "Error:%d+%d=%d(?) %d+%d=%d(?) n", tmpA, tmpB, tmpC); tmpA, tmpB, tmpC); }}else else{{ fprintf(stdout, n, fprintf(stdout,%d+%d=%d %d+%d=%d n, tmpA, tmpB, tmpC); tmpA, tmpB, tmpC); }} //wait(); //wait(); tmpA tmpA+= +=3; 3; tmpB += tmpB +=17; 17; }} }}
SystemC quick tutorial: 28
Copyright 2005 by Ando Ki

Ex1: Simple adder adder


adder.h
// //header headerfor foradder addermodule module // //adder.h adder.h #include #include"systemc.h" "systemc.h" SC_MODULE(adder) SC_MODULE(adder){{ sc_in<int> sc_in<int> A, A,B; B; sc_out<int> sc_out<int>SUM; SUM; void voiddo_adder(); do_adder(); SC_CTOR(adder) SC_CTOR(adder){{ SC_METHOD(do_adder); SC_METHOD(do_adder); sensitive(A); sensitive(A); sensitive(B); sensitive(B); }} }; };

adder.cpp
// //module modulefor foradder adder // //adder.cpp adder.cpp #include #include"adder.h" "adder.h" void voidadder::do_adder(void) adder::do_adder(void){{ SUM SUM= =A A+ +B; B; }}

SystemC quick tutorial: 29

Copyright 2005 by Ando Ki

Ex1: Simple adder Compilation


Compilation
[adki@garden] ls [adki@garden] ls Makefile adder.cpp adder.h Makefile adder.cpp adder.h [adki@garden] cat Makefile [adki@garden] cat Makefile TARGET_ARCH = gccsparcOS5 TARGET_ARCH = gccsparcOS5 main.cpp main.cpp testbench.cpp testbench.h testbench.cpp testbench.h

CC g++ CC = = g++ OPT = -O3 OPT = -O3 DEBUG -g DEBUG = = -g OTHER = -Wall OTHER = -Wall CFLAGS $(OPT) $(DEBUG) CFLAGS = = $(OPT)$(OTHER) $(OTHER) $(DEBUG) MODULE run MODULE= = run SRCS = main.cpp testbench.cpp adder.cpp SRCS = main.cpp testbench.cpp adder.cpp OBJS $(SRCS:.cpp=.o) OBJS= = $(SRCS:.cpp=.o) include ../../../Makefile.defs include ../../../Makefile.defs [adki@garden] make [adki@garden] make g++ -O3 -Wall -g -I/usr/local/SystemC/include -c main.cpp g++ -O3 -Wall -g -I/usr/local/SystemC/include -c main.cpp g++ -O3 -Wall -g -I/usr/local/SystemC/include -c testbench.cpp g++ -O3 -Wall -g -I/usr/local/SystemC/include -c testbench.cpp g++ -O3 -Wall -g -I/usr/local/SystemC/include -c adder.cpp g++ -O3 -Wall -g -I/usr/local/SystemC/include -c adder.cpp g++ -O3 -Wall -g -I/usr/local/SystemC/include -L/usr/local/SystemC/lib-gccsparcOS5 -o run.x main.o g++ -O3 -Wall -g -I/usr/local/SystemC/include -L/usr/local/SystemC/lib-gccsparcOS5 -o run.x main.o testbench.o adder.o -lsystemc -lm 2>&1 | c++filt testbench.o adder.o -lsystemc -lm 2>&1 | c++filt [adki@garden] ls [adki@garden] ls Makefile adder.cpp adder.h adder.o main.cpp main.o run.x* Makefile adder.cpp adder.h adder.o main.cpp main.o run.x* testbench.cpp testbench.h testbench.o testbench.cpp testbench.h testbench.o [adki@garden] [adki@garden]

SystemC quick tutorial: 30

Copyright 2005 by Ando Ki

Ex1: Simple adder Running


Running & Checking waveform
[adki@garden] ls [adki@garden] ls Makefile* adder.cpp adder.h adder.o Makefile* adder.cpp adder.h adder.o testbench.cpp testbench.h testbench.o testbench.cpp testbench.h testbench.o [adki@garden] run.x [adki@garden] run.x main.cpp main.cpp main.o main.o run.x* run.x*

SystemC 2.0 --- Oct 22 2001 09:50:16 SystemC 2.0 --- Oct 22 2001 09:50:16 Copyright (c) 1996-2001 by all Contributors Copyright (c) 1996-2001 by all Contributors ALL RIGHTS RESERVED ALL RIGHTS RESERVED WARNING: Default time step is used for VCD tracing. WARNING: Default time step is used for VCD tracing. 0+100=100 0+100=100 3+117=120 3+117=120 6+134=140 6+134=140 9+151=160 9+151=160 12+168=180 12+168=180 [adki@garden] ls [adki@garden] ls Makefile adder.cpp adder.h adder.o main.cpp Makefile adder.cpp adder.h adder.o main.cpp testbench.cpp testbench.h testbench.o wave.vcd testbench.cpp testbench.h testbench.o wave.vcd [adki@garden] winwave wave.vcd & [adki@garden] winwave wave.vcd & [adki@garden] [adki@garden]

main.o main.o

run.x* run.x*

SystemC quick tutorial: 31

Copyright 2005 by Ando Ki

Ex1: Simple adder Waveform


Initial window

SystemC quick tutorial: 32

Copyright 2005 by Ando Ki

Ex1: Simple adder Waveform


Selecting signals to view

SystemC quick tutorial: 33

Copyright 2005 by Ando Ki

Ex1: Simple adder Waveform


Simulated waveform

SystemC quick tutorial: 34

Copyright 2005 by Ando Ki

Ex1: Simple adder Waveform


Exiting GTKwave

SystemC quick tutorial: 35

Copyright 2005 by Ando Ki

Ex2: Count example


 This example shows how to compile a SystemC program and how to see the results in waveform fashion.
Step 1: Go to your directory.
[user@host] cd codes/sc_tutorial/examples/count [user@host] ls

Step Step Step Step

2: 3: 4: 5:

See the codes. Compile. Run. View the waveform.

SystemC quick tutorial: 36

Copyright 2005 by Ando Ki

Ex2: Count example


reset test go value clk CLK count

SystemC quick tutorial: 37

Copyright 2005 by Ando Ki

Ex2: count module


reset go value clk

count count do_count do_count


local_value

ports

constructor

1 // count.h 2 #include "systemc.h" 3 4 SC_MODULE(count) { 5 sc_in <bool> clk, reset, go; 6 sc_out<char> value; 7 8 void do_count(); process 9 unsigned char local_value; function data member 10 11 SC_CTOR(count) { 12 SC_METHOD(do_count); process 13 sensitive << reset << go << clk.pos(); sensitivity registration 14 local_value = 0; list 15 value.initialize(0); 16 } initialization 17 };
SystemC quick tutorial: 38

1 // count.cpp 2 #include "count.h" 3 4 void count::do_count() { 5 if (reset.read()) local_value = 0; 6 else if (go.read()) { 7 if (clk.posedge()) { 8 local_value++; 9 cout << "[" << sc_simulation_time() 10 << "] << (unsigned short)local_value 11 << endl; 12 } 13 } 14 value.write(local_value); 15 }

Copyright 2005 by Ando Ki

Ex2: test module


test test do_test do_test
reset go value clk
1 // test.cpp 2 #include "test.h" 3 4 void test::do_test() { 5 wait(); 6 reset.write(0); 7 wait(); 8 while (true) { 9 go.write(1); 10 wait(5); 11 go.write(0); 12 wait(2); 13 } 14 }

1 // test.h 2 #include "systemc.h" 3 4 SC_MODULE(test) { 5 sc_in <bool> clock; 6 sc_out<bool> reset, go; 7 sc_in <char> value; 8 9 void do_test(); 10 11 SC_CTOR(test) { 12 SC_CTHREAD(do_test, clock.neg()); 13 reset.initialize(1); 14 go.initialize(0); 15 } 16 };

Infinite loop

clk go

SystemC quick tutorial: 39

Copyright 2005 by Ando Ki

Ex2: Top-level
1 // main.cc 2 #include "count.h" Include module header 3 #include "test.h" files 4 5 int sc_main(int argc, char** argv) { Signals to connect 6 sc_signal<char> value; ports of modules 7 sc_signal<bool> reset, go; 8 make count 9 sc_clock CLK("clock", 10, SC_NS); Make clock 10 module with 11 count CNT("CNT"); named 12 CNT.clk(CLK); CNT.reset(reset); CNT.go(go); CNT.value(value); connection 13 14 test TST("TST"); 15 TST(CLK, reset, go, value); make test module with 16 positional connection 17 sc_trace_file *tf = sc_create_vcd_trace_file("wave"); 18 ((vcd_trace_file*)tf)->sc_set_vcd_time_unit(-9); Trace file creation: 19 sc_trace(tf, CLK, "clock"); sc_trace(tf, reset, "reset"); VCD format in 20 sc_trace(tf, go, "go"); sc_trace(tf, value, "value"); wave.vcd file 21 sc_trace(tf, CNT.local_value, "CNT.local_value"); 22 23 sc_start(200, SC_NS); Specify signals to be Run simulation 24 sc_close_vcd_trace_file(tf); monitored 25 return(0); Close trace file 26 }
SystemC quick tutorial: 40

Copyright 2005 by Ando Ki

Ex2: Makefile
# Makefile CC = g++ OPT = -O3 DEBUG = -g OTHER = -Wall -Wno-deprecated CFLAGS = $(OPT) $(OTHER) $(DEBUG) MODULE = run SRCS = main.cpp count.cpp test.cpp OBJS = $(SRCS:.cpp=.o) include ./Makefile.defs

Specify which file to compile Specify platform


## Makefile.defs TARGET_ARCH = cygwin # linux gccsparcOS5 SYSTEMC = /usr/local/SystemC INCDIR = -I$(SYSTEMC)/include LIBDIR = -L$(SYSTEMC)/lib-$(TARGET_ARCH) LIBS = -lsystemc -lm $(EXTRA_LIBS) EXE = $(MODULE).x .SUFFIXES: .cc .cpp .o .x $(EXE): $(OBJS) $(CC) $(CFLAGS) $(INCDIR) $(LIBDIR) -o $@ $(OBJS) $(LIBS) 2>&1 | c++filt .cpp.o: $(CC) $(CFLAGS) $(INCDIR) -c $< .cc.o: $(CC) $(CFLAGS) $(INCDIR) -c $<

Specify SystemC package

SystemC quick tutorial: 41

Copyright 2005 by Ando Ki

Ex2: Compilation

SystemC quick tutorial: 42

Copyright 2005 by Ando Ki

Ex2: Simulation

SystemC quick tutorial: 43

Copyright 2005 by Ando Ki

Ex2: Waveform

SystemC quick tutorial: 44

Copyright 2005 by Ando Ki

Ex2: Simple memory example


 This example shows how SystemC program looks like and how to run it.
Step 1: Go to your directory.
[user@host] cd ~/codes/SC_tutorial/examples/memory [user@host] ls

Step 2: Examine the codes. Step 3: Compile the design. run.x is generated.
For your convenience, Makefile, RunMe.csh, and RunMe.sh are given. Run either RunMe.csh or RunMe.sh depending on your shell.

Step 4: Run run.x. Step 5: View the waveform generated by run.x.

SystemC quick tutorial: 45

Copyright 2005 by Ando Ki

Ex3: Simple memory - Structure


Block diagram
memory memory
enable address

File hierarchy
systemc.h systemc.h ram.cpp ram.cpp ram.h ram.h

decoder decoder
selected
testbench.cpp testbench.cpp testbench.h testbench.h memory.cpp memory.cpp memory.h memory.h

rdwr we data

ram ram

main.cpp main.cpp

Makefile Makefile

SystemC quick tutorial: 46

Copyright 2005 by Ando Ki

Ex3: Simple memory - Memory


memory.h
#include #include"systemc.h" "systemc.h" #include #include"ram.h" "ram.h" SC_MODULE(memory) SC_MODULE(memory){{ sc_in<int> address; sc_in<int> address; sc_in<bool> enable, sc_in<bool> enable,rdwr, rdwr,we; we; sc_inout_rv<16> data; sc_inout_rv<16> data; ram* ram* RAM; RAM; SC_METHOD(do_decoder); SC_METHOD(do_decoder); sensitive sensitive<< <<address address<< <<enable; enable; selected = 0; selected = 0; }} }; };

memory.cpp
#include #include"memory.h "memory.h void voidmemory:: memory:: do_decoder() do_decoder(){{ if if(enable) (enable){{ int inttmp tmp= =address.read(); address.read(); if (0<=tmp if (0<=tmp&& &&tmp<256) tmp<256) selected.write(1); selected.write(1); else elseselected.write(0); selected.write(0); }}else elseselected.write(0); selected.write(0); }}

sc_signal<bool> sc_signal<bool>selected; selected; void voiddo_decoder(); do_decoder(); SC_CTOR(memory) SC_CTOR(memory){{ RAM RAM= =new newram("R"); ram("R"); RAM->address(address); RAM->address(address); RAM->enable(selected); RAM->enable(selected); RAM->rdwr(rdwr); RAM->rdwr(rdwr); RAM->we(we); RAM->we(we); RAM->data(data); RAM->data(data);

SystemC quick tutorial: 47

Copyright 2005 by Ando Ki

Ex3: Simple memory - ram


ram.h
#include #include"systemc.h" "systemc.h" SC_MODULE(ram) SC_MODULE(ram){{ sc_in<int> sc_in<int> address; address; sc_in<bool> sc_in<bool> enable; enable; sc_in<bool> sc_in<bool> rdwr; rdwr; sc_in<bool> sc_in<bool> we; we; sc_inout_rv<16> sc_inout_rv<16>data; data; sc_lv<16> sc_lv<16>ram_data[256]; ram_data[256]; void voiddo_ram(); do_ram(); SC_CTOR(ram) SC_CTOR(ram){{ SC_METHOD(do_ram); SC_METHOD(do_ram); sensitive sensitive<< <<address address<< <<enable; enable; sensitive << rdwr << we << sensitive << rdwr << we <<data; data; for for(int (inti=0; i=0;i<256; i<256;i++) i++) ram_data[i] ram_data[i]= ="XXXXXXXXXXXXXXX"; "XXXXXXXXXXXXXXX"; }} }; };
Note: unknown value assignment SystemC quick tutorial: 48

ram.cpp
#include #include"ram.h" "ram.h" void voidram:: ram:: do_ram() do_ram(){{ if Note: positive edge if(enable) (enable){{ detection if (rdwr) { // read if (rdwr) { // read data.write( data.write( ram_data[address.read()] ram_data[address.read()] ); ); }}else elseif if(we.posedge()) (we.posedge()){{// //write write ram_data[address] = data; ram_data[address] = data; }} }}else else{{ data data= ="ZZZZZZZZZZZZZZZZ"; "ZZZZZZZZZZZZZZZZ"; }} }}
Note: high-impedance value assignment

Copyright 2005 by Ando Ki

Ex3: Simple memory sc_main


main.cpp
#include #include"memory.h" "memory.h" #include #include"testbench.h" "testbench.h" int intsc_main(int sc_main(intargc, argc,char char*argv[]) *argv[]){{ sc_signal<int> add; sc_signal<int> add; sc_signal<bool> en; sc_signal<bool> en; sc_signal<bool> sc_signal<bool> rw; rw; sc_signal<bool> sc_signal<bool> we; we; sc_signal_rv<16> sc_signal_rv<16>data; data; sc_set_time_resolution(1, sc_set_time_resolution(1,SC_NS); SC_NS); sc_set_default_time_unit(1, sc_set_default_time_unit(1,SC_NS); SC_NS); sc_clock CLOCK("clock", 10, 0.5, sc_clock CLOCK("clock", 10, 0.5,5, 5,true); true); // //make makeMEMORY MEMORYmodule modulewith withnamed named // connection // connection memory memoryMEMORY("memory"); MEMORY("memory"); MEMORY.address(add); MEMORY.address(add); MEMORY.enable(en); MEMORY.enable(en); MEMORY.rdwr(rw); MEMORY.rdwr(rw); MEMORY.we(we); MEMORY.we(we); MEMORY.data(data); MEMORY.data(data); // //make makeTESTBENCH TESTBENCHmodule modulewith with // positional connection // positional connection testbench testbenchTESTER("tester"); TESTER("tester"); TESTER(add, TESTER(add,en, en,rw, rw,we, we,data, data,CLOCK); CLOCK); // //trace tracefile filecreation creation sc_trace_file sc_trace_file*tf *tf= = sc_create_vcd_trace_file( sc_create_vcd_trace_file( "wave"); "wave"); sc_trace(tf, sc_trace(tf,CLOCK, CLOCK,"clock"); "clock"); sc_trace(tf, add, sc_trace(tf, add, "AD"); "AD"); sc_trace(tf, Note how to sc_trace(tf,en, en, "EN"); "EN"); sc_trace(tf, rw, "RW"); select signals in sc_trace(tf, rw, "RW"); sc_trace(tf, we, "WE"); the sub-module. sc_trace(tf, we, "WE"); sc_trace(tf, sc_trace(tf,data, data, "DA"); "DA"); sc_trace(tf, MEMORY.selected, sc_trace(tf, MEMORY.selected,"SEL"); "SEL"); sc_start(600, sc_start(600,SC_NS); SC_NS); sc_close_vcd_trace_file(tf); sc_close_vcd_trace_file(tf); return(0); return(0); }}

SystemC quick tutorial: 49

Copyright 2005 by Ando Ki

Ex3: Simple memory testbench


testbench.h
#include #include"systemc.h" "systemc.h" SC_MODULE(testbench) SC_MODULE(testbench){{ sc_out<int> add; sc_out<int> add; sc_out<bool> en; sc_out<bool> en; sc_out<bool> rw; sc_out<bool> rw; sc_out<bool> we; sc_out<bool> we; sc_inout_rv<16> sc_inout_rv<16>data; data; sc_in<bool> clock; sc_in<bool> clock; void voiddo_test(); do_test(); SC_CTOR(testbench) SC_CTOR(testbench){{ SC_CTHREAD(do_test, SC_CTHREAD(do_test,clock.pos()); clock.pos()); }} private: private: int int read_cycle(int); read_cycle(int); void voidwrite_cycle(int, write_cycle(int,int); int); }; }; #include #includetestbench.h testbench.h testbench.cpp void voidtestbench:: testbench:: do_test() do_test(){{ int inti,i,j, j,flag, flag,tmpA, tmpA,tmpDW, tmpDW,tmpDR; tmpDR; for for(j=0; (j=0;1; 1;j++) j++){{ flag flag= =0; 0; wait(2); wait(2); tmpA tmpA= =1; 1;tmpDW tmpDW= =123; 123; for (i=0; i<3; i++) for (i=0; i<3; i++) read_cycle(tmpA+i+j); read_cycle(tmpA+i+j); for (i=0; for (i=0;i<3; i<3;i++) i++) write_cycle(tmpA+i+j, write_cycle(tmpA+i+j, tmpDW+i+j); tmpDW+i+j); for for(i=0; (i=0;i<3; i<3;i++) i++){{ tmpDR = read_cycle(tmpA+i+j); tmpDR = read_cycle(tmpA+i+j); if if(tmpDR (tmpDR!= !=(tmpDW+i+j)) (tmpDW+i+j)){{ fprintf(stderr, fprintf(stderr,"Error: "Error:expeced expeced0x%x, 0x%x, but 0x%x n", tmpDW+i+j, but 0x%xn", tmpDW+i+j,tmpDR); tmpDR); flag flag= =1; 1; }} }} if n"); if(!flag) (!flag)fprintf(stderr, fprintf(stderr,"Test "Testpassed passed... ... n");
Copyright 2005 by Ando Ki

}} }} SystemC quick tutorial: 50

Ex3: Simple memory testbench


testbench.cpp
int inttestbench:: testbench:: read_cycle(int read_cycle(intiadd) iadd){{ int tmp; int tmp; add.write(iadd); add.write(iadd); en.write(1); en.write(1); rw.write(1); rw.write(1); we.write(0); we.write(0); wait(2); wait(2); tmp tmp= =data.read().to_int(); data.read().to_int(); wait(1); wait(1); add.write(0); add.write(0); en.write(0); en.write(0); wait(1); wait(1); return returntmp; tmp; }} void voidtestbench:: testbench:: write_cycle(int write_cycle(intiadd, iadd,int intidata) idata){{ add.write(iadd); add.write(iadd); en.write(1); en.write(1); rw.write(0); rw.write(0); we.write(0); we.write(0); data.write(idata); data.write(idata); wait(1); wait(1); we.write(1); we.write(1); wait(1); wait(1); add.write(0); add.write(0); en.write(0); en.write(0); rw.write(1); rw.write(1); data.write("ZZZZZZZZZZZZZZZZ"); data.write("ZZZZZZZZZZZZZZZZ"); wait(1); wait(1); }}

enable address[] rdwr we data[]

SystemC quick tutorial: 51 READ WRITE

Copyright 2005 by Ando Ki

Ex3: Simple memory compilation


Makefile
# #Makefile Makefile CC CC = =g++ g++ OPT = -O3 OPT = -O3 DEBUG DEBUG = =-g -g OTHER = OTHER =-Wall -Wall CFLAGS CFLAGS = =$(OPT) $(OPT)$(OTHER) $(OTHER)$(DEBUG) $(DEBUG) MODULE MODULE = =run run SRCS = main.cpp SRCS = main.cppmemory.cpp memory.cpp ram.cpp testbench.cpp ram.cpp testbench.cpp OBJS OBJS = =$(SRCS:.cpp=.o) $(SRCS:.cpp=.o) include include../../../Makefile.defs ../../../Makefile.defs

Compilation & running


[adki@oarchard] cd ~/Lecture/codes/SC_tutorial/examples/memory [adki@oarchard] cd ~/Lecture/codes/SC_tutorial/examples/memory [adki@orchard] ls [adki@orchard] ls GNUmakefile main.cpp memory.cpp memory.h ram.cpp ram.h GNUmakefile main.cpp memory.cpp memory.h ram.cpp ram.h testbench.cpp testbench.h testbench.cpp testbench.h [adki@orchard] make [adki@orchard] make g++ -O3 -Wall -g -I/usr/local/SystemC/include -c main.cpp g++ -O3 -Wall -g -I/usr/local/SystemC/include -c main.cpp g++ -O3 -Wall -g -I/usr/local/SystemC/include -c memory.cpp g++ -O3 -Wall -g -I/usr/local/SystemC/include -c memory.cpp g++ -O3 -Wall -g -I/usr/local/SystemC/include -c ram.cpp g++ -O3 -Wall -g -I/usr/local/SystemC/include -c ram.cpp g++ -O3 -Wall -g -I/usr/local/SystemC/include -L/usr/local/SystemC/libg++ -O3 -Wall -g -I/usr/local/SystemC/include -L/usr/local/SystemC/libgccsparcOS5 -o run.x main.o memory.o ram.o -lsystemc -lm 2>&1 | gccsparcOS5 -o run.x main.o memory.o ram.o -lsystemc -lm 2>&1 | c++filt c++filt [adki@orchard] ls [adki@orchard] ls GNUmakefile main.cpp main.o memory.cpp memory.h GNUmakefile main.cpp main.o memory.cpp memory.h memory.o ram.cpp ram.h memory.o ram.cpp ram.h ram.o run.x* testbench.cpp testbench.h ram.o run.x* testbench.cpp testbench.h [adki@orchard] run.x [adki@orchard] run.x SystemC 2.0 --- Feb 5 2002 19:32:52 SystemC 2.0 --- Feb 5 2002 19:32:52 Copyright (c) 1996-2001 by all Contributors Copyright (c) 1996-2001 by all Contributors ALL RIGHTS RESERVED ALL RIGHTS RESERVED WARNING: Default time step is used for VCD tracing. WARNING: Default time step is used for VCD tracing. Test passed ... Test passed ... [adki@orchard] ls [adki@orchard] ls GNUmakefile main.cpp main.o memory.cpp GNUmakefile main.cpp main.o memory.cpp memory.o ram.cpp ram.h ram.o run.x* memory.o ram.cpp ram.h ram.o run.x* testbench.cpp testbench.h wave.vcd testbench.cpp testbench.h wave.vcd [adki@orchard] gtkwave wave.vcd & [adki@orchard] gtkwave wave.vcd & [3] 12311 [3] 12311 [adki@orchard] [adki@orchard] memory.h memory.h

Before running make, TARGET_ARCH macro in ../../Makefile.defs must be appropriate one. For example, cygwin for Cygwin on top of Windows.

SystemC quick tutorial: 52

Copyright 2005 by Ando Ki

Lab 1: Simple calculator - Structure


Block diagram
testbench testbench
cmd op1 op2 result cmd op1 op2

File hierarchy
engine engine
result
testbench.cpp testbench.cpp testbench.h testbench.h engine.cpp engine.cpp engine.h engine.h systemc.h systemc.h

CLOCK

main.cpp main.cpp

Makefile Makefile

clock clock
 Engine performs binary operation cmd on op1 and op2.  cmd includes addition (+), subtraction (-), multiplication (x), division (/).  Testbnech: stimulus & monitor & checking

SystemC quick tutorial: 53

Copyright 2005 by Ando Ki

Lab 1: Simple calculator Design Steps


 This lab introduces the process of making a module of the simple calculator example.  Follow the following steps:
Make an engine module consisting of engine.h and engine.cpp. Make it Run it Invoke waveform viewer

[user@host] [user@host]cd cd~/codes/SC_tutorial/labs ~/codes/SC_tutorial/labs [user@host] [user@host]cd cdcalculator calculator [user@host] [user@host]vi viengine.h engine.h [user@host] vi [user@host] viengine.cpp engine.cpp [user@host] [user@host]make make [user@host] [user@host]run.x run.x [user@host] [user@host]gtkwave gtkwavewave.vcd wave.vcd& &
SystemC quick tutorial: 54
Copyright 2005 by Ando Ki

Lab 1: Simple calculator sc_main


main.cpp
// //main.cpp main.cpp #include #include"engine.h" "engine.h" #include #include"testbench.h" "testbench.h" int intsc_main(int sc_main(intargc, argc,char char*argv[]) *argv[]){{ sc_signal<int> cmd; sc_signal<int> cmd; sc_signal<float> sc_signal<float>op1, op1,op2, op2,result; result; sc_set_time_resolution(1, sc_set_time_resolution(1,SC_NS); SC_NS);// //V2.0 V2.0 sc_set_default_time_unit(1, sc_set_default_time_unit(1,SC_NS); SC_NS); sc_clock sc_clockCLOCK("clock", CLOCK("clock",20, 20,0.5, 0.5,25, 25,true); true); // //make makeENGINE ENGINEmodule module engine ENGINE("engine"); engine ENGINE("engine"); ENGINE(cmd, ENGINE(cmd,op1, op1,op2, op2,result); result); // //make makeTESTBENCH TESTBENCHmodule module testbench TEST("test"); testbench TEST("test"); TEST(CLOCK, TEST(CLOCK,cmd, cmd,op1, op1,op2, op2,result); result); // trace file creation sc_trace_file *tf = sc_create_vcd_trace_file("wave"); sc_trace(tf, CLOCK, "clock"); sc_trace(tf, cmd, "cmd"); sc_trace(tf, op1, "op1"); sc_trace(tf, op2, "op2"); sc_trace(tf, result, "result"); sc_start(200, SC_NS); return(0); }

SystemC quick tutorial: 55

Copyright 2005 by Ando Ki

Lab 1: Simple calculator (4/6)


testbench.h
// //header headerfor fortestbench testbench // // #ifndef #ifndefTESTBENCH_H TESTBENCH_H # define # defineTESTBENCH_H TESTBENCH_H #include #include"systemc.h" "systemc.h" #include #include"engine.h" "engine.h" SC_MODULE(testbench) SC_MODULE(testbench){{ sc_in<bool> sc_in<bool> clock; clock; sc_out<int> sc_out<int> cmd; cmd; sc_out<float> sc_out<float>operand1; operand1; sc_out<float> sc_out<float>operand2; operand2; sc_in<float> sc_in<float> result; result; void voiddo_test(); do_test(); SC_CTOR(testbench) SC_CTOR(testbench){{ SC_CTHREAD(do_test, SC_CTHREAD(do_test, clock.neg()); clock.neg()); }} }; }; #endif #endif

testbench.cpp
#include #include"testbench.h" "testbench.h" void voidtestbench::do_test() testbench::do_test(){{ float floatA, A,B, B,C; C; A = 15.0; A = 15.0;B B= =5.0; 5.0; while (1) { while (1) { wait(); wait(); cmd.write(ADD); cmd.write(ADD); operand1.write(A); operand1.write(A); operand2.write(B); operand2.write(B); wait(); wait(); C C= =result.read(); result.read(); if (C!=(A+B)) n", if (C!=(A+B))printf("Error: printf("Error:%f+%f=%f(?) %f+%f=%f(?) n",A, A,B, B,C); C); else printf("Addition: %f+%f=%f n", A, B, C); else printf("Addition: %f+%f=%fn", A, B, C); //--------//--------cmd.write(SUB); cmd.write(SUB);operand1.write(A); operand1.write(A);operand2.write(B); operand2.write(B); wait(); wait(); C C= =result.read(); result.read(); if (C!=(A-B)) n", if (C!=(A-B))printf("Error: printf("Error:%f-%f=%f(?) %f-%f=%f(?) n",A, A,B, B,C); C); else n", elseprintf("Subtraction: printf("Subtraction:%f+%f=%f %f+%f=%f n",A, A,B, B,C); C); :: ::

SystemC quick tutorial: 56

Copyright 2005 by Ando Ki

Lab 1: Simple calculator (5/6)


testbench.h
// //header headerfor fortestbench testbench // // #ifndef #ifndefTESTBENCH_H TESTBENCH_H # define # defineTESTBENCH_H TESTBENCH_H #include #include"systemc.h" "systemc.h" #include #include"engine.h" "engine.h" SC_MODULE(testbench) SC_MODULE(testbench){{ sc_in<bool> sc_in<bool> clock; clock; sc_out<int> sc_out<int> cmd; cmd; sc_out<float> sc_out<float>operand1; operand1; sc_out<float> sc_out<float>operand2; operand2; sc_in<float> sc_in<float> result; result; void voiddo_test(); do_test(); SC_CTOR(testbench) SC_CTOR(testbench){{ SC_CTHREAD(do_test, SC_CTHREAD(do_test, clock.neg()); clock.neg()); }} }; }; #endif #endif

testbench.cpp

:: :: //--------//--------cmd.write(MUL); cmd.write(MUL);operand1.write(A); operand1.write(A);operand2.write(B); operand2.write(B); wait(); wait(); C C= =result.read(); result.read(); if (C!=(A*B)) n", if (C!=(A*B))printf("Error: printf("Error:%f*%f=%f(?) %f*%f=%f(?) n",A, A,B, B,C); C); else printf("Multiplication: %f*%f=%f n", A, B, C); else printf("Multiplication: %f*%f=%fn", A, B, C); //--------//--------cmd.write(DIV); cmd.write(DIV); operand1.write(A); operand1.write(A);operand2.write(B); operand2.write(B); wait(); wait(); C C= =result.read(); result.read(); if (C!=(A/B)) n", if (C!=(A/B))printf("Error: printf("Error:%f/%f=%f(?) %f/%f=%f(?) n",A, A,B, B,C); C); else printf("Division: %f/%f=%f n", A, B, C); else printf("Division: %f/%f=%fn", A, B, C);

}} }}

SystemC quick tutorial: 57

Copyright 2005 by Ando Ki

Lab 1: Simple calculator (6/6)


 Tips for engine.h
Input ports: cmd, op1, op2 and clock
Note: cmd is int, op1 and op2 are float.

Output ports: result The process should be SC_METHOD.


Note: sensitive with cmd, op1, op2.

SystemC quick tutorial: 58

Copyright 2005 by Ando Ki

Lab 2: Simplex data protocol


 The simplex data protocol is a simple data protocol used to transfer data from one device to another in a single direction.  Refer to SystemC Users Guide Version 2.0 Chapter 2.  Primary objectives
Understanding a SystemC system. Understanding the processor SystemC modeling and simulation.

 What to do:
Coding Compilation Simulation

SystemC quick tutorial: 59

Copyright 2005 by Ando Ki

Lab 2: Simplex data protocol Block diagram


timer timer
clock

Structure
display display
clock

transmit transmit
clock

channel channel
clock

receive receive
clock

clock clock

SystemC quick tutorial: 60

Copyright 2005 by Ando Ki

Session summary
 SystemC module creation  SystemC signal tracing  SystemC program compilation

SystemC quick tutorial: 61

Copyright 2005 by Ando Ki

Note

SystemC quick tutorial: 62

Copyright 2005 by Ando Ki

Note

SystemC quick tutorial: 63

Copyright 2005 by Ando Ki

Note

SystemC quick tutorial: 64

Copyright 2005 by Ando Ki