1 / 48

SystemC 2.0.1

SystemC 2.0.1. Tiago Salmito mahatma@natalnet.br. SystemC. Biblioteca de classes para C++. Suporta o co-design do hardware-software e a descrição da arquitetura de sistemas complexos que consistem de componentes de software e hardware.

olin
Download Presentation

SystemC 2.0.1

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. SystemC 2.0.1 Tiago Salmito mahatma@natalnet.br

  2. SystemC • Biblioteca de classes para C++. • Suporta o co-design do hardware-software e a descrição da arquitetura de sistemas complexos que consistem de componentes de software e hardware. • Serve para criar a "especificação executável" de um sistema.

  3. Por que C? • C++ provê a abstração de controle e de dados necessários para descrição de sistemas. • A orientação a objeto e as macros do C++ nos permite estender a linguagem com classes, sem mudar a sua sintaxe.

  4. Benefícios da "Especificação Executável" • Evitar inconsistências, erros e garantir a completude do sistema; • Assegurar uma interpretação não ambígua para a especificação do sistema. • Verificar a funcionalidade do sistema antes do inicio da sua implementação. • Criar modelos de performance do sistema, ou validar a performance do sistema. • Os casos de testes usados na EE podem ser usados no teste da implementação do sistema. • O exato comportamento do sistema pode ser validado usando-se o Waveform Tracing.

  5. Definições • Módulos: São entidades hierárquicas onde podem conter outros módulos ou processos. • Processos: São usados para descrever as funcionalidades dos módulos. • Portas: Módulos possuem portas nas quais o conecta a outros módulos. Podem ser unidirecionais ou bidirecionais. • Sinais: São usados para se conectar portas (fios). Podem ser controlados por um (unresolved) ou vários (resolved) drivers. • Clocks: É um sinal especial usado para a sincronização do sistema durante a simulação.

  6. Metodologia de design sem SystemC

  7. Metodologia de design com SystemC

  8. SystemC 1.0 - Módulos • São os blocos de construção básicos no SystemC para particionar o design. • Eles encapsulam as representações dos dados internos e algoritmos de outros módulos. • São declarados: • Com a Macro: SC_MODULE(nome) { ... }; • Usando OO: struct nome : sc_module { ... }; • Um módulo pode conter diversos outros atributos como portas, sinais locais, dados locais, outros módulos, e construtores. • O construtor é declarado com a macro: SC_CTOR(nome_do_modulo) { ... }

  9. Módulos: Portas • Passam dados de (ou para) processos de um módulo. • Podem ser declaradas de 3 maneiras: • Entrada - sc_in<tipo> nome; • Saída - sc_out<tipo> nome; • Entrada/Saída - sc_inout<tipo> nome; • Os tipos das portas podem ser qualquer tipo do C++, do SystemC ou tipos definidos pelo usuário. • Exemplo: Flip Flop D SC_MOLDULE(dff) { sc_in<bool> din; sc_in<bool> clock; sc_out<bool> dout; ... };

  10. Módulos: Sinais • Representam os fios que interconectam os dispositivos de mesma hierarquia na implementação física do sistema. • Sinais carregam dados, e pode ser conectado a várias portas. • Exemplo: Filtro

  11. "Positional mapping" SC_CTOR(filtro) { s1 = new sample ("s1"); (*s1)(q,s); c1 = new coeff ("c1"); (*c1)(c); m1 = new mult ("m1"); (*m1)(s,c,q); } "Named mapping" SC_CTOR(filtro) { s1 = new sample ("s1"); s1->din(q); s1->dout(s); c1 = new coeff ("c1"); c1->out(c); m1 = new mult ("m1"); m1->a(s); m1->b(c); m1->q(q); } Módulos: Maneiras de conectar sinais

  12. Módulos: Armazenamento interno de dados #include "systemc.h" SC_MODULE(count) { sc_in<bool> load; sc_in<int> din; sc_in<bool> clock; sc_out<int> dout; int count_val; //armazenamento void count_up() { if (load) { count_val = din;} else { count_val++; } dout = count_val; } SC_CTOR(count) { SC_METHOD(count_up); sensitive_pos << clock; } }; • Para isso o designer precisa apenas declarar variáveis locais aos módulos. • Podem ser de qualquer tipo do C++, do SystemC ou definidos pelo usuário. • Exemplo:

  13. O verdadeiro trabalho dos módulos são feitos em processos. Processos são funções registradas no kernel do SystemC e são sensíveis a sinais. São "executados" a qualquer troca de valor do sinal na qual o processo é sensível. Exemplo: #include "systemc.h" SC_MODULE(dff) { sc_in<bool> din; sc_in<bool> clock; sc_out<bool> dout; void doit() { dout = din; } SC_CTOR(dff) { SC_METHOD(doit); sensitive_pos << clock; } }; Módulos: Processos

  14. É executado sempre que houver uma instanciação a um módulo. Define a estrutura de processos no kernel do SystemC e inicializa as variáveis internas. Exemplo: SC_MODULE(ram) { sc_in<int> addr; sc_in<int> datain; sc_in<bool> rwb; sc_out<int> dout; int memdata[64]; // memoria local int i; void ramread(); //processos void ramwrite(); SC_CTOR(ram){ SC_METHOD(ramread); sensitive << addr << rwb; SC_METHOD(ramwrite) sensitive << addr << datain << rwb; for (i=0; i++; i<64) { memdata[i] = 0; } } }; Módulos: Construtor

  15. Módulos: Casos de teste • São feitos através de módulos que geram estímulos e módulos que checam se a saída é coerente com a pós-condição

  16. Processos • São a unidade básica de execução no SystemC, são chamados para simular o comportamento do dispositivo ou sistema. • Existem 3 tipos de processos: • Métodos (SC_METHOD) • Threads (SC_THREAD) • Clocked Threads (SC_CTHREAD) • Não são hierárquicos. • Possuem uma lista de sensitividade e para estimular um processo deve-se ocorrer um evento.

  17. Processos: Métodos (SC_METHOD)

  18. Processos: Threads (SC_THREAD) • Executam indefinidamente e podem ser suspendidas e reativadas. • Podem executar o comando wait() para suspender. • São o são o caso mais geral de processo e podem ser usados para praticamente tudo. • Threads são implementados usando co-rotinas e a biblioteca do SystemC. • Exemplo: Sinal de transito. • SC_THREAD(sinal);

  19. Processos: Clocked Threads (SC_CTHREADS) • São um caso especial de Threads. • São usados para criar maquinas de estado implícitas. • Um estado é definido entre dois comandos wait() ou wait_until(). • Só pode ser sensível ao clock. • Exemplo: Um controlador de barramento.

  20. Diferenças entre threads e clocked threads • O processo Cthread especifica um objeto do tipo clock. • Cthread não possui lista de sensitividade. • A instrução wait_until só pode ser chamada através de um processo Cthread. • Um uso para o wait_until: wait_until(sensor.delayed() == true);

  21. Processos: Watching • Watching só pode ser usado por um processo Cthread. • Processos Cthread são loops infinitos. • Watching é a maneira de se controlar o loop. • Exemplo: • SC_CTHREAD(gen_data, clk.pos()); • watching(reset.delayed() == true);

  22. Portas e Sinais: • Para ler sinais das portas: • Use os métodos read() ou write() das portas ou o operador de atribuição. • -Se precisar fazer conversões de tipo use os métodos read() e write();

  23. Portas e Sinais: Resolved Logic Vectors • São usados para sinais que possuem mais de um driver. • Declarando a porta: sc_inout_rv<n> x; • Declarando o sinal: sc_signal_rv<n> x; • Exemplo:

  24. Conectando sinais e portas • Para conectar uma porta a um sinal eles devem ser do mesmo tipo. • Se for entre portas de mesmo nível de abstração: • Deve-se usar sinais. • Usa-se os métodos de “positional” ou “named mapping” • Se for entre portas de níveis diferente. • Não necessita de sinal (porta a porta). • Usa-se o método “named mapping”

  25. Clocks • É um objeto especial do SystemC. • Para criar um sinal de clock: • sc_clock clock(“nome”, 20, 0.5, 0, true); • Para se acessar o sinal de clock usa-se o método clock.signal();

  26. Tipos de dados do SystemC • sc_bit –2 value single bit type • sc_bit v=‘1’; sc_bit f=‘0’; • sc_logic – 4 value single bit type • sc_logic l=‘Z’; l=‘X’; l=

  27. Tipos de dados do SystemC • sc_int – 1 to 64 bit signed integer type • sc_int<40> int_de_40bits; • sc_uint – 1 to 64 bit unsigned integer type • sc_uint<22> uint_de_22bits; • sc_bigint – arbitrary sized signed integer type • sc_bigint<128> b; • sc_biguint – arbitrary sized unsigned integer type

  28. Tipos de dados do SystemC • sc_bv – arbitrary sized 2 value vector type • sc_bv<10> vetor_de_10_bits=“1110110010”; • sc_lv – arbitrary sized 4 value vector type • sc_lv<70> vetor_de_3_bits=“ZX01”;

  29. Tipos de dados do SystemC • Tipos definidos pelo usuário: • Exemplo: struct tipo_pacote { long info; int seq; int reenvios; inline bool operator == (const tipo_pacote& rhs) const { return (rhs.info == info && rhs.seq == seq && rhs.reenvios == reenvios); } };

  30. Simulação • A instanciação dos módulos é feita na rotina sc_main(); • Após instanciar e conectar os módulos aos sinais, é feita uma chamada a função sc_start(double); • A simulação pode ser parada, através da função sc_stop(); • Pode-se saber o tempo atual de simulação através da função double sc_simulation_time(); • Para ajudar no debug, todos as variáveis, portas e sinais podem ter seus sinais lidos e impressos.

  31. Simulação avançada • O SystemC te dá a opção de controlar o controle de sinais assincronamente. • Criar seu próprio clock. • Criar sinais assíncronos para teste do sistema. • É feito através das performativas sc_initialize() e sc_cycle(); • Exemplo: • sc_signal<bool> clock; ...; • sc_initialize(); • for (int i = 0; i <= 200; i++) • clock = 1; sc_cycle(10); • clock = 0; sc_cycle(10); • } • Equivale à: • sc_clock clk(“meu clock”, 20, 0.5); • sc_start(200);

  32. Traçando Formas de Ondas • SystemC pode criar arquivos nos formatos: • VCD (Value Change Dump) • ASCII WIF (Waveform Intermediate Format) • ou ISDB (Integrated Signal Data Base) • As formas de onda geradas podem ser visualizadas com qualquer software que suporte esses formatos. • Podem ser traçadas: • Somente variáveis que estão no escopo durante toda a simulação. • Sinais escalares, vetores ou de tipos agregados.

  33. Traçando Formas de Ondas • Criando arquivos: • sc_trace_file * my_trace_file; • my_trace_file = sc_create_vcd_trace_file(“my_trace”); • Fechando arquivos • sc_close_vcd_trace_file(my_trace_file); • Traçando variáveis e sinais escalares: • sc_trace(my_trace_file, var, “Variável”); • O primeiro argumento e um arquivo do tipo sc_trace_file. • O segundo argumento é uma referencia a variável a ser traçada. • O terceiro é uma string de referência.

  34. Traçando Formas de Ondas • Exemplo: sc_signal<int> a; float b; sc_trace(trace_file, a, “MyA”); sc_trace(trace_file, b, “B”); • Traçando variáveis de tipo agregado: struct bus { unsigned end; bool read_write; unsigned dado; }; void sc_trace(sc_trace_file *tf, const bus& v, const sc_string& NAME) { sc_trace(tf, v.end, NAME + “.end”); sc_trace(tf, v.read_write, NAME + “.rw”); sc_trace(tf, v.dado, NAME + “.dado”); }

  35. Traçando Formas de Ondas • Traçando vetores: void sc_trace(sc_trace_file *tf, sc_signal<int> *v, const sc_string& NAME, int len) { char stbuf[20]; for (int i = 0; i< len; i++) { sprintf(stbuf, “[%d]”, i); sc_trace(tf, v[i], NAME + stbuf); } }

  36. Pequeno Exemplo: Módulos #include <systemc.h> SC_MODULE(produtor) { sc_out<int> dout; sc_in<bool> clock; int dado; void produz() { dout = dado++; } SC_CTOR(produtor) { SC_METHOD(produz); sensitive_pos << clock; dado=0; } }; SC_MODULE(consumidor) { sc_in<int> din; void consome() { int tmp=din; printf(“Dado = %d”,tmp); } SC_CTOR(consumidor) { SC_METHOD(consome); sensitive << din; } };

  37. Pequeno Exemplo: Juntando módulos #include “modulos.h” int sc_main(int argdc, char ** argc) { sc_signal<int> barramento; sc_clock clk(“clock”, 20); produtor p(“produtor”); p.dout(barramento); p.clock(clk); consumidor c(“consumidor”); c << barramento; sc_trace_file * tf=sc_create_vcd_trace_file”(“produtor_consumidor”); sc_trace(tf, barramento, “Barramento"); sc_trace(tf, clk.signal(), “Clock"); sc_start(-1); }

  38. Estendendo o SystemC – SystemC 2.0 • A descrição estrutural do SystemC é suficiente para modelar sistemas (portas e módulos). • Porem a comunicação e a sincronização não é geral o suficiente para modelar em todos os níveis de sistema. • O SystemC 2.0 introduz novos conceitos para preencher essa lacuna. • Canais • Interfaces • Eventos

  39. Tempo relativo vs Tempo absoluto • Definição do clock: • SystemC 1.0: sc_clock clk( “clk”, 20 ); • SystemC 2.0: sc_clock clk( “clk”, 20, SC_NS ); ou sc_time t1( 20, SC_NS ); sc_clock clk( “clk”, t1 ); • SC_FS – femtoseconds • SC_PS – picoseconds • SC_NS – nanoseconds • SC_US – microseconds • SC_MS – milliseconds • SC_SEC – seconds Para se setar a unidade de tempo: sc_set_default_time_unit( 1, SC_PS ); (deve ser uma potência de 10)

  40. Eventos - SystemC 2.0 • Processos são sensíveis a eventos • O caso do SystemC 1.0 (portas) são um caso especial. • Wait() agora recebe o evento a ser esperado (lista de sensibilidade dinâmica) • wait( e1 | e2 | e3 ); • wait( 200, SC_NS ); • wait( 200, SC_NS, e1 | e2 | e3 ); • wait(); //systemc 1.0 • sc_event my_event; • my_event.notify(); //notifica agora • my_event.notify( 10, SC_NS ); //notifica em 10 nanosegundos • my_event.notify( SC_ZERO_TIME ); //proximo delta-cycle

  41. Interfaces – SystemC 2.0 • Definem métodos a serem implementados em um canal: template <class T> class sc_read_if : virtual public sc_interface { public: virtual const T& read() const = 0; }; • Métodos de sc_interface: • void register_port( sc_port_base&, const char* ) • Usado para verificação quando se conecta uma porta a essa interface. • const sc_event& default_event() • Usado para a sensibilidade estática do SystemC 1.0.

  42. Portas – SystemC 2.0 • Possuem interfaces. • Exemplo: sc_in<tipo> possui a interface sc_read_if. • Exemplo de porta: template <class T> class meu_sc_in: public sc_port<sc_read_if<T> > { public: operator const T&() const { return (*this)->read(); } }; • Uma porta deve possuir pelo menos uma interface.

  43. Canais – SystemC 2.0 • Um canal implementa uma ou mais interfaces: • Exemplo de canal: sc_signal é um canal que implementa as interfaces if_read e if_write. • Porém o sc_signal só pode possuir uma porta de saída conectada. (essa verificação é feita no método register_port()). • Exemplo: • Canal sc_fifo: • Só pode ter uma porta de entrada e uma de saída (nenhuma bidirecional).

  44. Canais: sc_fifo • O método register_port verifica as condições de conexão dos canais. template <class T> void sc_fifo<T>::register_port( sc_port_base& port,const char* if_typename ) { sc_string nm( if_typename ); if( nm == typeid( inout_interface<T> ).name() ) { error( “cannot connect to a bi-directional port” ); } else if( nm == typeid( in_interface<T> ).name() ) { if( no input port registered so far ) input_port = port; else error( “cannot connect to multiple inputs” ); } else { // nm == typeid( out_interface<T> ).name() if( no output port registered so far ) output_port = port; else error( “cannot connect to multiple outputs” ); } }

  45. Implementando Canais • O método update() de um canal irá ser chamado na fase de atualização dos canais. • É a hora de se determinar se há algum evento a ser gerado. • Exemplo de update: sc_signal virtual void update() { if( !( m_new_val == m_cur_val ) ) { m_cur_val = m_new_val; m_value_changed_event.notify( SC_ZERO_TIME ); }

  46. Pequeno Exemplo: Canais – sc_signal template <class T> class sc_signal: public sc_prim_channel, public sc_signal_inout_if<T> { public: sc_signal() : m_output( 0 ), m_driver( 0 ) {} virtual void register_port( sc_port_base& port, const char* if_typename ) { sc_string nm( if_typename ); if( nm == typeid( sc_signal_inout_if<T> ).name() ) { // a write or read/write port; only one can be connected if( m_output != 0 )error( “more than one write port\n” ); m_output = &port; } // any number of read ports can be connected: no check needed } virtual const T& read() const { return m_cur_val; } virtual const sc_event& default_event() const{ return m_value_changed_event; } virtual void write( const T& value ) { // dynamic design rule checking if( current_process() != m_driver ) { if( m_driver == 0 ) m_driver = current_process(); else error( “more than one driver\n” ); } m_new_val = value; if( m_new_val != m_cur_val ) request_update(); }

  47. Pequeno Exemplo: Canais – sc_signal protected: virtual void update() { if( !( m_new_val == m_cur_val ) ) { m_cur_val = m_new_val; m_value_changed_event.notify(SC_ZERO_TIME ); //notifica no próximo delta-cycle } } sc_port_base* m_output; // for static design rule checking sc_process_b* m_driver; // for dynamic design rule checking T m_cur_val; T m_new_val; sc_event m_value_changed_event;

  48. Fim

More Related