CommunityProgramación y desarrollogithub.com

BeenLi/claude-skills

Convierte Verilog/SystemVerilog (y artículos, patentes, descripciones orales) en diagramas draw.io editables con cuatro perspectivas: diagrama de arquitectura, diagrama estructural (nivel de compuertas), máquina de estados y diagrama de control general.

¿Qué es claude-skills?

Esta habilidad permite a un agente AI (como Claude Code) generar diagramas draw.io editables a partir de código Verilog/SystemVerilog, artículos, patentes o descripciones orales. Ofrece cuatro perspectivas: (1) diagrama de arquitectura de estilo paper (por defecto): el agente lee el código, extrae los puntos de diseño clave y genera una descripción YAML que la herramienta convierte en un diagrama con etapas de pipeline, registros, FIFOs, realimentación, tablas SRAM y símbolos de circuitos clásicos; (2) diagrama estructural (nivel de detalle de compuertas): usa la netlist de Yosys para mostrar registros, MUX, unidades aritméticas, FIFO y submódulos organizados por etapas de pipeline; (3) diagrama de máquina de estados: para FSM con estructura case(state), dibuja círculos de igual tamaño con transiciones etiquetadas; (4) diagrama de control general: muestra solo las señales de control entre submódulos y cómo las FSM se impulsan entre sí. Depende de PyYAML, drawio, y opcionalmente yosys, sv2v, Graphviz. Todos los scripts aceptan --png/--svg/--scale. Es ideal para entender arquitectura, depurar flujo de datos, documentar diseños o generar figuras para publicaciones.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/BeenLi/claude-skills/tree/HEAD/skills/verilog-diagram

Installed? Explore more Programación y desarrollo skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Verilog → draw.io : Diagramas de Arquitectura / Estructural / Máquina de Estados / Control

Cuatro perspectivas, elige según la pregunta: ¿Cuál es la idea de diseño? (para explicar a otros, poner en un paper/informe) → arch2drawio.py (sección cero, por defecto); ¿Cómo se ve a nivel de compuertas? (ruta de datos unidad por unidad) → rtl2drawio.py; ¿Cómo funciona? (FSM individual) → fsm2drawio.py fsm; ¿Quién controla a quién? (estructura de control general) → fsm2drawio.py ctrl. Los módulos orientados al control (FSM, decodificadores, árbitros) se vuelven desordenados con diagramas estructurales; mejor usar los dos últimos.

Dependencias: PyYAML; para exportar PNG/SVG se necesita drawio (orden de búsqueda: $DRAWIO_BIN → PATH → app macOS → ~/.local/opt/drawio; Linux sin $DISPLAY usa automáticamente xvfb-run; si no hay root, usar tools/install-drawio-linux.sh del repositorio). Si no hay exportador, todos los comandos generan .drawio normalmente, solo falta PNG, con un aviso en stderr. Para diagramas estructurales y de control se necesita además yosys, sv2v (SystemVerilog), dot (Graphviz), y la habilidad drawio-skill ya instalada (por defecto ~/.claude/skills/drawio-skill, se puede cambiar con la variable de entorno DRAWIO_SKILL_DIR; solo llama a autolayout.py, no la modifica). Los tres scripts aceptan --png / --svg / --scale N (el PNG por defecto usa scale 3, ~1 model unit = 3 px; $DRAWIO_SCALE puede cambiar el valor por defecto). También se puede exportar individualmente: python3 $S/scripts/drawio_export.py X.drawio --png --svg. Para insertar en Markdown/Obsidian, priorizar SVG, no se pixelan. $S es el directorio de esta habilidad. examples/ contiene dos ejemplos de comparación: wrr_arbiter.v (single stage + state register) y load_pipe.v (multicycle pipeline con replay).

Cero: Diagrama de Arquitectura Estilo Paper (arch2drawio.py) — Por defecto

La entrada es código (también puede ser un artículo, patente o descripción del usuario). La netlist de Yosys es demasiado detallada para un diagrama de arquitectura, así que aquí no se sintetiza: el script da un esquema del código fuente, tú (el agente) lees el código, extraes lo esencial y escribes la descripción del diagrama, luego el script genera el diagrama de forma determinista. El usuario no necesita escribir ningún archivo de descripción; solo se muestra el diagrama al usuario, a menos que quiera modificar la descripción.

python3 $S/scripts/arch2drawio.py outline src/*.sv --top gpu [--module core]   # Esquema del código fuente (sin síntesis)
python3 $S/scripts/arch2drawio.py render  fig.yaml -o diagrams/arch_core.drawio --png

outline lista: árbol de jerarquía (generates copiados ×N), puertos, arreglos de almacenamiento (profundidad × ancho de bits, campos de packed struct, arreglos con misma profundidad indican "probablemente la misma tabla"), registros de pipeline nombrados por etapa (s1_ / stage2_ / if_id_ …), máquinas de estado, señales de realimentación sospechosas (replay/kill/flush/stall/forward/refill…), flujo de datos entre instancias (a través de señales compartidas, excluyendo clk/reset/variables de bucle). Para entrada de artículo/patente/descripción, se omite este paso.

Reglas para dibujar (al escribir la descripción)

  1. Solo lo esencial: Primero di en una o dos frases la idea central del diseño; conserva solo los componentes que la reflejan; omite lógica de pegamento, clk/reset, puertos de depuración y señales de control dispersas. Generalmente 8–20 cajas; si son más, divide en dos diagramas (uno superior + uno para la unidad clave).
  2. Destacar lo importante: 1–3 puntos de diseño clave con hl: true (color contrastante: fondo oscuro, texto blanco) o bold: true (negrita); las líneas de la ruta crítica también pueden tener | hl. Para destacar un área, usa groups + hl: true (recuadro de fondo claro).
  3. Numerar solo cuando sea necesario: Dale num: N solo a los componentes centrales cuando se necesite referencia en texto, y explica en callouts.
  4. Texto conciso en las cajas: Dentro de la caja solo el nombre (≤ 2 líneas); el significado se expresa con la forma: las operaciones usan adder / mult / cmp / op (símbolo circular) o alu, la selección usa mux (el selector x.sel entra por la parte inferior), el almacenamiento usa table, las colas usan fifo, los registros usan reg, las compuertas usan and/or/xor/not.
  5. Las tablas SRAM escriben los campos de cada entrada: Los fields de table escriben la función de cada campo (ej. [V, Tag (20b), Data (32b)]). Para memoria asociativa multivia, usa stack: 4 (apilado + ×4); los arreglos paralelos de misma profundidad y dirección se combinan en una sola tabla, cada arreglo como un campo.
  6. Pipeline: stages define las etapas (id + función sub, ej. {id: S1, sub: Hit detect}), el script dibuja las líneas discontinuas y los nombres de etapa; los registros / FIFOs entre etapas se indican con between: [S0, S1], el script los dibuja sobre la línea divisoria; las realimentaciones (destino en una etapa anterior) automáticamente se enrutan por el pasillo inferior, o se puede usar | fb, | fb via=top (desde arriba). Múltiples pipelines usan lanes, cada lane comparte la columna de la etapa, y las etapas correspondientes en el tiempo se alinean automáticamente.
  7. Los diagramas de bloque sin etapas (top-level, SoC) no escriben stages; las unidades replicadas usan stack: N, los recursos por hilo/núcleo se encierran con groups.

Formato de la descripción (YAML)

title: dcache_pipe: Pipeline de búsqueda D-Cache de mapeo directo
stages: [{id: S0, sub: Selección / Lectura de arreglo}, {id: S1, sub: Comparación de Tag}, {id: S2, sub: Fallo / Reproducción}]
lanes:  [{id: ld, name: Pipeline de Load}, {id: st, name: Pipeline de Store}]   # Opcional, para múltiples pipelines
nodes:
  - {id: arr, type: table, label: "Arreglo de Cache · 64 entradas", fields: [V, "Tag (20b)", "Data (32b)"], stage: S0}
  - {id: r1, type: reg, label: addr, between: [S0, S1]}              # Sobre la línea divisoria S0|S1
  - {id: tcmp, type: cmp, label: Comparación de Tag, stage: S1, hl: true}      # Círculo "=", texto explicativo debajo
  - {id: rmux, type: mux, stage: S0, ports: 2}
edges:
  - "rmux => arr : idx | w=6"            # -> datos  => bus (grueso)  ~> control (línea discontinua); w=N ancho de bits
  - "rpl -> rmux.sel : replay | fb hl"   # .sel/.en entra por abajo, .top entra por arriba; fb realimentación, hl enfatizar, via=top, pos=src|dst
groups: [{label: "×4 por hilo", members: [rf, alu, lsu], hl: true}]
legend: {reg: Registro de pipeline, fb: Realimentación, ctrl: Control, hl: Diseño clave}      # Claves posibles: data bus ctrl fb hl hl_edge hl_region reg
callouts: {1: "Numerar solo cuando se necesita referencia en texto"}

Tipos de nodo: block reg fifo table(fields, rows, stack) array(dims, cell) mux(ports) adder mult cmp/op(sym) alu and or xor nand nor xnor not cloud mem xbar in out text dot. Atributos generales: stage / lane / between, hl bold num stack, ajustes finos con row / col (fila/columna dentro de la etapa, puede ser negativo), dx / dy, w / h. Otros: array soporta cell_labels (etiqueta por celda, ej. T0..T3) y cell_h (celda alargada, para canales de hilo); groups soporta stack: N (apilar toda un área, ej. "Core ×2" y mostrar interior) y label_align: right; el name de lanes vacío = solo dividir sin dibujar etiqueta; en las aristas, | both dibuja flecha bidireccional (petición/respuesta); la realimentación entre dos unidades en la misma columna, una arriba y otra abajo, se dibuja como una línea vertical corta y ajustada (ej. Dispatcher ⇅ Core).

Flujo de trabajo

  1. outline + leer el código fuente clave (o leer el artículo/patente), anotar la idea central → decidir qué capa dibujar, cuáles son los puntos clave.
  2. Escribir la descripción en un directorio temporal (scratchpad), cada nodo debe tener stage (si hay etapas). Los bucles se rompen automáticamente: los nodos con nombre parecido a controlador (sched / ctrl / fsm / arbiter / dispatch / scheduler / control …, luego aquellos con muchos abanicos de salida en líneas de control) comienzan, sus salidas van a la derecha y las aristas que vuelven a ellos se dibujan como realimentación; si la suposición es incorrecta, escribe explícitamente | fb en esa arista. Opcional: Referencia de composición (gpt-image-bridge, requiere confirmación del usuario para cada una): el diseño de cuadrícula garantiza que las conexiones sean correctas, pero no "compone" el diagrama. Cuando el módulo tenga ≥ 10 o tenga particiones evidentes (plano de control/plano de datos/jerarquía de memoria), se puede generar primero la línea base en draw.io, luego escribir la lista de módulos y conexiones obtenidas del código en el prompt (estilo ilustración de paper, fondo blanco, un solo color de énfasis, diseño en tres regiones, texto mínimo, etiquetas cortas en inglés), usar gpt-image-bridge para generar 1 boceto y leerlo. Tomar solo prestado el diseño y la jerarquía visual (particiones, quién está arriba de quién, formación, espacio en blanco, posición de elementos clave); convertir a lane / row / col / groups; los módulos, conexiones y nombres deben basarse estrictamente en el código — errores comunes de los bocetos: conectar al origen equivocado, dibujar módulos de más o de menos, fondo oscuro. Antes de generar, según lo establecido en esta habilidad, listar las imágenes (propósito, ruta, tamaño, resumen de prompt) y esperar el consentimiento explícito del usuario; los bocetos se guardan en diagrams/sketch_*.png, y el archivo de descripción referencia el boceto en un comentario al inicio.
  3. render --png → validate.py (error debe ser 0; las advertencias de superposición de líneas divisorias de etapa con encabezados/registros son esperadas) → Leer PNG e inspeccionar visualmente, usar row / col para ajustes finos (como máximo dos rondas; común: hacer que la ruta de datos principal ocupe la fila 0 en línea recta, y las rutas secundarias/control en la siguiente fila).
  4. Entregar .drawio + .png; el archivo de descripción permanece en el scratchpad, se entrega al usuario solo si quiere modificarlo.

Ejemplos: top-level de tiny-gpu ~/hardware-project/tiny-gpu/diagrams/arch_gpu.* (diseño guiado por el boceto sketch_gpu_top.png, comparado con arch_gpu_baseline.png que no usó boceto); examples/dcache_pipe.v → dcache_pipe.arch.yaml (descripción escrita a partir del código) → .png; arch_dual_issue.yaml (alineación de dos pipelines + forwarding + anotaciones numeradas); arch_mac.yaml (nivel de circuito: símbolos de multiplicación/suma, realimentación de acumulación, selector MUX). El diagrama de bloques del core de tiny-gpu está en ~/hardware-project/tiny-gpu/diagrams/arch_core.*.

Uno: Diagrama Estructural (rtl2drawio.py, detalles a nivel de compuertas)

python3 $S/scripts/rtl2drawio.py src/*.sv --top gpu --list                     # Listar módulos y sus unidades constituyentes
python3 $S/scripts/rtl2drawio.py src/*.sv --top gpu --module alu -o diagrams/alu.drawio --png

Flujo: sv2v (automático al encontrar .sv) → Yosys proc; opt; opt_dff; wreduce; memory -nomap → netlist JSON → análisis de pipeline por unidad → simplificación → diseño con restricciones de columna. Después de generar, ejecutar python3 ~/.claude/skills/drawio-skill/scripts/validate.py X.drawio (error debe ser 0; las advertencias de "through-vertex" / "overlap" causadas por líneas divisorias de etapa que atraviesan registros que están sobre ellas son esperadas), luego leer PNG e inspeccionar visualmente.

Reglas de diseño (--layout pipeline; por defecto auto: módulos jerárquicos con principalmente subinstancias usan diseño libre, otros usan diseño por etapas de pipeline)

  • Entradas a la izquierda, salidas a la derecha, la lógica se organiza en columnas de izquierda a derecha según la profundidad combinacional; para pipelines multietapa, ordenar de S0 → Sn de izquierda a derecha, con líneas discontinuas divisorias de etapa y el número de etapa en el encabezado de la columna.
  • Los registros se clasifican en dos tipos:
    • Registros de pipeline (barra vertical estrecha) colocados sobre las líneas divisorias de etapa; la última fila de registros que solo alimentan puertos de salida son registros de salida (no cuentan como una etapa, no se dibuja línea divisoria).
    • Registros de estado (FSM / contadores / punteros: su salida se vuelve a conectar a su propia entrada solo a través de lógica combinacional) se dibujan dentro de la etapa, con su salida como realimentación.
    • Cuando el nombre del registro incluye un número de etapa (s2_x, x_s2, stage2_x, if_id_/id_ex_/ex_mem_/mem_wb_, y hay al menos dos patrones) el nombre tiene prioridad — el bit de valid con kill, aunque tenga un bucle combinacional, sigue siendo un registro de pipeline. Si el diseño no nombra las etapas, solo se puede inferir por la estructura; el tiempo de llegada de los puertos de entrada es desconocido, y el número de etapa podría ser adelantado.
  • Cálculo del número de etapa: partiendo de los registros con número de etapa, la etapa de una unidad = el operando de registro más tardío (tomar el máximo); la lógica impulsada solo por puertos de entrada se asigna a la etapa "según qué registro la captura" (ALAP), y el puerto de entrada correspondiente también se coloca al inicio de esa etapa (por ejemplo, la respuesta de TLB se coloca en S1).
  • Realimentación: las señales que entran al cono de entrada de algún registro con número de etapa, pero que solo pueden provenir de etapas posteriores (replay→S0, kill→S1), así como los bucles de los registros de estado, se dibujan como líneas rojas que rodean por el borde inferior, cuanto mayor es la distancia, más hacia afuera; si hay más de 3 realimentaciones entre el mismo par de etapas, solo se dibuja una línea gruesa que representa un haz (etiquetado Realimentaciones ×N: …).
  • Agrupación: cuando haya más de 4 registros de pipeline en la misma línea divisoria, se fusionan en un grupo de registros (barra vertical etiquetada Registros S1→S2 ×N y ancho total de bits).
  • Simplificación: fusionar rebanadas del mismo registro con el mismo nombre; las cadenas de MUX de if/case anidados se combinan en un solo MUX N:1; la lógica de decodificación pequeña que solo impulsa la línea de selección de un MUX o habilitación de un registro se incorpora y se dibuja como línea de selección / habilitación; las compuertas de hasta 3 se dibujan como símbolos de AND/OR/NOT/XOR, las más grandes se pliegan en una nube de "lógica combinacional" (que se corta en medio de las unidades aritméticas para evitar bucles falsos); las unidades generadas por bucles generate de la misma fuente (misma ubicación en el código fuente) y las instancias threads[i].x se pliegan en "×N" (con sombreado). Todas las fusiones se realizan solo dentro de la misma etapa. clk/reset están ocultos por defecto.
  • Conexiones: línea sólida = datos (gruesa = bus multibit, /N = ancho de bits); línea discontinua púrpura = selección de MUX; línea punteada azul = habilitación; línea roja = realimentación.

Parámetros

ParámetroFunción
--listListar módulos y sus unidades constituyentes y salir
--module MDibujar el módulo específico (la variante parametrizada dibuja la primera, y se indica)
--layout auto|pipeline|freePor defecto auto: si el módulo tiene subinstancias y los nodos de lógica combinacional no son más numerosos que las instancias (módulo de pegamento top-level), usar free (comunicación bidireccional entre bloques no es realimentación de pipeline), de lo contrario pipeline
--show-clockDibujar clk/reset
--no-foldNo plegar instancias generate / unidades de la misma fuente
--no-collapseNo plegar lógica de control/combinacional
--sv2v auto|always|neverFrontend para SV (sintaxis como puertos de arreglos no empaquetados requiere sv2v)
--keep-json PATHConservar la netlist JSON de Yosys

Dos: Diagrama de Máquina de Estados (fsm2drawio.py fsm)

python3 $S/scripts/fsm2drawio.py list src/*.sv
python3 $S/scripts/fsm2drawio.py fsm  src/*.sv [--module M] -d diagrams --png [--no-actions]
  • Analiza directamente el código fuente, las condiciones de transición mantienen las expresiones originales. Reconoce asignaciones a S (o a la variable de estado S) dentro de ramas case (S); los nombres de estado se toman de localparam; las constantes de variables de estado de otras FSM se traducen al nombre del estado de esa FSM (core_state == 3'b001 → core_state == FETCH).
  • Condiciones de transición = if/case/for que envuelve directamente la asignación de estado; else if escribe solo su propia condición; la condición dentro de for se escribe como ∃j: …; un for i externo que envuelve todo el case indica duplicación por i; las guardas fuera del case (enable, rama de lectura/escritura) van en un cuadro de comentario; las variables booleanas locales que se ponen a 1 en el bucle se definen en un cuadro de comentario.
  • Dibujo: cada estado es un círculo del mismo tamaño (el nombre se parte en el _ en una línea; debajo, en letra pequeña, el código y ⟳), los estados finales con doble círculo, un punto negro = entrada de reset. Cuando el flujo principal cubre la mayoría de los estados, se organizan en un bucle en forma de U (fila superior de izquierda a derecha, giro hacia abajo, fila inferior de derecha a izquierda); los tipos de ramificación se organizan en columnas uniformes según la distancia desde el estado inicial. Los estados adyacentes se conectan directamente; las transiciones que saltan sobre otros estados se arquean por encima o por debajo, con la etiqueta en la cima del arco; A↔B, cada ida se curva hacia un lado; los bucles explícitos se dibujan encima del círculo. La distancia entre columnas se ajusta automáticamente según la etiqueta más larga. Después del / están las asignaciones durante la transición (se muestran como máximo 2).
  • No reconoce: control sin estructura case(state) (contadores, decodificación puramente combinacional) — no aparecen en list, es esperado.

Tres: Estructura de Control General (fsm2drawio.py ctrl)

python3 $S/scripts/fsm2drawio.py ctrl src/*.sv --top gpu --module core -o diagrams/ctrl_core.drawio --png
  • Dibuja las instancias de submódulos dentro del módulo L (las instancias generate se pliegan ×N), conserva solo las señales de control: línea naranja gruesa = difusión del estado de la FSM; línea azul = handshake valid/ready; línea discontinua púrpura = start/done/habilitación/selección/reset, etc.; los buses de datos se omiten. Las cajas de instancias que contienen FSM listan la secuencia de estados; las de subniveles que tienen FSM se etiquetan "Contiene FSM".
  • Las señales de control se rastrean hasta su origen a través de como máximo 3 niveles de unidades básicas (comparadores, compuertas, registros). La clasificación se basa en el nombre de la señal; cuando la nomenclatura no es estándar, puede omitir o dibujar de más.
  • Se recomienda ir de arriba a abajo: primero top (quién inicia a quién, quién hace handshake con la memoria) → siguiente nivel (cómo la FSM principal programa) → diagrama de la máquina de estados de la FSM clave.

Limitaciones

  • El diseño lo realiza Graphviz automáticamente según restricciones de columna; los cruces no se pueden eliminar por completo; los ajustes finos se hacen arrastrando en draw.io (todos los objetos son nativos editables).
  • Los módulos de control grandes (cientos de unidades) seguirán siendo desordenados en el diagrama de bloques; cambiar a diagrama de máquina de estados / diagrama de estructura de control, o dibujar submódulo por submódulo.
  • Los círculos y arcos del diagrama de máquina de estados se dibujan directamente según coordenadas; al arrastrar un estado, los puntos de inflexión de los arcos no se mueven con él; hay que ajustarlos manualmente.

Skills relacionados