Copyright (c) 2005 Juan Pablo D. Borgna <jpborgna en inti gov ar>
Copyright (c) 2006-2007 Salvador E. Tropea <salvador en inti gov ar>
Copyright (c) 2005-2007 Instituto Nacional de Tecnología Industrial

Comandos y bloques:
                   Los archivos de template tienen comandos de bloque y
                   comandos de operacion. Los comandos de bloque comienzan con
                   dos signos menos "--" y los de operacion van encerrados entre
                   signos pesos "$". Los comandos de bloque indican la ejecucion
                   de un bloque y el fin de bloque debe ser indicado con la
                   instruccion "--END".


Variables internas:
                   Se proporcionan las siguientes variables internas que pueden
                   ser utilizadas invocando su nombre entre signos pesos "$" o
                   modificados si ademas se les asigna un valor entre
                   parentesis. Ej. $ADDRESS(0x0000)$ le asignara a esta variable
                   el valor 0x0000.

$ADDRESS$ :
           Acumulador que es util al momento de incrementar la direccion de una
           memoria, por ejemplo.
           
$STEP$    :
           Valor con el cual se incrementara la variable $ADDRESS$.

$SBYTES$  :
           Cantidad de bytes que posee el bitstream del bitfile.

$SBITES$  :
           Cantidad de bits que posee el bitstream del bitfile.

$MSIZE$   :
           Obtenido del campo msize de la definicion del dispositivo en el
           archivo DEVICES.
           Expresa la ultima posicion de memoria de un dispositivo con memoria.

$ID$      :
           Obtenido del campo id de la definicion del dispositivo en el archivo
           DEVICES.
           Expresa el IDCODE del dispositivo actual.

$IDMASK$  :
           Obtenido del campo idmask de la definicion del dispositivo en el
           archivo DEVICES.
           Expresa la mascara que se usara en la comprobacion del IDCODE.

$BSIZE$   :
           Obtenido del campo BSIZE de la definicion del dispositivo en el
           archivo DEVICES.
           Es el "block size" (cantidad de bits) a transferir expresando
           en bits.
           Nota: El valor BSIZE y el valor STEP no son cosas separadas.
           BSIZE es el tamaño en bits de la cache que tiene el dispositivo
           para almacenar los datos antes de transferirlos a la flash.
           Cada dirección de memoria direcciona una cantidad de bits (64
           o 128 es lo común), el STEP es el número de posiciones de memoria
           que entran en la cache, luego BSIZE=STEP*bits_por_dirección.
           Esto es en las XC18V: 32*64=2048 o 32*128=4096.

$BSIZEB$   :
           Obtenido del campo BSIZE de la definicion del dispositivo en el
           archivo DEVICES.
           Es el "block size" (cantidad de bits) a transferir expresando
           en bytes.

$BSIZEB2$  :
           $BSIZEB$ multiplicado por 2.

Comandos de bloque:

       
--LITERAL START :
                 Indica que se debe copiar en el archivo de salida el contenido
                 de este bloque y hasta el final del mismo tal y como esta.
                 Si se encuentra un comando de operacion entre medio este es
                 ejecutado.

--REPEAT START :
                Indica que se repetira de principio a fin el contenido de este
                bloque mientras que haya informacion que leer en el bitfile
                de entrada.
                Este comando de bloque debe tener en su interior algun comando
                de operacion que lea informacion del bitfile de entrada, si no
                este nunca llegara a su fin y el programa se quedara
                repitiendo el bloque hasta agotar el espacio en disco.
                Con cada iteracion del bloque se incrementa la variable
                $ADDRESS$ en $STEP$.

--REPEAT UNTIL valor :
                      Indica que se repetira de principio a fin el contenido de
                      este bloque hasta que la variable $ADDRESS$ tome el valor
                      pasado como parametro. Con cada iteracion del bloque se
                      incrementara la variable $ADDRESS$ en $STEP$.
                      El valor pasado como parametro debe ser multiplo de
                      $STEP$, si no la condicion de salida del bloque nunca se
                      conseguira y el programa se quedara repitiendo el bloque
                      hasta agotar el espacio en disco.
                      En lugar de valor se puede utilizar una variable:
                      Ej.: --REPEAT UNTIL MSIZE


--END :
       Indica el final de un bloque LITERAL, REPEAT o REPEAT UNTIL.


Comandos de operacion:
                      Los comandos de operacion pueden recibir como argumento
                      el nombre de una variable en lugar de una constante:
                      Ej.: $FILL(0xFF,BSIZE)$

$DATA(ndatabytes)$ :
                    Escribe en el archivo de salida una cantidad ndatabytes de
                    bytes del bitfile de entrada expresados en hexadecimal.

$DATA_INV(ndatabytes)$ :
                        Escribe en el archivo de salida una cantidad ndatabytes
                        de bytes del bitfile de entrada, invirtiendo el orden
                        de los bits del bloque, expresados en hexadecimal.

$FILL(VAL,TIMES)$ :
                   Escribe TIMES veces el valor VAL expresado en hexadecimal en
                   el archivo de salida.

$REWIND$ :
          Vuelve a poner el archivo de bits en la posicion del primer byte del
          stream para poder realizar otra pasada completa con un comando de
          bloque.

$CUTLINES(n):
             Con 0 deja de cortar las líneas largas, con 1 vuelve a cortarlas.
             Otros valores: reservados.

-------------------------------------------------------------------------------

Como crear un template para una FPGA:
-------------------------------------

Autor: Salvador E. Tropea

A) Crear un .SVF válido para esa FPGA:

1) Obtener un .bit para la FPGA en cuestión.
2) Abrir el impact:
$ . /usr/local/ISEWb/settings.sh
$ impact
3) Elegir "I want to (*) Create a new project", Ok. (Darle un nombre si se
quiere).
4) Elegir "(*) Prepare a boundary-scan file [SVF]", Finish.
5) Elegir un nombre para el SVF.
6) Elegir el .bit.
7) Presionar el botón derecho sobre la FPGA y elegir "Program", Ok.
8) Salir del impact

Automáticamente es:

setPreference -pref AutoSignature:FALSE
setPreference -pref KeepSVF:FALSE
setPreference -pref ConcurrentMode:FALSE
setPreference -pref UseHighz:FALSE
setPreference -pref UserLevel:NOVICE
setPreference -pref svfUseTime:FALSE
setMode -bs
setMode -bs
setCable -port svf -file "salida.svf"
addDevice -p 1 -file "archivo.bit"
Program -p 1 -s -defaultVersion 0 

B) Crear un nuevo template (ej: alg_Virtex_4.svft)

1) Abrir un template que ya exista para usarlo de guía.
2) Borrar "FREQUENCY 1E6 HZ;"
3) Reemplazar: $ID$ y $IDMASK$ en la parte que dice "Loading device with
'idcode' instruction.". (f167c093)
4) Reemplazar la megalínea del bitstream por:
SDR $SBITS$ TDI ($DATA_INV(-1)$) SMASK ($FILL(0xFF,-1)$);

C) Probar su funcionamiento

1) Colocar el nuevo template en /usr/share/bit2svf/
2) Editar /usr/share/bit2svf/DEVICES agregando el ID de la FPGA y el algoritmo
a usar:

// Virtex 4 family (10 bits IR)                                                 
XC4VLX25, f167c093, 0fffffff, alg_Virtex_4, VOID, 0l

3) Probar el template:

$ bit2svf display_test_lx25.bit v4-b2s.svf XC4VLX25

Esto genera v4-b2s.svf que debería ser practicamente idéntico al generado por
impact.
Nota: En este caso observé que el impact agrega 32 bits en 0 extra al
bitstream. Esto no parece ser indispensable y sospecho que sirve para
"limpiar/vaciar" la cadena.
4) Si todo fue OK se puede probar con el dispositivo:

$ jbit display_test_lx25.bit XC4VLX25


-------------------------------------------------------------------------------

Como crear un template para una PROM:
-------------------------------------

Autor: Salvador E. Tropea

A) Crear un archivo de PROM válido.

1) Obtener un .bit para la FPGA en cuestión.
2) Abrir el impact:
$ . /usr/local/ISEWb/settings.sh
$ impact
3) Elegir "I want to (*) Prepare a ROM file", Ok. (Darle un nombre si se
quiere).
4) Elegir "I want to target a (*) Xilinx PROM", "PROM File name" darle un
nombre. Next. (Ojo con el path).
5) Elegir la PROM y Add, luego Next.
6) Agregar el .bit
7) Elegir "Generate File ..." dentro de las acciones disponibles (la única).
8) Esto genera un .MCS con el contenido para la PROM.

B) Crear un .SVF válido para esa PROM. Esto es similar a la FPGA, la única
diferencia es que le especificamos el .MCS en lugar de un .bit. En este caso
nos preguntará cual es el dispositivo haciendo un guess de cual se trata. Esto
es porque el .mcs es un bitstream crudo y no dice para que dispositivo se
hizo.
Durante este proceso se pueden elegir opciones como si la PROM se conecta en
paralelo y si se incluye verificación. Además hay que elegir que primero la
borre.

B) Crear un nuevo template o usar uno ya hecho. Esto es como con la FPGA.

C) Probar su funcionamiento. Esto es más o menos lo mismo que con la FPGA. La
principal diferencia con las PROMs es que acá es necesario configurar su tamaño
y el tamaño de la caché o página donde se guardarán temporalmente los datos:

// XCFxxP memories
XCF08P , f5057093, 0fffffff, alg_XCFP ,8192 , 0x100000

