Tutorial #1: Síntesis Lógica

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.

FAQs

Para encontrar una lista actualizada de las preguntas más comunes puede ir al siguiente enlace.

Introducción

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.

Síntesis lógica

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.

OpenLane

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

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...

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.

Síntesis Lógica de un Sumador Completo de 1 bit

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.

Síntesis mediante Yosys

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.

Terminal con Yosys activo
Fig. 1 - Inicialización de Yosys en el ambiente OpenLane.

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.

Síntesis Lógica de un Sumador de 4 bits

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?

Síntesis con el flujo de OpenLane

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 /flow.tcl. 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

Síntesis Lógica de un Sumador de 8 bits con pipeline

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.

Síntesis lógica

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:

  1. Genere el directorio src y copie los archivos Verilog del diseño dentro de la misma.
  2. Verifique que la variable CLOCK_PORT del archivo config.json coincida con la señal clk del Verilog.
  3. Modifique la variable 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:

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:

En la sección del cálculo de tiempo requerido:

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:

Exploración del espacio de diseño de un controlador USB

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).

Referencias