Você está na página 1de 36

Tutorial de Uppaal

Joel Silva Carvalho e Simão Melo de Sousa

Universidade da Beira Interior

11 de Março de 2009
Conteúdo

1 Introdução 3
1.1 Objectivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Motivação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Limitações . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.4 Organização do documento . . . . . . . . . . . . . . . . . . . . . . . 4

2 Uppaal 5
2.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 Autómatos Temporizados e Extensões . . . . . . . . . . . . . . . . . 5
2.2.1 Modelos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2.2 Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2.3 Variáveis inteiras limitadas . . . . . . . . . . . . . . . . . . . 6
2.2.4 Matrizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.2.5 Funções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.2.6 Posições urgentes . . . . . . . . . . . . . . . . . . . . . . . . 6
2.2.7 Posições committed . . . . . . . . . . . . . . . . . . . . . . 6
2.2.8 Sincronizações . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3 Modelação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.3.1 Especificação Textual . . . . . . . . . . . . . . . . . . . . . . 7
2.3.2 Especificação Gráfica . . . . . . . . . . . . . . . . . . . . . . 8
2.3.3 Edges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3.4 Locations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.4 Simulação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.5 Verificação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.5.1 Correspondências TCTL em Uppaal . . . . . . . . . . . . . . 13
2.5.2 Reachability . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.5.3 Safety . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.5.4 Liveness . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.5.5 Deadlock Freeness . . . . . . . . . . . . . . . . . . . . . . . 14
2.5.6 Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

1
3 Casos de Estudo 16
3.1 Algoritmos de Dekker e Peterson . . . . . . . . . . . . . . . . . . . . 16
3.1.1 Descrição . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.1.2 Modelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.1.3 Simulação . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.1.4 Verificação . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.2 Biphase Mark Protocol . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.2.1 Descrição . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.2.2 Modelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.2.3 Verificação . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

4 Exercícios 27
4.1 Exercício 1 - Protocolo v1 . . . . . . . . . . . . . . . . . . . . . . . 27
4.2 Exercício 2 - Protocolo v2 . . . . . . . . . . . . . . . . . . . . . . . 28
4.3 Resoluções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

A TA e XTA BNF 32

2
Capítulo 1

Introdução

Este tutorial descreve o Uppaal como ferramenta de Model Checking para sistemas de
tempo real. O Uppaal surgiu em 1995 pela universidade de [Upp]sala e pela univer-
sidade de [Aal]borg. Esta ferramenta permite manipular três fazes da elaboração do
modelo do sistema. Na primeira fase o Uppaal permite a modelação do modelo, na se-
gunda fase permite a realização de simulações sobre a execução do modelo e na terceira
fase permite a verificação do modelo. A combinação destas três fases permite que as
equipas de desenvolvimento adquiram algumas garantias sobre o modelo construído.
Isto fornece maior segurança para a realização das fases seguintes do desenvolvimento.

A evolução do Uppaal tem sido considerável existindo hoje uma panóplia de ferra-
mentas auxiliares. Estas ferramentas merecem o seu destaque no entanto não no âmbito
deste tutorial. Para mais informações sobre este assunto recomenda-se a consulta da
página oficial do Uppaal em http://www.uppaal.com.

1.1 Objectivo
Este tutorial serve como documento de iniciação à utilização do UPPAAL, quer no con-
texto académico como empresarial, sintetizando alguma informação necessária para a
sua correcta e eficiente utilização.

1.2 Motivação
Grande parte dos sistemas de tempo real são considerados críticos e como tal exigem
cuidados acrescidos no desenvolvimento. Por exemplo, reforçando a importância da
fase de testes é possível reduzir o número de erros. No entanto os testes não são sufi-
cientes porque não fornecem certezas, apenas reduzem o espaço de incerteza. Torna-
se evidente que as ferramentas de verificação representam uma mais-valia podendo
fornecer certezas.

3
Inclusivamente no desenvolvimento de sistemas críticos é recomendável utilizar-se
mais do que uma ferramenta de verificação. No caso específico dos sistemas de tempo
real críticos é possível ver a combinação de ferramentas de verificação estática como o
SPARK com ferramentas de verificação de modelos como o Uppaal. Diferentes tipos
de ferramentas complementam-se e permitem a verificação de um maior número de
propriedades.

1.3 Limitações
Ferramentas como o Uppaal possuem todavia algumas limitações. Nomeadamente
porque aquilo que se verifica é o modelo e não o sistema em si. O modelo precisa
espelhar correctamente o que o sistema representa e é fundamental identificar e definir
as propriedades a verificar. Nada vai ser possível afirmar sobre toda e qualquer pro-
priedade que fique omissa.

1.4 Organização do documento


Cap. 2 - Uppaal Introdução e descrição de aspectos funcionais do Uppaal, quer no
que respeita à modelação, como à simulação e à verificação. Juntamente são apresen-
tados alguns conceitos teóricos pertinentes.

Cap. 3 - Casos de Estudo Descrição de dois casos de estudo relacionados com


algoritmos de exclusão mútua e descrição de um caso mais concreto de um protocolo
utilizado na indústria.

Cap. 4 - Exercícios Enunciado e resolução de exercícios práticos a realizar em Up-


paal para testar a compreensão da ferramenta.

4
Capítulo 2

Uppaal

2.1 Introdução
O Uppaal consiste numa aplicação cliente/servidor. O cliente (java) consiste numa
interface gráfica com um editor, um simulador e um verificador. Este cliente java co-
munica com um servidor (C++) que é nada mais do que o verificador de modelos
(verifyta). Assim existem duas formas de verificar um modelo, uma é recorrendo à
aplicação gráfica Uppaal outra é recorrendo directamente à aplicação verifyta.

Referências principais deste capítulo [5][7][3].

2.2 Autómatos Temporizados e Extensões


O Uppaal utiliza e estende as redes de autómatos temporizados para especificar o mod-
elo do sistema. De seguida apresentam-se alguns conceitos sobre autómatos tempo-
rizados em Uppaal e sobre as extensões introduzidas.

2.2.1 Modelos
No Uppaal os modelos (templates) são a representação individual de cada autómato,
opcionalmente com parâmetros. Os parâmetros são um conjunto de declarações de
qualquer tipo de variáveis existente no Uppaal e servem essencialmente para gener-
alizar a especificação dos autómatos.

2.2.2 Constantes
As constantes são declaradas com a palavra reservada const seguida do tipo e uma
inicialização, por exemplo: const int i = 2. Uma constante não pode ser modificada
ao longo da execução.

5
2.2.3 Variáveis inteiras limitadas
Quando uma variável inteira é declarada o seu intervalo deve ser definido, no entanto
se isso não for feito é assumido um valor por defeito (-32768 e 32767).

2.2.4 Matrizes
No Uppaal também é possível definir matrizes de tipos de dados simples. A declaração
deste novo tipo é feita recorrendo aos típicos parênteses rectos, por exemplo: int i[12].

2.2.5 Funções
O Uppaal permite definir e utilizar funções sintacticamente parecidas com a linguagem
C. Estas funções são importantes nas transições onde é necessário realizar operações
mais complexas, um exemplo muito simples de uma declaração de função é bool
teste(int a)return (a>2);.

2.2.6 Posições urgentes


Qualquer posição (estado) identificada como urgente permite que os relógios não evoluam
enquanto essa posição for mantida.

2.2.7 Posições committed


No Uppaal as designadas committed locations são ainda mais restritas que as posições
urgentes. Estas para além de não permitirem que o tempo evolua ainda obrigam a que
a próxima transição tenha origem na posição committed corrente. A utilização deste
tipo de posição entrou em desuso com a introdução das sincronizações múltiplas (ver
2.2.8), uma vez que esta era uma forma de simular as sincronizações múltiplas uti-
lizando apenas sincronizações binárias.

2.2.8 Sincronizações
As sincronizações são utilizadas nas transições e permitem que os autómatos comu-
niquem entre si. Uma transição com sincronização precisa de pelo menos uma tran-
sição emissora, pelo menos uma transição receptora e um canal de sincronização. O
autómato que pretende comunicar envia o pedido de sincronização recorrendo à eti-
queta ! antecedida do nome do canal de sincronização e o autómato receptor aguarda
essa sincronização com a etiqueta ? antecedida do mesmo nome.

Canais binários
Os canais de sincronização são declarados recorrendo à palavra reservada chan. Estes
canais são considerados binários uma vez que a acção de sincronização é feita apenas
entre duas transições.

6
Canais múltiplos
Apesar das sincronizações tradicionais serem binárias é possível definir sincronizações
de uma transição para um número arbitrário de transições recorrendo aos canais de
sincronização broadcast chan.

Sincronizações urgentes
Os canais de sincronização podem ainda ser urgentes recorrendo à palavra reservada
urgent. Isto obriga que as transições que usem este tipo de sincronizações não utilizem
restrições de tempo, ou seja não contemplem guardas sobre relógios.

2.3 Modelação
A modelação de um sistema em Uppaal pode ser feita de duas formas distintas, tex-
tualmente ou graficamente. Ambas as formas possuem vantagens e desvantagens. Por
exemplo, a especificação gráfica torna-se bastante intuitiva mas muito mais complexa
de automatizar. Ao contrário, a especificação textual permite ser automatizada, mas
requer um profundo conhecimento da linguagem.

2.3.1 Especificação Textual


O Uppaal permite a leitura de três tipos de ficheiros, no entanto a versão actual já só
permite gravar no formato mais recente. O formato mais antigo é o .ta e consiste num
ficheiro de texto plano com a especificação da rede de autómatos temporizados. Neste
formato cada autómato é definido por process seguido do nome, mas estes não são
equivalentes aos templates anteriormente falados.

A partir da versão 3.0 foi introduzido o formato .xta, muito semelhante ao .ta e
neste cada process corresponde realmente a um template com parâmetros. O formato
.xta permite ainda ser associado a um outro ficheiro .ugi que contém as coordenadas x
e y dos objectos.

Na versão 3.2 foi introduzido o formato .xml. A expressividade deste tipo de


ficheiro é semelhante ao .xta mas aqui os elementos são descritos recorrendo a tags.
Este formato é hoje utilizado nativamente pela interface gráfica e possui como grande
vantagem a possibilidade de conseguir gravar modelos sintacticamente mal definidos.
O mesmo não acontecia com o .xta que apenas permitia gravar o modelo sem erros
sintácticos. No apêndice A é apresentado a sintaxe no formato BNF para os ficheiros
.xta e .ta.
Associado a estes formatos de ficheiros existe ainda o formato .q com a especi-
ficação das propriedades que se pretendem verificar. Este formato é uma mera lista
textual das propriedades, para mais informações consultar a secção 2.5.

7
2.3.2 Especificação Gráfica
A especificação gráfica consiste na produção do modelo por intermédio do separador
editor disponível na interface gráfica do Uppaal. Esta interface de modelação (ver
Figura 2.1) é constituída por três zonas distintas. A zona superior da interface inclui
o menu da aplicação, alguns ícones de atalho e os separadores de navegação entre os
diferentes modos de visualização (edição/simulação/verificação).

Figura 2.1: Interface de modelação do Uppaal.

Na zona inferior esquerda consta uma estrutura de opções que permite mudar entre
as diferentes partes descritivas do modelo. A opção Declarations contém a especifi-
cação das variáveis globais do modelo (variáveis inteiras, canais de sincronização, reló-
gios e constantes). A opção T emplate representa um autómato temporizado do mod-
elo que por sua vez pode ter declarações locais. Por fim a opção System declarations
contém a declaração dos processos com a devida atribuição de parâmetros.

Na zona inferior direita consta uma área de trabalho que pode ser constituída por
texto, no caso de uma das opções de declaração estar seleccionada, ou por uma repre-
sentação gráfica de um autómato, no caso de algum template estar seleccionado.

8
Figura 2.2: Interface de modelação do Uppaal com o exemplo train-gate.

2.3.3 Edges
A cada transição entre dois estados de um autómato temporizado corresponde um edge
no Uppaal. Na figura 2.3 é apresentada a janela de edição de uma transição com algu-
mas opções preenchidas.

Select
O parâmetro select permite atribuir um valor a uma variável temporária (apenas válida
para essa transição), dado um intervalo, de forma não determinista. Um exemplo de
declaração possível para um select é i : int[0, 3]. Esta declaração permite que o i
receba um valor entre 0 e 3 (inclusive) e que seja utilizado nas declarações das restantes
opções da transição.

Guard
O parâmetro guard serve para activar a transição sobre uma dada condição. Um exem-
plo de declaração de uma guarda é x >= 4. Considerando x como sendo um relógio,
esta condição permite que a transição seja activada quando tiverem passado pelo menos
quatro unidades de tempo no relógio x.

9
Figura 2.3: Janela de propriedades de um Edge.

Sync
Outra forma de fazer evoluir os autómatos de forma "programada"é recorrendo aos
canais de sincronização. Com este parâmetro é possível invocar ou activar uma ou mais
transições utilizando um canal de sincronização previamente definido (ver 2.2.8). Sem-
pre que numa transição o parâmetro sync tiver uma declaração semelhante à seguinte
c1! significa que, pelo menos um outro autómato vai necessitar de uma transição semel-
hante a c1?. A utilização da etiqueta ! pode ser vista como um envio e a etiqueta ? como
uma recepção.

Update
O parâmetro update serve para actualizar variáveis globais ou locais, um exemplo de
declaração é x = 0. Considerando este x como sendo um relógio, esta declaração
permite reinicializar o relógio. Prática bastante comum na modelação de sistemas tem-
porizados. O update também pode incluir a utilização de funções ou até mesmo servir
para invocar uma função que não devolve nenhum valor mas que altera variáveis lo-
cais ou globais. Caso a função invocada não tenha um impacto no estado do sistema
a mesma torna-se inútil e é gerado um warning aquando da verificação sintáctica do
modelo.

2.3.4 Locations
A cada estado de um autómato temporizado corresponde uma location no Uppaal.
Na figura 2.4 é apresentada a janela de edição de um estado com algumas opções
preenchidas.

10
Figura 2.4: Janela de propriedades de uma Location.

Name
Cada estado possui idealmente (mas não obrigatoriamente) um nome que serve de iden-
tificador para a linguagem de especificação do modelo e para a linguagem de especifi-
cação de propriedades. Caso o nome seja definido o mesmo deve estar em conformi-
dade com ambas as linguagens. Por exemplo um nome não pode começar por um valor
numérico.

Invariant
As invariantes surgem da teoria dos autómatos temporizados e são condições que po-
dem ou não existir num estado. Numa configuração possível do autómato a invariante
do estado de controlo deve ser verdade para que se tenha uma execução válida do autó-
mato, já as invariantes dos restantes estados não interessam para essa configuração.

No Uppaal, os estados que violem a sua invariante são indefinidos, por definição
estes estados não existem.
As invariantes são expressões limitadas a conjunções de condições simples sobre reló-
gios, diferenças entre relógios e expressões booleanas que não envolvem relógios.
Quando uma invariante envolve a comparação do valor de um relógio com um inteiro
não é permitido verificar se o tempo é maior do que o inteiro ou estritamente igual, por
exemplo a > 4 ou a == 4. Assim apenas é possível utilizar expressões como a < 4
ou a <= 4.

Initial/Urgent/Committed
Estas opções são activadas com meras selecções na interface. Cada autómato tem
obrigatoriamente de possuir um único estado inicial. Mais informações sobre as outras
duass opções na secção 2.2.6 e 2.2.7.

11
2.4 Simulação
A simulação não é um processo fundamental para a verificação de modelos no entanto
torna-se útil e intuitiva para uma avaliação eficiente aquando da construção do modelo.
Dada a especificidade dos modelos é possível recorrer à simulação para realizar ajustes
e correcções. Inclusivamente com o problema da explosão de estados pode acontecer
que um modelo complexo não seja facilmente verificável. Neste tipo de situações a
simulação torna-se ainda mais importante.

Interface
O simulador do Uppaal permite três modos de funcionamento distintos. No primeiro
o utilizador executa a simulação passo a passo sendo livre de escolher a transição que
pretende fazer. No segundo o utilizador executa a simulação de forma automática e
aleatória podendo controlar a velocidade de simulação. No terceiro o utilizador pode
percorrer execuções anteriormente realizadas. Cada um destes modos de funciona-
mento pode ser intercalado a qualquer momento dando ao simulador toda a sua flexi-
bilidade.

Como é possível constatar na figura 2.5 a interface do simulador é composta por


diversas janelas. Na janela mais à esquerda é possível controlar os modos de execução
do simulador. Na janela logo à direita são listadas todas as variáveis do sistema. Na
janela inferior direita são apresentadas as sincronizações entre os diferentes autómatos
bem como os estados activos. Na janela logo acima desta são apresentados todos os
autómatos e a vermelho as transições e estados activos.

Figura 2.5: Interface de simulação do Uppaal.

12
2.5 Verificação
A verificação de modelos é um processo automatizado por algoritmos que permitem
confirmar que dadas propriedades estão presentes na representação feita do sistema.
Estando a verificação de modelos baseados em autómatos temporizados associada a
lógicas temporais, torna-se necessário classificar os diferentes tipos de propriedades.

2.5.1 Correspondências TCTL em Uppaal


Correspondências entre a Lógica TCTL e a especificação em Uppaal.
• A - Todos os caminhos(A em Uppaal).
• E - Existe um caminho (E em Uppaal).
• G - Todos os estados num caminho ([] em Uppaal).

• F - Algum estado num caminho (<> em Uppaal).

2.5.2 Reachability
As propriedades de acessibilidade são aquelas que permitem especificar que uma situ-
ação pode ser atingida. Sendo ϕ uma fórmula de estado, a especificação desta pro-
priedade faz-se recorrendo ao quantificador E e ao combinador F : EF ϕ. Por outras
palavras, diz-se que seguindo uma das execuções, ϕ pode ser verificado.

Este tipo de propriedades não garantem a exactidão do modelo mas permitem val-
idar o seu comportamento de base. Por exemplo num sistema de controlo de acessos,
esta propriedade permite validar que uma porta se abre.

Em Uppaal as propriedades de acessibilidade são expressas da seguinte forma:


E <> ϕ.

2.5.3 Safety
As propriedades de segurança são aquelas que permitem especificar que algo negativo
nunca vai acontecer. Este tipo de propriedades pode limitar-se a uma execução ou
abranger o conjunto de todas as execuções possíveis. Sendo ϕ uma fórmula de estado,
a especificação desta propriedade faz-se recorrendo quer ao quantificador E como ao
quantificador A e ao combinador G: AG¬ϕ ou EG¬ϕ.

Este tipo de propriedades é fundamental para garantir situações críticas num mod-
elo. Recorrendo ao exemplo de um sistema de controlo de acessos com fecho au-
tomático de portas, esta propriedade permite validar que uma porta nunca fica aberta
mais de x unidades de tempo. Ou no caso de existirem várias portas, como nos bancos,
que nunca estão abertas simultaneamente duas portas.

13
Em Uppaal as propriedades de segurança são expressas de forma positiva: A[]ϕ ou
E[]ϕ. Sendo que na primeira especificação (com o quantificador universal A) ϕ é obri-
gatoriamente verdade em todos os estados. Enquanto na segunda (com o quantificador
existencial E) ϕ é verdade em todos os estados de uma execução possível.

2.5.4 Liveness
As propriedades de evolução permitem especificar que dentro de determinadas condições
algo inevitavelmente vai acontecer.

Recorrendo ao exemplo de um sistema de controlo de acessos, esta propriedade


permite validar que quando alguém é identificado inevitavelmente uma porta vai abrir.

Em Uppal estas propriedades são expressas da seguinte forma: A <> ϕ ou ϕ−− >
ψ. Sendo que a primeira especificação significa que ϕ é inevitavelmente verdade nal-
gum estado de todas as execuções. E a segunda significa que sempre que ϕ for verdade
então ψ também vai ser verdade nalgum estado de todas as execuções seguintes.

2.5.5 Deadlock Freeness


Por fim a propriedade de ausência de deadlock permite especificar que o sistema não
entra numa situação da qual não consiga sair. Em Uppal esta propriedade é expressa
da seguinte forma: A[] not deadlock.

2.5.6 Interface
A interface de verificação possui uma lista de propriedades que pode ser seleccionada
e aumentada ou reduzida. Cada propriedade possui uma declaração (query), um texto
associado que é facultativo (comment) e um objecto que representa a propriedade na
lista. Quando uma prioridade é avaliada a mesma fica com o indicador a verde ou
vermelho. O verde significa que a propriedade foi correctamente verificada pelo algo-
ritmo de verificação de modelos enquanto o vermelho significa o contrário. Sempre
que uma propriedade não é verificada o Uppaal permite construir um contra-exemplo
que fica exposto no ambiente de simulação. No entanto esse contra-exemplo não é
construído por defeito. Para que isso seja feito é necessário ir ao menu Options >
DiagnosticT race e escolher uma das três opções Some, Shortest ou F astest.

14
Figura 2.6: Interface de verificação do Uppaal.

15
Capítulo 3

Casos de Estudo

Como casos de estudo são apresentados os modelos de dois algoritmos de exclusão


mútua, mais precisamente o algoritmo de Dekker e de Peterson. Estes algoritmos não
possuem qualquer restrição temporal, no entanto pela sua simplicidade tornam-se bons
exemplos para iniciar uma apresentação concreta sobre Uppaal.

Como terceiro caso de estudo é apresentado o modelo do Biphase Mark Protocol.


Trata-se de um caso mais completo com diversas restrições temporais e mais de trinta
propriedades especificadas e verificadas.

Referências principais deste capítulo [6][1][8].

3.1 Algoritmos de Dekker e Peterson


3.1.1 Descrição
Estes algoritmos permitem que dois processos partilhem um recurso conjunto recor-
rendo apenas a memória partilhada. O primeiro algoritmo foi definido em 1964 por T.
J. Dekker e o segundo em 1981 por Gary Peterson.

3.1.2 Modelo
Na Figura 3.1 é apresentado o único template do modelo do algoritmo de Dekker tal
como na Figura 3.2 para o modelo do algoritmo de Peterson. Ambos os modelos
possuem a particularidade de serem constituídos por dois autómatos que são nada mais
do que uma declaração duplicada do template de cada um com alteração dos respectivos
parâmetros de entrada (ver Listing 3.1 e Listing 3.2).

Listing 3.1: Declaração dos processos de sistema do modelo do algoritmo de Dekker.


/ / Insert process assignments .
P0 = P r o c e s s ( 0 ) ;
P1 = P r o c e s s ( 1 ) ;

16
Figura 3.1: Process(const int pid) do modelo do algoritmo de Dekker.

Figura 3.2: P(const int pid) do modelo do algoritmo de Peterson.

17
/ / Edit system d e f i n i t i o n .
s y s t e m P0 , P1 ;

Listing 3.2: Declaração dos processos de sistema do modelo do algoritmo de Peterson.


P0 = P ( 0 ) ;
P1 = P ( 1 ) ;

s y s t e m P0 , P1 ;
Os dois modelos utilizam também algumas variáveis globais (ver Listing 3.3 e
Listing 3.4) para permitir que a exclusão mútua seja devidamente realizada. A não
existência de canais de sincronização entre os autómatos justifica-se pela necessidade
do modelo representar os algoritmos fielmente.

Listing 3.3: Declaração das variáveis globais do modelo do algoritmo de Dekker.


/ / T h i s i s a s m a l l a d a p t a t i o n by F r i t s V a a n d r a g e r
/ / o f a model made by B a r t M e u l e n b r o e k
bool f l a g [2] = { false , f a l s e };
int turn = 1;
No caso do algoritmo de Dekker é declarada uma matriz booleana f lag de dois el-
ementos, inicializados a f alse, e uma variável inteira turn, inicializada a 1. A variável
f lag indica a intenção dos processos entrarem na zona crítica e a variável turn indica
qual dos processos possui prioridade para aceder à zona crítica.

Listing 3.4: Declaração das variáveis globais do modelo do algoritmo de Peterson.


/ / Number o f p r o c e s s e s
const int N = 2;
i n t [ 0 , 1 ] f l a g [N ] ;
int [0 ,1] turn ;
Analogamente no caso do algoritmo de Peterson é declarada uma constante inteira
N , inicializada com o valor 2, uma matriz de inteiros f lag de N elementos limitados
aos valores 0 e 1 e uma variável inteira turn. As variáveis inteiras que não são ini-
cializadas assumem por defeito o valor 0 ou o valor do limite inferior caso elas tenham
um limite definido na sua declaração. A constante N define o tamanho da matriz f lag
enquanto as duas restantes variáveis assumem a função descrita no caso do algoritmo
de Dekker.

De notar ainda que no autómato a matriz de inteiros é actualizada com valores


booleanos em vez de valores inteiros. À semelhança do que acontece em C, o Uppaal
assume valores inteiros para cada uma das expressões booleanas true (1) e f alse (0).

Observando detalhadamente o modelo do algoritmo de Dekker (Figura 3.1) verifica-


se que o mesmo inicia a sua execução actualizando a f lag do processo corrente para
true (Update f lag[pid] = true) indicando a intenção de aceder à zona crítica. No

18
estado seguinte existem duas execuções possíveis (Guard f lag[1 − pid] == true e
Guard f lag[1 − pid] == f alse) consoante o outro processo esteja ou não a pedir
acesso à zona crítica.

No caso do outro processo não estar a pedir acesso à zona crítica a execução do
processo corrente entra directamente na zona crítica (estado critical_section) e efec-
tua duas actualizações seguidas (Update turn = 1 − pid e Update f lag[pid] = f alse)
voltando ao estado inicial remainder. A actualização turn = 1 − pid indica que o
outro processo ganha prioridade e a actualização f lag[pid] = f alse remove a indi-
cação de acesso à zona critica por parte do processo corrente.

No caso do outro processo estar a pedir acesso à zona crítica são avaliadas mais
duas guardas turn == pid, turn == 1 − pid. Estas permitem verificar qual dos pro-
cessos possui prioridade no acesso à zona crítica. Caso a prioridade esteja do lado do
processo corrente então o modelo volta a avaliar a f lag do outro processo. Caso con-
trário a f lag do processo corrente é alterada para f alse (Update f lag[pid] = f alse) e
a execução seguinte fica avaliar as guardas turn == 1 − pid, turn == pid.

Estas guardas estão numa posição do ramo diferente no entanto são uma repetição
das anteriores com uma ligeira nuance, desta vez não existe transição de estado en-
quanto o outro processo tiver prioridade de acesso à zona crítica. Assim que o processo
corrente ganhe prioridade no acesso à zona crítica então é feita uma nova actualização
f lag[pid] = true para indicar a intenção de acesso à zona crítica e o modelo volta a
avaliar se existem condições para que o acesso seja feito.

Observando detalhadamente o modelo do algoritmo de Peterson (Figura 3.2) verifica-


se algo semelhante. Partindo do estado inicial a execução do modelo começa por fazer
duas actualizações de variáveis. A primeira f lag[pid] = true indica a intenção do
processo corrente ter acesso à zona crítica e a segunda turn = 1 − pid dá prioridade
de acesso ao outro processo. No estado seguinte existem duas guardas que verificam
se f lag[1 − pid] é f alse ou true.

Se o outro processo não indicou intenção de aceder à zona crítica (Guard f lag[1 −
pid] == f alse) então o modelo entra na zona crítica (estado cs). Posteriormente a
execução volta ao estado inicial actualizando a intenção do processo corrente em não
pretender aceder à zona crítica (Update f lag[pid] = f alse).

Se em contrapartida o outro processo indicou intenção de aceder à zona crítica


(Guard f lag[1 − pid] == true) então o modelo realiza uma segunda verificação mas
desta vez sobre a variável turn. Se a prioridade de acesso à zona crítica for do outro
processo turn == 1 − pid então o modelo volta ao estado anterior para nova avaliação
caso contrário turn == pid o modelo continua a sua execução para a zona crítica
(estado cs) e posteriormente volta ao estado inicial tal como anteriormente descrito.

19
3.1.3 Simulação
No modo de simulação do Uppaal é possível verificar que ambos os modelos possuem
dois processos designados por P0 e P1, tal como foi descrito nas declarações de sis-
tema. A simulação destes dois modelos permite verificar se a sua execução retrata o
comportamento desejado dos algoritmos. Apesar de aqui não existir uma relação for-
mal entre os modelos e o respectivo algoritmo de exclusão mútua é possível, mesmo
assim, tirar algumas conclusões sobre o seu funcionamento.

Algo especialmente interessante para este tipo de problemas é o de poder verificar


visualmente e das formas já descritas se o modelo realmente está a fazer aquilo que se
pretende. Esta metodologia pode inclusivamente ser utilizada para introduzir estes con-
ceitos de uma forma bastante prática. Programando estes algoritmos numa linguagem
"não formal", não existe a possibilidade de visualizar directamente ou verificar formal-
mente possíveis problemas.

Neste tipo de simulação o mesmo já não acontece. É muito intuitivo perceber que
o modelo avalia as variáveis descritas e consoante os seus valores o acesso à zona
crítica é dada a um ou outro processo. Inclusivamente é possível verificar a validade de
algumas propriedades do modelo tal como vai ser visto na secção seguinte.

Figura 3.3: Simulação do modelo do algoritmo de Dekker.

3.1.4 Verificação
A verificação destes dois modelos consiste na verificação de duas propriedades. Na
primeira verifica-se, como é de costume, se existe ou não deadlock freeness recorrendo

20
Figura 3.4: Simulação do modelo do algoritmo de Peterson.

à seguinte especificação A[]notdeadlock. Executando a verificação desta propriedade


no Uppaal verifica-se que realmente ambos os modelos a cumprem.

Na segunda verifica-se que em todas as execuções possíveis o modelo nunca está


simultaneamente na zona crítica dos dois processos. Essa especificação de propriedade
de segurança faz-se em Uppaal com a seguinte fórmula A[] (not (P 0.cs and P 1.cs)).

3.2 Biphase Mark Protocol


3.2.1 Descrição
Como terceiro caso de estudo apresenta-se o modelo do Biphase Mark Protocol. Este
protocolo é largamente utilizado especialmente para comunicação ao nível físico da
arquitectura OSI. O mesmo encontra-se implementado em micro controladores como
o Intel 82530 Serial Communications Controler.

Resumidamente neste protocolo cada bit de uma mensagem é codificado numa


célula que consiste num número de ciclos do relógio divido logicamente numa mark
subcell e numa code subcell. Tal como se pode ver na Figura 3.5 sempre que estas duas
subcells formarem um par de sinais iguais (1 e 1 ou 0 e 0) o bit da mensagem corre-
spondente é 1, sempre que o par de sinais for diferente (1 e 0 ou 0 e 1) então o bit da
mensagem corresponde é 0. A grande vantagem deste protocolo é que a sincronização
dos relógios do codificador e do descodificador é feita no início de cada célula.

21
Figura 3.5: Terminologia do Biphase Mark Protocol.

3.2.2 Modelo
A Figura 3.6 representa a arquitectura do modelo Uppaal deste protocolo. Este modelo
é constituído por 7 autómatos temporizados (representados na figura por rectângulos)
que comunicam quer por variáveis globais (representadas por círculos) como por sin-
cronizações (representadas por setas).

Figura 3.6: Arquitectura do modelo do BMP.

De forma sucinta descreve-se de seguida a funcionalidade de cada um dos autó-


matos:

• [Clock()] (Figura 3.7) - Modelação lógica do relógio físico do sistema do lado


do codificador. Este autómato produz tick’s, não confundir com as variáveis de
relógio do Uppaal.
• [Coder()] (Figura 3.9) - Modelação do processo de codificação. Através de uma
sequência de bits (variável in) e dos tick’s do relógio (do autómato Clock())
gera-se uma onda quadrada.

22
• [W ire()] (Figura 3.11) - Modelação do processo de transformação da onda quadrada
(dita perfeita) num sinal digital.
• [Clock2()] (Figura 3.8) - Semelhante ao Clock() mas desta vez para o descodi-
ficador.
• [Sampler()] (Figura 3.12) - Modelação do processo de cópia periódica do valor
de w para new.
• [Decoder()] (Figura 3.10) - Modelação do processo de descodificação. Aquando
de um novo tick se este autómato observar uma alteração da variável new ele
começa a contagem de um número específico de tick’s e compara o valor inicial
da variável new com o seu valor final. De seguida actualiza a variável out e
informa o T ester() da actualização através da sincronização put.
• [T ester()] (Figura 3.13) - Modelação do ambiente. Este autómato representa a
última componente do modelo no entanto não faz parte integrante do protocolo.
Neste modelo não existem declarações de variáveis locais nem existem parâmetros
nos templates criados. Assim a declaração do sistema (ver Listing ??) resume-se à
invocação de cada template e todos os canais de sincronização e variáveis utilizadas
são globais (ver Listing ??).

Listing 3.5: Declaração das variáveis globais do modelo do BMP.


/ / Global Declar ations
c h a n t i c k , t o c k , edge , g e t , p u t ;
b r o a d c a s t c h a n f u z z , s e t t l e , Sample ;
i n t m, n ;
b o o l i n , o u t , v , w, s , new , o l d , b u f ;
clock x , y , z ;
c o n s t i n t c e l l =14 , mark =7 , s a m p l e = 1 0 ;
c o n s t i n t min =93 , max =100 , e d g e l e n g t h = 1 0 0 ;

Listing 3.6: Declaração de sistema do modelo do BMP.


s y s t e m Coder , Clock , Wire , Sampler , Clock2 , Decoder , T e s t e r ;

Clock() e Clock2()
Tanto o Clock() como o Clock2() são compostos por um único estado e uma transição.
Ambos utilizam variáveis de relógio distintas (x e y respectivamente) reinicializadas
a cada tick. Cada um destes autómatos possui uma invariante que controla o tempo
durante o qual podem permanecer no estado inicial sem produzir um tick. Ambos
possuem uma guarda que activa a respectiva transição apenas quando a mesma for
verdade. Deste modo o Clock() só produz um tick entre as 93 e as 100 unidades de
tempo tal como o Clock2(), mas este último ainda precisa que a variável s tenha o
valor true (1). Esta variável serve para que o Sampler() apenas seja executado uma
vez por cada tick do Clock2().

23
Figura 3.7: Clock(). Figura 3.8: Clock2().

Figura 3.9: Coder().

Figura 3.10: Decoder().

Figura 3.11: Wire().


Figura 3.12: Sam-
pler().

Figura 3.13: Tester().

24
Coder()
O Coder() começa por permanecer no estado inicial enquanto a sincronização get?
não for invocada, sendo o estado inicial urgente o tempo não evolui. Assim que o
Tester() efectuar a sincronização get! o Coder() transita para o estado C1 (também
ele urgente) e consoante o valor do bit transmitido seja 1 ou 0 a respectiva transição
é efectuada gerando imediatamente uma nova aresta da onda quadrada. Se o bit for
1 o autómato fica no estado C2 durante 6 tick’s do Clock(), a transição para o estado
C4 corresponde a mais um tick e então é gerada uma nova aresta da onda quadrada.
O processo volta-se a repetir de forma análoga até ser gerada outra aresta ao 14o tick
(contando do ínicio). Se em contrapartida o bit for 0 o autómato passa directamente
para o estado C3 gerando uma aresta na transiçao e ao 14o tick do Clock() gera outra
ao voltando ao estado ínicial.

Wire()
Este autómato introduz o pressuposto que indica que um sinal eléctrico só estabiliza
após algum tempo da ocorrência de uma aresta da onda quadrada. Assim considera-se
que no estado W 0 o sinal é estável enquanto no estado W 1 não. Para os parâmetros que
permitem que o protocolo esteja correcto é fundamental que o Coder() nunca gere uma
nova aresta enquanto o sinal é instável, isto é, enquanto o Wire() se encontre no estado
W 1. No caso de ser gerada uma nova aresta sobre estas condições então o Wire() passa
ao estado W 2. No entanto a verificação do modelo vai provar que esta situação nunca
ocorre.

Sampler()
Este autómato apenas possui um estado e uma transição responsável por copiar o valor
do sinal w para a variável new utilizada como variável de entrada pelo Decoder().
Para garantir que apenas é copiado um valor por cada tick do Clock2()é utilizada uma
variável booleana s.

Decoder()
O Decoder() modela o processo de descodificação do sinal recolhido pelo Sampler().
De forma análoga ao Coder() este autómato rege a sua execução por tick’s, mas desta
feita do Clock2(). No estado inicial cada tick é responsável pela comparação do valor
recolhido do Sampler() com o valor anterior. Enquanto os valores forem iguais o pro-
cesso de comparação repete-se. Assim que for detectada uma variação no sinal o autó-
mato passa para o estado D1 armazenando o último valor recolhido. A execução vai
manter-se no estado D1 enquanto não passarem um número de tick’s iguais ao valor
da variável sample. Quando for efectuada a transição para o estado D2 é novamente
avaliado se o valor do sinal recolhido naquele momento pelo Sampler() é o mesmo
do que o inicial para permitir gerar o bit correspondente. Isto é, se os valores forem
diferentes o bit gerado vai ser 1 caso contrário 0. Quando a execução voltar ao estado
inicial é efectuada a sincronização put! para informar o Tester() de que um novo bit foi
gerado.

25
Tester()
Este autómato selecciona não deterministicamente bits e coloca-os na variável in, pos-
teriormente confirma se os bits recebidos através da variável out correspondem aos
anteriores. Sempre que for observada uma diferença nos valores o autómato entra num
estado de erro. Se o modelo estiver correcto esse estado nunca é atingido.

3.2.3 Verificação
Das 39 propriedades especificadas para este modelo descrevem-se apenas as seguintes:

• A[] Coder.C0 imply Tester.T0 - Sempre que o Coder está no estado inicial isso
implica que o Tester também se encontre no seu estado inicial.
• A[] not (Tester.T2 or Tester.T3 or Tester.Error) - Para qualquer execução o Tester
nunca atinge o estado T2, T3 ou Error. Esta verificação acaba por ser redundante
com a de deadlock freeness porque em ambas as situações se esses estados são
atingidos o modelo entra em deadlock.
• A[] Coder.C0 or Coder.C1 imply n == 0 - Sempre que o estado C0 ou C1 do
Coder é o estado corrente então a variável n tem de ser igual a 0. Isto é, o
contador de tick’s tem de estar reinicializado.

• A[] Decoder.D0 imply m == 0 - Sempre que o Decoder está no estado D0 então


a variável m tem de ser igual a 0. Análogo ao anterior.
• A[] y >= 0 and y <= Max - O relógio y está sempre compreendido entre 0 e
Max. Isto é, em nenhuma situação o tick do Clock2 ultrapassa o valor de Max.

• A[] Coder.C1 or Coder.C2 or Coder.C4 imply Tester.T1 - Sempre que o Coder


está num outro estado que não o C0 ou o C3 então o Tester está obrigatoriamente
no estado T1.
• A[] not Wire.W2 - O estado W2 do coder nunca é atingido. Isto garante que o
modelo nunca produz uma nova aresta da onda quadrada enquanto o Wire está
na posição W1 (de sinal instável).

26
Capítulo 4

Exercícios

Neste capítulo apresentam-se alguns exercícios a resolver com a ferramenta de veri-


ficação de modelos Uppaal. Estes exercícios contemplam quer a modelação, como a
simulação e a verificação dos modelos. No fim do capítulo encontram-se resoluções
para os exercícios propostos. No entanto é vivamente recomendado que essas res-
oluções só sejam consultadas no fim dos exercícios estarem resolvidos.

Referências principais deste capítulo [2][4].

4.1 Exercício 1 - Protocolo v1


Num contexto de comunicação, o mais simplista possível, é sugerida a implementação
de um protocolo com três componentes interligadas: emissor, meio e receptor (ver
Figura 4.1).
• O emissor transmite uma mensagem de tamanho fixo. Esse tamanho corre-
sponde ao tempo entre o início do envio e o fim do envio da mensagem.
• O meio corresponde à componente central responsável pela passagem da men-
sagem do emissor para o receptor. Este meio introduz um atraso fixo na comu-
nicação que corresponde ao tempo entre o início do envio por parte do emissor e
o início da recepção por parte do receptor ou o fim do envio por parte do emissor
e o fim da recepção por parte do receptor.
• O receptor recepciona a mensagem vinda do meio de comunicação.

Nesta primeira versão parte-se do princípio que o tamanho é menor que o atraso
(tamanho < atraso), i.e. o meio só transmite a mensagem para o receptor depois do
envio (por parte do emissor) ter sido finalizado.

É recomendada a utilização de constantes inteiras para o tamanho e para o atraso.


O meio não deve, nesta primeira versão, ter conhecimento do tamanho da mensagem,

27
Figura 4.1: Esquema das componentes do protocolo.

nem o emissor do atraso. O sistema modela-se com uma rede de autómatos sin-
cronizados, utilizando o início e fim de comunicação do emissor e do receptor como
sincronizações com o meio.

Pretende-se ainda que o modelo seja verificado garantido a não existência de dead-
lock’s e identificando qual o tempo decorrido do início do envio até ao fim da recepção
da mensagem.

4.2 Exercício 2 - Protocolo v2


Este exercício consiste na alteração do protocolo modelado anteriormente de modo
a que o mesmo agora consiga lidar com mensagens de tamanho maior que o atraso
do meio. Nesta versão não é exigido que o modelo seja rigoroso, admite-se a possi-
bilidade das execuções nem sempre escolherem a forma mais rápida de comunicar a
mensagem. Isto partindo do princípio que o meio continua a não conhecer o tamanho
da mensagem.

Pretende-se que o modelo seja verificado pelo menos com as propriedades anteri-
ormente definidas.

28
4.3 Resoluções

29
(* Texto em Falta - Versão com resoluções facultada a pedido. *)

30
Referências

[1] http://www.ita.cs.ru.nl/publications/papers/fvaan/
MCinEdu/mutex.html.
[2] http://www.it.uu.se/edu/course/homepage/realtid/
p1ht08/uppaal.
[3] Systems and software verification: model-checking techniques and tools. Springer-
Verlag New York, Inc., New York, NY, USA, 1999.
[4] Hugh Anderson. Verification of real time systems - cs5270 (lecture
11). http://www.comp.nus.edu.sg/~cs5270/2006-semesterII/
foils11.print.pdf, March 2007.
[5] Gerd Behrmann, Alexandre David, and Kim G. Larsen. A tutorial on UPPAAL. In
Marco Bernardo and Flavio Corradini, editors, Formal Methods for the Design of
Real-Time Systems: 4th International School on Formal Methods for the Design of
Computer, Communication, and Software Systems, SFM-RT 2004, number 3185 in
LNCS, pages 200–236. Springer–Verlag, September 2004.
[6] R. "Hamberg and F.W."Vaandrager. "Using Model Checkers in an Introductory
Course on Operating Systems". Technical Report "ICIS–R07031", "Radboud Uni-
versity Nijmegen", "December2007".
[7] Kim G. Larsen, Paul Pettersson, and Wang Yi. U PPAAL in a Nutshell. Int. Journal
on Software Tools for Technology Transfer, 1(1–2):134–152, Oct 1997.

[8] F.W. Vaandrager and A.L. de Groot. Analysis of a biphase mark protocol with Up-
paal and PVS. Formal Aspects of Computing Journal, 18(4):433–458, December
2006.

31
Apêndice A

TA e XTA BNF

Informação retirada da página pessoal do Professor Gerd Behrmann. Esta sintaxe


assemelha-se à da linguagem C, tanto que é possível declarar funções C dentro da
especificação do modelo.

Listing A.1: BNF do formato TA/XTA v3.x


OldXTA : : = < O l d D e c l a r a t i o n > ∗ < I n s t a n t i a t i o n >∗ <System >
O l d D e c l a r a t i o n : : = < VariableDecl > | <OldConstDecl >
| <OldProcDecl >
OldConstDecl : : = ’ const ’ <OldConstDeclId >
( ’ , ’ <OldConstDeclId >)∗ ’ ; ’
O l d C o n s t D e c l I d : : = ID < A r r a y D e c l >∗ [ < I n i t i a l i s e r > ]

O l d P r o c D e c l : : = ’ p r o c e s s ’ ID [ < O l d P r o c P a r a m s > ]
’ { ’ <OldProcBody > ’ } ’
O l d P r o c P a r a m s : : = ’ ( ’ [ < OldProcParam >
( ’ ; ’ < OldProcParam > ) ∗ ] ’ ) ’
O l d P r o c P a r a m : : = <Type > ID < A r r a y D e c l >∗ ( ’ , ’ ID < A r r a y D e c l > ∗ ) ∗
| ’ c o n s t ’ ID < A r r a y D e c l >∗ ( ’ , ’ ID < A r r a y D e c l > ∗ ) ∗

OldProcBody : : = ( < VarDecl > | < O l d C o n s t D e c l > ) ∗


< O l d S t a t e s > [ < Commit > ] [ < U r g e n t > ] < I n i t > [ < O l d T r a n s i t i o n s > ]

O l d S t a t e s : : = ’ s t a t e ’ < OldStateDecl > ( ’ , ’ < OldStateDecl >)∗ ’ ; ’


O l d S t a t e D e c l : : = ID [ ’ { ’ < O l d I n v a r i a n t > ’ } ’ ]
O l d I n v a r i a n t : : = < Expression > ( ’ , ’ < Expression >)∗

OldTransitions ::= ’ trans ’ <OldTransition >


( ’ , ’ < O l d T r a n s i t i o n O p t >)∗ ’ ; ’

O l d T r a n s i t i o n : : = ID ’−>’ ID < OldTransBody >


O l d T r a n s i t i o n O p t : : = O l d T r a n s i t i o n | ’−>’ ID < OldTransBody >

32
OldTransBody : : = ’ { ’ [ < OldGuard > ] [ < Sync > ] [ < A s s i g n > ] ’ } ’

OldGuard : : = ’ g u a r d ’ < E x p r e s s i o n > ( ’ , ’ < E x p r e s s i o n > ) ∗ ’ ; ’

Listing A.2: BNF do formato XTA v4.x


XTA : : = < D e c l a r a t i o n >∗ < I n s t a n t i a t i o n >∗ <System >
D e c l a r a t i o n : : = < F u n c t i o n D e c l > | < V a r i a b l e D e c l > | <TypeDecl >
| <ProcDecl >
I n s t a n t i a t i o n : : = ID ASSIGNMENT ID ’ ( ’ < A r g L i s t > ’ ) ’ ’ ; ’
System : : = ’ s y s t e m ’ ID ( ’ , ’ ID ) ∗ ’ ; ’

ParameterList : : = ’( ’ [ <Parameter > ( ’ , ’ <Parameter > )∗ ] ’) ’


P a r a m e t e r : : = <Type > [ ’& ’ ] ID < A r r a y D e c l >∗

F u n c t i o n D e c l : : = <Type > ID < P a r a m e t e r L i s t > < Block >

P r o c D e c l : : = ’ p r o c e s s ’ ID < P a r a m e t e r L i s t > ’ { ’ <ProcBody > ’ } ’


ProcBody : : = ( < F u n c t i o n D e c l > | < V a r i a b l e D e c l > | <TypeDecl > ) ∗
< S t a t e s > [ < Commit > ] [ < U r g e n t > ] < I n i t > [ < T r a n s i t i o n s > ]

S t a t e s : : = ’ s t a t e ’ < S t a t e D e c l > ( ’ , ’ < S t a t e D e c l >)∗ ’ ; ’


S t a t e D e c l : : = ID [ ’ { ’ < E x p r e s s i o n > ’ } ’ ]

Commit : : = ’ commit ’ S t a t e L i s t ’; ’
Urgent : : = ’ urgent ’ S t a t e L i s t ’; ’
S t a t e L i s t : : = ID ( ’ , ’ ID ) ∗

I n i t : : = ’ i n i t ’ ID ’ ; ’

T r a n s i t i o n s : : = ’ t r a n s ’ < T r a n s i t i o n > ( ’ , ’ < T r a n s i t i o n O p t >)∗ ’ ; ’


T r a n s i t i o n : : = ID ’−>’ ID < T r a n s i t i o n B o d y >
T r a n s i t i o n O p t : : = T r a n s i t i o n | ’−>’ ID < T r a n s i t i o n B o d y >
T r a n s i t i o n B o d y : : = ’ { ’ [ < Guard > ] [ < Sync > ] [ < A s s i g n > ] ’ } ’

Guard : : = ’ g u a r d ’ < E x p r e s s i o n > ’ ; ’


Sync : : = ’ sync ’ < E x p r e s s i o n > ( ’ ! ’ | ’? ’) ’; ’
Assign : : = ’ assign ’ <ExprList > ’; ’

TypeDecl : : = ’ t y p e d e f ’ <Type > < T y p e I d L i s t >


( ’ , ’ < TypeIdList >)∗ ’ ; ’
T y p e I d L i s t : : = ID < A r r a y D e c l >∗

Listing A.3: BNF da declaração de variáveis


V a r i a b l e D e c l : : = <Type > < D e c l I d > ( ’ , ’ < D e c l I d > ) ∗ ’ ; ’
D e c l I d : : = ID < A r r a y D e c l >∗ [ ASSIGNMENT < I n i t i a l i s e r > ]

33
I n i t i a l i s e r : : = <Expression >
| ’{ ’ < F i e l d I n i t > ( ’ , ’ < F i e l d I n i t > )∗ ’} ’
F i e l d I n i t : : = [ ID ’ : ’ ] < I n i t i a l i s e r >

ArrayDecl : : = ’[ ’ <Expression > ’] ’

Type : : = < P r e f i x > ID [ <Range > ]


| < P r e f i x > ’ s t r u c t ’ ’ { ’ < F i e l d D e c l >+ ’ } ’
F i e l d D e c l : : = <Type > < F i e l d D e c l I d > ( ’ , ’ < F i e l d D e c l I d > ) ∗ ’ ; ’
F i e l d D e c l I d : : = ID < A r r a y D e c l >∗

Pref ix : : = ( [ ’ urgent ’ ] [ ’ broadcast ’ ] | [ ’ const ’ ] )


Range : : = ’ [ ’ < E x p r e s s i o n > ’ , ’ < E x p r e s s i o n > ’ ] ’

Listing A.4: BNF das instruções


B l o c k : : = ’ { ’ ( < V a r i a b l e D e c l > | <TypeDecl > ) ∗ < S t a t e m e n t >∗ ’ } ’
S t a t e m e n t : : = <Block >
| ’; ’
| <Expression > ’; ’
| ’ for ’ ’( ’ < ExprList > ’ ; ’ < ExprList > ’ ; ’
<ExprList > ’) ’ <Statement >
| ’ while ’ ’( ’ < ExprList > ’) ’ < Statement >
| ’ do ’ < S t a t e m e n t > ’ w h i l e ’ ’ ( ’ < E x p r L i s t > ’ ) ’ ’ ; ’
| ’ if ’ ’( ’ <ExprList > ’) ’ <Statement >
[ ’ else ’ <Statement > ]
| ’ break ’ ’; ’
| ’ continue ’ ’; ’
| ’ s w i t c h ’ ’ ( ’ < E x p r L i s t > ’ ) ’ ’ { ’ <Case >+ ’ } ’
| ’ return ’ ’; ’
| ’ return ’ <Expression > ’; ’
Case : : = ’ c a s e ’ < E x p r e s s i o n > ’ : ’ < S t a t e m e n t >∗
| ’ d e f a u l t ’ ’ : ’ < S t a t e m e n t >∗

Listing A.5: BNF das expressões


ExprList : : = <Expression > ( ’ , ’ <Expression > )∗
E x p r e s s i o n : : = ID
| NAT
| ’ true ’ | ’ f a l s e ’
| ID ’ ( ’ < A r g L i s t > ’ ) ’
| <Expression > ’[ ’ <Expression > ’] ’
| ’( ’ <Expression > ’) ’
| < E x p r e s s i o n > ’++ ’ | ’++ ’ < E x p r e s s i o n >
| < E x p r e s s i o n > ’−−’ | ’−−’ < E x p r e s s i o n >
| < E x p r e s s i o n > <AssignOp > < E x p r e s s i o n >
| <UnaryOp > < E x p r e s s i o n >

34
| <Expression > <Rel > < E x p r e s s i o n >
| <Expression > <BinIntOp > < Expression >
| <Expression > <BinBoolOp > < E x p r e s s i o n >
| <Expression > ’? ’ <Expression > ’: ’ <Expression >
| <Expression > ’ . ’ ID>

AssignOp : : = ASSIGNMENT | ’+= ’ | ’−=’ | ’∗= ’ | ’ / = ’ | ’%=’


| ’ | = ’ | ’&= ’ | ’ ^ = ’ | ’ < <= ’ | ’ > >= ’
UnaryOp : : = ’ − ’ | ’ ! ’
R e l : : = ’ < ’ | ’ <= ’ | ’== ’ | ’ ! = ’ | ’ >= ’ | ’ > ’
B i n I n t O p : : = ’+ ’ | ’ − ’ | ’ ∗ ’ | ’ / ’ | ’% ’ | ’& ’ | ’ | ’ | ’ ^ ’
| ’<<’ | ’>>’
BinBoolOp : : = ’&&’ | ’ | | ’
ArgList : : = [ <Expression > ( ’ , ’ <Expression > )∗ ]

35

Você também pode gostar