230 likes | 389 Views
Reconfigurable Computing (EN2911X, Fall07) Lecture 13: SystemC (1/3). Prof. Sherief Reda Division of Engineering, Brown University http://ic.engin.brown.edu. Introduction to SystemC. SystemC is not a language, but rather a class library within a well established language C++.
E N D
Reconfigurable Computing (EN2911X, Fall07) Lecture 13: SystemC (1/3) Prof. Sherief Reda Division of Engineering, Brown University http://ic.engin.brown.edu
Introduction to SystemC • SystemC is not a language, but rather a class library within a well established language C++. • The primary motivation for using SystemC is to attain the productivity increases required to design modern electronic systems with their ever increasing complexity. [SystemC: From Ground Up]
SystemC resources • SystemC: from the ground up / by David C. Black and Jack Donovan • SystemC: methodologies and applications / edited by Wolfgang Müller, Wolfgang Rosenstiel, and Jürgen Ruf • System design with SystemC / by Thorsten Grotker, Stan Liao, Grant Martin, Stuart Swan
C++ mini refresher • C++ is an object oriented language • A key concept in C++ is the class.A class is an expanded concept of a data structure: instead of holding only data, it can hold both data and functions. class CRectangle { private: int x, y; public: void set_values (int,int); int area (void); } rect; rect.set_values (3,4); myarea = rect.area(); Examples from http://www.cplusplus.com/doc/tutorial/classes.html
CRectangle example #include <iostream> class CRectangle { private: int x, y; public: void set_values (int,int); int area () { return (x*y); } }; void CRectangle::set_values (int a, int b) { x = a; y = b; } int main () { CRectangle rect; rect.set_values (3,4); cout << "area: " << rect.area(); return 0; } declaration declaration & definition definition
Constructors #include <iostream> class CRectangle { int width, height; public: CRectangle (int,int); int area () { return (width*height); } }; CRectangle::CRectangle (int a, int b) { width = a; height = b; } int main () { CRectangle rect (3,4); CRectangle rectb (5,6); return 0; } A constructor is automatically called whenever a new object of this class is created. The constructor function must have the same name as the class, and cannot have any return type; not even void.
(Destructors) class CRectangle { int *width, *height; public: CRectangle (int,int); ~CRectangle (); int area () { return (*width * *height); } }; CRectangle::CRectangle (int a, int b) { width = new int; height = new int; *width = a; *height = b; } CRectangle::~CRectangle () { delete width; delete height; } destructor definition allocating memory destructor definition freeing memory
Pointer to classes • It is perfectly valid to create pointers that point to classes. We simply have to consider that once declared, a class becomes a valid type, so we can use the class name as the type for the pointer. For example: CRectangle *prect; prect = new CRectangle; prect->set_values(1, 2); As with data structures, in order to refer directly to a member of an object pointed by a pointer we can use the arrow operator (->) of indirection.
Inheritance between classes • A key feature of C++ classes is inheritance. Inheritance allows to create classes which are derived from other classes, so that they automatically include some of its "parent's" members, plus its own. polygon rectangle triangle • The class CPolygon contain members that are common for both types of polygon. In our case: width and height. And CRectangle and CTriangle would be its derived classes, with specific features that are different from one type of polygon to the other. • Classes that are derived from others inherit all the accessible members of the base class.
Inheritance example class CPolygon { protected: int width, height; public: void set_values (int a, int b) { width=a; height=b; } }; class CRectangle: public CPolygon { public: int area () { return (width * height); } }; class CTriangle: public CPolygon { public: int area () { return (width * height / 2); } }; int main () { CRectangle rect; CTriangle trgl; rect.set_values (4,5); trgl.set_values (4,5); } The protected access specifier is similar to private. The only difference occurs in fact with inheritance. When a class inherits from another one, the members of the derived class can access the protected members inherited from the base class, but not its private members.
Class templates motivation class mypairi { int a, b; public: mypair (int first, int second) { a=first; b=second; } int getmax () { int retval; retval = a>b? a : b; return retval; }; int main () { mypairi myobject (100, 75); cout << myobject.getmax(); return 0; } class mypairf { float a, b; public: mypair (float first, float second) { a=first; b=second; } float getmax () { float retval; retval = a>b? a : b; return retval; }; int main () { mypairf myobject (100, 75); cout << myobject.getmax(); return 0; } Can we have an automatic way to avoid writing multiple versions of the same class for different data types?
Class templates template <class T> class mypair { T a, b; public: mypair (T first, T second) { a=first; b=second; } T getmax () { T retval; retval = a>b? a : b; return retval; }; int main () { mypair <int> myobject (100, 75); cout << myobject.getmax(); return 0; } C++ Class Templates are used where we have multiple copies of code for different data types with the same logic. If a set of functions or classes have the same functionality for different data types, they become good candidates for being written as Templates.
What is wrong with plain C++? • Concurrency: hardware systems are inherently parallel; SW are not. • Time: C++ has no notion of time • Hardware style communication: signals, protocols • Reactivity: hardware is inherently reactive • Hardware data types: bit type, multi-valued logic • Some of the functionalities in C++ are not simply applicable in hardware systems (e.g. destructors)
Extending C++ with SystemC library • SystemC library of C++ classes: • Processes (for concurrency) • Clocks (for time) • Hardware data types (bit vectors, 4-valued logic, fixed-point types, arbitrary precision integers) • Waiting, watching, and sensitivity (for reactivity) • Modules, ports, signals (for hierarchy)
Synthesizable SystemC • Our discussions will focus on SystemC synthesis as afforded by the Celoxica SystemC agility compiler
SC_MODULE creates a class inherted from sc_module SC_MODULE(module_name) { ... // port declarations to connect modules together ... // variable declarations ... // function declarations/definitions SC_CTOR(module_name) { ... // body of constructor ... // process declarations, sensitivities } }; The arguments to SC_MODULE and SC_CTOR must be the same.
Module ports • Ports are used to communicate with the external modules or channels. • Input ports (defined using sc_in and sc_in_clk) • Output ports (defined using sc_out and sc_out_clk) • Input/output ports (defined using sc_inout, sc_inout_clk and sc_inout_rv ) SC_MODULE (module_name) { //Module port declarations sc_in <port_data_type> port_name; sc_out <port_data_type> port_name; sc_inout <port_data_type> port_name; sc_in <port_data_type> port_name; … };
Datatypes • Supported native C++ synthesizable data types • long long • long • int • short • char • bool • SystemC also allows further refined storage types • sc_bit • sc_bv<width> • sc_int <width> • sc_uint <width> • sc_bigint <width> • sc_biguint <width>
Module process • Processes describe the parallel behavior of hardware systems. Processes execute concurrently. The code within a process, however, executes sequentially. • Defining a process is similar to defining a C++ function. A process is declared as a member function of a module class and registered as a process in the module’s constructor. SC_MODULE (my_module) { sc_in <bool> clk; sc_in <bool> in1; sc_out <bool> out1; void my_method(); SC_CTOR(my_module) { SC_METHOD(my_method); sensitive << in1 << clk.pos(); } } module in1 out process clk
Definition of process body • The process body contains the implementation of the process. Like C++ functions, it may be defined: • • within the module definition, typically in a .h header file • • outside the module, typically in a .cpp file my_module.h my_module.h SC_MODULE (my_module) { void my_method() { ... } ... }; SC_MODULE (my_module) { void my_method(); ... }; my_module.cpp void my_module::my_thread() { ... } A thread process body within a module definition A thread process body outside a module definition
SC_CTOR construct • The SC_CTOR constructor is used to: • Initialize variables declared in the module. • Specify the functionality of the module in terms of SC_METHOD, SC_THREAD andSC_CTHREAD. • The threads and methods must be defined using synthesizable code. • The constructor should also contain: • The sensitivity lists describing the inputs that each process is sensitive to. • Instantiation of sub-modules. • Port mapping code for hierarchical modules.
OR gate example #include "systemc.h"SC_MODULE(or_gate) { sc_in<sc_bit> a; sc_in<sc_bit> b; sc_out<sc_bit> c; void prc_or_gate() { c=a | b; } SC_CTOR(or_gate) { SC_METHOD(prc_or_gate); sensitive << a << b; }}; a OR_GATE b c
Full adder example SC_MODULE( half_adder ) { sc_in<bool> a,b; sc_out<bool> sum, carry; void half_adder_defn(); SC_CTOR( half_adder ) { SC_METHOD ( half_adder_defn ); sensitive << a << b; } }; void half_adder::half_adder_defn() { sum = a ^ b; carry = a & b; } a FA b sum carry