├── .gitignore ├── basic ├── 00_hello_world │ ├── Makefile │ └── hello_world.cpp ├── 01_module │ ├── Makefile │ └── module.cpp ├── 02_sc_ctor │ ├── Makefile │ └── sc_ctor.cpp ├── 03_sc_has_process │ ├── Makefile │ └── sc_has_process.cpp ├── 04_simu_process │ ├── Makefile │ └── simu_process.cpp ├── 05_simu_stage │ ├── Makefile │ └── simu_stage.cpp ├── 06_time │ ├── Makefile │ └── time.cpp ├── 07_concurrency │ ├── Makefile │ └── concurr.cpp ├── 08_event │ ├── Makefile │ └── event.cpp ├── 09_event_combined │ ├── Makefile │ └── event_combined.cpp ├── 10_delta_cycle │ ├── Makefile │ └── delta_cycle.cpp ├── 11_sensitivity │ ├── Makefile │ └── sensitivity.cpp ├── 12_initialization │ ├── Makefile │ └── initialization.cpp ├── 13_method │ ├── Makefile │ └── method.cpp ├── 14_event_queue │ ├── Makefile │ └── event_queue.cpp ├── 15_event_queue_combined │ ├── Makefile │ └── event_queue_combined.cpp ├── 16_channel_mutex │ ├── Makefile │ └── mutex.cpp ├── 17_channel_semaphore │ ├── Makefile │ └── semaphore.cpp ├── 18_channel_fifo │ ├── Makefile │ └── fifo.cpp ├── 19_signal_readwrite │ ├── Makefile │ └── signal_readwrite.cpp ├── 20_signal_event │ ├── Makefile │ └── signal_event.cpp ├── 21_signal_many_writer │ ├── Makefile │ └── signal_many_writer.cpp ├── 22_resolved_signal │ ├── Makefile │ └── resolved_signal.cpp ├── 23_signal_bool │ ├── Makefile │ └── signal_bool.cpp ├── 24_buffer │ ├── Makefile │ └── buffer.cpp ├── 25_port │ ├── Makefile │ └── port.cpp ├── 26_export │ ├── Makefile │ └── export.cpp ├── 27_port2port │ ├── Makefile │ └── port2port.cpp ├── 28_specialized_port │ ├── Makefile │ └── specialized_port.cpp ├── 29_port_array │ ├── Makefile │ └── port_array.cpp ├── 30_primitive_channel │ ├── Makefile │ └── prim_channel.cpp ├── 31_hierarchical_channel │ ├── Makefile │ └── hierarchical_channel.cpp ├── 32_trace │ ├── Makefile │ └── trace.cpp ├── 33_report │ ├── Makefile │ └── report.cpp ├── 34_customized_datatype │ ├── Makefile │ └── customized_datatype.cpp ├── 35_clock │ ├── Makefile │ └── clock.cpp └── 36_cthread │ ├── Makefile │ └── cthread.cpp └── pattern ├── 00_trigger_when_busy ├── Makefile └── trigger.cpp ├── 01_trigger_when_busy2 ├── Makefile └── trigger2.cpp ├── 02_interrupt_when_busy ├── Makefile └── interrupt.cpp └── 03_interrupt_when_busy2 ├── Makefile └── interrupt2.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | setup/ 2 | -------------------------------------------------------------------------------- /basic/00_hello_world/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/00_hello_world/hello_world.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include // include the systemC header file 3 | using namespace sc_core; // use namespace 4 | 5 | void hello1() { // a normal c++ function 6 | std::cout << "Hello world using approach 1" << std::endl; 7 | } 8 | 9 | struct HelloWorld : sc_module { // define a systemC module 10 | SC_CTOR(HelloWorld) {// constructor function, to be explained later 11 | SC_METHOD(hello2); // register a member function to the kernel 12 | } 13 | void hello2(void) { // a function for systemC simulation kernel, void inside () can be omitted 14 | std::cout << "Hello world using approach 2" << std::endl; 15 | } 16 | }; 17 | 18 | int sc_main(int, char*[]) { // entry point 19 | hello1(); // approach #1: manually invoke a normal function 20 | HelloWorld helloworld("helloworld"); // approach #2, instantiate a systemC module 21 | sc_start(); // let systemC simulation kernel to invoke helloworld.hello2(); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /basic/01_module/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/01_module/module.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(MODULE_A) { // approach #1, use systemC provided SC_MODULE macro 6 | SC_CTOR(MODULE_A) { // default constructor 7 | std::cout << name() << " constructor" << std::endl; // name() returns the object name, which is provided during instantization 8 | } 9 | }; 10 | struct MODULE_B : public sc_module { // approach #2, this uses c++ syntax and is more readiable 11 | SC_CTOR(MODULE_B) { 12 | std::cout << name() << " constructor" << std::endl; 13 | } 14 | }; 15 | class MODULE_C : public sc_module { // approach #3, use class instead of struct 16 | public: // have to explicitly declare constructor function as public 17 | SC_CTOR(MODULE_C) { 18 | std::cout << name() << " constructor" << std::endl; 19 | } 20 | }; 21 | 22 | int sc_main(int, char*[]) { // systemC entry point 23 | MODULE_A module_a("module_a"); // declare and instantiate module_a, it's common practice to assign module name == object name 24 | MODULE_B module_b("modb"); // declare and instantiate module_b, module name != object name 25 | MODULE_C module_c("module_c"); // declare and instantiate module_c 26 | sc_start(); // this can be skipped in this example because module instantiation happens during elaboration phase which is before sc_start 27 | return 0; 28 | } -------------------------------------------------------------------------------- /basic/02_sc_ctor/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/02_sc_ctor/sc_ctor.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(MODULE_A) { 6 | SC_CTOR(MODULE_A) { // constructor taking only module name 7 | SC_METHOD(func_a); // register member function to systemC simulation kernel, to be explained later. 8 | } 9 | void func_a() { // a member function with no input, no output 10 | std::cout << name() << std::endl; 11 | } 12 | }; 13 | 14 | SC_MODULE(MODULE_B) { 15 | SC_CTOR(MODULE_B) { // constructor 16 | SC_METHOD(func_b); // register member function 17 | } 18 | void func_b(); // declare function 19 | }; 20 | void MODULE_B::func_b() { // define function outside class definition 21 | std::cout << this->name() << std::endl; 22 | } 23 | SC_MODULE(MODULE_C) { // constructor taking more arguments 24 | const int i; 25 | SC_CTOR(MODULE_C); // SC_HAS_PROCESS is recommended, see next example for details 26 | MODULE_C(sc_module_name name, int i) : sc_module(name), i(i) { // explcit constructor 27 | SC_METHOD(func_c); 28 | } 29 | void func_c() { 30 | std::cout << name() << ", i = " << i << std::endl; 31 | } 32 | }; 33 | 34 | int sc_main(int, char*[]) { 35 | MODULE_A module_a("module_a"); 36 | MODULE_B module_b("module_b"); 37 | MODULE_C module_c("module_c",1); 38 | sc_start(); 39 | return 0; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /basic/03_sc_has_process/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/03_sc_has_process/sc_has_process.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(MODULE_A) { // module without simulation processes doesn't need SC_CTOR or SC_HAS_PROCESS 6 | MODULE_A(sc_module_name name) { // c++ style constructor, the base class is implicitly instantiated with module name. 7 | std::cout << this->name() << ", no SC_CTOR or SC_HAS_PROCESS" << std::endl; 8 | } 9 | }; 10 | 11 | SC_MODULE(MODULE_B1) { // constructor with module name as the only input argument 12 | SC_CTOR(MODULE_B1) { // implicitly declares a constructor of MODULE_B1(sc_module_name) 13 | SC_METHOD(func_b); // register member function to simulation kernel 14 | } 15 | void func_b() { // define function 16 | std::cout << name() << ", SC_CTOR" << std::endl; 17 | } 18 | }; 19 | 20 | SC_MODULE(MODULE_B2) { // constructor with module name as the only input argument 21 | SC_HAS_PROCESS(MODULE_B2); // no implicit constructor declarition 22 | MODULE_B2(sc_module_name name) { // explicit constructor declaration, also instantiate base class by default via sc_module(name) 23 | SC_METHOD(func_b); // register member function 24 | } 25 | void func_b() { // define function 26 | std::cout << name() << ", SC_HAS_PROCESS" << std::endl; 27 | } 28 | }; 29 | 30 | SC_MODULE(MODULE_C) { // pass additional input argument(s) 31 | const int i; 32 | SC_HAS_PROCESS(MODULE_C); // OK to use SC_CTOR, which will also define an un-used constructor: MODULE_A(sc_module_name); 33 | MODULE_C(sc_module_name name, int i) : i(i) { // define the constructor function 34 | SC_METHOD(func_c); // register member function 35 | } 36 | void func_c() { // define function 37 | std::cout << name() << ", additional input argument" << std::endl; 38 | } 39 | }; 40 | 41 | SC_MODULE(MODULE_D1) { // SC_CTOR inside header, constructor defined outside header 42 | SC_CTOR(MODULE_D1); 43 | void func_d() { 44 | std::cout << this->name() << ", SC_CTOR inside header, constructor defined outside header" << std::endl; 45 | } 46 | }; 47 | MODULE_D1::MODULE_D1(sc_module_name name) : sc_module(name) { // defines constructor. Fine with/without "sc_module(name)" 48 | SC_METHOD(func_d); 49 | } 50 | 51 | SC_MODULE(MODULE_D2) { // SC_HAS_PROCESS inside header, constructor defined outside header 52 | SC_HAS_PROCESS(MODULE_D2); 53 | MODULE_D2(sc_module_name); // declares constructor 54 | void func_d() { 55 | std::cout << this->name() << ", SC_CTOR inside header, constructor defined outside header" << std::endl; 56 | } 57 | }; 58 | MODULE_D2::MODULE_D2(sc_module_name name) : sc_module(name) { // defines constructor. Fine with/without "sc_module(name)" 59 | SC_METHOD(func_d); 60 | } 61 | 62 | SC_MODULE(MODULE_E) { // SC_CURRENT_USER_MODULE and constructor defined outside header 63 | MODULE_E(sc_module_name name); // c++ style constructor declaration 64 | void func_e() { 65 | std::cout << this->name() << ", SC_HAS_PROCESS outside header, CANNOT use SC_CTOR" << std::endl; 66 | } 67 | }; 68 | MODULE_E::MODULE_E(sc_module_name name) { // constructor definition 69 | SC_HAS_PROCESS(MODULE_E); // NOT OK to use SC_CTOR 70 | SC_METHOD(func_e); 71 | } 72 | 73 | int sc_main(int, char*[]) { 74 | MODULE_A module_a("module_a"); 75 | MODULE_B1 module_b1("module_b1"); 76 | MODULE_B2 module_b2("module_b2"); 77 | MODULE_C module_c("module_c", 1); 78 | MODULE_D1 module_d1("module_d1"); 79 | MODULE_D2 module_d2("module_d2"); 80 | MODULE_E module_e("module_e"); 81 | sc_start(); 82 | return 0; 83 | } 84 | 85 | -------------------------------------------------------------------------------- /basic/04_simu_process/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/04_simu_process/simu_process.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(PROCESS) { 6 | sc_clock clk; // declares a clock 7 | SC_CTOR(PROCESS) : clk("clk", 1, SC_SEC) { // instantiate a clock with 1sec periodicity 8 | SC_METHOD(method); // register a method 9 | SC_THREAD(thread); // register a thread 10 | SC_CTHREAD(cthread, clk); // register a clocked thread 11 | } 12 | void method(void) { // define the method member function 13 | // no while loop here 14 | std::cout << "method triggered @ " << sc_time_stamp() << std::endl; 15 | next_trigger(sc_time(1, SC_SEC)); // trigger after 1 sec 16 | } 17 | void thread() { // define the thread member function 18 | while (true) { // infinite loop make sure it never exits 19 | std::cout << "thread triggered @ " << sc_time_stamp() << std::endl; 20 | wait(1, SC_SEC); // wait 1 sec before execute again 21 | } 22 | } 23 | void cthread() { // define the cthread member function 24 | while (true) { // infinite loop 25 | std::cout << "cthread triggered @ " << sc_time_stamp() << std::endl; 26 | wait(); // wait for next clk event, which comes after 1 sec 27 | } 28 | } 29 | }; 30 | 31 | int sc_main(int, char*[]) { 32 | PROCESS process("process"); // init module 33 | std::cout << "execution phase begins @ " << sc_time_stamp() << std::endl; 34 | sc_start(2, SC_SEC); // run simulation for 2 second 35 | std::cout << "execution phase ends @ " << sc_time_stamp() << std::endl; 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /basic/05_simu_stage/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/05_simu_stage/simu_stage.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(STAGE) { 6 | SC_CTOR(STAGE) { // elaboration 7 | std::cout << sc_time_stamp() << ": Elaboration: constructor" << std::endl; 8 | SC_THREAD(thread); // initialization + simulation 9 | } 10 | ~STAGE() { // cleanup 11 | std::cout << sc_time_stamp() << ": Cleanup: desctructor" << std::endl; 12 | } 13 | void thread() { 14 | std::cout << sc_time_stamp() << ": Execution.initialization" << std::endl; 15 | int i = 0; 16 | while(true) { 17 | wait(1, SC_SEC); // advance-time 18 | std::cout << sc_time_stamp() << ": Execution.simulation" << std::endl; // evaluation 19 | if (++i >= 2) { 20 | sc_stop(); // stop simulation after 2 iterations 21 | } 22 | } 23 | } 24 | void before_end_of_elaboration() { 25 | std::cout << "before end of elaboration" << std::endl; 26 | } 27 | void end_of_elaboration() { 28 | std::cout << "end of elaboration" << std::endl; 29 | } 30 | void start_of_simulation() { 31 | std::cout << "start of simulation" << std::endl; 32 | } 33 | void end_of_simulation() { 34 | std::cout << "end of simulation" << std::endl; 35 | } 36 | }; 37 | 38 | int sc_main(int, char*[]) { 39 | STAGE stage("stage"); // Elaboration 40 | sc_start(); // Execution till sc_stop 41 | return 0; // Cleanup 42 | } -------------------------------------------------------------------------------- /basic/06_time/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/06_time/time.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | int sc_main(int, char*[]) { 6 | sc_core::sc_report_handler::set_actions( "/IEEE_Std_1666/deprecated", 7 | sc_core::SC_DO_NOTHING ); // suppress warning due to set_time_resolution 8 | sc_set_time_resolution(1, SC_FS); // deprecated function but still useful, default is 1 PS 9 | sc_set_default_time_unit(1, SC_SEC); // change time unit to 1 second 10 | std::cout << "1 SEC = " << sc_time(1, SC_SEC).to_default_time_units() << " SEC"<< std::endl; 11 | std::cout << "1 MS = " << sc_time(1, SC_MS).to_default_time_units() << " SEC"<< std::endl; 12 | std::cout << "1 US = " << sc_time(1, SC_US).to_default_time_units() << " SEC"<< std::endl; 13 | std::cout << "1 NS = " << sc_time(1, SC_NS).to_default_time_units() << " SEC"<< std::endl; 14 | std::cout << "1 PS = " << sc_time(1, SC_PS).to_default_time_units() << " SEC"<< std::endl; 15 | std::cout << "1 FS = " << sc_time(1, SC_FS).to_default_time_units() << " SEC"<< std::endl; 16 | sc_start(7261, SC_SEC); // run simulation for 7261 second 17 | double t = sc_time_stamp().to_seconds(); // get time in second 18 | std::cout << int(t) / 3600 << " hours, " << (int(t) % 3600) / 60 << " minutes, " << (int(t) % 60) << "seconds" << std::endl; 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /basic/07_concurrency/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/07_concurrency/concurr.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(CONCURRENCY) { 6 | SC_CTOR(CONCURRENCY) { // constructor 7 | SC_THREAD(thread1); // register thread1 8 | SC_THREAD(thread2); // register thread2 9 | } 10 | void thread1() { 11 | while(true) { // infinite loop 12 | std::cout << sc_time_stamp() << ": thread1" << std::endl; 13 | wait(2, SC_SEC); // trigger again after 2 "simulated" seconds 14 | } 15 | } 16 | void thread2() { 17 | while(true) { 18 | std::cout << "\t" << sc_time_stamp() << ": thread2" << std::endl; 19 | wait(3, SC_SEC); 20 | } 21 | } 22 | }; 23 | 24 | int sc_main(int, char*[]) { 25 | CONCURRENCY concur("concur"); // define an object 26 | sc_start(10, SC_SEC); // run simulation for 10 seconds 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /basic/08_event/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/08_event/event.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(EVENT) { 6 | sc_event e; // declare an event 7 | SC_CTOR(EVENT) { 8 | SC_THREAD(trigger); //register a trigger process 9 | SC_THREAD(catcher); // register a catcher process 10 | } 11 | void trigger() { 12 | while (true) { // infinite loop 13 | e.notify(1, SC_SEC); // trigger after 1 second 14 | if (sc_time_stamp() == sc_time(4, SC_SEC)) { 15 | e.cancel(); // cancel the event triggered at time = 4 s 16 | } 17 | wait(2, SC_SEC); // wait for 2 seconds before triggering again 18 | } 19 | } 20 | void catcher() { 21 | while (true) { // loop forever 22 | wait(e); // wait for event 23 | std::cout << "Event cateched at " << sc_time_stamp() << std::endl; // print to console 24 | } 25 | } 26 | }; 27 | 28 | int sc_main(int, char*[]) { 29 | EVENT event("event"); // define object 30 | sc_start(8, SC_SEC); // run simulation for 8 seconds 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /basic/09_event_combined/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/09_event_combined/event_combined.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(COMBINED) { 6 | sc_event e1, e2, e3, e4, e5, e6, e7, e8, e9, e10; // declare multiple events 7 | SC_CTOR(COMBINED) { 8 | SC_THREAD(trigger); // reigster trigger 9 | SC_THREAD(catcher_0); // register catchers 10 | SC_THREAD(catcher_1); 11 | SC_THREAD(catcher_2and3); 12 | SC_THREAD(catcher_4or5); 13 | SC_THREAD(catcher_timeout_or_6); 14 | SC_THREAD(catcher_timeout_or_7or8); 15 | SC_THREAD(catcher_timeout_or_9and10); 16 | } 17 | void trigger(void) { 18 | e1.notify(1, SC_SEC); // e1 fires at 1s 19 | e2.notify(2, SC_SEC); // ... 20 | e3.notify(3, SC_SEC); 21 | e4.notify(4, SC_SEC); 22 | e5.notify(5, SC_SEC); 23 | e6.notify(6, SC_SEC); 24 | e7.notify(7, SC_SEC); 25 | e8.notify(8, SC_SEC); 26 | e9.notify(9, SC_SEC); 27 | e10.notify(10, SC_SEC); // e10 fires at 10s 28 | } 29 | void catcher_0(void) { 30 | wait(2, SC_SEC); // timer triggered 31 | std::cout << sc_time_stamp() << ": 2sec timeout" << std::endl; 32 | } 33 | void catcher_1(void) { 34 | wait(e1); // e1 triggered 35 | std::cout << sc_time_stamp() << ": catch e1" << std::endl; 36 | } 37 | void catcher_2and3(void) { 38 | wait(e2 & e3); // e2 and e3 39 | std::cout << sc_time_stamp() << ": catch e2 and e3" << std::endl; 40 | } 41 | void catcher_4or5(void) { 42 | wait(e4 | e5); // e4 or e5 43 | std::cout << sc_time_stamp() << ": catch e4 or e5" << std::endl; 44 | } 45 | void catcher_timeout_or_6(void) { 46 | wait(sc_time(5, SC_SEC), e6); // timer or e6 47 | std::cout << sc_time_stamp() << ": 5sec timeout or catch e6"<< std::endl; 48 | } 49 | void catcher_timeout_or_7or8(void) { 50 | wait(sc_time(20, SC_SEC), e7 | e8); // timer or (e7 or e8) 51 | std::cout << sc_time_stamp() << ": 20sec timeout or catch e7 or e8" << std::endl; 52 | } 53 | void catcher_timeout_or_9and10(void) { 54 | wait(sc_time(20, SC_SEC), e9 & e10); // timer or (e9 and e10) 55 | std::cout << sc_time_stamp() << ": 20sec timeout or catch (e9 and e10)" << std::endl; 56 | } 57 | }; 58 | 59 | int sc_main(int, char*[]) { 60 | COMBINED combined("combined"); 61 | sc_start(); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /basic/10_delta_cycle/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/10_delta_cycle/delta_cycle.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(DELTA) { 6 | int x = 1, y = 1; // defines two member variables 7 | SC_CTOR(DELTA) { 8 | SC_THREAD(add_x); // x += 2 9 | SC_THREAD(multiply_x); // x *= 3 10 | SC_THREAD(add_y); // y += 2 11 | SC_THREAD(multiply_y); // y *= 3 12 | } 13 | void add_x() { // x += 2 happens first 14 | std::cout << "add_x: " << x << " + 2" << " = "; 15 | x += 2; 16 | std::cout << x << std::endl; 17 | } 18 | void multiply_x() { // x *= 3 happens after a delta cycle 19 | wait(SC_ZERO_TIME); 20 | std::cout << "multiply_x: " << x << " * 3" << " = "; 21 | x *= 3; 22 | std::cout << x << std::endl; 23 | } 24 | void add_y() { // y += 2 happens after a delta cycle 25 | wait(SC_ZERO_TIME); 26 | std::cout << "add_y: " << y << " + 2" << " = "; 27 | y += 2; 28 | std::cout << y << std::endl; 29 | } 30 | void multiply_y() { // y *=3 happens first 31 | std::cout << "multiply_y: " << y << " * 3" << " = "; 32 | y *= 3; 33 | std::cout << y << std::endl; 34 | } 35 | }; 36 | 37 | int sc_main(int, char*[]) { 38 | DELTA delta("delta"); 39 | sc_start(); 40 | return 0; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /basic/11_sensitivity/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/11_sensitivity/sensitivity.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(SENSITIVITY) { 6 | sc_event e1, e2; // events for inter-process triggering 7 | SC_CTOR(SENSITIVITY) { 8 | SC_THREAD(trigger_1); // register processes 9 | SC_THREAD(trigger_2); 10 | SC_THREAD(catch_1or2_dyn); 11 | SC_THREAD(catch_1or2_static); 12 | sensitive << e1 << e2; // static sensitivity for the preceeding process, can only "OR" the triggers 13 | } 14 | void trigger_1() { 15 | wait(SC_ZERO_TIME); // delay trigger by a delta cycle, make sure catcher is ready 16 | while (true) { 17 | e1.notify(); // trigger e1 18 | wait(2, SC_SEC); // dynamic sensitivity, re-trigger after 2 s 19 | } 20 | } 21 | void trigger_2() { // delay trigger by a delta cycle 22 | wait(SC_ZERO_TIME); 23 | while (true) { 24 | e2.notify(); // trigger e2 25 | wait(3, SC_SEC); // dynamic sensitivity, re-trigger after 3 s 26 | } 27 | } 28 | void catch_1or2_dyn() { 29 | while (true) { 30 | wait(e1 | e2); // dynamic sensitivity 31 | std::cout << "Dynamic sensitivty: e1 or e2 @ " << sc_time_stamp() << std::endl; 32 | } 33 | } 34 | void catch_1or2_static(void) { 35 | while (true) { 36 | wait(); // static sensitivity 37 | std::cout << "Static sensitivity: e1 or e2 @ " << sc_time_stamp() << std::endl; 38 | } 39 | } 40 | }; 41 | 42 | int sc_main(int, char*[]) { 43 | SENSITIVITY sensitivity("sensitivity"); 44 | sc_start(7, SC_SEC); 45 | return 0; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /basic/12_initialization/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/12_initialization/initialization.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(INITIALIZATION) { 6 | sc_event e; // event for inter-process trigger 7 | SC_CTOR(INITIALIZATION) { 8 | SC_THREAD(trigger); // no static sensitivity 9 | SC_THREAD(catcher_1); // no static sensitivity 10 | SC_THREAD(catcher_2); // no static sensitivity 11 | SC_THREAD(catcher_3); 12 | sensitive << e; // statically sensitive to e 13 | dont_initialize(); // don't initialize 14 | } 15 | void trigger() { 16 | while (true) { // e triggered at 1, 3, 5, 7 ... 17 | e.notify(1, SC_SEC); // notify after 1 s 18 | wait(2, SC_SEC); // trigger every 2 s 19 | } 20 | } 21 | void catcher_1() { 22 | while (true) { 23 | std::cout << sc_time_stamp() << ": catcher_1 triggered" << std::endl; 24 | wait(e); // dynamic sensitivity 25 | } 26 | } 27 | void catcher_2() { 28 | wait(e); // avoid initialization --- mimic systemC 1.0 behavior 29 | while (true) { 30 | std::cout << sc_time_stamp() << ": catcher_2 triggered" << std::endl; 31 | wait(e); // dynamic sensitivity 32 | } 33 | } 34 | void catcher_3() { // relies on dont_initialize() to avoid initialization 35 | while (true) { 36 | std::cout << sc_time_stamp() << ": catcher_3 triggered" << std::endl; 37 | wait(e); // dynamic sensitivity 38 | } 39 | } 40 | }; 41 | 42 | int sc_main(int, char*[]) { 43 | INITIALIZATION init("init"); 44 | sc_start(4, SC_SEC); 45 | return 0; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /basic/13_method/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/13_method/method.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(PROCESS) { 6 | SC_CTOR(PROCESS) { // constructor 7 | SC_THREAD(thread); // register a thread process 8 | SC_METHOD(method); // register a method process 9 | } 10 | void thread() { 11 | int idx = 0; // declare only once 12 | while (true) { // loop forever 13 | std::cout << "thread"<< idx++ << " @ " << sc_time_stamp() << std::endl; 14 | wait(1, SC_SEC); // re-trigger after 1 s 15 | } 16 | } 17 | void method() { 18 | // notice there's no while loop here 19 | int idx = 0; // re-declare every time method is triggered 20 | std::cout << "method" << idx++ << " @ " << sc_time_stamp() << std::endl; 21 | next_trigger(1, SC_SEC); 22 | } 23 | }; 24 | 25 | int sc_main(int, char*[]) { 26 | PROCESS process("process"); 27 | sc_start(4, SC_SEC); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /basic/14_event_queue/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/14_event_queue/event_queue.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(QUEUE) { 6 | sc_event e; 7 | sc_event_queue eq; 8 | SC_CTOR(QUEUE) { 9 | SC_THREAD(trigger); 10 | SC_THREAD(catch_e); 11 | sensitive << e; // catch_e() will be triggered by event e 12 | dont_initialize(); // don't run cach_e() during initialization phase 13 | SC_THREAD(catch_eq); 14 | sensitive << eq; // cach_eq() will be triggered by event queue eq 15 | dont_initialize(); // don't run catch_eq() during initialization phase 16 | } 17 | void trigger() { 18 | while (true) { 19 | e.notify(2, SC_SEC); // trigger e afer 2 s 20 | e.notify(1, SC_SEC); // trigger e after 1 s, replaces previous trigger 21 | eq.notify(2, SC_SEC); // trigger eq after 2 s 22 | eq.notify(1, SC_SEC); // trigger eq after 1 s, both triggers available 23 | wait(10, SC_SEC); // another round 24 | } 25 | } 26 | void catch_e() { 27 | while (true) { 28 | std::cout << sc_time_stamp() << ": catches e" << std::endl; 29 | wait(); // no parameter --> wait for static sensitivity, i.e. e 30 | } 31 | } 32 | void catch_eq() { 33 | while (true) { 34 | std::cout << sc_time_stamp() << ": catches eq" << std::endl; 35 | wait(); // wait for eq 36 | } 37 | } 38 | }; 39 | 40 | int sc_main(int, char*[]) { 41 | QUEUE queue("queue"); // instantiate object 42 | sc_start(20, SC_SEC); // run simulation for 20 s 43 | return 0; 44 | } -------------------------------------------------------------------------------- /basic/15_event_queue_combined/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/15_event_queue_combined/event_queue_combined.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(QUEUE_COMBINED) { 6 | sc_event_queue eq1, eq2; 7 | SC_CTOR(QUEUE_COMBINED) { 8 | SC_THREAD(trigger); 9 | SC_THREAD(catcher); 10 | sensitive << eq1 << eq2; // eq1 "or" eq2, cannot "and" 11 | dont_initialize(); 12 | } 13 | void trigger() { 14 | eq1.notify(1, SC_SEC); // eq1 at 1 s 15 | eq1.notify(2, SC_SEC); // eq1 at 2 s 16 | eq2.notify(2, SC_SEC); // eq2 at 2 s 17 | eq2.notify(3, SC_SEC); // eq2 at 3 s 18 | } 19 | void catcher() { 20 | while (true) { 21 | std::cout << sc_time_stamp() << ": catches trigger" << std::endl; 22 | wait(); // cannot use event queue in dynamic sensitivity 23 | } 24 | } 25 | }; 26 | 27 | int sc_main(int, char*[]) { 28 | QUEUE_COMBINED combined("combined"); 29 | sc_start(); 30 | return 0; 31 | } -------------------------------------------------------------------------------- /basic/16_channel_mutex/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/16_channel_mutex/mutex.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(MUTEX) { 6 | sc_mutex m; 7 | SC_CTOR(MUTEX) { 8 | SC_THREAD(thread_1); 9 | SC_THREAD(thread_2); 10 | } 11 | void thread_1() { 12 | while (true) { 13 | if (m.trylock() == -1) { // try to lock the mutex 14 | m.lock(); // failed, wait to lock 15 | std::cout << sc_time_stamp() << ": thread_1 obtained resource by lock()" << std::endl; 16 | } else { // succeeded 17 | std::cout << sc_time_stamp() << ": thread_1 obtained resource by trylock()" << std::endl; 18 | } 19 | wait(1, SC_SEC); // occupy mutex for 1 s 20 | m.unlock(); // unlock mutex 21 | std::cout << sc_time_stamp() << ": unlocked by thread_1" << std::endl; 22 | wait(SC_ZERO_TIME); // give time for the other process to lock the mutex 23 | } 24 | } 25 | void thread_2() { 26 | while (true) { 27 | if (m.trylock() == -1) { // try to lock the mutex 28 | m.lock(); // failed, wait to lock 29 | std::cout << sc_time_stamp() << ": thread_2 obtained resource by lock()" << std::endl; 30 | } else { // succeeded 31 | std::cout << sc_time_stamp() << ": thread_2 obtained resource by trylock()" << std::endl; 32 | } 33 | wait(1, SC_SEC); // occupy mutex for 1 s 34 | m.unlock(); // unlock mutex 35 | std::cout << sc_time_stamp() << ": unlocked by thread_2" << std::endl; 36 | wait(SC_ZERO_TIME); // give time for the other process to lock the mutex 37 | } 38 | } 39 | }; 40 | 41 | int sc_main(int, char*[]) { 42 | MUTEX mutex("mutex"); 43 | sc_start(4, SC_SEC); 44 | return 0; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /basic/17_channel_semaphore/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/17_channel_semaphore/semaphore.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(SEMAPHORE) { 6 | sc_semaphore s; // declares semaphore 7 | SC_CTOR(SEMAPHORE) : s(2) { // init semaphore with 2 resources 8 | SC_THREAD(thread_1); // register 3 threads competing for resources 9 | SC_THREAD(thread_2); 10 | SC_THREAD(thread_3); 11 | } 12 | void thread_1() { 13 | while (true) { 14 | if (s.trywait() == -1) { // try to obtain a resource 15 | s.wait(); // if not successful, wait till resource is available 16 | } 17 | std::cout<< sc_time_stamp() << ": locked by thread_1, value is " << s.get_value() << std::endl; 18 | wait(1, SC_SEC); // occupy resource for 1 s 19 | s.post(); // release resource 20 | std::cout<< sc_time_stamp() << ": unlocked by thread_1, value is " << s.get_value() << std::endl; 21 | wait(SC_ZERO_TIME); // give time for the other process to lock 22 | } 23 | } 24 | void thread_2() { 25 | while (true) { 26 | if (s.trywait() == -1) { // try to obtain a resource 27 | s.wait(); // if not successful, wait till resource is available 28 | } 29 | std::cout<< sc_time_stamp() << ": locked by thread_2, value is " << s.get_value() << std::endl; 30 | wait(1, SC_SEC); // occupy resource for 1 s 31 | s.post(); // release resource 32 | std::cout<< sc_time_stamp() << ": unlocked by thread_2, value is " << s.get_value() << std::endl; 33 | wait(SC_ZERO_TIME); // give time for the other process to lock 34 | } 35 | } 36 | void thread_3() { 37 | while (true) { 38 | if (s.trywait() == -1) { // try to obtain a resource 39 | s.wait(); // if not successful, wait till resource is available 40 | } 41 | std::cout<< sc_time_stamp() << ": locked by thread_3, value is " << s.get_value() << std::endl; 42 | wait(1, SC_SEC); // occupy resource for 1 s 43 | s.post(); // release resource 44 | std::cout<< sc_time_stamp() << ": unlocked by thread_3, value is " << s.get_value() << std::endl; 45 | wait(SC_ZERO_TIME); // give time for the other process to lock 46 | } 47 | } 48 | }; 49 | 50 | int sc_main(int, char*[]) { 51 | SEMAPHORE semaphore("semaphore"); 52 | sc_start(4, SC_SEC); 53 | return 0; 54 | } -------------------------------------------------------------------------------- /basic/18_channel_fifo/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/18_channel_fifo/fifo.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(FIFO) { 6 | sc_fifo f1, f2, f3; 7 | SC_CTOR(FIFO) : f1(2), f2(2), f3(2) { // fifo with size 2 8 | SC_THREAD(generator1); 9 | SC_THREAD(consumer1); 10 | 11 | SC_THREAD(generator2); 12 | SC_THREAD(consumer2); 13 | 14 | SC_THREAD(generator3); 15 | SC_THREAD(consumer3); 16 | } 17 | void generator1() { // blocking write 18 | int v = 0; 19 | while (true) { 20 | f1.write(v); // same as f = v, which is not recommended. 21 | std::cout << sc_time_stamp() << ": generator1 writes " << v++ << std::endl; 22 | wait(1, SC_SEC); // write every 1 s 23 | } 24 | } 25 | void consumer1() { // blocking read 26 | int v = -1; 27 | while (true) { 28 | f1.read(v); // same as v = int(f), which is not recommended; or, v = f1.read(); 29 | std::cout << sc_time_stamp() << ": consumer1 reads " << v << std::endl; 30 | wait(3, SC_SEC); // read every 3 s, fifo will fill up soon 31 | } 32 | } 33 | void generator2() { // non-blocking write 34 | int v = 0; 35 | while (true) { 36 | while (f2.nb_write(v) == false ) { // nb write until succeeded 37 | wait(f2.data_read_event()); // if not successful, wait for data read (a fifo slot becomes available) 38 | } 39 | std::cout << sc_time_stamp() << ": generator2 writes " << v++ << std::endl; 40 | wait(1, SC_SEC); // write every 1 s 41 | } 42 | } 43 | void consumer2() { // non-blocking read 44 | int v = -1; 45 | while (true) { 46 | while (f2.nb_read(v) == false) { 47 | wait(f2.data_written_event()); 48 | } 49 | std::cout << sc_time_stamp() << ": consumer2 reads " << v << std::endl; 50 | wait(3, SC_SEC); // read every 3 s, fifo will fill up soon 51 | } 52 | } 53 | void generator3() { // free/available slots before/after write 54 | int v = 0; 55 | while (true) { 56 | std::cout << sc_time_stamp() << ": generator3, before write, #free/#available=" << f3.num_free() << "/" << f3.num_available() << std::endl; 57 | f3.write(v++); 58 | std::cout << sc_time_stamp() << ": generator3, after write, #free/#available=" << f3.num_free() << "/" << f3.num_available() << std::endl; 59 | wait(1, SC_SEC); 60 | } 61 | } 62 | void consumer3() { // free/available slots before/after read 63 | int v = -1; 64 | while (true) { 65 | std::cout << sc_time_stamp() << ": consumer3, before read, #free/#available=" << f3.num_free() << "/" << f3.num_available() << std::endl; 66 | f3.read(v); 67 | std::cout << sc_time_stamp() << ": consumer3, after read, #free/#available=" << f3.num_free() << "/" << f3.num_available() << std::endl; 68 | wait(3, SC_SEC); // read every 3 s, fifo will fill up soon 69 | } 70 | } 71 | }; 72 | 73 | int sc_main(int, char*[]) { 74 | FIFO fifo("fifo"); 75 | sc_start(10, SC_SEC); 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /basic/19_signal_readwrite/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/19_signal_readwrite/signal_readwrite.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(SIGNAL) { 6 | sc_signal s; 7 | SC_CTOR(SIGNAL) { 8 | SC_THREAD(readwrite); 9 | } 10 | void readwrite() { 11 | s.write(3); 12 | std::cout << "s = " << s << "; " << s.read() << std::endl; 13 | wait(SC_ZERO_TIME); 14 | std::cout << "after delta_cycle, s = " << s << std::endl; 15 | 16 | s = 4; 17 | s = 5; 18 | int tmp = s; 19 | std::cout << "s = " << tmp << std::endl; 20 | wait(SC_ZERO_TIME); 21 | std::cout << "after delta_cycle, s = " << s.read() << std::endl; 22 | } 23 | }; 24 | 25 | int sc_main(int, char*[]) { 26 | SIGNAL signal("signal"); 27 | signal.s = -1; 28 | sc_start(); 29 | return 0; 30 | } -------------------------------------------------------------------------------- /basic/20_signal_event/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/20_signal_event/signal_event.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(SIGNAL_EVENT) { 6 | sc_signal s1, s2; // defines two signal channels 7 | SC_CTOR(SIGNAL_EVENT) { 8 | SC_THREAD(producer1); 9 | SC_THREAD(producer2); 10 | SC_THREAD(consumer); // consumer sensitive to (s1 OR s2) 11 | sensitive << s1 << s2; // same as: sensitive << s1.default_event() << s2.value_changed_event(); 12 | dont_initialize(); 13 | } 14 | void producer1() { 15 | int v = 1; 16 | while (true) { 17 | s1.write(v++); // write to s1 18 | wait(2, SC_SEC); 19 | } 20 | } 21 | void producer2() { 22 | int v = 1; 23 | while (true) { 24 | s2 = v++; // write to s2 25 | wait(3, SC_SEC); 26 | } 27 | } 28 | void consumer() { 29 | while (true) { 30 | if ( s1.event() == true && s2.event() == true) { // both triggered 31 | std::cout << sc_time_stamp() << ": s1 & s2 triggered" << std::endl; 32 | } else if (s1.event() == true) { // only s1 triggered 33 | std::cout << sc_time_stamp() << ": s1 triggered" << std::endl; 34 | } else { // only s2 triggered 35 | std::cout << sc_time_stamp() << ": s2 triggered" << std::endl; 36 | } 37 | wait(); 38 | } 39 | } 40 | }; 41 | 42 | int sc_main(int, char*[]) { 43 | SIGNAL_EVENT signal_event("signal_event"); 44 | sc_start(7, SC_SEC); 45 | return 0; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /basic/21_signal_many_writer/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/21_signal_many_writer/signal_many_writer.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(MULTI) { 6 | sc_signal s1; // a single-writer signal 7 | sc_signal s2; // a multi-writer signal 8 | SC_CTOR(MULTI) { 9 | SC_THREAD(writer1); // writes to s1 10 | SC_THREAD(writer2); // writes to s1 and s2 11 | SC_THREAD(consumer1); 12 | sensitive << s1; // sensitive to s1 13 | dont_initialize(); 14 | SC_THREAD(consumer2); 15 | sensitive << s1 << s2; // sensitive to s1 and s2 16 | dont_initialize(); 17 | } 18 | void writer1() { 19 | int v = 1; // init value 20 | while (true) { 21 | s1.write(v); // write to s1 22 | s2.write(v); // write to s2 23 | std::cout << sc_time_stamp() << ": writer1 writes " << v++ << std::endl; 24 | wait(1, SC_SEC); // write every 1 s 25 | } 26 | } 27 | void writer2() { 28 | int v = -1; // init value 29 | while (true) { 30 | // s1.write(v); /* cannot, otherwise runtime error: (E115) sc_signal cannot have more than one driver*/ 31 | wait(SC_ZERO_TIME); // needed to offset the write time. Otherwise runtime error: conflicting write in delta cycle 0 32 | s2.write(v); // write to s2 33 | std::cout << sc_time_stamp() << ": writer2 writes " << v-- << std::endl; 34 | wait(1, SC_SEC); // write every 1 s 35 | } 36 | } 37 | void consumer1() { 38 | while (true) { 39 | std::cout << sc_time_stamp() << ": consumer1 reads s1=" << s1.read() << "; s2=" << s2.read() << std::endl; // read s1 and s2 40 | wait(); // wait for s1 41 | } 42 | } 43 | void consumer2() { 44 | while (true) { 45 | std::cout << sc_time_stamp() << ": consumer2 reads s1=" << s1.read() << "; s2=" << s2.read() << std::endl; // read s1 and s2 46 | wait(); // wait for s1 or s2 47 | } 48 | } 49 | }; 50 | 51 | int sc_main(int, char*[]) { 52 | MULTI consumers("consumers"); 53 | sc_start(2, SC_SEC); // run simulation for 2 s 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /basic/22_resolved_signal/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/22_resolved_signal/resolved_signal.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | #include // use c++ vector lib 4 | using namespace sc_core; 5 | using namespace sc_dt; // sc_logic defined here 6 | using std::vector; // use namespace for vector 7 | 8 | SC_MODULE(RESOLVED_SIGNAL) { 9 | sc_signal_resolved rv; // a resolved signal channel 10 | vector levels; // declares a vector of possible 4-level logic values 11 | SC_CTOR(RESOLVED_SIGNAL) : levels(vector{sc_logic_0, sc_logic_1, sc_logic_Z, sc_logic_X}){ // init vector for possible 4-level logic values 12 | SC_THREAD(writer1); 13 | SC_THREAD(writer2); 14 | SC_THREAD(consumer); 15 | } 16 | void writer1() { 17 | int idx = 0; 18 | while (true) { 19 | rv.write(levels[idx++%4]); // 0,1,Z,X, 0,1,Z,X, 0,1,Z,X, 0,1,Z,X 20 | wait(1, SC_SEC); // writes every 1 s 21 | } 22 | } 23 | void writer2() { 24 | int idx = 0; 25 | while (true) { 26 | rv.write(levels[(idx++/4)%4]); // 0,0,0,0, 1,1,1,1, Z,Z,Z,Z, X,X,X,X 27 | wait(1, SC_SEC); // writes every 1 s 28 | } 29 | } 30 | void consumer() { 31 | wait(1, SC_SEC); // delay read by 1 s 32 | int idx = 0; 33 | while (true) { 34 | std::cout << " " << rv.read() << " |"; // print the read value (writer1 and writer2 resolved) 35 | if (++idx % 4 == 0) { std::cout << std::endl; } // print a new line every 4 values 36 | wait(1, SC_SEC); // read every 1 s 37 | } 38 | } 39 | }; 40 | 41 | int sc_main(int, char*[]) { 42 | RESOLVED_SIGNAL resolved("resolved"); 43 | sc_start(17, SC_SEC); // runs sufficient time to test all 16 resolve combinations 44 | return 0; 45 | } -------------------------------------------------------------------------------- /basic/23_signal_bool/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/23_signal_bool/signal_bool.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(SIGNAL_BOOL) { 6 | sc_signal b; 7 | SC_CTOR(SIGNAL_BOOL) { 8 | SC_THREAD(writer); 9 | SC_THREAD(consumer); 10 | sensitive << b; // triggered by every value change 11 | dont_initialize(); 12 | SC_THREAD(consumer_pos); 13 | sensitive << b.posedge_event(); // triggered by value change to true 14 | dont_initialize(); 15 | SC_THREAD(consumer_neg); 16 | sensitive << b.negedge_event(); // triggered by value change to false 17 | dont_initialize(); 18 | } 19 | void writer() { 20 | bool v = true; 21 | while (true) { 22 | b.write(v); // write to channel 23 | v = !v; // toggle value 24 | wait(1, SC_SEC); // write every 1 s 25 | } 26 | } 27 | void consumer() { 28 | while (true) { 29 | if (b.posedge()) { // if new value is true 30 | std::cout << sc_time_stamp() << ": consumer receives posedge, b = " << b << std::endl; 31 | } else { // if new value is false 32 | std::cout << sc_time_stamp() << ": consumer receives negedge, b = " << b << std::endl; 33 | } 34 | wait(); // wait for any value change 35 | } 36 | } 37 | void consumer_pos() { 38 | while (true) { 39 | std::cout << sc_time_stamp() << ": consumer_pos receives posedge, b = " << b << std::endl; 40 | wait(); // wait for value change to true 41 | } 42 | } 43 | void consumer_neg() { 44 | while (true) { 45 | std::cout << sc_time_stamp() << ": consumer_neg receives negedge, b = " << b << std::endl; 46 | wait(); // wait for value change to false 47 | } 48 | } 49 | }; 50 | 51 | int sc_main(int, char*[]) { 52 | SIGNAL_BOOL signal_bool("signal_bool"); 53 | sc_start(4, SC_SEC); 54 | return 0; 55 | } -------------------------------------------------------------------------------- /basic/24_buffer/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/24_buffer/buffer.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(BUFFER) { 6 | sc_signal s; // declares a signal channel 7 | sc_buffer b; // declares a buffer channel 8 | SC_CTOR(BUFFER) { 9 | SC_THREAD(writer); // writes to both signal and buffer 10 | SC_THREAD(consumer1); 11 | sensitive << s; // triggered by signal 12 | dont_initialize(); 13 | SC_THREAD(consumer2); 14 | sensitive << b; // triggered by buffer 15 | dont_initialize(); 16 | } 17 | void writer() { 18 | int val = 1; // init value 19 | while (true) { 20 | for (int i = 0; i < 2; ++i) { // write same value to channel twice 21 | s.write(val); // write to signal 22 | b.write(val); // write to buffer 23 | wait(1, SC_SEC); // wait after 1 s 24 | } 25 | val++; // value change 26 | } 27 | } 28 | void consumer1() { 29 | while (true) { 30 | std::cout << sc_time_stamp() << ": consumer1 receives " << s.read() << std::endl; 31 | wait(); // receives from signal 32 | } 33 | } 34 | void consumer2() { 35 | while (true) { 36 | std::cout << sc_time_stamp() << ": consumer2 receives " << b.read() << std::endl; 37 | wait(); // receives from buffer 38 | } 39 | } 40 | }; 41 | 42 | int sc_main(int, char*[]) { 43 | BUFFER buffer("buffer"); 44 | sc_start(4, SC_SEC); 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /basic/25_port/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/25_port/port.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(MODULE1) { // defines one module 6 | sc_signal s; // a signal (channel) inside the module 7 | sc_port > p; // a port used to write to an outside channel 8 | SC_CTOR(MODULE1) { 9 | SC_THREAD(selfWrite); // a process to write to own channel 10 | SC_THREAD(selfRead); // a process to read from own channel 11 | sensitive << s; // triggered by value change on the channel 12 | dont_initialize(); 13 | SC_THREAD(outsideWrite); // a process to write to an outside channel 14 | } 15 | void selfWrite() { 16 | int val = 1; // init value 17 | while (true) { 18 | s.write(val++); // write to own channel 19 | wait(1, SC_SEC); // repeat after 1 s 20 | } 21 | } 22 | void selfRead() { 23 | while (true) { 24 | std::cout << sc_time_stamp() << ": reads from own channel, val=" << s.read() << std::endl; // read from own channel 25 | wait(); // receives from signal 26 | } 27 | } 28 | void outsideWrite() { 29 | int val = 1; // init value 30 | while (true) { 31 | p->write(val++); // write to an outside channel, calls the write method of the outside channel. p is a pointer. 32 | wait(1, SC_SEC); 33 | } 34 | } 35 | }; 36 | SC_MODULE(MODULE2) { // a module that reads from an outside channel 37 | sc_port > p; // a port used to read from an outside channel 38 | SC_CTOR(MODULE2) { 39 | SC_THREAD(outsideRead); // a process to read from an outside channel 40 | sensitive << p; // triggered by value change on the channel 41 | dont_initialize(); 42 | } 43 | void outsideRead() { 44 | while (true) { 45 | std::cout << sc_time_stamp() << ": reads from outside channel, val=" << p->read() << std::endl; // use port to read from the channel, like a pointer. 46 | wait(); // receives from port 47 | } 48 | } 49 | }; 50 | 51 | int sc_main(int, char*[]) { 52 | MODULE1 module1("module1"); // instantiate module1 53 | MODULE2 module2("module2"); // instantiate module2 54 | sc_signal s; // declares a signal (channel) outside module1 and moudle2 55 | module1.p(s); // binds (connects) port p of module1 to channel (signal) s 56 | module2.p(s); // binds port p of module2 to channel s 57 | sc_start(2, SC_SEC); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /basic/26_export/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/26_export/export.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(MODULE1) { // defines one module 6 | sc_export> p; // an export for other modules to connect 7 | sc_signal s; // a signal (channel) inside the module. If not using export, the channel need to be defined outside module1. 8 | SC_CTOR(MODULE1) { 9 | p(s); // bind an export to an internal channel 10 | SC_THREAD(writer); // a process to write to an internal channel 11 | } 12 | void writer() { 13 | int val = 1; // init value 14 | while (true) { 15 | s.write(val++); // write to an internal channel 16 | wait(1, SC_SEC); 17 | } 18 | } 19 | }; 20 | SC_MODULE(MODULE2) { // a module that reads from an export 21 | sc_port> p; // a port used to read from an export of another module 22 | SC_CTOR(MODULE2) { 23 | SC_THREAD(reader); // a process to read from an outside channel 24 | sensitive << p; // triggered by value change on the channel 25 | dont_initialize(); 26 | } 27 | void reader() { 28 | while (true) { 29 | std::cout << sc_time_stamp() << ": reads from outside channel, val=" << p->read() << std::endl; // use port to read from the channel, like a pointer. 30 | wait(); // receives from port 31 | } 32 | } 33 | }; 34 | 35 | int sc_main(int, char*[]) { 36 | MODULE1 module1("module1"); // instantiate module1 37 | MODULE2 module2("module2"); // instantiate module2 38 | module2.p(module1.p); // connect module2's port to module1's export. No need to declare a channel outside module1 and module2. 39 | sc_start(2, SC_SEC); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /basic/27_port2port/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/27_port2port/port2port.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(SUBMODULE1) { // a submodule that writes to channel 6 | sc_port> p; 7 | SC_CTOR(SUBMODULE1) { 8 | SC_THREAD(writer); 9 | } 10 | void writer() { 11 | int val = 1; // init value 12 | while (true) { 13 | p->write(val++); // write to channel through port 14 | wait(1, SC_SEC); 15 | } 16 | } 17 | }; 18 | SC_MODULE(SUBMODULE2) { // a submodule that reads from channel 19 | sc_port> p; 20 | SC_CTOR(SUBMODULE2) { 21 | SC_THREAD(reader); 22 | sensitive << p; // triggered by value change on the channel 23 | dont_initialize(); 24 | } 25 | void reader() { 26 | while (true) { 27 | std::cout << sc_time_stamp() << ": reads from channel, val=" << p->read() << std::endl; 28 | wait(); // receives from channel through port 29 | } 30 | } 31 | }; 32 | SC_MODULE(MODULE1) { // top-level module 33 | sc_port> p; // port 34 | SUBMODULE1 sub1; // declares submodule 35 | SC_CTOR(MODULE1): sub1("sub1") { // instantiate submodule 36 | sub1.p(p); // bind submodule's port directly to parent's port 37 | } 38 | }; 39 | SC_MODULE(MODULE2) { 40 | sc_port> p; 41 | SUBMODULE2 sub2; 42 | SC_CTOR(MODULE2): sub2("sub2") { 43 | sub2.p(p); // bind submodule's port directly to parent's port 44 | } 45 | }; 46 | 47 | int sc_main(int, char*[]) { 48 | MODULE1 module1("module1"); // instantiate module1 49 | MODULE2 module2("module2"); // instantiate module2 50 | sc_signal s; // define channel outside module1 and module2 51 | module1.p(s); // bind module1's port to channel, for writing purpose 52 | module2.p(s); // bind module2's port to channel, for reading purpose 53 | sc_start(2, SC_SEC); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /basic/28_specialized_port/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/28_specialized_port/specialized_port.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(WRITER) { 6 | sc_out p1, p2; // specialized ports 7 | SC_CTOR(WRITER) { 8 | SC_THREAD(writer); 9 | p1.initialize(true); // #10, initialize default value to true 10 | } 11 | void writer() { 12 | bool v = true; 13 | while (true) { 14 | p1->write(v); // #2 write through port 15 | v = !v; // value change 16 | wait(1, SC_SEC); // repeat after 1 s 17 | } 18 | } 19 | }; 20 | SC_MODULE(READER) { 21 | sc_in p1, p2; // specialized ports 22 | SC_CTOR(READER) { 23 | SC_THREAD(reader1); 24 | sensitive << p1 << p2; // #3 default_event(), same as p->default_event() or p.default_event() 25 | dont_initialize(); 26 | SC_THREAD(reader2); 27 | sensitive << p1.value_changed(); // #11, sensitive to value change event of an un-bound port 28 | dont_initialize(); 29 | SC_THREAD(reader3); 30 | sensitive << p1.neg(); // #13, sensitive to neg event of an un-bound port 31 | dont_initialize(); 32 | SC_THREAD(reader4); 33 | sensitive << p1.pos(); // #12, sensitive to pos event of an un-bound port 34 | dont_initialize(); 35 | } 36 | void reader1() { 37 | while (true) { 38 | std::cout << sc_time_stamp() << ": default_event. p1 = " << p1->read() << "; p1 triggered? " << p1->event() << "; p2 triggered? " << p2->event() << std::endl; // #1 read(), #4 event() 39 | wait(); 40 | } 41 | } 42 | void reader2() { 43 | while (true) { 44 | std::cout << sc_time_stamp() << ": value_changed_event. p1 = " << p1->read() << std::endl; // #1 read() 45 | wait(); 46 | } 47 | } 48 | void reader3() { 49 | while (true) { 50 | std::cout << sc_time_stamp() << ": negedge_event. p1 = " << p1->read() << "; negedge = " << p1->negedge() << std::endl; // #8, if negedge happened 51 | wait(); 52 | } 53 | } 54 | void reader4() { 55 | while (true) { 56 | std::cout << sc_time_stamp() << ": posedge_event. p1 = " << p1->read() << "; posedge = " << p1->posedge() << std::endl; // #6, if posedge happened 57 | wait(); 58 | } 59 | } 60 | }; 61 | 62 | int sc_main(int, char*[]) { 63 | WRITER writer("writer"); // instantiate writer 64 | READER reader("reader"); // instantiate reader 65 | sc_signal b1, b2; // declare boolean signal channel 66 | writer.p1(b1); // port binding 67 | writer.p2(b2); 68 | reader.p1(b1); 69 | reader.p2(b2); 70 | sc_start(4, SC_SEC); 71 | return 0; 72 | } -------------------------------------------------------------------------------- /basic/29_port_array/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/29_port_array/port_array.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | #include // used to define a vector of ports 4 | using namespace sc_core; 5 | 6 | SC_MODULE(WRITER) { 7 | sc_port> p1; // #1: exactly 1 channel 8 | sc_port, 0> p2; // #2: 1 or more channels, no upper limit 9 | sc_port, 3> p3; // #3: 1, 2, or 3 channels 10 | sc_port, 0, SC_ZERO_OR_MORE_BOUND> p4; // #4: 0 or more channels, no upper limit 11 | sc_port, 1, SC_ZERO_OR_MORE_BOUND> p5; // #5: 0 or 1 channels 12 | sc_port, 3, SC_ZERO_OR_MORE_BOUND> p6; // #6: 0, 1, 2, or 3 channels 13 | sc_port, 3, SC_ALL_BOUND> p7; // #7: exactly 3 channels 14 | std::vector>> p9; // #9: vector of port 15 | SC_CTOR(WRITER) : p9(3) { // init p9 to size of 3 16 | SC_THREAD(writer); 17 | } 18 | void writer() { 19 | int v = 1; 20 | while (true) { 21 | p9[0]->write(v); // write to p9[0] 22 | p7[1]->write(v++); // write to p7[1] 23 | wait(1, SC_SEC); 24 | } 25 | } 26 | }; 27 | SC_MODULE(READER) { 28 | sc_port> p1; // #1: exactly 1 channel 29 | sc_port, 0> p2; // #2: 1 or more channels, no upper limit 30 | sc_port, 3> p3; // #3: 1, 2, or 3 channels 31 | sc_port, 0, SC_ZERO_OR_MORE_BOUND> p4; // #4: 0 or more channels, no upper limit 32 | sc_port, 1, SC_ZERO_OR_MORE_BOUND> p5; // #5: 0 or 1 channels 33 | sc_port, 3, SC_ZERO_OR_MORE_BOUND> p6; // #6: 0, 1, 2, or 3 channels 34 | sc_port, 3, SC_ALL_BOUND> p7; // #7: exactly 3 channels 35 | std::vector>> p9; // #9: exactly 3 channels 36 | SC_CTOR(READER) : p9(3) { // init p9 to size of 3 37 | SC_THREAD(reader7); 38 | sensitive << p7; // sensitive to any element of port array p7 39 | dont_initialize(); 40 | SC_THREAD(reader9); 41 | sensitive << p9[0] << p9[1] << p9[2]; // sensitive to any element of port array p9 42 | dont_initialize(); 43 | } 44 | void reader7() { 45 | while (true) { 46 | std::cout << sc_time_stamp() << "; reader7, port 0/1/2 = " << p7[0]->read() << "/" << p7[1]->read() << "/" << p7[2]->read() << std::endl; 47 | wait(); 48 | } 49 | } 50 | void reader9() { 51 | while (true) { 52 | std::cout << sc_time_stamp() << "; reader9, port 0/1/2 = " << p9[0]->read() << "/" << p9[1]->read() << "/" << p9[2]->read() << std::endl; 53 | wait(); 54 | } 55 | } 56 | }; 57 | 58 | int sc_main(int, char*[]) { 59 | WRITER writer("writer"); // instantiate writer 60 | READER reader("reader"); // instantiate reader 61 | // declare channels 62 | sc_signal s1; // 1 channel 63 | std::vector> s2(10); // 10 channels 64 | std::vector> s3(2); // 2 channel 65 | // leave s4 un-bound 66 | sc_signal s5; // 1 channel 67 | std::vector> s6(2); // 2 channels 68 | std::vector> s7(3); // 3 channels 69 | // #8 is same as #9, omitted 70 | std::vector> s9(3); // 3 channels 71 | // bind ports 72 | writer.p1(s1); // #1 73 | reader.p1(s1); // #1 74 | for (unsigned int i = 0; i < s2.size(); ++i) { // #2 75 | writer.p2(s2[i]); 76 | reader.p2(s2[i]); 77 | } 78 | for (unsigned int i = 0; i < s3.size(); ++i) { // #3 79 | writer.p3(s3[i]); 80 | reader.p3(s3[i]); 81 | } 82 | // s4 un-bound 83 | writer.p5(s5); // #5 84 | reader.p5(s5); // #5 85 | for (unsigned int i = 0; i < s6.size(); ++i) { // #6 86 | writer.p6(s6[i]); 87 | reader.p6(s6[i]); 88 | } 89 | for (unsigned int i = 0; i < s7.size(); ++i) { // #7 90 | writer.p7(s7[i]); 91 | reader.p7(s7[i]); 92 | } 93 | for (unsigned int i = 0; i < s9.size(); ++i) { // #9 94 | writer.p9[i](s9[i]); 95 | reader.p9[i](s9[i]); 96 | } 97 | sc_start(2, SC_SEC); 98 | return 0; 99 | } 100 | -------------------------------------------------------------------------------- /basic/30_primitive_channel/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/30_primitive_channel/prim_channel.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | #include 4 | using namespace sc_core; 5 | 6 | class GENERATOR_IF : public sc_interface { // interface for interrupt generator 7 | public: 8 | virtual void notify() = 0; 9 | }; 10 | class RECEIVER_IF : public sc_interface { // interface for interrupt receiver 11 | public: 12 | virtual const sc_event& default_event() const = 0; // needed for sensitive 13 | }; 14 | class INTERRUPT : public sc_prim_channel, public GENERATOR_IF, public RECEIVER_IF { // interrupt class 15 | public: 16 | INTERRUPT(sc_module_name name) : sc_prim_channel(name) {} // constructor, construct sc_prim_channel 17 | void notify() { // implement GENERATOR_IF 18 | e.notify(); 19 | } 20 | const sc_event& default_event() const { // implement RECEIVER_IF 21 | return e; 22 | } 23 | private: 24 | sc_event e; // private event for synchronization 25 | }; 26 | SC_MODULE(GENERATOR) { // interrupt generator class 27 | sc_port p; // port to generate interrupt 28 | SC_CTOR(GENERATOR) { // constructor 29 | SC_THREAD(gen_interrupt); 30 | } 31 | void gen_interrupt() { 32 | while (true) { 33 | p->notify(); // calls notify function of the INTERRUPT channel 34 | wait(1, SC_SEC); 35 | } 36 | } 37 | }; 38 | SC_MODULE(RECEIVER) { // interrupt receiver class 39 | sc_port p; // port to receive interrupt 40 | SC_CTOR(RECEIVER) { // constructor 41 | SC_THREAD(rcv_interrupt); 42 | sensitive << p; // monitors interrupt on port p 43 | dont_initialize(); 44 | } 45 | void rcv_interrupt() { // triggered upon interrupt 46 | while (true) { 47 | std::cout << sc_time_stamp() << ": interrupt received" << std::endl; 48 | wait(); 49 | } 50 | } 51 | }; 52 | 53 | int sc_main(int, char*[]) { 54 | GENERATOR generator("generator"); // instantiate generator 55 | RECEIVER receiver("receiver"); // instantiate receiver 56 | INTERRUPT interrupt("interrupt"); // instantiate interrupt 57 | generator.p(interrupt); // port binding 58 | receiver.p(interrupt); // port binding 59 | sc_start(2, SC_SEC); 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /basic/31_hierarchical_channel/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/31_hierarchical_channel/hierarchical_channel.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | // this is a simple implementation as compared to sc_signal, just to illustrate the concept of a hieracical channel 6 | class SIGNAL : public sc_channel, public sc_signal_inout_if { // declares SIGNAL channel, inherits from sc_chanel and signal_inout_if 7 | public: 8 | SC_HAS_PROCESS(SIGNAL); 9 | SIGNAL(sc_module_name name = sc_gen_unique_name("SIG")) : sc_channel(name) {} // constructor, construct base class 10 | void write(const int& v) { // implements write method 11 | if (v != m_val) { // update only if value is new 12 | m_val = v; // update value 13 | e.notify(); // trigger event 14 | } 15 | } 16 | const int& read() const { 17 | return m_val; 18 | } 19 | const sc_event& value_changed_event() const { 20 | return e; // return reference to the event 21 | } 22 | const sc_event& default_event() const { 23 | return value_changed_event(); // allows used in static sensitivity list 24 | } 25 | const int& get_data_ref() const { 26 | return m_val; 27 | } 28 | bool event() const { 29 | return true; // dummy implementation, always return true 30 | } 31 | private: 32 | int m_val = 0; 33 | sc_event e; 34 | }; 35 | 36 | SC_MODULE(TEST) { // a test class 37 | SIGNAL s; // declares SIGNAL channel 38 | SC_CTOR(TEST) { // no name provided to s, use default 39 | SC_THREAD(writer); // register a writer process 40 | SC_THREAD(reader); // register a reader process 41 | sensitive << s; // use SIGNAL channel in static sensitivity list 42 | dont_initialize(); 43 | } 44 | void writer() { 45 | int v = 1; 46 | while (true) { 47 | s.write(v++); // write to channel 48 | wait(1, SC_SEC); 49 | } 50 | } 51 | void reader() { 52 | while (true) { 53 | std::cout << sc_time_stamp() << ": val = " << s.read() << std::endl; // read from channel 54 | wait(); 55 | } 56 | } 57 | }; 58 | int sc_main(int, char*[]) { 59 | TEST test("test"); // instantiate generator 60 | sc_start(2, SC_SEC); 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /basic/32_trace/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/32_trace/trace.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(MODULE) { // a module write to a channel 6 | sc_port> p; // a port 7 | SC_CTOR(MODULE) { 8 | SC_THREAD(writer); // a writer process 9 | } 10 | void writer() { 11 | int v = 1; 12 | while (true) { 13 | p->write(v++); // write to channel via port 14 | wait(1, SC_SEC); // write every 1 s 15 | } 16 | } 17 | }; 18 | int sc_main(int, char*[]) { 19 | MODULE module("module"); // instantiate module 20 | sc_signal s; // declares signal channel 21 | module.p(s); // bind port to channel 22 | 23 | sc_trace_file* file = sc_create_vcd_trace_file("trace"); // open trace file 24 | sc_trace(file, s, "signal"); // trace "s" under the name of "signal" 25 | sc_start(5, SC_SEC); // run simulation for 5 s 26 | sc_close_vcd_trace_file(file); // close trace file 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /basic/33_report/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/33_report/report.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(MODULE) { // a test module 6 | sc_port> p; // a port 7 | SC_CTOR(MODULE) { // constructor 8 | SC_REPORT_WARNING("ctor", "register function"); // gen report to "ctor" 9 | SC_THREAD(writer); // a writer process 10 | SC_THREAD(reader); // a reader process 11 | sensitive << p; // sensitive to p 12 | dont_initialize(); 13 | } 14 | void writer() { 15 | int v = 1; 16 | while (true) { 17 | SC_REPORT_INFO("writer", ("write " + std::to_string(v)).c_str()); // gen report to "writer" 18 | p->write(v++); // write to channel via port 19 | wait(1, SC_SEC); // write every 1 s 20 | } 21 | } 22 | void reader() { 23 | while (true) { 24 | SC_REPORT_INFO("reader", ("read " + std::to_string(p->read())).c_str()); // gen report to "reader" 25 | wait(); 26 | } 27 | } 28 | }; 29 | int sc_main(int, char*[]) { 30 | sc_report_handler::set_log_file_name("report.log"); // initialize report 31 | sc_report_handler::set_actions("writer", SC_INFO, SC_LOG); // INFO of "writer" saved in log, no display 32 | 33 | MODULE module("module"); // instantiate module 34 | sc_signal s; // declares signal channel 35 | module.p(s); // bind port to channel 36 | 37 | SC_REPORT_INFO("main", "simulation starts"); // gen report to "main" 38 | sc_start(2, SC_SEC); // run simulation for 2 s 39 | SC_REPORT_INFO("main", "simulation ends"); // gen report to "main" 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /basic/34_customized_datatype/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/34_customized_datatype/customized_datatype.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | #include 4 | using namespace sc_core; 5 | 6 | struct CUSTOMIZED_TYPE { 7 | int x, y; // member variables 8 | CUSTOMIZED_TYPE(int x = 0, int y = 0) : x(x), y(y) {} // constructor 9 | CUSTOMIZED_TYPE& operator=(const CUSTOMIZED_TYPE& rhs) { // assignment operator, needed for read() write() 10 | x = rhs.x; 11 | y = rhs.y; 12 | return *this; 13 | } 14 | bool operator==(const CUSTOMIZED_TYPE& rhs) { // equality operator, needed for value_changed_event() 15 | return x == rhs.x && y == rhs.y; 16 | } 17 | }; 18 | std::ostream& operator<<(std::ostream& os, const CUSTOMIZED_TYPE& val) { // streaming output, needed for printing 19 | os << "x = " << val.x << "; y = " << val.y << std::endl; 20 | return os; 21 | } 22 | inline void sc_trace(sc_trace_file*& f, const CUSTOMIZED_TYPE& val, std::string name) { // needed for tracing 23 | sc_trace(f, val.x, name + ".x"); 24 | sc_trace(f, val.y, name + ".y"); 25 | } 26 | 27 | SC_MODULE(MODULE) { // test module 28 | sc_signal s; // customized signal 29 | SC_CTOR(MODULE) { // constructor 30 | SC_THREAD(writer); // writer process 31 | SC_THREAD(reader); // reader process 32 | sensitive << s; // sensitive to customized signal s 33 | dont_initialize(); 34 | } 35 | void writer() { 36 | int x = 1; // init signal 37 | int y = 2; 38 | while (true) { 39 | s.write(CUSTOMIZED_TYPE{x++, y++}); // write to signal 40 | wait(1, SC_SEC); // wait 1 s 41 | } 42 | } 43 | void reader() { 44 | while (true) { 45 | std::cout << sc_time_stamp() << ": receives " << s.read() << std::endl; // read from signal 46 | wait(); // wait for value_changed_event 47 | } 48 | } 49 | }; 50 | 51 | int sc_main(int, char*[]) { 52 | MODULE module("module"); // instantiate module 53 | sc_trace_file* file = sc_create_vcd_trace_file("trace"); // open trace file 54 | sc_trace(file, module.s, "customized_type"); // trace customized signal 55 | sc_start(2, SC_SEC); // run simulation for 2 s 56 | sc_close_vcd_trace_file(file); // close trace file 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /basic/35_clock/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/35_clock/clock.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(CLOCK) { 6 | sc_port> clk; // a port to access clock 7 | SC_CTOR(CLOCK) { 8 | SC_THREAD(thread); // register a thread process 9 | sensitive << clk; // sensitive to clock 10 | dont_initialize(); 11 | } 12 | void thread() { 13 | while (true) { 14 | std::cout << sc_time_stamp() << ", value = " << clk->read() << std::endl; // print current clock value 15 | wait(); // wait for next clock value change 16 | } 17 | } 18 | }; 19 | 20 | int sc_main(int, char*[]) { 21 | sc_clock clk("clk", 10, SC_SEC, 0.2, 10, SC_SEC, false); // 10s period, 2s true, 8s false, start at 10s, start at false. 22 | CLOCK clock("clock"); // instantiate module 23 | clock.clk(clk); // bind port 24 | sc_start(31, SC_SEC); // run simulation for 31 s 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /basic/36_cthread/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /basic/36_cthread/cthread.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(MODULE) { 6 | sc_in clk; // need event_finder method, cannot use basic sc_port 7 | SC_CTOR(MODULE) { 8 | SC_CTHREAD(cthread1, clk); // sensitive to clk pos edge 9 | // no static sensitivity, thus, cannot use dont_initialize() 10 | SC_CTHREAD(cthread2, clk.pos()); // sensitive to clk pos edge 11 | SC_CTHREAD(cthread3, clk.neg()); // sensitive to clk neg edge 12 | } 13 | void cthread1() { 14 | while (true) { 15 | wait(); // wait for clk pos edge; wait() right after while loop to avoid initialization 16 | std::cout << sc_time_stamp() << ", cthread1, value = " << clk->read() << std::endl; 17 | } 18 | } 19 | void cthread2() { 20 | while (true) { 21 | wait(); // wait for clk pos edge 22 | std::cout << sc_time_stamp() << ", cthread2, value = " << clk->read() << std::endl; 23 | } 24 | } 25 | void cthread3() { 26 | while (true) { 27 | wait(); // wait for clk neg edge 28 | std::cout << sc_time_stamp() << ", cthread3, value = " << clk->read() << std::endl; 29 | } 30 | } 31 | }; 32 | 33 | int sc_main(int, char*[]) { 34 | sc_clock clk("clk", 10, SC_SEC, 0.2, 10, SC_SEC, false); // 10s period, 2s true, 8s false, start at 10s, start at false. 35 | MODULE module("module"); // instantiate module 36 | module.clk(clk); // bind port 37 | sc_start(31, SC_SEC); // run simulation for 31 s 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /pattern/00_trigger_when_busy/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /pattern/00_trigger_when_busy/trigger.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | #include 4 | using namespace sc_core; 5 | 6 | SC_MODULE(MODULE) { 7 | sc_event trigger, dispatchTask; 8 | std::deque bufferedEvent; // can use other types to store states needed for the task processor 9 | SC_CTOR(MODULE) { 10 | SC_THREAD(task_trigger); 11 | SC_THREAD(trigger_handler); 12 | sensitive << trigger; 13 | dont_initialize(); 14 | SC_THREAD(task_processor); 15 | sensitive << dispatchTask; 16 | dont_initialize(); 17 | } 18 | void task_trigger() { 19 | while (sc_time_stamp() < sc_time(5, SC_SEC)) { // fire trigger even second for 5 seconds 20 | trigger.notify(); 21 | std::cout << "Trigger task at " << sc_time_stamp().to_seconds() << std::endl; 22 | wait(1, SC_SEC); 23 | } 24 | } 25 | void trigger_handler() { 26 | while (true) { 27 | bufferedEvent.push_back(true); // buffer the trigger 28 | dispatchTask.notify(); // dispatch the task 29 | wait(); 30 | } 31 | } 32 | void task_processor() { 33 | while (true) { 34 | while (!bufferedEvent.empty()) { // continue process while there are buffered events 35 | bufferedEvent.pop_front(); 36 | std::cout << "Process task at " << sc_time_stamp().to_seconds() << std::endl; 37 | wait(1.3, SC_SEC); // takes 1.3 second to process each trigger 38 | } 39 | wait(); 40 | } 41 | } 42 | }; 43 | 44 | int sc_main(int, char*[]) { 45 | MODULE module("module"); // instantiate module 46 | sc_start(); // run simulation 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /pattern/01_trigger_when_busy2/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /pattern/01_trigger_when_busy2/trigger2.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | #include 4 | using namespace sc_core; 5 | 6 | SC_MODULE(BufferTrigger_t) { // parent class to buffer the trigger 7 | sc_event trigger, dispatchTask; 8 | std::deque bufferedEvent; // can use other types to store states needed for the task processor 9 | SC_CTOR(BufferTrigger_t) { 10 | SC_THREAD(trigger_handler); 11 | sensitive << trigger; 12 | dont_initialize(); 13 | SC_THREAD(task_processor); 14 | sensitive << dispatchTask; 15 | dont_initialize(); 16 | } 17 | void trigger_handler() { 18 | while (true) { 19 | bufferedEvent.push_back(true); // buffer the trigger 20 | dispatchTask.notify(); // dispatch the task 21 | wait(); 22 | } 23 | } 24 | virtual void process_trigger() = 0; 25 | void task_processor() { 26 | while (true) { 27 | while (!bufferedEvent.empty()) { // continue process while there are buffered events 28 | bufferedEvent.pop_front(); 29 | process_trigger(); 30 | } 31 | wait(); 32 | } 33 | } 34 | }; 35 | struct MODULE2 : BufferTrigger_t { // derived class 36 | SC_HAS_PROCESS(MODULE2); 37 | MODULE2(sc_module_name name) : BufferTrigger_t(name) { 38 | SC_THREAD(task_trigger); // add a thread that notifies the trigger 39 | } 40 | void process_trigger() { // this is indirectly called by the trigger 41 | std::cout << "Process task at " << sc_time_stamp().to_seconds() << std::endl; 42 | wait(1.3, SC_SEC); // takes 1.3 second to process each trigger 43 | } 44 | void task_trigger() { // trigger function 45 | while (sc_time_stamp() < sc_time(5, SC_SEC)) { // fire trigger even second for 5 seconds 46 | trigger.notify(); // this will invoke the functions at the template class 47 | std::cout << "Trigger task at " << sc_time_stamp().to_seconds() << std::endl; 48 | wait(1, SC_SEC); 49 | } 50 | } 51 | }; 52 | 53 | int sc_main(int, char*[]) { 54 | MODULE2 module2("module2"); // instantiate module 55 | sc_start(); // run simulation 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /pattern/02_interrupt_when_busy/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /pattern/02_interrupt_when_busy/interrupt.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | 5 | SC_MODULE(MODULE) { // option: action upon interruption. 0: abort; 1: pause and resume 6 | sc_event trigger, dispatchTask, interrupt, taskDone; 7 | SC_HAS_PROCESS(MODULE); 8 | int option; 9 | sc_time taskDoneTime = SC_ZERO_TIME, taskRemainningTime = SC_ZERO_TIME; 10 | MODULE(sc_module_name name, int option = 0) : sc_module(name), option(option) { 11 | SC_THREAD(task_trigger); 12 | SC_THREAD(interrupt_generator); 13 | SC_THREAD(trigger_handler); // receive trigger, dispatch task 14 | sensitive << trigger; 15 | dont_initialize(); 16 | 17 | SC_THREAD(task_processor); // process task 18 | sensitive << dispatchTask; 19 | dont_initialize(); 20 | 21 | SC_THREAD(interrupt_handler); // receive interrupt 22 | sensitive << interrupt; 23 | dont_initialize(); 24 | 25 | SC_THREAD(task_done); 26 | sensitive << taskDone; 27 | dont_initialize(); 28 | } 29 | void task_trigger() { 30 | while (sc_time_stamp() < sc_time(2, SC_SEC)) { // fire trigger every second for 2 seconds 31 | trigger.notify(); 32 | std::cout << name() << ": Trigger task at " << sc_time_stamp().to_seconds() << std::endl; 33 | wait(1, SC_SEC); 34 | } 35 | } 36 | void interrupt_generator() { 37 | wait(0.2, SC_SEC); // interrupt fired 0.2 sec after task is triggered 38 | while (sc_time_stamp() < sc_time(2, SC_SEC)) { // fire interrupt every second for 2 seconds 39 | interrupt.notify(); 40 | std::cout << name() << ": Interrupt task at " << sc_time_stamp().to_seconds() << std::endl; 41 | wait(1, SC_SEC); 42 | } 43 | } 44 | void trigger_handler() { 45 | while (true) { 46 | dispatchTask.notify(); // dispatch the task 47 | wait(); 48 | } 49 | } 50 | void task_processor() { 51 | while (true) { 52 | std::cout << name() << ": Process task at " << sc_time_stamp().to_seconds() << std::endl; 53 | taskRemainningTime = sc_time(0.5, SC_SEC); // process takes 0.5 sec to finish 54 | taskDone.notify(taskRemainningTime); // process takes 0.5 second to finish 55 | taskDoneTime = sc_time_stamp() + taskRemainningTime; // if not interrupted, proc will be done at this time 56 | wait(); 57 | } 58 | } 59 | void interrupt_handler() { 60 | while (true) { 61 | taskDone.cancel(); // stop current process 62 | if (taskRemainningTime > SC_ZERO_TIME) { 63 | if (option == 0) { 64 | std::cout << name() << ": Process task aborted at " << sc_time_stamp().to_seconds() << std::endl; 65 | } else if (option == 1) { // pause and resume 66 | taskRemainningTime = (taskDoneTime - sc_time_stamp()); // process takes 0.5 sec to finish 67 | wait(0.3, SC_SEC); // wait 0.3 second, to handle interrupt 68 | std::cout << name() << ": Process task resumed at " << sc_time_stamp().to_seconds() << std::endl; 69 | taskDone.notify(taskRemainningTime); // process takes 0.5 second to finish 70 | taskDoneTime = sc_time_stamp() + sc_time(taskRemainningTime); // if not interrupted, proc will be done at this time 71 | } 72 | } 73 | wait(); 74 | } 75 | } 76 | void task_done() { 77 | while (true) { 78 | taskRemainningTime = SC_ZERO_TIME; 79 | std::cout << name() << ": Task completes at " << sc_time_stamp().to_seconds() << std::endl; 80 | wait(); 81 | } 82 | } 83 | }; 84 | 85 | int sc_main(int, char*[]) { 86 | MODULE module0("module0", 0); // task will be aborted upon interruption 87 | MODULE module1("module1", 1); // task will pause, and resume after interruption 88 | sc_start(); // run simulation 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /pattern/03_interrupt_when_busy2/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = out 2 | 3 | IDIR = . 4 | SDIR = . 5 | ODIR = . 6 | 7 | SRC = $(wildcard $(SDIR)/*.cpp) 8 | OBJ = $(SRC:$(SDIR)/%.c=$(ODIR)/%.o) 9 | 10 | CXX = g++ 11 | CXXFLAGS = -I$(IDIR) 12 | CXXFLAGS += -g -O0 13 | CXXFLAGS += -Iinclude 14 | CFLAGS += -Wall 15 | SCPATH = /usr/local/systemc-2.3.3 16 | LIBS = -lm 17 | 18 | $(TARGET): $(OBJ) 19 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -I$(SCPATH)/include -L. -L$(SCPATH)/lib-linux64 -Wl,-rpath $(SCPATH)/lib-linux64 $^ $(LIBS) -o $@ -lsystemc 20 | 21 | $(ODIR)/%.o: $(SDIR)/%.c 22 | $(CXX) $(CXXFLAGS) $(CFLAGS) -c $< -o $@ 23 | 24 | clean: 25 | $(RM) $(TARGET) 26 | -------------------------------------------------------------------------------- /pattern/03_interrupt_when_busy2/interrupt2.cpp: -------------------------------------------------------------------------------- 1 | // Learn with Examples, 2020, MIT license 2 | #include 3 | using namespace sc_core; 4 | struct sc_event2 : sc_event { // first extend sc_event, to allow pause/resume 5 | sc_time remainningTime, doneTime; 6 | bool isRunning = false; 7 | void notify(sc_time t) { 8 | isRunning = true; 9 | remainningTime = t; 10 | doneTime = sc_time_stamp() + remainningTime; 11 | sc_event::notify(t); 12 | } 13 | void pause() { 14 | remainningTime = doneTime - sc_time_stamp(); 15 | cancel(); 16 | } 17 | void resume() { 18 | notify(remainningTime); 19 | } 20 | void abort() { 21 | isRunning = false; 22 | cancel(); 23 | } 24 | operator bool() { 25 | return isRunning; 26 | } 27 | }; 28 | 29 | SC_MODULE(AllowIntrrupt_t) { 30 | sc_event task, dispatchTask, interrupt; 31 | sc_event2 taskDone; // allow being interrupted 32 | int option; // different options: abort or pause/resume 33 | SC_HAS_PROCESS(AllowIntrrupt_t); 34 | AllowIntrrupt_t(sc_module_name name, int option = 0) : sc_module(name), option(option) { 35 | SC_THREAD(task_handler); // receive task trigger, dispatch task 36 | sensitive << task; 37 | dont_initialize(); 38 | 39 | SC_THREAD(task_processor); // process task 40 | sensitive << dispatchTask; 41 | dont_initialize(); 42 | 43 | SC_THREAD(task_done); // callback when task completes 44 | sensitive << taskDone; 45 | dont_initialize(); 46 | 47 | SC_THREAD(interrupt_handler); // receive interrupt 48 | sensitive << interrupt; 49 | dont_initialize(); 50 | } 51 | void task_handler() { 52 | while (true) { 53 | dispatchTask.notify(); // dispatch the task 54 | wait(); 55 | } 56 | } 57 | void interrupt_handler() { 58 | while (true) { 59 | std::cout << name() << ": Task interrupted at " << sc_time_stamp().to_seconds() << std::endl; 60 | (option == 1 && taskDone) ? taskDone.pause() : taskDone.abort(); // pause if option 1 && isRunning 61 | interrupt_processor(); 62 | if (option == 1 && taskDone) { // result 63 | taskDone.resume(); 64 | } 65 | wait(); 66 | } 67 | } 68 | void task_done() { 69 | while (true) { 70 | taskDone.isRunning = false; 71 | std::cout << name() << ": Task complete at " << sc_time_stamp().to_seconds() << std::endl; 72 | wait(); 73 | } 74 | } 75 | virtual void task_processor() = 0; 76 | virtual void interrupt_processor() = 0; 77 | }; 78 | 79 | struct MODULE2 : AllowIntrrupt_t { 80 | SC_HAS_PROCESS(MODULE2); 81 | MODULE2(sc_module_name name, int option) : AllowIntrrupt_t(name, option) { 82 | SC_THREAD(task_trigger); 83 | SC_THREAD(interrupt_trigger); 84 | } 85 | void interrupt_processor() { // interruption will consume 0.3 second 86 | wait(0.3, SC_SEC); 87 | } 88 | void task_processor() { 89 | while (true) { 90 | std::cout << name() << ": Task start at " << sc_time_stamp().to_seconds() << std::endl; 91 | taskDone.notify(sc_time(0.5, SC_SEC)); // process takes 0.5 second to finish 92 | wait(); 93 | } 94 | } 95 | void task_trigger() { 96 | while (sc_time_stamp() < sc_time(2, SC_SEC)) { // fire trigger every second for 2 seconds 97 | task.notify(); 98 | wait(1, SC_SEC); 99 | } 100 | } 101 | void interrupt_trigger() { 102 | wait(0.2, SC_SEC); // interrupt fired 0.2 sec after task is triggered 103 | while (sc_time_stamp() < sc_time(2, SC_SEC)) { // fire interrupt every second for 2 seconds 104 | interrupt.notify(); 105 | wait(1, SC_SEC); 106 | } 107 | } 108 | }; 109 | int sc_main(int, char*[]) { 110 | MODULE2 module2a("module2a", 0); // task will abort 111 | MODULE2 module2b("module2b", 1); // task will pause, and resume after interruption 112 | sc_start(); // run simulation 113 | return 0; 114 | } 115 | --------------------------------------------------------------------------------