PROJECTO FINAL DE CURSOpaginas.fe.up.pt/~ee00236/RelatorioFINAL.pdf · 5.5.4- LVS 31 5.6-...
Transcript of PROJECTO FINAL DE CURSOpaginas.fe.up.pt/~ee00236/RelatorioFINAL.pdf · 5.5.4- LVS 31 5.6-...
PROJECTO FINAL DE CURSO
Criação de layouts digitais utilizando ferramentas de síntese e place&route automáticas
Relatório Final
Julho 2004
Aluno: Fernando José Soares Leal ( [email protected] ) Orientador: Prof. João Canas Ferreira ( [email protected] ) Página do Projecto: www.fe.up.pt/~ee00236/
ÍNDICE Pág.
1- OBJECTIVOS 3 1.1- Âmbito do trabalho 3
1.2- Objectivo do trabalho 4
2- ORGANIZAÇÃO 5 2.1- Faseamento e Calendarização 5
2.2- Local de Trabalho 5
2.3- Ferramentas de CAD utilizadas 6
3- DESCRIÇÃO DAS TAREFAS 7 3.1- Síntese Lógica 7
3.2- Place&Route 7
3.1- Extração e Verificação ( DRC e LVS ) 8
4- TRABALHO INICIAL 9 5- BLOCO 1 – TRABALHO 11 5.1- Descrição do Bloco 11
5.2- Tecnologia 11
5.3- Síntese 12
5.3.1- Configuração do Design Compiler 12
5.3.2- Estratégia de Síntese 13
5.3.3- Scripts de Síntese para os Sub-Blocos 14
5.3.4- Scritpt de Síntese para o Top-Level 16
5.3.5- Resultados da Síntese 19
5.3.6- Notas finais relativas à Síntese 19
5.4- Place&Route 20
5.4.1- Trabalho Inicial 20
5.4.2- Descrição do Place&Route 20
5.4.2.1- CT-Gen 23
5.4.3- Ficheiro Final 26
5.4.4- Circuito 27
5.5- DRC e LVS 28
5.5.1- Requisitos 28
5.5.2- GDS e Extracção da Netlist spice 28
5.5.3- DRC 30
1
5.5.4- LVS 31
5.6- Conclusão 32
5.7- Nota sobre os ficheiros Utilizados 32
6- PROGRESSO DO TRABALHO 33
7- CONCLUSÕES 34
BIBLIOGRAFIA 35
2
1- OBJECTIVOS
Antes de descrever mais pormenorizadamente os objectivos do trabalho, convirá
talvez situá-lo no contexto do projecto de circuitos digitais em microelectrónica.
1.1- Âmbito do trabalho
O projecto de circuitos integrados digitais para fins específicos ( ASIC1 ) pode ser feito
utilizando uma de várias técnicas diferentes, como por exemplo Full-Custom,
Standard Cells, Sea-of-Gates (SOG) ou implementação numa FPGA. Qualquer um
deles tem vantagens e desvantagens conforme o tipo de circuito e especificações
pretendidas. Talvez os mais utilizados sejam o Full-Custom, em que o circuito é
desenhado de raiz ao nível físico pelo projectista ( utilizando ferramentas de CAD
apropriadas ) e que permite obter resultados muito optimizados em termos de
especificações; e o Standard-Cells, em que o projectista dispõe de uma biblioteca de
células para uma dada tecnologia, já correctamente codificadas e testadas e, fazendo
uso de ferramentas de CAD apropriadas, as utiliza para obter o circuito desejado
cumprindo o melhor possível as especificações.
O projecto de circuitos digitais em Standard Cells divide-se em duas grandes fases
designadas por Frontend e Backend Diigitais:
1ª fase ( Frontend )- Criação de netlists do circuito elaboradas utilizando uma
das linguagens de descrição de hardware ( HDL ) - Verilog ou VHDL – e posterior
verificação e validação das mesmas, recorrendo a ferramentas de simulação.
2ª fase ( Backend )- Síntese, Place & Route, extração e verificação efectuadas
partindo das netlists geradas na fase anterior.
No final da segunda fase, o projectista dispõe de um ficheiro em formato adequado
pronto para enviar para produção.
1 ASIC- Application Specific Integrated Circuit
3
1.2- Objectivo do trabalho
O trabalho insere-se na segunda fase do processo de projecto em Standard-Cells
descrito no ponto anterior.
Pretendia-se portanto, executar as tarefas de Síntese e Place&Route de um
determinado número de blocos digitais, descritos em Verilog e já correctamente
validados.
Estas tarefas são parcialmente automatizadas, sendo para tal utilizadas diversas
ferramentas de CAD disponíveis no laboratório da faculdade e utilizadas não só pela
empresa, mas também pela generalidade das empresas da área a nível mundial.
Apesar de parcialmente automatizadas, estas tarefas são de vital importância para o
sucesso ou fracasso do circuito pretendido.
É portanto de primordial importância uma utilização correcta das ferramentas de
software. Estas ferramentas são bastante poderosas, permitindo inúmeras hipóteses
de utilização, e dando por isso ao utilizador uma grande liberdade em termos de
projecto. Tornam-se no entanto bastante complexas de utilizar e, especialmente, de
utilizar tirando delas aquilo que pretendemos.
Pretende-se com o trabalho assegurar que, no final do mesmo, tenham sido
adquiridos conhecimentos profundos na utilização das várias ferramentas de CAD
envolvidas, bem como tomar contacto com os diversos pormenores / problemas que
se poderão colocar ao projectista, de forma a obter os melhores resultados possíveis
para cada um dos blocos digitais a trabalhar.
4
2- ORGANIZAÇÃO
Pretendo, neste capítulo, sumarizar todos os aspectos relacionados com a
organização do trabalho, nomeadamente faseamento e calendário previsto, locais de
trabalho e ferramentas de software utilizadas.
2.1- Faseamento e Calendarização
Tal como descrito na proposta de projecto, o mesmo consistiria na realização de um
primeiro bloco, seguido de um segundo um pouco mais complexo. Conforme o
andamento do trabalho, poder-se-ia pôr a hipótese de um terceiro bloco. No final
reservava-se ainda um período para realização do relatório final e preparação da
apresentação.
Inicialmente estava previsto um período prévio de estudo das várias ferramentas a
utilizar. Ficou no entanto acordado, numa reunião de planeamento entre os
intervenientes, que o estudo de cada ferramenta seria feito quando a mesma fosse
necessária para a sequência do trabalho.
Previa-se a realização do primeiro bloco durante os meses de Março e Abril sendo o
restante trabalho distribuído por Maio e Junho.
2.2- Local de Trabalho
O trabalho seria desenvolvido no Laboratório de Microelectrónica ( I223 ) da FEUP,
sendo algumas partes realizadas nas instalações da Chipidea na Maia.
5
2.3- Ferramentas de CAD utilizadas
O trabalho seria realizado em ambiente UNIX utilizando as seguintes ferramentas de
CAD:
Síntese: Design Compiler da Synopsys ( versão 2001.08 )
Place& Route: Silicon Ensemble da Cadence ( versão 5.3 )
LVS e DRC: Calibre da Synopsys2
Foi igualmente usado o Cadence ICFB na versão 4.4.5.
2 aconselhado pela foundry para verificação final ( signoff ) na tecnologia utilizada.
6
3- DESCRIÇÃO DAS TAREFAS
Pretendo, neste capítulo, apresentar uma pequena descrição genérica daquilo em
que consistem as tarefas referidas atrás. As descrições pormenorizadas relativas
especificamente aos blocos trabalhados, serão apresentadas nos capítulos referentes
à descrição do trabalho efectuado, apresentados mais à frente neste relatório.
3.1- Síntese Lógica
A síntese de um bloco digital corresponde à tradução e optimização do HDL que
descreve o bloco em portas lógicas. Esta tarefa tem portanto como início, a descrição
de alto nível do bloco, feita no caso em Verilog, e origina no final, uma netlist ao nível
de portas lógicas ( gate-level ). O processo é executado utilizando a ferramenta de
síntese, com todos os comandos necessários à definição de condições de operação,
particularidades do circuito e imposição de restrições temporais que permitam o
cumprimento das especificações. Resumidamente, a ferramenta irá fazer, de acordo
com as instruções recebidas, a compilação do Verilog e optimização do resultado,
gerando no final a netlist gate-level que irá ser utilizada na fase seguinte.
3.2- Place&Route
O Place & Route, ou colocação e encaminhamento, corresponde à criação do layout
físico do circuito. Sendo assim, e partindo da netlist gerada pela síntese, a ferramenta
de P&R irá proceder à colocação das células da biblioteca tecnológica adequadas às
referidas na netlist da forma que o utilizador indicar ( colocação ), para posteriormente
fazer todas as ligações necessárias entre elas ou com o exterior ( encaminhamento ).
Resumindo, a ferramenta irá receber a netlist e procederá ao “desenho” físico do
7
circuito para posterior produção, sendo que para tal será gerado no final um ficheiro
bitstream no formato adequado ( GDS ).
3.3- Extração e Verificação ( DRC e LVS )
Esta é uma fase final de verificação ( chamada signoff ) em que se procede ao DRC (
Design Rule Check ) e ao LVS ( Layout Versus Schematic ). O LVS consiste numa
comparação entre a conectividade existente no layout gerado e uma netlist spice
extraída a partir do esquemático do circuito pretendido. É feita uma ferramenta
automática de forma a tentar encontrar eventuais discrepâncias. O DRC consiste
mais uma vez na utilização de uma ferramenta automática para detecção de
eventuais violações das regras de desenho específicas da tecnologia.
8
4- TRABALHO INICIAL
Comecei o trabalho com a ambientação à primeira ferramenta de CAD a utilizar-
Design Compiler da Synopsys. Este estudo consistiu na leitura dos manuais
disponíveis e na execução de alguns tutoriais.
Através deles tomei contacto com as duas formas de utilizar o software - através de
linha de comandos ( dc_shell ) ou através de uma interface gráfica ( design_analyzer
). Embora o segundo método seja bastante mais agradável e intuitivo, o primeiro
permite uma utilização bastante mais rápida e eficiente, nomeadamente na repetição
de tarefas. Para tal são usados scripts com os comandos necessários.
Pretendia-se que, para fazer a síntese dos blocos, fossem criados scripts para serem
utilizados directamente em linha de comandos. No entanto, nesta fase de trabalho
inicial, preocupei-me essencialmente em tomar conhecimento dos comandos mais
importantes disponíveis, bem como do funcionamento geral da ferramenta, tendo
para isso utilizado maioritariamente o modo gráfico, procedendo à introdução de
comandos através dos menus. Este modo permite ter uma melhor noção de como
ficam organizados os diversos blocos hierárquicos dentro do circuito a sintetizar, e
assim tentar organizar a melhor sequência de comandos para a síntese. Devo dizer
que mesmo depois, durante o trabalho efectivo no circuito pretendido, utilizei o modo
gráfico por algumas vezes para “confirmar” de uma forma mais visível a sequência da
síntese feita através de scripts.
Os circuitos usados nestes tutoriais eram bastante simples não contendo grandes
particularidades, o que fez com que tudo corresse bastante suavemente, e penso
tendo eu conseguido captar bastante bem as ideias base em causa. Mais tarde viria a
verificar que nem tudo seria tão suave e que realmente cada circuito tem as suas
particularidades e a síntese tem que ser muito bem adaptada às mesmas. Mas isso
será relatado mais à frente.
Uma vez que ainda não tinha disponíveis os ficheiros com as descições Verilog do
circuito a trabalhar, esta fase durou todo o mês de Março, tendo eu aproveitado para
9
ir testando algumas idéias, utilizando algumas descrições feitas por mim em
disciplinas de anos anteriores. Aproveitei igualmente para tomar contacto com
algumas questões de configuração da ferramenta, questões essas que viriam a
revelar-se mais importantes depois.
10
5- BLOCO 1- TRABALHO
5.1- Descrição do Bloco
Este circuito digital era constituido por quatro sub-blocos e um bloco de top-level. A
figura seguinte dá uma descrição do circuito com todas as entrada e saídas:
SPI
CONVERSIONCONTROL
spiclkspicsspidispido
adcsoc
adcclk
adcout[9:0]
rstz
scan
clk
scan
mod
e
scan
en
scan
in
scan
out
adcsel[3:0]
CLOCKGENERATION
adcon
digclk
extsoc
rxtx
clki
n
adceoc
adcrstzSYNC
figura 1- Descrição funcional do circuito
Para cada componente do circuito, existia um ficheiro de texto com a sua descrição
em Verilog. Eram eles: ci3gbbauxadcdig.v ( top-level )
auxadcSocCtrl.v
auxadcSpi.v
auxadcClkGen.v
auxadcSync.v
Seriam pois estas descrições, o ponto de partida para o processo de síntese e
place&route que, no final, originaria um layout digital para o circuito.
11
Como restrição principal, era pretendida uma frequência de operação do bloco que
rondasse o valor máximo de 30.72 MHz.
O circuito possuia uma característica especial que consistia na existência de cadeias
de scan para scan interno. Estas cadeias ( scan-chains ) não vêm referidas nas
descrições verilog e são introduzidas no circuito durante a síntese, da forma que
explicarei mais à frente, na descrição da fase de síntese. Esta questão foi uma das
que mais problemas me colocou e mais tempo me ocupou.
5.2- Tecnologia
A tecnologia alvo utilizada foi uma tecnologia de standard-cells de 0.18 µm com
quatro níveis de metal. Para tal, estavam, obviamente, disponibilizados todos os
ficheiros a ela relacionados, tanto para uso durante a síntese ( em formato Synopsys )
como durante as restantes fases ( em formato Cadence, ou convertível como
explicarei mais à frente, na descrição da fase de place&route ).
5.3- Síntese 5.3.1- Configuração do Design Compiler Para a síntese, seriam utilizados, os já referidos ficheiros .v, e os ficheiros relativos á
tecnologia em formato .db ( formato de base dados interno da Synopsys ). No caso,
seria utilizado o ficheiro slow.db por ser a versão mais pessimista. Para conseguir
configurar a ferramenta – Design Compiler – de forma a encontrar estes últimos
ficheiros, foi necessário criar um ficheiro chamado .synopsys_dc, que teria de ser
colocado na directoria de onde se correria posteriormente o DC. Este ficheiro,
contendo uma série de instruções de configuração, seria o último, de uma série de
três com este nome, a ser lido quando da inicialização da ferramenta, sendo que cada
um deles se vai sobrepondo ao anterior. O primeiro está colocado na directoria de
instalação do DC, o segundo no root do utilizador. Ao colocar o terceiro na directoria
12
de projecto garante-se que, para este projecto, as últimas configurações a serem
lidas são as específicas dele mesmo. Para a criação deste ficheiro, utilizei o original
da instalação, alterando-lhe as linhas correspondentes aos paths das bibliotecas e
aos nomes da target library e da link library, da forma que se pode ver nas seguintes
linhas:
... set search_path [list . /export/home/fleal/libsnovas ${synopsys_root}/libraries/syn] set link_library [list slow.db] set target_library [list slow.db] set synthetic_library "" set command_log_file "./command.log" set designer "" set company "" set find_converts_name_lists "false" set symbol_library []
...
nota: Achei por bem dedicar um sub-capítulo a esta parte devido às dificuldades que
esta me causou na descoberta do funcionamento dos ficheiros de configuração
referidos, funcionamento este que obviamente não estava coberto nos tutoriais que
tinha feito.
5.3.2- Estratégia de Síntese Escolheu-se, para a criação dos scripts de síntese, uma estratégia hierárquica em
que os vários blocos seriam sintetizados individualmente e posteriormente todos
agrupados durante a síntese do top-level. Seriam pois criados scripts individuais para
cada sub-bloco, e um referente ao top-level que inclui chamadas aos outros, além
obviamente das outras instruções necessárias. Este último foi escrito de forma a
poder ser corrido sem mexer nos sub-blocos se assim se pretender, para possibilitar
repetições do procedimento que de outra forma seriam muito morosas. Isto veio a
provar-se muito útil mais tarde como explicarei.
Esta estratégia facilita depois a inserção das scan-chains, especialmente a sua
correcta ligação em sequência, que será feita de forma “manual” no script de top-
level, da forma que explicarei mais à frente.
13
5.3.3- Scripts de Síntese para os Sub-Blocos Para cada um dos quatro sub-blocos foi criado um script de síntese. O formato básico
de cada um deles era o mesmo, seguindo mais ou menos esta sequência:
- um conjunto de comandos de estabelecimento de condições de operação
- uma primeira compilação ( com nível de esforço médio )
- comandos de inserção de restrições ( timing constraints )
- uma segunda compilação ( desta feita com esforço máximo )
- inserção de cadeias de scan
- verifição do resultado
- criação de reports
A utilização de duas compilações permite a obtenção de resultados superiores no
final, uma vez que a segunda compilação / optimização vai ser feita sobre a primeira,
mas depois da introdução das restrições. O resultado desta segunda compilação
será, desta forma, uma optimização da primeira ( ainda para mais feita com um nível
de esforço de mapeamento superior ) para as restrições entretanto introduzidas.
Passarei agora a uma descrição mais ou menos breve dos principais comandos
utilizados nas várias partes dos scripts que sejam comuns aos vários sub-blocos.
Comandos específicos de um dado sub-bloco serão focados logo a seguir a esta
parte. Para cada comando ou conjunto de comandos retirados dos scripts farei um
pequeno comentário por baixo, assinalado com c:. Não farei uma descrição
pormenorizada dos mesmos, pois penso que tal seria um pouco fastidioso e mesmo
desnecessário. Assim:
Na parte de estabelecimento de condições de operação: set_min_library slow.db -min_version fast.db set_operating_conditions -min fast -min_library fast -max slow -max_library slow c: Estes dois comandos estabelecem os limites de operação entre as versões mais optimista e mais pessimista das bibliotecas. /*set_wire_load_model -name "umc18_wl10"*/ c: Esta linha foi excluída ( daí aparecer comentada ) pois, durante as primeiras experiências, verificou-se que este modelo, embora sendo o mais optmista disponível era, ainda assim, muito pessimista, originado áreas de interligação muito grandes no resultado final. A síntese foi por isso feita sem utilizar um wire load model.
14
set_max_area 0 -ignore_tns c: Permitirá a obtenção da menor área possível set_drive 0 digclk set_driving_cell -cell BUFX1 -pin Y all_inputs() - find(port,"digclk") set_load 0.05 all_outputs() c: Comandos que estabelecem valores de drive para as várias entradas e de carga para as saídas. Podem consistir de pins de outras células em vez de um valor absoluto, tal como se vê na 2ª linha. set_dont_use {slow/SDFFN* fast/SDFFN*} c:( importante! ) Este comando é essencial pois indica à ferramenta que não deverá usar os flip-flops do tipo indicado. Digo que é essencial pois estes FF disparam no flanco descendente, e todo o script está escrito partindo do pressuposto que o trigger dos FF será feito no flanco ascendente.
A primeira compilação será sempre feita recorrendo ao seguinte comando: compile -scan -ungroup_all -map_effort medium c: De notar a opção de map_effort medium. A introdução das timing constraints será feita criando nos pins relevantes, relógios
com os valores necessários de período de modo a satisfazer a restrição dos 30.72
MHz. Para tal seriam utilizados entre outros, os seguintes comandos: create_clock filter(all_connected(all_connected(find(pin,"clk1ana_reg/CK"))),"@pin_direction == out") -name "spiclk" -period 32 -wave {0 16} c: O create_clock será sempre utilizado para atribuir um clock a um determinado pin. O pin será indicado através deste, talvez um pouco complexo, mas eficiente processo de procura do mesmo. create_clock find(port,"scanclk") -name scanclk -period 50 -wave {0 25} c: Este é mais um create_clock, mas específico do bloco de onde esta linha foi tirada, uma vez que é o bloco onde existe o port do clock para o scan ( scanclk ). Obviamente que também para ele terá que ser criado um clock para restrição. De notar que o valor do período é maior reflectindo a menor exigência em termos de frequência do relógio de scan. set_clock_skew -propagated -uncertainty 0.3 all_clocks() c: Introduz um valor de skew para todos os clocks definidos. set_dont_touch_network {spiclk spics spiclkn} c: Irá fazer com que as nets indicadas não sejam mexidas quando da compilação / optimização que vai ser feita a seguir. set_input_delay 5 -max -clock spiclk all_inputs() - find(port,"spiclk") - find(port,"spics") set_output_delay 5 -max -clock spiclk all_outputs() c: Introduzem atrasos em todas as entradas e saídas em relação ao clock indicado. set_fix_hold all_clocks() c: Obriga a ferramenta a, se necessário, introduzir células que permitam o cumprimento dos tempos de hold.
A segunda compilação que será de optimização, utilizará o seguinte comando: compile -map_effort high -area_effort high c: De notar as opções de map_effort medium e area_effort high.
15
A introdução dos componentes para scan será feita com os comandos: create_port scanin -direction in create_port scanout -direction out create_port scanen -direction in c: Servem para criar os ports no sub-bloco referentes às entradas e saídas dos sinais de teste. set_scan_signal test_scan_enable -port scanen set_scan_signal test_scan_in -port scanin set_scan_signal test_scan_out -port scanout c: Atribui um determinado sinal de teste ao port adequado. set_scan_configuration -chain_count 1 -clock_mixing mix_clocks_not_edges c: Cria a configuração de scan pretendida. Neste caso, com uma cadeia de scan. Por exemplo, no caso do bloco auxadcSpi, existirão três cadeias. preview_scan check_test insert_scan check_test report_test -scan_path c: Comandos que fazem a inserção efectiva das cadeias de scan e a sua verificação.
A verificação será feita através de: check_design
A parte da geração dos reports é feita através de uma chamada a um outro script –
create_reports.scr – muito simples criado apenas para essa função. Isto evita ter que
estar a repetir as mesmas instruções no final de cada um dos quatro scripts.
As diferenças entre cada um deles são apenas as resultantes de particularidades de
cada um dos sub-blocos. Obviamente os nomes dos sinais mas também a quantidade
de clocks envolvidos em cada bloco e também o número de cadeias de scan que não
é igual em todos os blocos. Tudo o resto é relativamente parecido.
5.3.4- Script de Síntese para o Top-Level O script de síntese para o bloco Top-Level começa por fazer a leitura dos vários
ficheiros de entrada em verilog de forma a criar a base de dados para o trabalho. Isto
é feito recorrendo aos comandos básicos: analyze -f verilog -lib work {../rtl/auxadcSpi.v,../rtl/auxadcClkGen.v,../rtl/auxadcSync.v,../rtl/auxadcSocCtrl.v} elaborate -lib work auxadcSpi elaborate -lib work auxadcClkGen elaborate -lib work auxadcSync
16
elaborate -lib work auxadcSocCtrl analyze -f verilog -lib work "../rtl/ci3gbbauxadcdig.v" elaborate -lib work ci3gbbauxadcdig
A partir daqui, os vários designs pertencem ao mesmo projecto e o script continua
fazendo as chamadas aos scripts de sítese de cada um dos sub-blocos: include sync.script remove_design -hier auxadcSync read -f db DBDIR + "auxadcSync.db" /* permite saltar a sintese */ current_design "ci3gbbauxadcdig" set_dont_touch auxadcSync c: De notar a questão, já mencionada atrás, de podermos eliminar a síntese do sub-bloco comentado a linha de include. A ferramenta irá buscar a última versão do mesmo através de read. Notar também a última instrução, que irá fazer com que, na compilação do top-level, não sejam mexidos os sub-blocos, dado estes já se encontrarem optimizados pelos seus scripts.
Aqui começa a parte mais diferente deste script de top-level. Estou a referir-me à
ligação na sequência correcta das diversas scan-chains dos sub-blocos. Tal como
referi atrás, esta ligação será feita de forma “manual”3 através da inserção e ligação
de latches, seguindo a idéia apresentada na figura seguinte:
scaninauxadcSpi
scanin3 scanout3
auxadcSocCtrlscanin scanout
auxadcClkGenscanin scanout
LookLatch1(LATP01)
LookLatch2(LATP01)
LookLatch3(LATP01)
LookLatch4(LATP01)
LookLatch5(LATP01)
scanclk
scanout
scanen
auxadcSpiscanin1 scanout1
auxadcSpiscanin2 scanout2
figura 2- Ligação das scan-chains
Começa-se por se criar uma instância com o nome de LOCKUP_LATCH a partir de
uma latch da biblioteca. Esta instância será depois utilizada para criar cells desse tipo
de forma a introduzir as latches. Usando os comandos seguintes são atribuídos sinais
de teste específicos aos ports adequados do top-level ( um pouco como se tinha feito
nos sub-blocos ):
3 Digo manual uma vez que a ferramenta permite que este processo seja feito automaticamente por ela. No entanto, verificam-se muito melhores resultados quando feito de forma manual.
17
set_scan_signal test_scan_in -port scanin set_scan_signal test_scan_out -port scanout set_scan_signal test_scan_enable -port scanen
São depois criadas nets que permitirão ligar os ports de scanin e scanen do top-level
aos pins correspondentes dos sub-blocos. O scanout será ligado directamente à
saída da última latch. Para tal foram usados os seguintes comandos: create_net scani create_net scane connect_net scani find(port,"scanin") /* ligacoes aos ports do top level */ connect_net scane find(port,"scanen") connect_net scani find(pin,"I1AUXADCSPI/scanin1") /* extremos */ connect_net scane find(pin,"I1AUXADCSPI/scanen") /* enables dos varios subdesigns */ connect_net scane find(pin,"I1AUXADCSOCCTRL/scanen") connect_net scane find(pin,"I1AUXADCCLKGEN/scanen") connect_net scane find(pin,"I1AUXADCSYNC/scanen")
De seguida procede-se à inserção das latches utilizando os seguintes comandos: /*EXEMPLO--------------------------------*/ /* LockUp Latch entre SPI scan2 e CLKGEN */ /*---------------------------------------*/ create_cell LockLatch2 LOCKUP_LATCH D_input = "LockLatch2/D" C_input = "LockLatch2/GN" L_output = "LockLatch2/Q" c: Cria uma cell do tipo LOCKUP_LATCH definido anteriormente e atribui nomes aos seus pins. create_net scan3 create_net scan4 c: Cria uma net para a entrada e outra para a saída da latch. connect_net scan3 find(pin,"I1AUXADCSPI/scanout2") connect_net scan3 find(pin,D_input) connect_net scanclk find(pin,C_input) connect_net scan4 find(pin,L_output) connect_net scan4 find(pin,"I1AUXADCCLKGEN/scanin") c: Insere a latch, ligando a net de entrada entre o pin de scanout do bloco anterior e a entrada da latch e a net de saída entre a saída da mesma e o pin de scanin do bloco seguinte. Liga também o clock de scan ao clock da latch. Após a correcta inserção de todas as latches e ligação dos pins relativos à parte de
scan, o script de síntese continua com um conjunto de instruções bastante idênticas
às já utilizadas nos outros scripts ( e já descritas atrás ), destinadas ao
estabelecimento de condições de operação.
18
Igualmente, são também utilizadas o mesmo tipo de instruções já apresentadas atrás
para a introdução das restrições temporais relativas aos clocks presentes neste bloco
de top-level.
A compilação / optimização é feita de seguida, utilizando o mesmo comando que
anteriormente, mas desta vez com a forma: compile -only_design_rule c: A opção only_design_rule irá fazer com que nada do já foi feito manualmente atrás seja alterado pela síntes, especialmente a parte das cadeias de scan.
Para finalizar, é feita, tal como em todos os outros blocos, a verificação através de
check_design e a geração dos reports. Neste caso é também feita a gravação,
através de write, da netlist final pretendida ( formato .v ). Este será então o ficheiro
que irá ser utilizado na fase seguinte- place&route.
5.3.5- Resultados da Síntese Analisando os vários reports relativos ao circuito top-level, verifica-se a obtenção de
uma área de 22250 µm2. Este valor refere-se apenas à chamada cell area, dado que
como não utilizei wireload model para esta síntese, não existe uma estimativa para a
net interconnect area, que iria aumentar a área total final.
Verifica-se igualmente que, como pretendido, todas as restrições introduzidas foram
cumpridas.
5.3.6- Notas finais relativas à Síntese Devo dizer que depois de tudo resumido e organizado, poderá parecer uma tarefa
relativamente simples e apenas de repetição. No entanto obrigou a um estudo
muitíssimo apurado dos vários comandos utilizados e de muitos outros que acabaram
por não o ser, de forma a determinar o que seria essencial ou dispensável. Os
comandos que acabaram por ser utilizados foram os que melhores resultados
produziram depois de vários testes com estes e outros. Tudo isto foi um trabalho que
exigiu bastante tempo e uma boa interacção com os orientadores do trabalho,
nomeadamente do lado da empresa, dada a experiência no assunto.
19
5.4- Place&Route 5.4.1- Trabalho Inicial Como primeira abordagem a esta tarefa, comecei, tal como na anterior, por tomar
contacto com a ferramenta de CAD a utilizar – Silicon Ensemble. Para tal, recorri uma
vez mais aos manuais e tutorial disponíveis. Desta vez, e dado que o tutorial não
cobria uma parte importante do trabalho, utilizei também alguns documentos sobre o
assunto recolhidos na internet.
5.4.2- Descrição do Place&Route Vou agora descrever pormenorizadamente a seguência de operações que efectuei
para executar o Place & Route. Todas estas operações, à excepção das relacionadas
com a geração de clock-trees, foram por mim feitas recorrendo aos menus da
ferramenta. Havia no entanto também a hipótese de escrever scripts ( chamados
MAC files ) para uma maior rapidez de utilização.
A tarefa de Place & Route iniciava-se portanto, fazendo a importação da biblioteca
tecnológica em formato LEF ( Library Exchange Format ): FILE → Import → LEF
De seguida ( e tem que ser exactamente nesta ordem ) será importado o ficheiro
verilog da tecnologia: File → Import → Verilog
Finalmente, faz-se a importação da netlist gate-level. Igualmente: File → Import → Verilog
nota: Devo dizer nesta altura, que há mais um ficheiro que é necessário importar
nesta altura, mas tal será explicado mais à frente. A razão de só o fazer depois,
prende-se com o facto de também só ter sido descoberto por mim no final, o que me
obrigou a refazer todo o trabalho mais uma vez.
20
Continuando a sequência, passamos ao Floorplanning. Esta operação consiste, tal
como o nome indicia, na definição de alguns parâmetros para desenhar uma planta,
segundo a qual depois o circuito irá ser colocado e encaminhado. Para tal, foi
sugerido, numa reunião com o orientador da empresa, tentar uma abordagem
utilizando o software Cadence ICFB, através da criação de uma vista de auto-layout e
posterior geração do floorplan. Esta abordagem, apesar de aparentemente permitir
uma maior liberdade no desenho, criou-nos bastantes problemas, pelo que, passado
algum tempo foi abandonada, optando-se então pela simples utilização do comando: Floorplan → Initialize Floorplan
No formulário correspondente foram utilizados, para os diversos parâmetros, os
seguintes valores: -Aspect Ratio- 1:1
c: Planta quadrangular. Diferente do apresentado no documento de apresentação do circuito.
-IO to Core distance- 15 µm nas duas direcções.
c: Representa basicamente a distância que se irá deixar entre a zona onde ficarão as células e o limite do circuito. Será o espaço utilizado para fazer o power routing, como explicado mais à frente, altura em que será claro o porquê deste valor.
-Row Utilization- 80%
c: Representa a percentagem do espaço das várias linhas de células ( rows ) que deverá ser ocupado com elas. Tem por isso um impacto grande no tamanho final do circuito. O valor utilizado é mais ou menos normal, talvez até um pouco conservador.
-Flip Every Other Row- checked
c: Fará com que linhas adjacentes tenham orientações opostas. Permite poupar bastante espaço uma vez que efectua a partilha de barras de alimentação comuns entre células dessas mesmas linhas.
O formulário de preenchimento destes parâmetros tem um botão que permite obter
estimativas em relação ao resultado final. No final disto, tinha o floorplan feito.
O passo seguinte foi o da colocação das células ( placement ). Para tal, foi utilizado o
comando: Place → Cell
21
Este comando procederá ao placement automático das células ( Qplace ) nas rows de
acordo com o floorplan. No final, ter-se-á um layout com as células todas colocadas e
orientadas ( a orientação pode ser vista no canto das mesmas ), podendo-se passar
ao power routing.
Esta operação tem por objectivo o planeamento e routing dos anéis de alimentação
( power rings ) a serem colocados em torno da zona onde estão as células. Para tal é
usado o comando: Route → Plan Power → Add Rings
No formulário correspondente há que preencher, no caso deste circuito, o valor para o
Core Ring Width, ou seja, a espessura das barras de alimentação, tanto para as
verticais como para as horizontais. Há também que especificar qual a camada de
metal ( layer ) em que deverão ser feitas. Para este último parâmetro foram
escolhidas as duas últimas camadas de metal, metal3 e metal4, de forma a diminuir
ao mínimo eventuais futuros conflitos quando do routing do sinal. Para a espessura
das barras de alimentação foi escolhido o valor de 5 µm. Este valor foi obtido a partir
de uma análise empírica feita numa das reuniões com o orientador do projecto, e tem
em conta as dimensões previstas para o circuito bem como a frequência prevista de
operação. A existência de duas barras de alimentação paralelas a toda a volta do
circuito, levou ao valor de 15 µm mencionado atrás para a distância IO to core.
Comecei por utilizar valores diferentes, nas primeiras vezes que tentei fazer o
Place&Route, mas depois de algumas experiências optei por esse último, de modo a
reservar espaço suficiente para que não fossem violadas regras de desenho.
Ainda em relação ao power routing, deverei dizer que, em outros circuitos
eventualmente maiores e especialmente se não forem quadrados, poderá haver
também a necessidade de inserir Stripes, que não são mais que linhas de
alimentação que atravessam o circuito dividindo-o, permitindo que pontos que
estariam mais afastados das linhas tenham agora um acesso a elas mais facilitado.
No entanto, devido a restrições de desenho, estas stripes originam muito maiores
22
dificuldades no routing do sinal. Felizmente, neste caso não foram necessárias, dado
a dimensão do circuito não o justificar.
No final, seria feita a ligação dos anéis, utilizando para isso o comando: Route → Connect Ring
Nesta altura, o processo de Place&Route sofre um “desvio” para que seja feita
geração das clock-trees. Essa geração será feita utilizando a ferramenta CT-Gen que,
embora pudesse ser utilizada directamente a partir do Silicon Ensemble, será
utilizada como ferramenta autónoma, da forma que descreverei no próximo sub-
capítulo.
5.4.2.1- CT-Gen Para que pudesse utilizar esta ferramenta, tive primeiro que exportar o circuito no
ponto em que estava, em formato DEF.
Criei então os dois ficheiros de texto necessários à utilização do CT-Gen, sendo eles: ctgen.commands
ctgen.constraints
O primeiro é o ficheiro que irá ser chamado na linha de comandos do CT-Gen e
contém a indicação dos ficheiros de tecnologia, do ficheiro DEF de entrada e do
ficheiro de restrições ( que no caso é o ctgen.constraints ). O segundo ficheiro contém
as descrições das diversas clock-trees a serem criadas, nomeadamente pins de
origem do sinal de relógio a que se referem e definições de atrasos e formas de onda
dos mesmos. Uma questão que provocou algumas dificuldades foi exactamente a
obtenção dos nomes dos pins de origem dos vários sinais de relógio. Foi conseguida
através de uma inspecção exaustiva do ficheiro DEF de entrada. A escrita do ficheiro
de constraints foi feita tendo em conta a sequência de sinais de relógio pretendida
para o circuito e apresentada na figura seguinte:
23
digclk
rxtxclkin
spics
spiclk
spiclkn
figura 3- Relação entre Clock-Trees
Depois de criado o ficheiro de constraints, deparei-me com o principal problema que
encontrei nesta fase, problema esse que me custou bastante tempo. Refiro-me a
inexistência de uma timing library em formato CTLF para a tecnologia. Ora sem esta
biblioteca era simplesmente impossível correr o CT-Gen. Depois de muito investigar,
descobri um pequeno utilitário – SYN2TLF - que permitia muito simplesmente
converter a bibliotecas que eu tinha em formato LIB ( da Synopsys ) para formato
CTLF ( usado na Cadence ). Isto resolveu-me o problema e a criação das clock-trees
foi feita usando o comando: ctgentool ctgen.commands
Não apareceram mais questões. No final, o CT-Gen gerou um ficheiro em formato
DEF que poderia ser importado novamente para o Silicon Ensemble.
No seguimento do processo, agora novamente no Silicon Ensemble, comecei por
importar o DEF gerado pelo CT-Gen, sendo que primeiro foi necessário importar
novamente o ficheiro LEF.
O próximo passo foi a colocação das filler cells, de forma a eliminar as
descontinuidades nas linhas de alimentação entre rows, provocadas por espaços sem
células. Para tal usei o comando: Place → FillerCells → AddCells
No formulário correspondente, era necessário o preenchimento do nome das filler
cells bem como o seu prefixo. Os nomes foram encontrados por consulta do ficheiro
da tecnologia de forma a verificar quais os tipos de célula disponíveis. A inserção das
mesmas foi feita repetindo o comando sucessivamente, começando nas maiores
24
células ( 64 ) e até às menores (1). Desta forma, garante-se que todos os espaços
foram correctamente preenchidos. No final desta operação, o circuito estava pronto a
que fosse feito o encaminhamento ( routing ). Nas figuras seguintes podem ser vistos
pormenores do circuito, nomeadamente células ( a verde ), nets ( a azul ) e compará-
los antes do CTGen e antes do Routing ( é visível a ausência de zonas sem células
na segunda figura ):
figura 4- Pormenores antes do CTGen (esquerda) e antes do Routing (direita)
Esta última operação foi feita em dois passos. Primeiro o routing dos sinais de relógio,
uma vez ser mais prioritário, utilizando: Route → Clock Route
Depois o routing final, que poderia ser feito utilizando os comandos de GlobalRoute
seguido de FinalRoute, mas que no caso desta versão do software pode ser feito
apenas utilizando o UltraRouter ( WRoute ). Isto permite, entre outros benefícios, uma
muito maior rapidez numa tarefa normalmente bastante demorada. Para tal usou-se: Route → WRoute
Após isto, o circuito estava terminado e poderia ser gravado nos formatos DEF e
GDS2 ( formato de bit stream normal de tapeout para os fabricantes e interpretado
por várias ferramentas ). Esta última parte, devido às várias questões que levantou,
será descrita separadamente a seguir.
25
5.4.3- Ficheiro Final A geração do ficheiro final em formato GDS2 causou muitos problemas, razão pela
qual resolvi dedicar este sub-capítulo ao assunto.
A questão surgiu quando, para verificar se o ficheiro que tinha sido gerado o tinha
sido de forma correcta, se tentou importá-lo através de um stream-in para o Cadence
ICFB ( de forma a gerar uma vista de layout ). Constatou-se que tal não acontecia. O
primeiro problema a ser descoberto prendia-se com o ficheiro de mapeamento usado
para gerar o GDS. Este ficheiro não era o correcto, pelo que se teve que escrever um
novo. No entanto ainda não se conseguia o objectivo pretendido. Após bastante
investigação ( que motivou até uma reunião entre os três intervenientes no projecto )
conseguiu-se chegar finalmente à raiz do problema. Era algo tão simples como o
facto de, no início do place&route, a importação do ficheiro LEF ter sido feito sem
atenção às maiúsculas e minúsculas nele presentes. Esta pequena questão, junto
com outra que referirei mais à frente, obrigou a refazer mais uma vez todo o processo
de place&route, agora com atenção à opção de Case Sensitive.
26
5.4.4- Circuito Na figura seguinte, retirada do Silicon Ensemble, pode-se ter uma ideia do aspecto
visual do circuito final:
figura 5- Aspecto do layout do Circuito ( Silicon Ensemble )
nota: devido a um pequeno problema de configuração da visualização, não é possível
ver as linhas de metal4 ( verticais ), apesar de elas estarem efectivamente presentes.
27
5.5- LVS e DRC 5.5.1- Requisitos Para poder proceder às operações de verificação final seria necessário utilizar o
ficheiro GDS do circuito contendo todas as células. Ora o GDS exportado a partir do
Silicon Ensemble contém apenas instanciações das standard cells da tecnologia. Foi
devido a este facto que foi necessário importar o GDS para Cadence tal como tinha
dito atrás. A idéia é juntar o novo circuito às restantes células da tecnologia, para
depois voltar a exportar um novo GDS do circuito mas que agora contenha todas as
células da tecnologia nele utilizadas. Este GDS seria utilizado tanto para o DRC como
para o LVS.
Para o LVS seria igualmente necessária uma netlist spice extraída a partir do
esquemático da forma que descreverei a seguir.
5.5.2- GDS e Extração da Netlist spice Este processo criou diversos problemas, alguns dos quais já foram explicados
anteriormente ( a questão das maiúsculas e do ficheiro de mapeamento ). Outros
apareceram, especialmente na organização das librarys e cells no Cadence ICFB.
Com maior ou menor dificuldade acabaram por ser resolvidos.
Foi então feita a importação por stream-in do GDS, desta vez tendo em conta uma
opção de match case disponível, utilizado o ficheiro com a layertable adequada. Esta
importação gerou a nova célula correspondente ao circuito, com a vista layout. Esta
vista, que corresponde ao layout observado no Silicon Ensemble, é apresentada na
figura 6 da página seguinte.
Procedi então à geração do esquemático correspondente, fazendo a importação da
descrição verilog do meu circuito, descrição essa que teve primeiro de ser exportada
do Silicon Ensemble. Aqui pôs-se mais um problema. A exportação dessa netlist
verilog post-layout implicava que se tivesse feito todo o processo de place&route
utilizando desde o início a timing library em formato CTLF que referi a propósito do
28
CT-Gen. Esta foi a outra questão que implicou que o place&route tivesse que ser
repetido de início. Implicou igualmente a escrita de um pequeno ficheiro, formato
GCF, para proceder à importação da timing library para o Silicon Ensemble.
Depois de tudo repetido, tinha pois, não só o ficheiro GDS correctamente gerado tal
como tinha referido atrás, mas também a netlist verilog post-layout. Com esta netlist
foi-me finalmente possível gerar a vista schematic que apresento na figura 7 da
página seguinte.
figura 6- Layout do Circuito ( Cadence )
29
figura 7- Esquemático do Circuito ( Cadence )
Depois de ter obtido esta vista, criei uma nova, chamada schematic_lvs por
instanciação do símbolo do anterior. Pode ser observada na seguinte figura:
figura 8- Esquemático para o LVS ( Cadence )
Foi a partir desta nova vista que foi feita a extracção, no Cadence, da netlist spice
para utilização no LVS.
5.5.3- DRC O processo de DRC serve, como já foi dito atrás, para detectar eventuais violações às
regras de desenho da tecnologia em questão. Utilizará, como entradas, o ficheiro
30
GDS completo gerado depois da importação para Cadence e o ficheiro com as regras
a cumprir. Este último deverá ser o ficheiro fornecido e suportado pela foundry.
Como já foi também mencionado, para o caso desta tecnologia, a foundry suporta e
aconselha para o signoff ( verificação final ), a ferramenta Calibre, da Synopsys.
Devido à indisponibilidade desta ferramenta na faculdade, esta tarefa, bem como o
LVS resumido a seguir, foi executada nas instalações da Chipidea com a supervisão
do orientador.
Após a realização do DRC, e por análise do report de erros, verificou-se apenas a
existência de alguns erros relativos a densidade de metal e pad corners, que decrevo
a seguir:
- metal density rules – estes erros têm a ver com uma densidade mínima de
metal que deverá existir no design. Normalmente, recorre-se a procedimentos
que preenchem os espaços vazios com metal ( não ligado a nada ), o que irá
assegurar a referida densidade mínima. No caso, não foram efectuados.
- pad corner rules – estes erros referem-se aos pads dos cantos do circuito.
Dado que, para este circuito, não foram usados pads, esta verificação não faz
sentido.
Pode-se considerar então o DRC efectuado como satisfatório.
5.5.4- LVS Tal como já foi explicado, o processo de LVS tem como finalidade a detecção de
eventuais discrepâncias entre o layout gerado e o esquemático do circuito pretendido.
Utilizará como entradas, igualmente o ficheiro GDS completo, o ficheiro de regras a
cumprir descrito atrás, e a netlist spice para lvs gerada a partir do Cadence da forma
que também já foi explicada.
Por análise do report de LVS, observa-se que o design passou esta verificação sem
problemas.
31
5.6- Conclusão Foram cumpridas, para este bloco, todas as tarefas do backend digital, partindo das
descrições Verilog provenientes do frontend, até ao ficheiro final em GDS2.
Considera-se pois o layout digital do circuito correctamente criado e validado.
5.7- Nota sobre os ficheiros Utilizados Todos os ficheiros relativos ao trabalho neste bloco mencionados ao longo deste
relatório, podem ser encontrados na página web do projecto em:
www.fe.up.pt/~ee00236/. Alguns deles, por questões de confidencialidade da
empresa, encontram-se protegidos por password, disponibilizada apenas aos
intervenientes no projecto.
Para uma consulta mais facilitada dos scripts de síntese, eles são fornecidos como
anexo a este relatório, embora de forma separada, uma vez mais por questões de
confidencialidade. Da mesma forma serão fornecidos os reports de Síntese, DRC e
LVS obtidos.
32
6- PROGRESSO DO TRABALHO
O trabalho iniciou-se com algum atraso, o que practicamente pôs de lado à partida a
execução de um terceiro bloco. Previa-se no entanto ser possível fazer os dois
primeiros sem grandes problemas, deixando ainda um pequeno período para
elaboração deste relatório e preparação da apresentação.
Infelizmente, com o evoluir do trabalho os atrasos foram-se acumulando, muito devido
ao tempo que se demorou na resolução dos diversos problemas que foram surgindo.
Esta situação levou a que sobrasse muito pouco tempo para iniciar a execução do
segundo bloco digital. Optou-se por isso, e por sugestão dos orientadores, por acabar
o primeiro de forma correcta, e não chegar a iniciar o trabalho num segundo que iria
inevitavelmente ter que ficar a meio.
Consegui no entanto, e por virtude das muitas repetições de passos que fui obrigado
a fazer, experimentar várias opções para as diversas tarefas. Isso permitiu-me ter
uma idéia concreta sobre o efeito que essas diferenças tinham nos resultados.
Cheguei portanto, ao final do projecto, com o trabalho no primeiro bloco digital
completo. Penso no entanto, que um segundo bloco, ainda que mais complexo, seria
obrigatoriamente feito de uma forma muito mais expedita dada a experiência
adquirida até aqui.
33
7- CONCLUSÕES
Apesar de não se ter concluído tudo aquilo que era proposto, penso que o trabalho foi
bastante profícuo em termos de contacto com todas as questões que se poderão pôr
a um engenheiro de design digital, especificamente nesta área de criação automática
de layouts.
Pude verificar que, embora muitas tarefas possam ser semi-automatizadas, o
engenheiro desempenha um papel vital através das opções por ele tomadas. O
mesmo processo de criação automática de um layout digital a partir de uma mesma
descrição HDL, para uma mesma tecnologia, utilizando as mesmas ferramentas de
CAD e o mesmo hardware, pode resultar num sucesso ou num fracasso apenas a
partir das decisões tomadas, quer na utilização das ferramentas automáticas, quer na
sequência das operações ( workflow ).
Tal como pude verificar, todos os passos, por mais banais que possam parecer à
primeira vista, têm bastante importância no resultado final. Por isso, e por ser muito
fácil ocasionalmente negligenciar algum ( mesmo inadvertidamente ), é de primordial
importância uma atenção muito grande a todos os pormenores por parte do
engenheiro de projecto. Penso igualmente que, como em tudo, a experiência
desempenha um papel muito importante, uma vez que pormenores que a mim me
passavam perfeitamente despercebidos e depois me causavam problemas,
chamavam imediatamente a atenção dos orientadores.
Em resumo, penso que no final deste projecto, consegui adquirir conhecimentos
bastante razoáveis nesta área do projecto de circuitos integrados digitais, ainda que
tenha a certeza que a repetição do trabalho para um segundo bloco fosse bastante
produtiva e consolidadora dos conhecimentos adquiridos.
FIM
34
BIBLIOGRAFIA
[1]- User’s Guide e Quick Reference do Design Compiler 2001.08 [2]- Tutorial disponibilizado pela Synopsys
[3]- User’s Guide e Quick Reference do Silicon Ensemble 5.3 [4]- Tutorial disponibilizado pela Cadence para a versão anterior
[5]- Introduction to Design Synthesis Autora: P. Vega-Castillo - Technical University Hamburg em: http://www.et5.tu-Harburg.de/Lehre/Praktikum/Cadence_digital/Introduction_to_Synthesis.pdf
[6]- Cadence Silicon Ensemble in the Digital Backend Domain for AMIS 0.35 Autores: J. Neves Rodrigues, T. Olsson e T. Lenart em: http://www.es.lth.se/home/tlt/dicp/2003/images/SEtraining.pdf
[7]- Automatic Place and Route in Silicon Ensemble using DEF
Autor: R.W. Daasch - Portland State University em: http://ece.pdx.edu/~daasch/course/x26/tutorials/Tutorial5.pdf
[8]- Place & Route with Silicon Ensemble
Autor: T. Lenart - Lund University em: http://www.es.lth.se/home/tlt/dicp/2002/images/se_manual.pdf
[9]- Step by Step guide to Place&Route with Cadence Silicon Ensemble
Autor: J.C.Alves - FEUP [10]- Clock Tree Generation Autor: Lund University
em: http://www.es.lth.se/ugradcourses/cadsys/Ectgen.pdf E ainda alguns outros pequenos artigos encontrados na Internet ou fornecidos pelos
orientadores.
35