nimcdl

Circuit Design language made in Nim


Keywords
circuit, HDL, PCB, DSL
License
GPL-3.0
Install
nimble install nimcdl

Documentation

NimCDL: Lenguaje de diseño de circuitos en Nim!

Este paquete es un pequeño DSL(Domain Specific Language) para Nim que permite diseñar circuitos electrónicos, hacer una ligera evaluación(composer.nim) y generar un netlist para Fritzing o Kicad.

Todavía está en fase experimental y tiene muchas cosas por acabar (Véase TODO).

Instalación

Teniendo instalado nim y nimble, se instala con el simple comando: nimble install nimcdl

Uso

Esta librería define un DSL para definir primeramente los componentes del circuito, luego el propio circuito y finalmente componerlo y exportarlo.

Claramente lo primero que tendremos que hacer en nuestro script Nim es importa esta librería:

import nimcdl

Definición de componentes

En un futuro, los componentes se podran importar y/o esta librería tendrá unos componentes estándares. Por el momento tendremos que definir cada uno de los componentes que vayamos a utilizar.

Lo primero será asignar el componente a una variable e iniciar una definición:

let led = component("led"):

Especificar pines

Cada componente electrónico tiene una series de pins que pueden ser entradas o salidas (también pueden ser ambos, pero esto todavía no eta soportado), para definir estos pines, simplemente añadimos al código anterior lo siguiente:

let led = component("led"):
pins:
P1 -> PinIn((1.0,5.0), (0.1,0.3))
P2..P3 -> PinOut()

Aquí vemos el pin 1(P1), que se asigna como un pin de entrada (PinIn), luego asignamos un voltaje mínimo y máximo que soporta el componente ((1.0,5.0)) y realizamos lo mismo con el amperaje que requiere ((0.1,0.3)).

Después, vemos como se puede asignar un rango de pin (PX..PY), en este caso desde el pin 2 hasta el 3 se le asigna como un pin de salida(PinOut), en este caso estos pines por defecto no proporcionan ninguna corriente electrica (Voltaje 0 y Amperaje 0).

Lógica(conexiones) de pines

Los pines de nuestro componente puede que no se comporten igual al estar ciertos pines conectados, así podemos definir las conexiones y sus lógicas de la siguiente forma:

let led = component("led"):
pins:
P1 -> PinIn((1.0,5.0), (0.1,0.3))
P2..P3 -> PinOut()
pinsLogic:
logic L1:
p2.p.maxVoltage = p1.p.maxVoltage

P1 <-> P2
P1<L1>P3

Vayamos por partes, primero conectamos el pin 1 al pin 2, es decir que si por este entra corriente, esta sale sin ser alterada por el pin 2 (P1 <-> P2). A continuación, entre el pin 1 y 3 queremos asignar una lógica, ya sea resistencia o cualquier otra alteración al pin de salida o a la corriente(net) de entrada. Para esto definimos lo siguiente:

logic L1:
p2.p.maxVoltage = p1.p.maxVoltage

Que gracias a macros se convertira en:

proc (netIn: var Net, p1, p2: var tuple[n: uint, p: Pin]) =
p2.p.maxVoltage = p1.p.maxVoltage

En tanto, especificamos a que pins se asignara esta lógica(P1P3)


De esta forma ya tendríamos nuestro componente listo.

Definición de circuitos

Con nuestros componentes ya en variables, estamos listos para inicializar nuestro circuito:

let ledCircuit = cirucit("ledTest"):

Creación de cables

A la hora de definir cables o redes, el primero que definamos será nuestra red de entrada mientras que el último, la de salida. Por el momento, solo le podremos poner nombres pero no asignar la corriente de entrada. Aunque después de componer el circuito, podremos saber el voltaje y amperaje mínimo y máximo necesario para estas.

let ledCircuit = cirucit("ledTest"):
nets:
N0 -> Net(name: "VDD")
N1 -> Net()

Asignacion de componentes

Otra parte fundamental de cualquier circuito, sin duda, son sus componentes. Estos se asignan de tal forma:

let ledCircuit = cirucit("ledTest"):
nets:
N0 -> Net(name: "VDD")
N1 -> Net()
components:
CL0 -> f
CL1 -> f

Como observamos, podemos elegir una referencia para el componente con este formato CXY, donde X es solo una letra para identificar el componente y Y un numero que puede tener tantos dígitos como se desee.

Conexiones

Ahora el toque final, las conexiones entre redes y componentes o entre componentes, para esto tenemos varias formas de expresarlo gracias al DSL. La primera es la conexión de pin a pin o de red a pin, ideal para hacer circuitos en serie, que se puede poner de estas formas:

N0 <-> P1.CL0.P2 <-> N1

N0 <-> CL0.P1
N1 <-> CL0.P2

N0 <-> P1.CL0.P2 <-> P1.CL1.P2 <-> N1

La segunda es más para de red a múltiples pins, perfecta para conexiones en paralelo:

N0 || N1
|| P1.CL0.P2
|| P1.CL1.P2

| N0
| CL0.P1
| CL1.P1

Asi, nuestro circuito podria quedar algo tal que asi:

let ledCircuit = cirucit("ledTest"):
nets:
N0 -> Net(name: "VDD")
N1 -> Net()
components:
CL0 -> f
CL1 -> f

connections:
N0 || N1
|| P1.CL0.P2
|| P1.CL1.P2

Composicion de circuitos

Finalmente, componemos el circuito, en donde el compositor trasforma la red para poder ser exportada fácilmente además de hacer una ligera evaluación de esta(En un futuro será más exhaustiva).

let final = ledCircuit.compose(2)

El 2 es el numero total de redes que hemos definido en el apartado nets. Esta funcion, nos devuelve un tuple con el circuito final (final.circuit) y una coleccion de errores encontrados en el circuito (final.errors).

Exportación del circuito

Con este circuito en Nim ya no podremos hacer mucho mas(por el momento), por la tanto nos toca exportarlo a una netlist:

  • Kicad: con la función toKicadNetlist('D') (final.toKicadNetlist('D'))
  • Fritzing: con la función toFritzingNetlist("nombre del circuito")` (final.toFritzingNetlist("ledTest"))

Contribuir

Pulls requests aceptados y bien valorados!!. Voy a emepzar otro proyecto y no tengo tiempo de seguir avanzando en este. Ademas de los TODOs sueltos por el codigo aqui hay una lista de cosas que hay que hacer:

  • Composer: Hacer una comprobacion mas corecta de ERC y optimizar.
  • types: añadir mas informacion importante.
  • DSL: añadir los buses(y documentarlos) y permitir añadir logicas cuando se obtiene la corriente necesaria para una red.
  • Crear un "importer" para poder importar componentes de fuera.
  • hacer una mejora general de codigo
  • Otros