Elaborado por Erick Carvajal Barboza y Ana Eugenia Sánchez Villalobos
Email: erick punto carvajal punto barboza arroba ucr punto ac punto cr
Escuela de Ingeniería Eléctrica, Universidad de Costa Rica
En este tutorial se utilizarán las herramientas Yosys y OpenLane para ilustrar los procedimientos de síntesis lógica.
Para encontrar una lista actualizada de las preguntas más comunes puede ir al siguiente enlace.
Los sistemas digitales pueden ser descritos en varios dominios distintos (Kaeslin, 2008), de más a menos abstracto se tiene: (1) el dominio conductual, (2) el dominio estructural y (3) el dominio físico.
En el dominio conductual únicamente es importante la funcionalidad del sistema, y no tiene relevancia el cómo está construido. En el dominio estructural se especifican las interconexiones de cada bloque que conforma el sistema sin embargo, es únicamente en el dominio físico en el cuál se tiene información sobre cómo está construido cada componente, que ubicación tiene en el chip y cómo se deben realizar las conexiones entre bloques. El flujo de diseño de circuitos integrados se encarga de convertir la especificación conductual de un sistema digital en una especificación física, y para eso tiene, como paso intermedio, que obtener une especificación estructural.
El paso que permite la conversión de una especificación conductual de un sistema digital a una especificación estructural se conoce como síntesis lógica (Weste & Harris, 2015) y será el tema principal de este tutorial.
En este paso del flujo de diseño se toma una especificación conductual del sistema digital, usualmente escrita en un lenguaje de descripción de hardware (HDL, por sus siglas en inglés) como Verilog o VHDL, y la convierte en una descripción estructural conocida como netlist, donde se enlistan todas las compuertas lógicas, elementos secuenciales y puertos de entrada y salida, así como todas las conexiones que existen entre los mismos. Este proceso es, usualmente, realizado de forma automática por herramientas conocidas como sintetizadores, quienes además de realizar la conversión, implementan optimizaciones de área, temporización, potencia y otros aspectos relevantes para el diseño (Wang et al., 2009).
Para poder efectuar la síntesis lógica, el sintetizador requiere que se especifique el conjunto de compuertas lógicas a las que se tendrán acceso, para esto se utilizan librerías de celdas estándar. Estas librerías son colecciones de funciones lógicas (INV, NAND, NOR, Flip-Flops, etc) en las cuales es especifican las características de cada una (layout, símbolo, esquemático, retardo, potencia, tolerancia al ruido, etc). Un aspecto fundamental de estas librerías es que todas las celdas tienen la misma altura, mientras que su ancho sí varía, esto facilita las labores de posicionamiento automático, pues se pueden acomodar siguiendo filas. En este tutorial utilizaremos la librería SkyWater PDK, la cual es open-source y utiliza un proceso de manufactura en 130nm.
Una vez que se ha obtenido la definición estructural del sistema, es común realizar múltiples chequeos para verificar la sanidad de los resultados, entre esos chequeos se tiene:
Aunque durante esta etapa se pueden obtener estimaciones de temporización y potencia, es importante recalcar que dichos valores no son muy exactos, aún hay información relevante que se desconoce, como la distancia de las interconexiones, la capa de metal en la que realizarán, efectos de ruido, etc. Por estos motivos es indispensable volver a realizar estos chequeos en etapas posteriores del diseño.
En este tutorial, se hará uso de la herramienta libre para diseño de circuitos integrados llamada OpenLane. Se sugiere al lector investigar sobre el flujo de diseño que sigue OpenLane antes de continuar con el tutorial.
Yosys es una herramienta libre para la síntesis lógica de circuitos digitales. OpenLane utiliza Yosys para sintetizar sus diseños. Se sugiere al lector investigar sobre Yosys antes de continuar con el tutorial.
Antes de iniciar este laboratorio, asegúrese de haber completado satisfactoriamente todas las instrucciones de la Guía de Instalación.
El laboratorio se basa en ejemplos sencillos, que permitirán ilustrar los procedimientos que se ejecutan durante el flujo de síntesis. Las instrucciones mostradas a continuación proveen una guía para generar los archivos de los ejemplos:
>$ cd /designs/
>$ mkdir adder_1b adder_4b adder_8b_pipeline
Los comandos anteriores crearán las carpetas de los tres ejemplos que se
utilizarán a lo largo del tutorial. Ahora, utilizando los siguientes comandos,
ingresará al directorio adder_1b
y creará el archivo
adder_1b.v
>$ cd adder_1b
>$ touch adder_1b.v
Dentro del archivo adder_1b.v
escriba lo siguiente:
module adder_1b (
input A, B, C_in,
output Sum, C_out
) ;
assign {C_out, Sum} = A + B + C_in;
endmodule
A continuación, utilizando los siguientes comandos, ingrese al directorio
adder_4b
y genere el archivo adder_4b.v
>$ cd ../adder_4b
>$ touch adder_4b.v
Dentro del archivo adder_4b.v
escriba lo siguiente:
module adder_4b (
input [3:0] A, B,
input C_in,
output [3:0] Sum,
output C_out
);
assign {C_out, Sum} = A + B + C_in;
endmodule
Y para finalizar, con los siguientes comandos, ingrese al directorio
adder_8b_pipeline
, copie el archivo adder_4b.v
del
paso anterior y genere el archivo adder_8b_pipeline.v
>$ cd ../adder_8b_pipeline
>$ cp ../adder_4b/adder_4b.v .
>$ touch adder_8b_pipeline.v
Dentro del archivo adder_8b_pipeline.v
escriba lo siguiente:
module adder_8b_pipeline (
input [7:0] A, B,
input C_in, clk, rst,
output [7:0] Sum,
output C_out
);
wire C_out_a0, C_out_a1;
reg C_out_a0_reg;
wire [3:0] Sum_a0, Sum_a1;
reg [3:0] A_msbits, B_msbits, Sum_a0_reg;
adder_4b a40 (
A[3:0], B[3:0], C_in,
Sum_a0[3:0], C_out_a0
) ;
adder_4b a41 (
A_msbits, B_msbits, C_out_a0_reg,
Sum_a1[3:0], C_out_a1
) ;
assign Sum[3:0] = Sum_a0_reg;
assign Sum[7:4] = Sum_a1;
assign C_out = C_out_a1;
always @(posedge clk) begin
if (!rst) begin
Sum_a0_reg <= 0;
C_out_a0_reg <= 0;
A_msbits <= 4'b0;
B_msbits <= 4'b0;
end
else begin
A_msbits <= A[7:4];
B_msbits <= B[7:4];
Sum_a0_reg[3:0] <= Sum_a0[3:0];
C_out_a0_reg <= C_out_a0;
end
end
endmodule
Antes de continuar con el tutorial, se sugiera al lector leer y comprender cada uno de los diseños de los sumadores que se utilizarán.
En esta sección se introducirá el uso de la herramienta Yosys, la cual se encarga de la síntesis lógica en el ambiente de diseño libre OpenLane. Esta introducción se realizará mediante el uso de un diseño sencillo, un sumador completo de 1 bit.
Primero, se debe entrar al docker de OpenLane:
>$ cd
>$ make mount
Si este paso es ejecutado satisfactoriamente la terminal ahora debería mostrar una línea como la mostrada a continuación:
OpenLane Container (XYWZ):/openlane$
La línea anterior indica que se ha entrado al docker de OpenLane, y ahora se pueden utilizar todas las herramientas instaladas en el mismo.
Una vez en el docker, se entrará a la herramienta Yosys:
:/openlane$ yosys
En la terminal se desplegará un banner como en mostrado en la siguiente figura.
El comando más importante de Yosys es help
, el cual brinda
información sobre el uso del resto de comandos. Incluso help
tiene
un help
. Intente ejecutar el siguiente comando:
yosys> help help
El primer paso para iniciar el proceso de síntesis lógica es indicarle a Yosys cuáles archivos leer. Para eso se usa el siguiente comando:
yosys> read -sv designs/adder_1b/adder_1b.v
Luego, se le debe indicar a Yosys cuál de los módulos leídos es el que está
ubicado más alto en la jerarquía (en este caso no únicamente hay un módulo:
adder_1b
, pero en diseños más grandes es de suma importancia
ser explícitos con esto). Para eso ejecutamos el siguiente comando:
yosys> hierarchy -top full_adder
A continuación le indicaremos a Yosys que inicie el proceso de transformación desde la descripción conductual, hacia una descripción estructural. Para esto ejecute el siguiente comando:
yosys> proc
Ante el comando anterior, Yosys imprimirá una serie de pasos que ejecutó para llevar a cabo este proceso. Investigue en la documentación de Yosys sobre cada uno de los pasos ejecutados y reflexione brevemente sobre la complejidad del proceso realizado.
Luego, procedemos a realizar una serie de optimizaciones al proceso, para eso ejecute el siguiente comando:
yosys> opt
Al igual que con el paso anterior, investigue sobre los pasos ejecutados y reflexione brevemente sobre la complejidad del proceso realizado.
En otra terminal (donde no haya ingresado al docker de OpenLane) genere un directorio para almacenar los resultados de la corrida, usando el siguiente comando:
$ mkdir /designs/adder_1b/results/
Ahora, escribiremos el netlist generado en un archivo de Verilog, guarde mediante el siguiente comando:
yosys> write_verilog designs/adder_1b/results/adder_1b_synth.v
Utilizando cualquier editor de texto abra el archivo que acaba de generar. Interprete el netlist obtenido. Es importante recalcar que, en este caso, no es difícil interpretar los resultados del paso anterior sin embargo, en diseños complejos, resulta prácticamente imposible comprender el circuito obtenido.
La plataforma OpenLane aún no cuenta con una herramienta que permita
visualizar los netlist de una forma interactiva, por este motivo utilizaremos
la herramienta libre netlistsvg
para generar imágenes de los
netlists obtenidos con Yosys. Para instalar esta herramienta ejecute los
siguientes comandos en una terminal nueva:
>$ sudo apt update
>$ sudo apt install nodejs npm
>$ npm install -g netlistsvg
La herramienta netlistsvg
convierte netlists en formato JSON
a imágenes en formato SVG. Por lo tanto, generaremos el archivos JSON en Yosys,
utilizando el siguiente comando:
yosys> write_json designs/adder_1b/results/adder_1b_synth.json
En una terminal que no tenga Yosys u OpenLane abierto, se ejecuta el siguiente comando para generar la imagen del netlist (es un único comando).
>$ netlistsvg designs/adder_1b/results/adder_1b_synth.json -o
Abra el diagrama obtenido (el cual fue guardado en
designs/adder_1b/results/adder_1b_synth.svg
) y observe cómo
relaciona con el netlist creado por Yosys.
Durante el proceso de síntesis lógica, es necesario realizar un mapeo de las celdas escogidas por el sintetizador, a las celdas disponibles en la librería de celdas estándar que se utilizaran en el diseño. Este proceso se conoce como technology mapping. En Yosys, se puede ejecutar ese paso mediante el siguiente comando:
yosys> techmap
Para general el netlist nuevo en formato Verilog y JSON ejecute:
yosys> write_verilog designs/adder_1b/results/adder_1b_synth_techmap_noopt.v
yosys> write_json designs/adder_1b/results/adder_1b_synth_techmap_noopt.json
Genere un diagrama con el nuevo netlist. Relacione el diagrama nuevo con el obtenido antes de hacer technology mapping.
Resulta claro del diagrama obtenido, que la implementación no es la adecuada, por lo que es necesario efectuar los procesos de optimizaciones de Yosys, una vez que el technology mapping fue ejecutado. Para esto:
yosys> opt
yosys> write_verilog designs/adder_1b/results/adder_1b_synth_techmap.v
yosys> write_json designs/adder_1b/results/adder_1b_synth_techmap.json
Genere un diagrama con el nuevo netlist. Compare los tres netlists generados hasta el momento.
En esta sección se aplicarán los aprendizajes obtenidos en la sección anterior mediante la utilización de la herramienta Yosys para realizar la síntesis lógica de un circuito sumador con entradas de cuatro bits. Posteriormente, se brindarán instrucciones para ejecutar la síntesis lógica utilizando el flujo de OpenLane.
Siguiendo los pasos brindados en la sección anterior, realice la síntesis lógica del sumador de 4 bits.
Compare los archivos Verilog y SVG producidos tras sintetizar el sumador de 4 bits. Considere tanto los resultados de realizar síntesis SIN technology mapping, como los resultados OPTIMIZADOS de síntesis CON technology mapping. ¿Cuál es más útil?
El proceso de síntesis lógica también puede ser ejecutado siguiendo el
flujo de diseño de OpenLane. Para esto, el docker de OpenLane incluye un
archivo con un flujo sugerido, el cual se puede encontrar en
. Utilizando cualquier editor de texto,
abra el archivo flow.tcl
, Analice e intente comprender el archivo.
Para agregar un diseño nuevo, y que OpenLane genere la estructura de directorios y otros archivos de configuración necesarios se debe ejecutar, en una terminal con el docker de OpenLane activo, el siguiente comando:
:/openlane$ ./flow.tcl -design adder_4b -init_design_config -add_to_designs
Si usted observa un mensaje que inicia con [SUCCESS]
, significa
que la estructura de directorios fue creada satisfactoriamente. Diríjase al
directorio designs/adder_4b
, ahí deberá encontrar un archivo
config.json
, abra el archivo en cualquier editor de texto.
Dicho archivo contiene variables que le indican a OpenLane información
fundamental durante la ejecución. Para más detalles sobre dichas variables
haga clic en este enlace.
Se recomienda mover los archivos Verilog del diseño a un directorio
src
dentro de la carpeta del diseño, para eso ejecute los
siguientes comando en una terminal nueva:
>$ cd /designs/adder_4b/
>$ mkdir src/
>$ mv *.v src/
Si no realiza el paso anterior, asegúrese de modificar la variable
VERILOG_FILES
del archivo config.json
para que apunte
a la dirección correcta.
Ahora, procederemos a ejecutar el flujo OpenLane. El archivo
flow.tcl
describe el flujo completo, por lo que al ejecutarlo sin mayor
detalle, OpenLane procederá a correr la totalidad del flujo (hasta generar un
layout) del circuito. Dado que en esta laboratorio nos enfocamos únicamente en
síntesis lógica, procederemos a correr OpenLane en modo interactivo, para ir
ejecutando el flujo paso a paso. Para eso, ejecute el siguiente comando:
:/openlane$ ./flow.tcl -design adder_4b -interactive -tag only_synth
La bandera -tag
permite ponerle un nombre específico a la
corrida que estamos generando. Revise el directorio designs/adder_4b/runs
.
El comando anterior desplegará varios mensajes de información, asegúrese de
que todo luzca correcto. Para correr el proceso de síntesis lógica, en la misma
terminal, ejecute el siguiente comando:
% run_synthesis
Una vez que el comando haya finalizado, diríjase al directorio generado para
esta corrida, es decir, designs/adder_4b/runs/only_synth
. Además
del directorio src
generado anteriormente, encontrará el directorio
runs
, dentro del mismo se irán guardando las salidas de OpenLane
cada vez que se ejecute el flujo para este diseño. Note que el tag otorgado
durante el comando para ejecutar el flujo, only_synth
indica el
nombre de la carpeta donde se almacenarán los resultados.
Ingrese a runs/only_synth/results/
, observe que dentro de esta
carpeta existen varios directorios, cada uno almacena los resultados de
distintos pasos del flujo. En este caso, únicamente revisaremos los
resultados en synthesis
, en ese directorio encontrará el netlist
generado por OpenLane, puede abrirlo utilizando cualquier editor de texto.
Revise el netlist generado y contrástelo con el netlist generado utilizando
Yosys, ¿En qué se diferencian? ¿En qué se asemejan?. Investigue sobre SkyWater
Open Source PDK
En esta sección se utilizará OpenLane para realizar la síntesis lógica de un circuito un poco más complejo que los anteriores, y que además cuenta con elementos secuenciales, un sumador de 8 bits con pipeline.
Proceda a agregar el diseño del adder_8b_pipeline
y generar la
estructura de directorios usando el archivo flow.tcl
, tal y como
se instruyó para el sumador de 4 bits.
En una terminal nueva, diríjase a la carpeta designs/adder_8b_pipeline
y realice lo siguiente:
src
y copie los archivos Verilog del
diseño dentro de la misma.CLOCK_PORT
del archivo
config.json
coincida con la señal clk
del
Verilog.CLOCK_PERIOD
del archivo
config.json
para que sea 2.0 , esta variable indica el
período, en ns, de la red de reloj.Ahora, vuelva a la terminal donde estaba corriendo OpenLane, abra de nuevo
el diseño adder_8b_pipeline
utilizando el archivo flow.tcl
con los flags -interactive
y -tag
,
tal y como se hizo en el sumador de 4 bits y ejecute el comando run_synthesis
.
Diríjase al directorio designs/adder_8b_pipeline/runs/
.
Ahí encontrará la misma estructura de directorios que se describió en el sumador de
4 bits. En el directorio results/synthesis/
encontrará el netlist
generado por la síntesis. Revise el archivo generado e intente identificar
todas las compuertas lógicas que pueda.
En el directorio reports/synthesis/
encontrará varios reportes
con información sobre la síntesis, en particular, nos interesa
1-synthesis.AREA\_0.stat.rpt
. Abra el archivo y analice los resultados
obtenidos.
En el directorio logs/synthesis/
encontrará las bitácoras de
ejecución de los pasos ejecutados, en este caso, únicamente ejecutamos síntesis
y un análisis de temporización estática (el cual se ejecuta por defecto luego
de la síntesis). En el archivo 1-synthesis.log
encontrará la
información de cada uno de los pasos ejecutados durante el proceso de síntesis.
El archivo 2-sta.log
muestra los resultados del análisis de
temporización estática, tanto para temporización mínima como máxima, así como un
reporte de potencia. En el archivo se muestran los reportes de los peores
caminos de temporización. A continuación se muestra un ejemplo.
Startpoint: B[0] (input port clocked by clk)
Endpoint: _125_ (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Fanout Cap Slew Delay Time Description
-----------------------------------------------------------------------------
0.15 0.00 0.00 clock clk (rise edge)
0.00 0.00 clock network delay (ideal)
0.30 0.30 v input external delay
0.02 0.01 0.31 v B[0] (in)
2 0.01 B[0] (net)
0.02 0.00 0.31 v _082_/A (sky130_fd_sc_hd__or2_2)
0.08 0.33 0.64 v _082_/X (sky130_fd_sc_hd__or2_2)
3 0.01 _038_ (net)
0.08 0.01 0.65 v _084_/A2 (sky130_fd_sc_hd__a21boi_2)
0.21 0.24 0.89 ^ _084_/Y (sky130_fd_sc_hd__a21boi_2)
4 0.02 _040_ (net)
0.21 0.00 0.89 ^ _089_/A1 (sky130_fd_sc_hd__o211a_2)
0.07 0.24 1.13 ^ _089_/X (sky130_fd_sc_hd__o211a_2)
3 0.01 _045_ (net)
0.07 0.01 1.14 ^ _090_/B (sky130_fd_sc_hd__nor2_2)
0.04 0.03 1.18 v _090_/Y (sky130_fd_sc_hd__nor2_2)
1 0.00 _046_ (net)
0.04 0.00 1.18 v _093_/A2 (sky130_fd_sc_hd__o211a_2)
0.04 0.23 1.41 v _093_/X (sky130_fd_sc_hd__o211a_2)
1 0.00 _000_ (net)
0.04 0.00 1.42 v _125_/D (sky130_fd_sc_hd__dfxtp_2)
1.42 data arrival time
0.15 1.50 1.50 clock clk (rise edge)
0.00 1.50 clock network delay (ideal)
-0.25 1.25 clock uncertainty
0.00 1.25 clock reconvergence pessimism
1.25 ^ _125_/CLK (sky130_fd_sc_hd__dfxtp_2)
-0.09 1.16 library setup time
1.16 data required time
-----------------------------------------------------------------------------
1.16 data required time
-1.42 data arrival time
-----------------------------------------------------------------------------
-0.25 slack (VIOLATED)
Del encabezado del reporte es importante recalcar:
Startpoint
se refiere al punto donde inicia la
trayectoria, en el caso del ejemplo se trata del puerto
B[0]
.Endpoint
se refiere al punto donde finaliza la trayactoria,
en este caso se trata del Flip-Flop llamado _125_
Path Group
corresponde al único reloj del
diseño, clk
.Path Type
indica el tipo de análisis realizado,
max
o min
.Posteriormente, inicia una tabla que muestra la trayectoria, cada fila de la
misma indica un elemento (compuerta o interconexión). Dicha tabla se puede
separar en dos grandes secciones, en la primera se calcula el tiempo de llegada
(data arrival time
} o AT
}) de la señal, y en la
segunda se calcula el tiempo de llegada de requerido (data required time
o RAT
). Para la sección de cálculo del tiempo de llegada:
Fanout
indica la cantidad de compuertas
(sinks
) conectadas a la salida de otra compuerta o puerto de
entrada del circuito (source
o driver
). Cap
indica retardos de interconexiones, ocasionados
por las capacitancias parasíticas del mismo.Slew
indica el tiempo de transición de la señal
(del 20% al 80% de VDD) al llegar a la entrada de alguna compuerta.Delay
indica el retardo agregado por cada compuerta
o el tiempo de llegada de la señal al puerto de entrada del circuito
(mostrado como input external delay
).Time
lleva la cuenta del tiempo total transcurrido
hasta cada etapa. Description
muestra la ubicación el trayectoria,
ya sea un puerto de entrada (e.g. B[0] (in)
),
un cable de interconexión (e.g. B[0] (net),
_038_ (net)
), el puerto de entrada de una compuerta (e.g.
_082_/A
), o el puerto de salida de la compuerta
e.g. _082_/X
). Junto a cada puerto se muestran el
tipo de transición que lleva la señal, ya sea ascendente (^
)
o decreciente (v
).
En la sección del cálculo de tiempo requerido:
clock network delay
muestra el retardo de propagación del
reloj desde su fuente, hasta el pin de CLK del Flip-Flop destino, en este
caso, al no existir información física aún, se asume una red ideal, con 0ns
de retardo.clock uncertainty
muestra la incertidumbre del reloj,
usualmente debido al efecto conocido como jitter
.clock reconvergence pessimism
muestra pesimismo
introducido al análisis al propagar las señales de reloj.library setup time
muestra el tiempo de setup del Flip-Flop
destino, obtenido de la librería de celdas estándar.Note que en la parte de cálculo de tiempo de llegada, los retardos se van sumando, para identificar el momento en el que la señal llega a su destino, mientras que en el cálculo de tiempo requerido los retardos se restan, pues se toman en cuenta efectos que disminuyen el período efectivo del reloj.
Finalmente, el slack
es calculado mediante la diferencia entre el
tiempo requerido y el tiempo de llegada. Si el slack es negativo, la
trayectoria presenta una violación de temporización.
Identifique la trayectoria con una violación más grande (slack más negativo) del diseño sintetizado y realice un análisis del mismo.
Además del análisis de temporización, en el archivo 2-sta.log
se muestra un reporte de potencia, realice un breve análisis del mismo. Además
¿por qué considera que la diferencia entre potencia dinámica y potencia
estática es tan grande?
Modifique ahora el archivo config.json
para que el período del
reloj sea 11.0. Corra de nuevo los pasos para ejecutar la síntesis
(utilice un tag diferente para no sobrescribir la corrida anterior). Con los
datos de esta corrida:
Como se pudo observar en la sección anterior, existe un balance entre las ganancias de retardo y área. Diseños que corren más rápido usualmente consumen más área, y viceversa. En esta sección utilizaremos uno de los ejemplos incluidos en OpenLane, el controlador USB para explorar este balance.
La herramienta OpenLane permite la exploración del espacio de diseño de forma automática. Para ello, en una terminal nueva, habiendo abierto OpenLane, ejecute el siguiente comando:
:/openlane$./flow.tcl -design usb -tag explore -synth_explore
Este comando ejecutará la síntesis lógica para distintas optimizaciones.
El reporte de este comando se puede observar en el archivo
0-exploration_analysis.html
, en el directorio de reportes de
síntesis de la corrida explore
. Discuta, ¿Cuál diseño usaría si
usted estuviera a cargo de un proyecto encargado de implementar un chip con
dicho controlador? ¿Por qué? Compare las compuertas utilizadas en las distintas
variaciones del diseño (revise los archivos del directorio de reportes para
recabar esta información).