// Пример типа данных C++ int spark_offset; unsigned repairs = 0 ; // Count repair unsigned long mileage; // Miles driven short int speedometer; // -20.. 0.. 100 MPH float temperature; // Engine temp in C double time_of_last_request; //Time of bus std:: string license_plate; // Text for license const bool WARNING_LIGHT = true; // Status enum compass {SW,W,NW,N,NE,E, SE, S} ;
// Пример целочисленных типов данных C++ sc_int<LENGTH> NAME...; sc_uint<LENGTH> NAME...; sc_bigint<BITWIDTH> NAME...; sc_biguint<BITWIDTH> NAME...; // SystemC integer data types sc_int<5> seat_position=3; //5 bits: 4 plus sign sc_uint<13> days_SLOC(4000); //13 bits: no sign sc_biguint<80> revs_SLOC; // 80 bits: no sign
// Пример типа данных SystemC sc_bit NAME...; sc_bv<BITWIDTH> NAME...;
sc_bit flag(SC_LOGIC_1); // more efficient to use bool sc_bv<5> positions = "01101"; sc_bv<6> mask = "100111"; sc_bv<5> active = positions & mask;// 00101 sc_bv<1> all = active. and_reduce (); // SC_LOGIC_0 positions. range (3,2) = "00"; // 00001 positions [2] = active[0] ^ flag;
// Пример типа данных SystemC sc_logic NAME[,NAME]...; sc_lv<BITNIDTH> NAME[,NAME ]...; sc_logic buf(sc_dt::Log_Z); sc_lv<8> data_drive ("zz01XZ1Z"); data_drive.range (5,4) = "ZZ";// ZZZZXZ1Z buf = '1';
int main(int argc, char* argv[]) { BODY_OF_PROGRAM return EXIT_CODE; // }
int sc_main(int argc, char* argv[]) { //ELABORATION sc_start(); // <-- Simulation begins & ends // in this function! //[POST-PROCESSING] return EXIT_CODE; // }
#include <systemc.h> SC_MODULE(module_name) { MODULE_BODY };
Содержит:
SC_CTOR(module_name) : Initialization // могут отсутствовать объявления и инициализация сигналов { Subdesign_Allocation Subdesign_Connectivity Process_Registration Miscellaneous_Setup }
//FILE: module_name.h SC_MODULE(module_name) { SC_HAS_PROCESS(module_name); module_name(sc_module_name instname[, other_args…]) : sc_module(instname) [, other_initializers] { CONSTRUCTOR_BODY } };
SC_MODULE(simple_process_ex) { SC_CTOR(simple_process_ex) { SC_THREAD(my_thread_process); } void my_thread_process(void); };
SC_THREAD в SystemC:
Единицы измерения времени
SC_SEC // seconds SC_MS // milliseconds SC_US // microseconds SC_NS // nanoseconds SC_PS // picoseconds SC_FS // femtoseconds
sc_time t_PERIOD(5, SC_NS) ; sc_time t_TIMEOUT (100, SC_MS) ; sc_time t_MEASURE, t_CURRENT, t_LAST_CLOCK; t_MEASURE = (t_CURRENT-t_LAST_CLOCK) ; if (t_MEASURE > t_HOLD) { error ("Setup violated") }
Функция запускающая выполнения главного процесса
Пример запуска моделирования на 60 секунд модельного времени
int sc_main(int argc, char* argv[]) { // args unused simple_process_ex my_instance ("my_instance"); sc_start(60.0,SC_SEC); // Limit sim to one minute return 0 ; }
std::cout << " The time is now " << sc_time_stamp() << "!" << std::endl;
После запуска моделирования в консоли получим
The time is now 0 ns!
Функция останавливающая выполнение процесса до заданного времени или до прихода события
void simple_process_ex::my_thread_process (void) { wait (10,SC_NS); std::cout<< "Now at "<< sc_time_stamp() << std::endl; sc_time t_DELAY(2,SC_MS); // keyboard debounce time t_DELAY *= 2; std::cout<< "Delaying "<< t_DELAY<< std::endl; wait(t_DELAY); std::cout << "Now at " << sc_time_stamp() << std::endl; }
% . /run_example Now at 10 ns Delaying 4 ms Now at 4000010 ns
Процесс SC_THREAD процес выполняющийся один раз!!, для управления работой такого процесса используют функцию задержки выполнения wait
wait(time); wait(event); wait(event1 | event2) // до прихода любого из событий wait(event1 & event2) // до прихода всех событий вместе wait(timeout, event); // до прихода события ожидает в течении времени wait ( timeout, event1 | event2 ) wait ( timeout, event1 & event2 ) wait(); // ожидание дельта цикла выполнения, статическая задержка
Для запуска события используется атрибут .notify()
Он выполняет запуск событий, отсчет времени идет от запуска моделирования. Для сброса точки отсчета используют .cancel()
sc_event action; sc_time now(sc_time_stamp()); //вытягиваем текущее время моделирования //стартуем событие немедленно action.notify(); //следующее событие через 20 ms от текущего момента action.notify(20, SC_MS); //переопределим событие на время 1.5 ns от текущего момента action.notify(1.5,SC_NS); //продублируем событие (не имеет эффекта) action.notify(1.5, SC_NS); //зададим событие от предыдущего на 1.5 ns action.notify(3.0,SC_NS); //запустим дельта цикл (не имеет эффекта) action.notify(SC_ZERO_TIME); //сбросим время задания события action.cancel(); //зададим событие на 20 fs после сброса action.notify(20,SC_FS);
Отменяет начальную установку значений
Событие можно задать не только от начального момента времени, а и от текущего.
Для этого используется функция sc_event_queue()
sc_event_queue action; sc_time now(sc_time_stamp()); action.notify(20, SC_MS); action.notify(1.5,SC_NS); action.notify(1.5,SC_NS); action.notify(3.0,SC_NS); action.notify(SC_ZERO_TIME); action.notify(1,SC_SEC); action.cancel_all();
sc_mutex NAME; // блокируем mutex NAME (ждем пока разблокируется) NAME.lock(); // Возвращает статус состояния блокировки NAME.try lock() // Снимает блокировку NAME.unlock();
Если управлением доступом к нескольким ресурсам
sc_semaphore NAME(COUNT); // блокируем mutex NAME (ждем пока разблокируеться) NAME.wait(); // Возвращает статус состояния блокировки NAME.trywait() //Возвращает число свободных ресурсов NAME.get_value() // Снимает блокировку NAME.post();
Подключение и создание модуля внутри главного модуля аналогично созданию объекта заданного класса
Стандартная конструкция блока хранения информации для RFID
//FILE: main.cpp #include "Wheel.h" int sc_main(int argc, char* argv[]) { Wheel wheel_FL("wheel_FL"); Wheel wheel_FR("wheel_FR"); sc_start(); } |
//FILE: main.cpp #include "Wheel.h" int sc_main(int argc, char* argv[]) { Wheel* wheel_FL; // pointer to FL wheel Wheel* wheel_FR; // pointer to FR wheel wheel_FL = new Wheel ("wheel_FL"); // create FL wheel_FR = new Wheel ("wheel_FR"); // create FR sc_start(); delete wheel_FL; delete wheel_FR; } |
Подключение и создание модуля внутри другого модуля аналогично созданию объекта заданного класса, внутри другого класса. Поэтому объявления производиться в конструкторе верхнего модуля
//FILE:Body.h #include "Wheel.h" SC_MODULE(Body) { Wheel wheel_FL; Wheel wheel_FR; SC_CTOR(Body) : wheel_FL("wheel_FL"), //initialization wheel_FR("wheel_FR") //initialization { // other initialization } }; } |
//FILE:Body.h #include "Wheel.h" SC_MODULE(Body) { Wheel* wheel_FL; Wheel* wheel_FR; SC_CTOR(Body) { wheel_FL = new Wheel("wheel_FL"); wheel_FR = new Wheel("wheel_FR"); // other initialization } }; } |
Механизм использования sc_export порта напоминает доступ к сигналам по иерархии, как в VHDL-2008.
Пример поведенческой модели накопителя (VHDL) | Пример поведенческой модели накопителя (SystemVerilog) |
---|---|
entity soft is generic ( UART_Speed : integer := 115200; -- UART Speed System_CLK : integer := 50000000; -- System CLK in Hz comand_file : string :="/home/user/comfile.txt" ); port ( CLK : out std_logic; -- system clk RST_N : out std_logic; -- system reset# DATA_IN : out std_logic_vector(7 downto 0); -- Transmit data DATA_OUT : in std_logic_vector(7 downto 0); -- Recieved data RX_VALID : in std_logic; -- RX buffer data ready TX_VALID : out std_logic; -- Data for TX avaible TX_BUSY : in std_logic; -- RX_BUSY : in std_logic); end soft; |
SC_MODULE (soft_sc_module) { public : sc_in < sc_logic > tx_busy; sc_in < sc_logic > rx_busy; sc_in < sc_lv < 8 > > data_out; sc_in < sc_logic > rx_valid; sc_out < sc_logic > tx_valid; sc_out < bool > clk; sc_out < sc_logic > rst_n; sc_out < sc_lv < 8 > > data_in; public: ifstream fin; SC_CTOR(soft_sc_module) : rst_n("rst_n"), data_in("data_in"), data_out ("data_out"), rx_valid("rx_valid"), tx_valid("tx_valid"), tx_busy("tx_busy"), rx_busy("rx_busy"), rst_n_i("rst_n_i"), clk_i("clk_i"), clk("clk") { } ~soft_sc_module() { delete [] str_b; } }; #endif |
Пример Архитектуры на VHDL | Пример аналогичной конструкции на SystemC |
---|---|
architecture beh of soft is file comfile : text open read_mode is comand_file; begin -- beh -- тело архитектуры signal str : string(1 to 1000) := (others => ' '); signal RST_N_i : std_logic; signal DATA_IN_i : std_logic_vector(7 downto 0); signal f_get_answer : boolean := false; signal tmd : time := 0 ms; end beh; |
SC_MODULE (soft_sc_module) { public : std::string comand_file; public : sc_signal< sc_logic > rst_n_i; sc_signal< sc_lv < 8 > > data_in_i; sc_signal < bool > f_get_answer; sc_signal < sc_time > tmd; sc_time btmd (0, SC_MS); SC_CTOR(soft_sc_module) : rst_n_i("rst_n_i"), data_in_i("data_in_i"), f_get_answer("f_get_answer"), tmd("tmd") { str = new char [1000]; //объявление функций //выбор списка чувствительности //установка значений по умолчанию tmd.write(btmd); // tmd = btmd; // оператор присваивания перегружен и // выолнит вызов функции write } ~soft_sc_module() { delete [] str; } |
Пример на VHDL | Пример на SystemC (sc_get_param) |
---|---|
entity soft is generic (UART_Speed : integer := 115200; System_CLK : integer := 50000000 ); -- architecture beh of soft is CLK_i <= not CLK_i after 1 ns * (1e9 / System_CLK ); end beh; |
SC_MODULE (soft_sc_module) { public: SC_CTOR(soft_sc_module) : rst_n("rst_n"), tmd("tmd") { if (!sc_get_param("System_CLK",System_CLK)) cout << "error get generic"; if (!sc_get_param("UART_Speed",UART_Speed)) cout << "error get generic"; period_ns=(1000000000)/System_CLK; str = new char [1000]; } ~soft_sc_module() { delete [] str_b; } }; |
Пример на VHDL
wait_byte_timer: process begin -- process wiat_timer wait for 0.5 ms; if (NOW - tmd) > 1 ms then if f_start_get_answer then f_byte_timer <= true; wait for 0.1 ms; f_byte_timer <= false; end if; end if; end process wait_byte_timer; |
Пример на SystemC SC_MODULE (soft_sc_module) { public: SC_CTOR(soft_sc_module): { SC_METHOD (wait_byte_timer); } ~soft_sc_module() { } }; void soft_sc_module :: wait_byte_timer () { next_trigger (0.5,SC_MS); if ((sc_time_stamp()-tmd) > sc_time(1, SC_MS) ) if (f_start_get_answer) {f_byte_timer=true; next_trigger (0.1,SC_MS); f_byte_timer=false; } cout<< "wait_byte_timer work\n"; } |
Пример на VHDL
CLK_i <= not CLK_i after 1 ns * (1000000000 / System_CLK ); --или process (clk) begin if clk'event then clk_i <= not clk_i after 1 ns * (1000000000 / System_CLK ); end if; end process; |
Пример на SystemC SC_MODULE (soft_sc_module) { public: SC_CTOR(soft_sc_module): { clk_i=true; period_ns=(1000000000)/System_CLK; SC_METHOD (clk_gen); } ~soft_sc_module() { } }; void soft_sc_module :: clk_gen () { clk_i.write(!clk_i.read()); next_trigger (period_ns, SC_NS); } |
Пример на VHDL
RST_N <= RST_N_i; --или process (RST_N_i) begin if RST_N_i'event then RST_N <= RST_N_i; end if; end process; |
Пример на SystemC SC_MODULE (soft_sc_module) { public: SC_CTOR(soft_sc_module): { clk_i=true; SC_METHOD (rst_n_i2rst_n); sensitive << rst_n_i; dont_initialize(); } ~soft_sc_module() { } }; void soft_sc_module :: reset_gen () { rst_n_i.write( SC_LOGIC_0 ); wait (100, SC_NS); cout << "run reset"; rst_n_i.write( SC_LOGIC_1 ); } |
Пример на VHDL
p_send : process variable l : line; variable byte_r : std_logic_vector(0 to 7); variable good : boolean; variable f_first_byte : boolean:=false; begin -- process p1 loop1: while not endfile(comfile) loop readline (comfile,l); skip_space (l); next loop1 when l'length = 0; for i in 1 to l'length loop str(i) <= l(i); end loop; -- i str((l'length)+1 to 1000) <= (others => ' '); str_l <= l'length; |
if l(1) = '#' then assert false report "коментарий:"&str(1 to str_l) severity NOTE; else assert false report "коментарий"&str(1 to str_l) severity NOTE; f_first_byte := true; while l'length /= 0 loop hread (l,byte_r,good); assert good report "ошибка" severity FAILURE; if f_first_byte then f_first_byte := false; comand <= byte_r; end if; TX_VALID_i <= '1'; DATA_IN_i <= byte_r; skip_space (l); wait until TX_BUSY = '1'; end loop; f_start_timer <= true; TX_VALID_i <= '0'; wait until f_get_answer or f_timer; assert not f_timer report "1мкс" severity FAILURE; f_start_timer <= false; end if; end loop; assert false report "======" severity failure; end process p_send; |
Пример на SystemC
void soft_sc_module :: p_send () { fin.open(comand_file.c_str(),ios::out); cout << "work4\n"; bool f_first_byte=false; if (!fin){ std::cout << "File invalide open"; exit (0); } while (!fin.eof()){ fin.getline (str,1000); skip_space (&(str)); if (strlen(str)){ if (str[0] == '#') cout << "koment: "<< str <<endl; else { cout << "data: "<< str <<endl; f_first_byte=true; //while ( str[0] != '\0' ){ while ( strlen(str) ){ if ( str[0] == ' ' ) skip_space(&(str)); else { //cout << "1/2\n"; byte_b.range(7,4)=str[0]; str++; skip_space(&(str)); if (!strlen(str)){ cout<<endl<<"error"; sc_stop(); } else { //cout << "2/2\n"; byte_b.range(3,0)=str[0]; str++; } |
if (f_first_byte){ f_first_byte=false; comand=byte_b; } //cout << byte_b << endl; tx_valid_i.write(SC_LOGIC_1); data_in.write(byte_b); wait (tx_busy.posedge_event()); } } f_start_timer = true; tx_valid_i.write(SC_LOGIC_0); wait ( f_get_answer.posedge_event() | f_timer.posedge_event() ); if ( f_timer ) {cout << "error";sc_stop();} f_start_timer = false; } } str=str_b; } cout << "error"; fin.close(); sc_stop(); } |
Пример на VHDL
entity soft is end soft; architecture beh of soft is procedure skip_space (variable l : inout line) is variable char : character; variable flag : boolean:=true; begin -- skip_space while flag loop if l'length = 0 then flag := false; elsif l(1) = ' ' then read(l, char); else flag := false; end if; end loop; end skip_space; end beh; |
Пример на SystemC
SC_MODULE (soft_sc_module) { public: SC_CTOR(soft_sc_module): { SC_METHOD (wait_byte_timer); } void skip_space (char ** str); ~soft_sc_module() { } }; void soft_sc_module :: skip_space (char ** str) { bool flag = true; while ( flag ) { // if ( !strlen((*str)) ) flag = false; else if ((*str)[0]==' ') (*str) += 1; else flag = false; } } |
Пример на VHDL
procedure skip_space (variable l : inout line) is variable char : character; variable flag : boolean:=true; begin -- skip_space while flag loop if l'length = 0 then flag := false; elsif l(1) = ' ' then read(l, char); else flag := false; end if; end loop; end skip_space; |
Пример на SystemC void soft_sc_module :: skip_space (char ** str) { bool flag = true; while ( flag ) { // if ( !strlen((*str)) ) //if ( (*str)[0] == '\0' ) //EOS flag = false; else if ((*str)[0]==' ') (*str) += 1; else flag = false; } } |
Пример на VHDL
wait until f_get_answer or f_timer; --ждем пока придет ответ или пройдет время assert not f_timer report "превышено время ожидания ответа 1 мс" severity FAILURE; |
Пример на SystemC wait ( f_get_answer.posedge_event() | f_timer.posedge_event() ); if ( f_timer ) {cout << "превышено время ожидания ответа 1 мс";sc_stop();} |
Для запуска моделирования:
vsim voptargs=+acc work sc_module