Introdução
O exemplo que será apresentado agora é baseado na implementação da Transformada Rá- pida de Fourier (Fast Fourier Transform - FFT), disponibilizada no arquivo de exemplos do SystemC.
O objetivo da implementação original é fornecer uma implementação da FFT para ser usada com números inteiros e uma outra para ser utilizada com números de ponto flutuante. Para al- cançar este objetivo a implementação foi dividida em dois diretórios e seu respectivo conjunto de arquivos. A figura 25 nos mostra a estrutura dos módulos, que é a mesma para as duas im- plementações (o componente main não é verdadeiramente um módulo SystemC, mas representa a função principal do sistema, i.e., sc_main).
Motivação
Embora as duas implementações da FFT compartilhem a mesma estrutura, a escolha da transformada rápida de Fourier afeta bastante os módulos do sistema, de forma que todos os módulos do sistema precisam ser modificados para que se passe a utilizar uma FFT ao invés da outra. Podemos observar que a mudança de implementação da FFT altera o caminho de dados dos módulos, porém, os sinais/portas relacionados com o controle dos mesmo, permanecem inalterados, não sofrendo nenhuma modificação. Sendo assim, podemos tratar este exemplo
Sink FFT Source Wrapper
main
Figura 26: Nova Organização dos Módulos que Implementam a FFT
como um problema de separação entre controle e dados (THEKKATH; LEVY; LAZOWSKA,
1994;YANG; LI, 2004).
A idéia então é utilizar POA para encapsular em um aspecto este código relativo à imple- mentação da transformada rápida de Fourier que se espalha por vários módulos do sistema e que eventualmente será modificado se desejarmos mudar a nossa implementação. Tal código consiste de diversas portas de entrada e saída, além de funções que realizam o algoritmo da FFT.
Iremos também propor uma nova estrutura de módulos, inserindo o módulo Wrapper, que conterá o código responsável por conectar os módulos Sink, Source e FFT, de forma que o módulo main não sofrerá mais nenhuma influência desses módulos e nem será afetado pelo nosso aspecto. A nova estrutura dos módulos pode ser vista na figura 26.
Implementação
Com a nova estrutura elaborada, podemos ver como fica o esqueleto do nosso aspecto, o qual está representado na figura 27. Serão necessários dois aspectos, cada um será responsável por uma implementação diferente da FFT, de forma que poderemos escolher qual deles iremos utilizar apenas mudando uma opção de compilação. O aspecto apresentado na figura 27 é responsável pela implementação da FFT com números inteiros.
Na linha 1 nós declaramos o aspecto FXPT e em seguida, na linha 3, declaramos o con- junto de junção ptwrapper. Em seguida (linhas 5 −8), introduzimos variáveis relacionadas com implementação da FFT no módulo Wrapper, de forma a adaptá-lo para o algoritmo em ques- tão. Uma abordagem similar é realizada para os módulos Sink (linhas 10 − 13), Source (linhas 15 − 18) e FFT (linhas 20 − 25).
1 aspect FXPT { 2
3 pointcut ptwrapper () = "Wrapper"; 4
5 advice ptwrapper () : public: sc_signal <sc_int <WORD> > in_real; 6 advice ptwrapper () : public: sc_signal <sc_int <WORD> > in_imag; 7 advice ptwrapper () : public: sc_signal <sc_int <WORD> > out_real; 8 advice ptwrapper () : public: sc_signal <sc_int <WORD> > out_imag; 9
10 pointcut ptsink () = "Sink"; 11
12 advice ptsink () : public: sc_in <sc_int<WORD> > in_real; 13 advice ptsink () : public: sc_in <sc_int<WORD> > in_imag; 14
15 pointcut ptsource () = "Source"; 16
17 advice ptsource () : public: sc_out<sc_int<WORD> > out_real; 18 advice ptsource () : public: sc_out<sc_int<WORD> > out_imag; 19
20 pointcut ptfft () = "FFT"; 21
22 advice ptfft () : public: sc_in<sc_int<WORD> > in_real; 23 advice ptfft () : public: sc_in<sc_int<WORD> > in_imag; 24 advice ptfft () : public: sc_out<sc_int<WORD> > out_real; 25 advice ptfft () : public: sc_out<sc_int<WORD> > out_imag; 26
27 advice ptfft () : public: void func_butterfly ( ... ) { ... }; 28
29 advice execution ("void FFT::entry()") && that (ff): around (FFT& ff) 30 { ... }
31 32 };
Figura 27: Aspecto FXPT
O módulo FFT requer uma atenção especial, pois além de inserirmos um novo conjunto de portas de entrada/saída, devemos também modificar a sua função que realiza a transformada rápida de Fourier, bem como introduzir alguma outra função auxiliar. Na linha 27, adicionamos ao módulo FFT a função func_butterfly, que aqui teve a sua lista de parâmetros omitida e o seu corpo omitidos, para realizar a computação borboleta (butterfly).
Finalmente, nas linhas 29−30, introduzimos o método entry que será responsável por reali- azar a transformada rápida de Fourier, este método também teve o seu corpo omitido. Devemos notar, na linha 29, a chamada da função that para se obter um ponteiro para o objeto do tipo
Conclusão
Com a abordagem aqui apresentada, o código relacionado com a transformada rápida de Fourier para números inteiros, que antes encontrava-se espalhado por todos os módulos do nosso sistema, agora está bem localizado no aspecto FXPT, não afetando mais o restante do sistema. Esta abordagem também propiciou uma boa separação entre o código relacionado com fluxo de dados e o código relacionado com o fluxo de controle.
Uma abordagem utilizando somente técnicas de OO talvez não conseguisse uma boa se- paração de interesses, principalmente porque o código relacionado com a FFT ainda ficaria espalhado por diversos módulos do sistema, o que tornaria difícil a modificação do mesmo.