mastk escreveu:Essa tecnica é muito rica e versátil como todos falaram, acho que o deveríamos pensar e no que toca o empresariado é:
Seriamos mais rápidos em colocar uma solução no mercado com isso?
Aumentaria a recursos/funcionalidade/valor de um produto usar FPGA?
Quais chances existem de ter todo uma nova dimensão de possíveis bugs?
Logico que nada disso impede que tenhamos isso como carta na manga.
depende do tamanho da natureza e nivel de complexidade do seu problema!
evidentemente o "empresariado" tem que entender que nao existe uma solucao universal para todos os problemas, do contrario a sua continua sede de "lucros crescentes" vai fatidicamente se transformar em "prejuizos crescentes!" (:
na minha concepcao, qualquer problema generico pode ser expresso em duas formas: hardware ou software. e aqui entra o pulo do gato: perceber qual a melhor forma de expressar o problema! se vc pegar o extremo de cada solucao, problemas de software sao essencialmente sequenciais (pq o software tem o conceito de rodar sequencialmente passo a passo) enquanto que problemas de hardware sao essencialmente paralelos (pq o hardware tem o conceito de rodar tudo ao mesmo tempo em paralelo). vc pode paralelizar o software, mas o limite de n->inf software(n) = hardware, ou seja, paralelizar macicamente software acaba gerando um hardware que roda tudo em paralelo. da mesma forma, vc pode sequenciar o hardware, mas o limite de n->inf hardware(n) = software, ou seja, sequenciar macicamente o hardware acaba gerando um software que roda passo a passo. claro que o problema varia, de modo que o ponto ideal pode ser qualquer coisa entre um extremo paralelizavel ateh um extremo sequencial. antes fosse apenas isso, o problema varia em termos de complexidade, de modo que, independente de ser paralelizavel ou sequencial, o problema pode ser mais simples ou mais complexo. eventualmente, problemas sequenciais simples podem caber tranquilamente em uma solucao de hardware (as custas de sequenciar o hardware e, portanto, desperdicar logica), da mesma forma que problemas paralelos simples podem caber tranquilamente em uma solucao de software (multiplexando temporalmente o software sequencial e inserindo um certo jitter). assim, eh facil ver que a solucao correta para determinado problema acaba sendo a mais economica.
enfim, entendendo que os problemas podem ser natureza sequencia (software), paralela (hardware) ou um mix dos dois, variando bi-dimensionalmente na questao de complexidade, vc tem a disposicao as ferramentas para cada caso:
- problema puramente sequencial: a solucao aqui eh software, variando a ferramente de acordo com a performance requerida: microcontrolador para problemas mais simples (menos necessidade de performance e memoria), microprocessador para problemas mais complexos (mais necessidade de performance e memoria). arriscaria encaixar alguns DSPs baratos aqui, mas analisando bem eu nao sei dizer se o que chamam de DSPs baratos na realidade nao passam de microcontroladores. em essencia, sao para resolver problemas simples de software. o exemplo eh simples: vc tem um main() com um loop principal e nesse loop vc roda a sua aplicacao. eventualmente ela tem uma parte de input e output, mas eh puramente sequencial, algo como while(1) { input(); process(); output(); }... bem classico e simples. nao apenas nao existe simultaneidade, como o sequenciamento pode estar sujeito a um forte jitter e wander. a vantagem eh densidade: o codigo costuma ser compacto.
- problema sequencial que admite um certo grau de paralelismo: a solucao aqui ainda eh software, mas eventualmente admite algum tipo de paralelismo ou concorrencia. o leque de opcoes eh mais vasto, variando de microcontroladores mais potentes, com performance suficiente para multiplexar multiplos contextos e simular processos concorrentes, passando por microprocessadores (a vasta maioria jah projetada com foco em multiplos contextos concorrentes, incluindo possibilidade de multiplos cores e multiplas threads) e culminando com DSPs (geralmente projetados com foco no conceito de "multiplos canais", o que seria o apice da multiplexacao macica de recursos de software). o exemplo eh mais elaborado: vc tem um main() que dispara threads ou processos concorrentes. eh um negocio bem mais elaborado e, eventualmente, essa concorrencia pode ser melhorada atraves de multiplos cores/threads. observacionalmente, vc acha que as coisas rodam ao mesmo tempo, mas na pratica o que tem lah dentro eh um software sequencial que roda instrucao apos instrucao. um efeito colateral forte eh que a simultaneidade aparente, na realidade, estah sujeita a um forte jitter, mas a natureza mutiplexada costuma evitar wander. a densidade de codigo eh bem afetada nesse caso, mas ainda assim, a solucao eh compacta.
no outro extremo:
- problema puramente paralelo: a solucao aqui eh hardware, variando a ferramenta de acordo com a performance requerida: logica discreta 74xx (para problemas muito simples), CPLD (para problemas muito simples em uma forma mais compacta), FPGA (para problemas muito mais elaborados) ou ASIC (para problemas extremamente complexos!). bom, aqui nao tem segredo: se vc quiser, vc faz tudo com logica discreta 74xx. o limite eh a sua imaginacao e o espaco fisico disponivel. eventualmente, migrar para uma CPLD, FPGA ou ASIC eh um passo natural: vc nao tem espaco fisico. mas o problema se resolve da mesma forma em todos os casos: portas logicas e flip-flops, variando apenas a quantidade delas no mesmo encapsulamento. o exemplo classico eh a aplicacao que querer simultaneidade impecavel, sem jitter ou wander. a contra-partida eh a densidade: se vc tiver n instancias, vc vai ter n x a area em silicio. nao apenas isso, a area em silicio para esse tipo de solucao eh enorme comparada com um problema puramente sequencial: para m regras, vc tem m ramificacoes. no caso do software, eh computada apenas a ramificacao que vc executa, mas no caso do hardware todas as m ramificacoes sao computadas. eu chamo isso de solucao espacial, pq existe um hardware que ocupa espaco e cada instancia espacial computa um resultado diferente. para n instancias, tenho n * bandwidth de uma instancia.
- problema paralelo que admite um certo grau de sequencialidade: a solucao aqui eh hardware, mas pode ser multiplexado no tempo. devido a necessidade de armazenar contextos temporarios, acredito que requer pelo menos uma FPGA ou ASIC. em essencia, eh como pegar um problema puramente paralelo, implementado puramente em hardware e, ao inves de criar multiplas instancias paralelas, multiplexar uma unica instancia no tempo. isso significa que vc pode ter n instancias multiplexadas usando um unico hardware, o que significa fazer n canais, mas gastar 1/n do que gastaria se apenas replicasse tudo diretamente. eh um conceito desconfortavel para 90% dos desenvolvedores, mas eh onde eu moro 90% do tempo quando trabalho com FPGAs. o exemplo classico eh a aplicacao que requer simultaneidade impecavel, com jitter deterministico e ausencia de wander. ocupa menos espaco do que simplesmente replicar, mas na pratica tem um certo overhead: armazenar contextos e compensar jitter. assim, a vantagem de 1/n em comparacao com apenas replicar acaba sendo 2/n (observacao experimental minha), o que ainda eh um bom negocio. mas tem o impacto da performance: o bandwidth por instancia cai para 1/n. eu chamo isso de solucao temporal, pq existe um unico hardware mapeado no espaco e que eh compartilhado no tempo, onde cada instancia de tempo computa um resultado diferente. para n instancias, tenho bandwidth de uma instancia / n.
um adendo aqui... eh um tanto complexo, mas vamos lah: um exemplo pratico de problema puramente paralelo pode ser uma interface ethernet de 100Mbps que consome m slices. se vc for montar um switch com 8 interfaces, vc vai replicar o modulo 8x, consumindo assim 8 x m slices. porem, quando des-serializado, a interface ethernet de 100Mbps requer um bandwidth de apenas 12.5Mbytes/s. se vc conseguir entao multiplexar as interfaces (o que nao eh trivial), vc vai ter um bandwidth total de 100Mbytes/s, ainda tranquilo de atingir na maioria das FPGAs. claro, existe um overhead para trocar contexto e tal, mas no lugar de 8 x m slices, vc teria algo como 2 x m slices, o que jah seria 1/4 do silicio de uma solucao puramente replicada. o legal de ter 100Mbytes/s de bandwidth eh que rotear os frames diretamente de interface para interface pode ser algo bem otimizado e simples, tipo um crossbar 1 x n. outro exemplo complementar: uma ethernet de 1Gbps. nesse caso o bandwidth requerido para a interface des-serializada seria de 125Mbytes/s, jah acima do que seriam 8 x 100Mbps... bem consideravel! nesse caso, acredito que nao tem como multiplexar, pq nao tem bandwith suficiente na FPGA. aqui, entao, nao tem muito o que fazer, a nao ser replicar as portas. pior ainda, rotear os frames de 8 x 125Mbytes/s interfaces sem bandwidth extra pode nao ser nada trivial, entao ao contrario do caso acima, o roteamento de frames tem que ser passo a passo em um array de roteamento, o que adiciona latencia e consome area em silicio. no caso, 8 interfaces seriam necessarios, creio eu, 8 x (8-1) = 56 elementos de roteamento simples 1 x 2, se bem me lembro da teoria do negocio... uma salada que consome consideravelmente mais espaco! (:
bom, e aqui chegamos ao apice do negocio: vale a pena usar FPGA em tudo? acredito que nao. para problemas de hardware, faz todo sentido desde que nao caiba em uma solucao menor, mas nao para problemas de software. o primeiro contratempo eh que tentar paralelizar problemas de natureza essencialmente sequencial pode ser uma tarefa impossivel: cada if() no codigo sequencial causa uma mudanca de fluxo no codigo, mas os resultados sao computados apenas para uma ramificacao no software. no caso do hardware paralelizado, o ganho eh justamente computar os resultados para ambas as ramificacoes. entao, se o seu codigo tem 1 milhao de if()s sequenciais, vc tem um hardware com 1 milhao de resultados computados em paralelo. o ganho de performance eh realmente brutal (1 milhao de vezes!), mas o consumo de area em silicio provavelmente vai ser inviavel (1 milhao de vezes maior!). mas entao vc tem uma ideia genial: reciclar o hardware, ou seja, no lugar de computar 1 milhao de if()s sequenciais, criar uma forma de computacao generica em que possa parametrizar a entrada e com um unico modulo de processamento computar qualquer um dos if()s arbitrariamente... lamento informar que isso se chama microprocessador hehehe na pratica, vc vai gastar tempo projetando um hardware que te permite rodar software, mas como isso jah existe, seria melhor simplesmente usar um microcontrolador ou microprocessador existente.
e daih vem o supra-sumo da logica programavel: projetar um processador em uma FPGA. vale a pena? sim e nao. francamente, acho que colocar uma arquitetura existe costuma nao valer a pena: um exemplo pratico, que acompanho pq estou querendo matar um 68SEC000 faz anos e nao consigo... o chip continua em producao e eh barato, mais barato do que a FPGA necessaria para comportar a implementacao do 68SEC000 em verilog. o grande problema eh que as implementacoes existentes consomem muito silicio na FPGA, o que implica em uma FPGA muito mais cara que o processador real. ao mesmo tempo, a vantagem de performance nao existe: como trata-se de um processador complexo, alem de implementarem usando muito silicio, o resultado eh complexo demais e o clock maximo nao fica muito melhor: o chip real roda a 20MHz e builds tipicos rodam a 27MHz. mesmo a eventualidade de uma descontinuacao nao ajuda: o chip existe aos milhoes em brokers e eh barato o suficiente para ser estocado em grande quantidade. eh dificil, para a FPGA, bater o chip real, pq o overhead eh muito grande!
fugindo dos cores existentes, eh possivel colocar cores otimizados em uma FPGA rodando com performance elevada e com nivel de paralelismo maior que um core convencional. por exemplo, eu montei um core de 16 bits com apenas 100 linhas de verilog que consome 1/3 de uma XC3S50A, que eh a FPGA mais barata da xilinx, e roda a 80MHz. no caso da lattice, acredito que consome 1/2 da FPGA mais barata e roda a 40MHz, se bem me lembro da epoca em que testei. mesmo assim, sao FPGAs caras se comparadas com um microcontrolador barato, valendo a pena apenas no caso extremo de vc ter um problema que requer paralelizacao em hardware. nesse caso, ter um microcontrolador integrado na FPGA pode ajudar bastante, mas tem que ver bem: eh um hardware que tem como bonus um microcontrolador ali para ajudar. outra opcao eh o microblaze, mas ele eh meio grande e requer uma FPGA um pouco maior e mais cara, o que inviabiliza colocar multiplos cores... ele eh bom, mas eh um solucao bem convencional e fica bem pau a pau com uma solucao baseada em microprocessador tradicional, como um arm ou coldfire. a conta meio que nao fecha: vc coloca o microblaze em uma FPGA com, digamos 16 unidades MAC capazes de atingir 250MMAC/s, mas nivela em um unico core que malemal chega aos 100MMAC/s dos 4GMAC/s que a FPGA possui disponivel, ou seja, desperdicio. melhor entao usar um processador convencional... mas explorando a questao de paralelismo e performance, eh possivel arranhar a area de DSPs!
um exemplo pratico eh um core de DSP que um colega do trabalho desenvolveu em torno da unidade MAC da familia spartan-6 da xilinx. ele conseguiu otimizar um set de instrucoes e registros de modo que o tamanho do core ficasse compacto e, ao mesmo tempo, fosse possivel paralelizar multiplas operacoes, totalizando ateh 9 possibilidades. efetivamente, eu consigo usar umas 3 ou 4, mas mesmo assim eh um bonus interessante, pq rodando a 122MHz, se traduz em uma performance efetiva da ordem de uns 400 MIPS por core (das quais, uns 100 MMAC/s). mais interessante ainda, consegui entupir 15 destes cores em uma FPGA, o que se traduz em mais de 6000 MIPS (uns 1500MMAC/s). embora seja limitado a assembler apenas, eh ideal para otimizar manualmente o codigo e aproveitar o paralelismo do set de instrucoes. a parte legal eh que, depois de uns 2 anos que foi desenvolvido, eu estava trabalhando em outra FPGA e apareceu a necessidade de fazer algumas coisas um pouco mais complicadas... justamente resolver alguns problemas puramente sequenciais, como gerenciar uma FLASH SPI, calcular MD5 de imagens armazenadas e rodar algumas rotinas de self-test... poderia fazer com maquinas de estado, mas iria ocupar bastante espaco, entao eu simplesmente emprestei um daqueles cores de DSP e fiz tudo em assembler, jah com o bonus que o DSP estava debugado e nao iria perder tempo com isso.
e daih puxa o que vc perguntou sobre debugar: em essencia eu faco tudo no PC em C primeiro. quando tenho o codigo rodando redondo, comeco a portar aquele codigo de C para o assembler do DSP. obviamente tem um salto grande aqui, pq o DSP eh 16 bits com acumulador de 48 bits, bem diferente do PC que eh todo 32 bits, mas usando unsigned short e long long eu consigo mais ou menos simular numericamente os resultados como 16 e 64 bits. alem disso, tem inumeras restricoes de instrucoes e, ao mesmo tempo, suporta uma serie de paralelismos malucos. em primeira instancia, eu consigo encher o codigo C de printf() e consigo colocar $display() em pontos similares do codigo, de modo que eu posso bater numericamente os calculos e ver se esta tudo rodando certo. ao mesmo tempo, eu consigo colocar no simulador da FPGA os registros que quero acompanhar, como o program counter, acumulador e registros diversos. da mesma forma q vc acompanha formas de onda variando no tempo, os registros mudam conforme o fluxo das instrucoes. eh realmente bem interessante e nunca vi nada do genero para debugar software por aih. mas claro, passado o debug inicial de algumas funcoes, acompanhar isso comeca a ficar complicado... em milisegundos, vc vai ver milhares de instrucoes passando. entao eu costumo comecar a deixar o codigo rodar no simulador sem olhar muito pontualmente e comeco a bater os resultados macros entre o PC e o DSP. para isso coloco alguns $display() em pontos mais estrategicos, como variaveis principais de resultados e alguns $stop() ativados por instrucoes de breakpoint. em termos de simulacao, eh muito bom, mas restrito a milisegundos: nao existe memoria para simular a FPGA inteira por mais de 1 segundo! entao para algo mais complexo e longo, tem que ir para o HW real. e daih o debug eh osciloscopio ou via chipscope!
dito isso, vc pode ver que o negocio nao vai muito longe em termos de complexidade como microcontrolador e processador. ah, mas tem o zinq, por exemplo, que tem um core ARM... daih eh uma historia completamente diferente: o core eh silicio direto e roda com 800MHz. na pratica, eh um microprocessador com uma FPGA embutida, nao o contrario. ironicamente, parece ser melhor para rodar software do que para rodar hardware, visto que as necessidades do processador (FLASH, SDRAM, etc) consomem pinos e limitam as funcionalidades da FPGA. e bom, nao eh uma solucao barata ou simples: cobre um certo nivel de mercado, mas evidentemente nao eh uma solucao universal. como falei: para cada problema, tem uma solucao ideal.