SystemC Syntax Summary
This section contains all the essential syntax necessary to start designing using SystemC.
For a more detailed practical guide to using SystemC, see our SystemC Golden Reference Guide
- Modules, Instancing, sc_main
- Signals
- Commonly-Used Signal Methods
- Other primitive Channels
- Ports
- Port Specializations
- Processes
- Timing Control
- Time and Clocks
- Time Methods
- Clocks
- Simulation Control Methods
- Debugging
- Tracing
- Data Types
- Fixed Point Types
//ModuleName.h - interface file #include "systemc.h" #include "SubModulename.h"; // lower-level module SC_MODULE( ModuleName) { //port declarations // member variable declarations //internal channels //sub-module declaration SubModuleName InstName1; // see 2nd example below for hierarchy using pointers //local methods int local_method(); //process declarations void MyProc1(); void MyProc2(); void MyProc3(); //module constructor SC_CTOR( ModuleName): InstName1("InstName1") { InstName1.SubPortName1(SigName1);//named mapping InstName1.SubPortName2(SigName2);//named mapping //process/local method definition SC_METHOD(MyProc1); //sensitivity list SC_THREAD(MyProc2); //sensitivity list SC_CTHREAD(MyProc3,ClkName); } }; // Alternative form of module declaration without using SC_MODULE macro class ModuleName: public sc_module { public: // declarations ... //sub-module pointer declaration SubModuleName *InstName1; //alternative macro to register module constructor: SC_HAS_PROCESS(ModuleName); //module constructor ModuleName(sc_module_name Nm, [other constructor arguments] ): sc_module(Nm), [argument initialisers] { //module instances InstName1 = new SubModuleName("Instlabel"); InstName1->SubPortName1(SigName1); //named mapping InstName1->SubPortName2(SigName2);//named mapping //process/local method definition SC_METHOD(MyProc1); //sensitivity list SC_THREAD(MyProc2); //sensitivity list SC_CTHREAD(MyProc3,ClkName); } }; //ModuleName.cpp - implementation file #include "systemc.h" #include "ModuleName.h" int ModuleName :: local_method() { int x; // sequential statements... return x; }; void ModuleName :: MyProc1() { // sequential statements... }; //main.cpp #include "systemc.h" #include "ModuleName.h" int sc_main(int argc, char*argv[]) { //signal declaration sc_signal <type> P1; ... //clock declaration //module instantiation ModuleName MN ("ModNm"); //module mapping MN.port1(P1); ... // trace file creation //run simulation //close trace file return(0); }
sc_signal< type> ListOfNames; sc_signal< type> S1("Sig1"); // assign label "Sig1" resolved signals: sc_signal_resolved Signal_name1, …; sc_signal_rv<width> Vector_name1, …;
SigName.read() SigName.write() SigName.event() SigName.value_changed_event()
//mutex declaration sc_mutex Mutex1; sc_mutex Mutex2("Mutex2"); //semaphore declaration sc_semaphore Semaphore1(5); //initial value=5 sc_semaphore Semaphore2("Sem2",8); //initial value=8 //fifo declaration sc_fifo<type> Fifo1; //default length = 16 sc_fifo<type> Fifo2("Fifo2",2); //length = 2 //buffer declaration sc_buffer<type> B1("Buf1");
sc_port<interface_type, N, Policy> P1, P2, ...; (base class for all port specialization types):
Unresolved signal ports: {sc_in | sc_out | sc_inout} <type> P1, P2, ...; Resolved signal ports: {sc_in_resolved | sc_out_resolved | sc_inout_resolved} P1, P2, ...; Resolved logic vector ports: {sc_in_rv | sc_out_rv | sc_inout_rv} <width> A1,A2, ...; Clock ports : (Use {sc_in | sc_out | sc_inout} <bool> FIFO ports: sc_fifo_in<type> FifoPortName1, ...; sc_fifo_out<type> FifoPortName1, ...;
Process definitions SC_METHOD (M_ProcName); //or SC_THREAD (M_Proc_Name); sensitive(SigName1); sensitive(SigName2); //or sensitive << SigName1 << SigName2; sensitive << BoolSigName.pos(); sensitive << BoolSigName.neg(); SC_CTHREAD(CTh_ProcName, BoolSigName.pos()); //or SC_CTHREAD(CTh_ProcName, BoolSigName.neg()); Process implementation Method process ModuleName::M_ProcName() {//when invoked, executes until returns //cannot be suspended //should not have infinite loop next_trigger(event); //specify next dynamic event to trigger process } Thread process ModuleName::Th_ProcName() {//usually has infinite loop, that continuously executes while(true) { //can be suspended and reactivated wait(); //wait for event in static sensitivity list //wait on events wait(event); //wait on event wait(e1 & e2); //wait on events e1 and e2 wait(e1 | e2 |e3); //wait on event e1 or e2 or e3 wait(x, SC_NS); // wait for x ns wait(0, SC_NS); //wait for 1 delta cycle wait(SC_ZERO_TIME); //wait for 1 delta cycle wait(N); // wait for N occurrences of static sensitivity event } }; Clocked thread process ModuleName::CTh_ProcName() {//only triggered on one edge of one clock while(true) {//can be suspended and reactivated wait();//or wait(N); } //signals updated when process suspends, //other SC_CTHREAD processes do not see new value until next active clock event };
wait(); //suspends execution for one clock cycle //(for SC_CTHREADs), or until an event specified // in the sensitivity list (for SC_THREADs) wait(N); // suspends execution for N lots of static sensitivity events, // where N can be constant, variable
sc_time t(int/double, sc_time_unit); where sc_time_unit can be: SC_FS, SC_PS, SC_NS, SC_US, SC_MS, SC_SEC The default time resolution: SC_PS
sc_set_time_resolution(double, sc_time_unit) sc_get_time_resolution()
sc_clock ClkName(sc_module_name name, sc_time period, double duty_cycle, sc_time start_time, bool positive_first) defaults: sc_clock ClkName("Clk", 1, SC_NS, 0.5, 0, true); ClkName.posedge() ClkName.negedge() ClkName.name() ClkName.period() ClkName.duty_cycle() ClkName.read() ClkName.signal() ClkName.first_edge()
sc_start(sc_time X); sc_stop();
//C-style printf("%s: SigName = %s\n", sc_time_stamp(), SigName.to_string()); //C++-style cout <<"( << sc_time_stamp() << "): SigName=" << SigName << endl;
sc_trace_file *F;//declare trace file F = sc_create_vcd_trace_file("Name");//create file //set the default vcd time unit to ns F->sc_set_time_unit(1, SC_NS); sc_trace(TraceFile, WhatToTrace, "LabelInWaveViewer"); //register for tracing //run the simulation using sc_start(), sc_close_vcd_trace_file(F);//close file
sc_logic Bitwise &(and) |(or) ^(xor) ~(not) Assignment = &= |= ^= Equality == != Values: sc_logic: '0', '1', 'X', 'Z' also SC_LOGIC_0, SC_LOGIC_1, SC_LOGIC_X, SC_LOGIC_Z sc_int, sc_uint, sc_bigint, sc_biguint Bitwise ~ & | ^ >> << Arithmetic + - * / % Assignment = += -= *= /= %= &= ^= |= Equality == != Relational < <= > >= Autoinc/dec ++ -- Bit Select [x] Part Select range() Concatenate (,) to_string Yes ( sc_int, sc_uint) to_double Yes to_signed Yes ( sc_int) to_unsigned Yes ( sc_uint) sc_int: 64bit, 2's complement sc_uint: 64bit unsigned sc_bigint, sc_biguint: default 512bits sc_bv, sc_lv Bitwise ~ & | ^ >> << Assignment = &= |= ^= Equality == != Reduction and_reduce() or_reduce() xor_reduce() Bit Select [x] Part Select range() Concatenation (,) to_string Yes
//wl:total word length,iwl:integer word length //q_mode: quantisation mode, o_mode: overflow mode //n_bits: no. of saturated bits sc_fixed(_fast)(wl, iwl, q_mode, o_mode, n_bits) X; sc_ufixed(_fast)(wl, iwl, q_mode, o_mode, n_bits) Y; sc_fix(_fast) X(list of options);//non-static arguments sc_ufix(_fast) Y(list of options); //for fast fixed types mantissa is limited to 53bits Quantisation modes: SC_RND, SC_RND_ZERO, SC_RND_MIN_INF, SC_RND_INF, SC_RND_CONV, SC_TRN, SC_TRN_ZERO Overflow modes: SC_SAT, SC_SAT_ZERO, SC_SAT_SYM, SC_WRAP, SC_WRAP_SM sc_fixed, sc_ufixed, sc_fix, sc_ufix Bitwise ~ & ^ | Arithmetic * / + - << >> ++ -- Assignment = += -= *= /= <<= &= ^= |= >>= Equality == != Relational < <= > >= Bit Select [x] Part Select range() to_string() Yes Arithmetic shifts preserve the sign bit Bitwise operators do not work on mixtures of signed and unsigned types.