ppt

advertisement

CPE 626

The SystemC Language

Aleksandar Milenkovic

E-mail: milenka@ece.uah.edu

Web: http://www.ece.uah.edu/~milenka

Outline

 Motivation for SystemC

 What is SystemC?

 Modules

 Processes

A. Milenkovic 2

Standard Methodology for ICs

 System-level designers write a

C or C++ model

 Written in a stylized, hardware-like form

 Sometimes refined to be more hardware-like

 C/C++ model simulated to verify functionality

 Parts of the model to be implemented in hardware are given to Verilog/VHDL coders

 Verilog or VHDL specification written

 Models simulated together to test equivalence

 Verilog/VHDL model synthesized

A. Milenkovic 3

Designing Big Digital Systems

 Current conditions

 Every system company was doing this differently

 Every system company used its own simulation library

 System designers don’t know Verilog or VHDL

 Verilog or VHDL coders don’t understand system design

 Problems with standard methodology:

 Manual conversion from C to HDL o Error prone and time consuming

 Disconnect between system model and HDL model o C model becomes out of date as changes are made only to the HDL model

 System testing o Tests used for C model cannot be run against HDL model => they have to be converted to the HDL environment

A. Milenkovic 4

Idea of SystemC

 C and C++ are being used as ad-hoc modeling languages

 Why not formalize their use?

 Why not interpret them as hardware specification languages just as Verilog and VHDL were?

 SystemC developed at Synopsys to do just this

A. Milenkovic 5

SystemC Design Methodology

 Refinement methodology

 Design is slowly refined in small sections to add necessary hardware and timing constructs

 Written in a single language

 higher productivity due to modeling at a higher level

 testbenches can be reused saving time

 Future releases will have constructs to model RTOS

A. Milenkovic 6

What Is SystemC?

 A subset of C++ that models/specifies synchronous digital hardware

 A collection of simulation libraries that can be used to run a SystemC program

 A compiler that translates the “synthesis subset” of SystemC into a netlist

A. Milenkovic 7

What Is SystemC?

 Language definition is publicly available

 Libraries are freely distributed

 Compiler is an expensive commercial product

 See www.systemc.org for more information

A. Milenkovic 8

Quick Overview

 A SystemC program consists of module definitions plus a top-level function that starts the simulation

 Modules contain processes (C++ methods) and instances of other modules

 Ports on modules define their interface

 Rich set of port data types (hardware modeling, etc.)

 Signals in modules convey information between instances

 Clocks are special signals that run periodically and can trigger clocked processes

 Rich set of numeric types

(fixed and arbitrary precision numbers)

A. Milenkovic 9

Modules

 Hierarchical entity

 Similar to Verilog’s module

 Actually a C++ class definition

 Simulation involves

 Creating objects of this class

 They connect themselves together

 Processes in these objects (methods) are called by the scheduler to perform the simulation

A. Milenkovic 10

Modules

SC_MODULE(mymod) { // struct mymod : sc_module {

/* port definitions */

/* signal definitions */

/* clock definitions */

/* storage and state variables */

/* process definitions */

};

}

SC_CTOR(mymod) {

/* Instances of processes and modules */

A. Milenkovic 11

Ports

 Define the interface to each module

 Channels through which data is communicated

 Port consists of a direction

 input sc_in

 output sc_out

 bidirectional sc_inout

 and any C++ or

SystemC type

SC_MODULE(mymod) { sc_in<bool> load, read; sc_inout<int> data; sc_out<bool> full;

};

/* rest of the module */

A. Milenkovic 12

Signals

 Convey information between modules within a module

 Directionless: module ports define direction of data transfer

 Type may be any C++ or built-in type

SC_MODULE(mymod) {

/* port definitions */ sc_signal<sc_uint<32> > s1, s2; sc_signal<bool> reset;

*/

}

/* … */

SC_CTOR(mymod) {

/* Instances of modules that connect to the signals

};

A. Milenkovic 13

Instances of Modules

 Each instance is a pointer to an object in the module

Connect instance’s ports to signals

SC_MODULE(mod1) { … };

SC_MODULE(mod2) { … };

SC_MODULE(foo) { mod1* m1; mod2* m2; sc_signal<int> a, b, c;

};

}

SC_CTOR(foo) { m1 = new mod1(“i1”); (*m1)(a, b, c); m2 = new mod2(“i2”); (*m2)(c, b);

A. Milenkovic 14

Positional Connection

// filter.h

#include "systemc.h“ // systemC classes

#include "mult.h“ // decl. of mult

#include "coeff.h“ // decl. of coeff

#include "sample.h“ // decl. of sample

SC_MODULE(filter) { sample *s1; // pointer declarations coeff *c1; mult *m1;

// signal declarations sc_signal<sc_uint<32> > q, s, c;

SC_CTOR(filter) { // constructor s1 = new sample ("s1"); // create obj.

(*s1)(q,s); // signal mapping c1 = new coeff ("c1");

(*c1)(c); m1 = new mult ("m1");

(*m1)(s,c,q);

}

}

A. Milenkovic 15

Named Connection

#include "systemc.h“ // systemC classes

#include "mult.h“ // decl. of mult

#include "coeff.h“ // decl. of coeff

#include "sample.h“ // decl. of sample

SC_MODULE(filter) { sample *s1; coeff *c1; mult *m1; sc_signal<sc_uint<32> > q, s, c;

SC_CTOR(filter) { s1 = new sample ("s1"); s1->din(q); // din of s1 to signal q s1->dout(s); // dout to signal s c1 = new coeff ("c1"); c1->out(c); // out of c1 to signal c m1 = new mult ("m1"); m1->a(s); // a of m1 to signal s m1->b(c); // b of m1 to signal c m1->q(q); // q of m1 to signal c

}

}

A. Milenkovic 16

Internal Data Storage

 Local variables to store data within a module

 May be of any legal C++, SystemC, or user-defined type

 Not visible outside the module unless it is made explicitly

// count.h

#include "systemc.h"

SC_MODULE(count) { sc_in<bool> load; sc_in<int> din; // input port sc_in<bool> clock; // input port sc_out<int> dout; // output port int count_val; // internal data storage void count_up();

SC_CTOR(count) {

SC_METHOD(count_up); //Method process sensitive_pos << clock;

}

};

// count.cc

#include "count.h" void count::count_up() { if (load) { count_val = din;

} else {

}

// could be count_val++ count_val = count_val + 1;

} dout = count_val;

A. Milenkovic 17

Processes

 Only thing in SystemC that actually does anything

 Functions identified to the SystemC kernel and called whenever signals these processes are sensitive to change value

 Statements are executed sequentially until the end of the process occurs, or the process is suspended using wait function

 Very much like normal C++ methods

+ Registered with the SystemC kernel

 Like Verilog’s initial blocks

A. Milenkovic 18

Processes (cont’d)

 Processes are not hierarchical

 no process can call another process directly

 can call other methods and functions that are not processes

 Have sensitivity lists

 signals that cause the process to be invoked, whenever the value of a signal in this list changes

 Processes cause other processes to execute by assigning new values to signals in the sensitivity lists of the processes

 To trigger a process, a signal in the sensitivity list of the process must have an event occur

A. Milenkovic 19

Three Types of Processes

Determines how the process is called and executed

 METHOD

 Models combinational logic

 THREAD

 Models testbenches

 CTHREAD

 Models synchronous FSMs

A. Milenkovic 20

METHOD Processes

 Triggered in response to changes on inputs

 Cannot store control state between invocations

 Designed to model blocks of combinational logic

A. Milenkovic 21

METHOD Processes

SC_MODULE(onemethod) { sc_in<bool> in; sc_out<bool> out; void inverter();

SC_CTOR(onemethod) {

SC_METHOD(inverter); sensitive(in);

};

}

A. Milenkovic

Process is simply a method of this class

Instance of this process created and made sensitive to an input

22

METHOD Processes

 Invoked once every time input “in” changes

 Should not save state between invocations

 Runs to completion: should not contain infinite loops

 Not preempted void onemethod::inverter() { bool internal; internal = in; out = ~internal;

}

Read a value from the port

Write a value to an output port

A. Milenkovic 23

THREAD Processes

 Triggered in response to changes on inputs

 Can suspend itself and be reactivated

 Method calls wait() function that suspends process execution

 Scheduler runs it again when an event occurs on one of the signals the process is sensitive to

 Designed to model just about anything

A. Milenkovic 24

THREAD Processes

SC_MODULE(onemethod) { sc_in<bool> in; sc_out<bool> out; void toggler();

SC_CTOR(onemethod) {

};

}

SC_THREAD(toggler); sensitive << in;

A. Milenkovic

Process is simply a method of this class

Instance of this process created alternate sensitivity list notation

25

THREAD Processes

 Reawakened whenever an input changes

 State saved between invocations

 Infinite loops should contain a wait() void onemethod::toggler() { bool last = false; for (;;) { last = in; out = last; wait(); last = ~in; out = last; wait();

}

}

Relinquish control until the next change of a signal on the sensitivity list for this process

A. Milenkovic 26

CTHREAD Processes

 Triggered in response to a single clock edge

 Can suspend itself and be reactivated

 Method calls wait to relinquish control

 Scheduler runs it again later

 Designed to model clocked digital hardware

A. Milenkovic 27

CTHREAD Processes

SC_MODULE(onemethod) { sc_in_clk clock; sc_in<bool> trigger, in; sc_out<bool> out; void toggler();

SC_CTOR(onemethod) {

};

}

SC_CTHREAD(toggler, clock.pos());

Instance of this process created and relevant clock edge assigned

A. Milenkovic 28

CTHREAD Processes

 Reawakened at the edge of the clock

State saved between invocations

Infinite loops should contain a wait()

Relinquish control until the next clock cycle in which the trigger input is 1 void onemethod::toggler() { bool last = false; for (;;) { wait_until(trigger.delayed() == true); last = in; out = last; wait(); last = ~in; out = last; wait();

}

}

Relinquish control until the next clock cycle

A. Milenkovic 29

A CTHREAD for Complex Multiply

struct complex_mult : sc_module { sc_in<int> a, b, c, d; sc_out<int> x, y; sc_in_clk clock; void do_mult() { for (;;) { x = a * c - b * d; wait(); y = a * d + b * c; wait();

}

}

};

SC_CTOR(complex_mult) {

SC_CTHREAD(do_mult, clock.pos());

}

A. Milenkovic 30

Put It All Together

Process Type

Exec. Trigger

Exec.

Suspend

Infinite Loop

Suspend /

Resume by

Construct &

Sensitize

Method

SC_METHOD

Signal Events

NO

NO

N.A.

SC_METHOD(call_back); sensitive(signals); sensitive_pos(signals); sensitive_neg(signals);

SC_THREAD

Signal Events

YES

SC_CTHREAD

Clock Edge

YES

YES wait()

SC_THREAD(call_back); sensitive(signals); sensitive_pos(signals); sensitive_neg(signals);

YES wait() wait_until()

SC_CTHREAD(

call_back,

clock.pos());

SC_CTHREAD(

call_back,

clock.neg());

A. Milenkovic 31

Watching

 SC_THREAD and SC_CTHREAD processes typically have infinite loops that will continuously execute

 Use watching construct to jump out of the loop

 Watching construct will monitor a specified condition

 When condition occurs control is transferred from the current execution point to the beginning of the process

A. Milenkovic 32

Watching: An Example

// datagen.h

#include "systemc.h"

SC_MODULE(data_gen) { sc_in_clk clk; sc_inout<int> data; sc_in<bool> reset; void gen_data();

SC_CTOR(data_gen){

}

};

SC_CTHREAD(gen_data, clk.pos()); watching(reset.delayed() == true);

// datagen.cc

#include "datagen.h" void gen_data() { if (reset == true) { data = 0;

}

}

} while (true) { data = data + 1; wait(); data = data + 2; wait(); data = data + 4; wait();

Watching expressions are tested at the wait() or wait_until() calls.

All variables defined locally will lose their value on the control exiting.

A. Milenkovic 33

Local Watching

 Allows us to specify exactly which section of the process is watching which signal, and where event handlers are located

W_BEGIN

// put the watching declarations here watching(...); watching(...);

W_DO

// This is where the process functionality goes

...

W_ESCAPE

// This is where the handlers

// for the watched events go if (..) {

...

}

W_END

W_BEGIN macro marks the beginning of the local watching block.

W_BEGIN – W_DO: watching declarations

W_DO – W_ESCAPE: process functionality

W_ESCAPE – W_END: event handlers

W_END macro ends local watching block

A. Milenkovic 34

Local Watching Rules

 All of the events in the declaration block have the same priority. If a different priority is needed then local watching blocks will need to be nested

 Local watching only works in SC_CTHREAD processes

 The signals in the watching expressions are sampled only on the active edges of the process. In an SC_CTHREAD process this means only when the clock that the process is sensitive to changes

 Globally watched events have higher priority than locally watched events

A. Milenkovic 35

D-FF in SystemC

// dff.h

#include "systemc.h"

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

// data input

// clock input

// data output void doit(); // method in the module

}

};

SC_CTOR(dff) { // constructor

SC_METHOD(doit); // doit type is SC_METHOD

// method will be called whenever a

// positive edge occurs on port clock sensitive_pos << clock;

// dff.cc

#include "dff.h" void dff::doit() { dout = din;

}

A. Milenkovic 36

Bus Controller in SystemC

 Assumptions

 32-bit internal data path; 8-bit external data path

 every address and data transaction will have to be multiplexed over the 8-bit bus

 Protocol

 32-bit address is sent to the bus controller (BC) process

 address will be multiplexed byte by byte and sent to MC

 bus controller will wait for ready signal from memory

 receive the data

 send the data to microcontroller

A. Milenkovic 37

Bus Controller: bus.h

// bus.h

#include "systemc.h"

SC_MODULE(bus) { sc_in_clk clock; sc_in<bool> newaddr; sc_in<sc_uint<32> > addr; sc_in<bool> ready; sc_out<sc_uint<32> > data;

}

}; sc_out<bool> start; sc_out<bool> datardy; sc_inout<sc_uint<8> > data8; sc_uint<32> tdata; sc_uint<32> taddr; void xfer();

SC_CTOR(bus) {

SC_CTHREAD(xfer, clock.pos());

// ready to accept new address datardy = true;

A. Milenkovic 38

Bus Controller: bus.cc

// bus.cc

#include "bus.h" void bus::xfer() { while (true) {

// wait for a new address to appear wait_until( newaddr.delayed() == true);

// got a new address so process it taddr = addr.read(); datardy = false; // cannot accept new address now data8 = taddr.range(7,0); start = true; // new addr for memory controller wait();

// wait 1 clock between data transfers data8 = taddr.range(15,8); start = false; wait(); data8 = taddr.range(23,16); wait(); data8 = taddr.range(31,24); wait();

A. Milenkovic 39

Bus Controller: bus.cc (cont’d)

}

}

// now wait for ready signal from memory controller wait_until(ready.delayed() == true);

// now transfer memory data to databus tdata.range(7,0) = data8.read(); wait(); tdata.range(15,8) = data8.read(); wait(); tdata.range(23,16) = data8.read(); wait(); tdata.range(31,24) = data8.read(); data = tdata; datardy = true; // data is ready, new addresses ok

A. Milenkovic 40

Local Watching Example

 Modify bus controller by allowing the bus controller to be interrupted during the transfer from the memory but not to the memory

...

// now wait for ready signal from memory controller wait_until(ready.delayed() == true);

A. Milenkovic 41

Local Watching Example

}

}

W_BEGIN watching(reset.delayed()); // Active value of reset will trigger watching

W_DO

// the rest of this block is as before tdata.range(7,0) = data8.read(); // now transfer memory data to databus wait(); tdata.range(15,8) = data8.read(); wait(); tdata.range(23,16) = data8.read(); wait(); tdata.range(31,24) = data8.read(); data = tdata; datardy = true; // data is ready, new addresses ok

W_ESCAPE if (reset) {

} datardy = false;

W_END

A. Milenkovic 42

Download