All Projects → nturley → Netlistsvg

nturley / Netlistsvg

Licence: mit
draws an SVG schematic from a JSON netlist

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Netlistsvg

ansible-role-elasticsearch
Ansible Role - Elasticsearch
Stars: ✭ 144 (-48.39%)
Mutual labels:  elk
fluent-plugin-cloudwatch-ingest
Alternative to ryotarai/fluent-plugin-cloudwatch-logs for ingesting AWS Cloudwatch logs via fluentd
Stars: ✭ 11 (-96.06%)
Mutual labels:  elk
Helk
The Hunting ELK
Stars: ✭ 3,097 (+1010.04%)
Mutual labels:  elk
cloudtrailbeat
Easily export AWS CloudTrail events to ElasticSearch
Stars: ✭ 31 (-88.89%)
Mutual labels:  elk
JAlgoArena
JAlgoArena programming contest platform
Stars: ✭ 32 (-88.53%)
Mutual labels:  elk
ansible-roles
Library of Ansible plugins and roles for deploying various services.
Stars: ✭ 14 (-94.98%)
Mutual labels:  elk
docker-repo
A repository stores some dockerfiles or docker-compose files for quickly starting service or service cluster.
Stars: ✭ 26 (-90.68%)
Mutual labels:  elk
Detectionlabelk
DetectionLabELK is a fork from DetectionLab with ELK stack instead of Splunk.
Stars: ✭ 273 (-2.15%)
Mutual labels:  elk
pinout
An open source Python package that generates hardware pinout diagrams as SVG images.
Stars: ✭ 298 (+6.81%)
Mutual labels:  diagram
synesis lite syslog
Syslog collection with the Elastic Stack.
Stars: ✭ 31 (-88.89%)
Mutual labels:  elk
eddy
A graphical editor for the specification and visualization of Graphol ontologies
Stars: ✭ 24 (-91.4%)
Mutual labels:  diagram
docker-elk
ELK Stack on Docker
Stars: ✭ 43 (-84.59%)
Mutual labels:  elk
elastic-search-analyzer
基于elasticsearch,ik, 分词,全文搜索,使用demo
Stars: ✭ 41 (-85.3%)
Mutual labels:  elk
GiGraph
Simple yet versatile library for generating graphs in the DOT language
Stars: ✭ 25 (-91.04%)
Mutual labels:  diagram
Swift Diagram Playgrounds
Drawing diagrams in Swift using a recursive enum data structure
Stars: ✭ 264 (-5.38%)
Mutual labels:  diagram
idle
parse source code(objective-c, java) generate uml(class diagram)
Stars: ✭ 44 (-84.23%)
Mutual labels:  diagram
elk-examples
Example collection for Elk
Stars: ✭ 29 (-89.61%)
Mutual labels:  elk
Fw Spring Cloud
SpringCloud构建实战、从入门到高级,包含eureka、zuul、gateway、feign、ribbon、hystrix、mq、turbine、nacos、elk、consul、zookeeper、rocketmq、kafka、分布式事务(RocketMq、LCN、Seata)、分库分表(Sharding-JDBC)、分布式锁(Redis、Guava)、jwt、SkyWalking、Zipkin、bootadmin等使用案例
Stars: ✭ 276 (-1.08%)
Mutual labels:  elk
Fediagram
图说前端>>收集各种前端技术图谱 🚕🚖🚗🚚🚛🚜
Stars: ✭ 273 (-2.15%)
Mutual labels:  diagram
jframework
基于对spring boot的二次封装,目的是减少重复代码,提高开发效率
Stars: ✭ 88 (-68.46%)
Mutual labels:  elk

Linux Build Status Windows Build status Gitter chat npm version npm

netlistsvg

draws an SVG schematic from a yosys JSON netlist. This can be generated the write_json command. It uses elkjs for layout.

You can see an online demo here

Installation/Usage Instructions

Command Line Interface

Install nodejs if isn't already installed

npm install -g netlistsvg

You can execute netlistsvg like this.

netlistsvg input_json_file [-o output_svg_file] [--skin skin_file]

The default value for the output file is out.svg.

Should work on Linux, OSX, and Windows. Running the build scripts (makefiles and the web demo) is easiest on Linux and OSX.

Web bundle

I have a web bundle hosted on github pages here: https://nturley.github.io/netlistsvg/built/netlistsvg.bundle.js It doesn't wrap ELKjs, so you'll need to include it separately. ELK creates a global variable, so you'll need to include ELKjs before netlistsvg.

In HTML it would look something like this

<script type="text/javascript" src="https://nturley.github.io/netlistsvg/elk.bundled.js"></script>
<script type="text/javascript" src="https://nturley.github.io/netlistsvg/built/netlistsvg.bundle.js"></script>

On ObservableHQ, you can require it like this.

netlistsvg = {
  var ELK = await require('https://nturley.github.io/netlistsvg/elk.bundled.js')
  window.ELK = ELK
  return require('https://nturley.github.io/netlistsvg/built/netlistsvg.bundle.js')
}

You may want to download and host your own copy.

The web bundle includes both the analog and digital skin and an example netlist for each. Using a promise would look like this.

await netlistsvg.render(netlistsvg.digitalSkin, netlistsvg.exampleDigital);

Or to log the result to console using the callback API:

netlistsvg.render(netlistsvg.digitalSkin, netlistsvg.exampleDigital, (err, result) => console.log(result));

To turn Verilog into YosysJSON in the browser, you can use YosysJS

Examples

Here's an digital netlist produced by Yosys along with the diagram that netlistsvg created from it.

JSON Source
{
  "modules": {
    "up3down5": {
      "ports": {
        "clock": {
          "direction": "input",
          "bits": [ 2 ]
        },
        "data_in": {
          "direction": "input",
          "bits": [ 3, 4, 5, 6, 7, 8, 9, 10, 11 ]
        },
        "up": {
          "direction": "input",
          "bits": [ 12 ]
        },
        "down": {
          "direction": "input",
          "bits": [ 13 ]
        },
        "carry_out": {
          "direction": "output",
          "bits": [ 14 ]
        },
        "borrow_out": {
          "direction": "output",
          "bits": [ 15 ]
        },
        "count_out": {
          "direction": "output",
          "bits": [ 16, 17, 18, 19, 20, 21, 22, 23, 24 ]
        },
        "parity_out": {
          "direction": "output",
          "bits": [ 25 ]
        }
      },
      "cells": {
        "$add$input.v:17$3": {
          "type": "$add",
          "port_directions": {
            "A": "input",
            "B": "input",
            "Y": "output"
          },
          "connections": {
            "A": [ 16, 17, 18, 19, 20, 21, 22, 23, 24 ],
            "B": [ "1", "1" ],
            "Y": [ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 ]
          }
        },
        "$and$input.v:28$5": {
          "type": "$and",
          "port_directions": {
            "A": "input",
            "B": "input",
            "Y": "output"
          },
          "connections": {
            "A": [ 12 ],
            "B": [ 35 ],
            "Y": [ 36 ]
          }
        },
        "$and$input.v:29$6": {
          "type": "$and",
          "port_directions": {
            "A": "input",
            "B": "input",
            "Y": "output"
          },
          "connections": {
            "A": [ 13 ],
            "B": [ 37 ],
            "Y": [ 38 ]
          }
        },
        "$procdff$40": {
          "type": "$dff",
          "port_directions": {
            "CLK": "input",
            "D": "input",
            "Q": "output"
          },
          "connections": {
            "CLK": [ 2 ],
            "D": [ 39, 40, 41, 42, 43, 44, 45, 46, 47 ],
            "Q": [ 16, 17, 18, 19, 20, 21, 22, 23, 24 ]
          }
        },
        "$procdff$41": {
          "type": "$dff",
          "port_directions": {
            "CLK": "input",
            "D": "input",
            "Q": "output"
          },
          "connections": {
            "CLK": [ 2 ],
            "D": [ 36 ],
            "Q": [ 14 ]
          }
        },
        "$procdff$42": {
          "type": "$dff",
          "port_directions": {
            "CLK": "input",
            "D": "input",
            "Q": "output"
          },
          "connections": {
            "CLK": [ 2 ],
            "D": [ 38 ],
            "Q": [ 15 ]
          }
        },
        "$procdff$43": {
          "type": "$dff",
          "port_directions": {
            "CLK": "input",
            "D": "input",
            "Q": "output"
          },
          "connections": {
            "CLK": [ 2 ],
            "D": [ 48 ],
            "Q": [ 25 ]
          }
        },
        "$procmux$36": {
          "type": "$pmux",
          "port_directions": {
            "A": "input",
            "B": "input",
            "S": "input",
            "Y": "output"
          },
          "connections": {
            "A": [ 16, 17, 18, 19, 20, 21, 22, 23, 24 ],
            "B": [ 26, 27, 28, 29, 30, 31, 32, 33, 34, 49, 50, 51, 52, 53, 54, 55, 56, 57, 3, 4, 5, 6, 7, 8, 9, 10, 11 ],
            "S": [ 58, 59, 60 ],
            "Y": [ 39, 40, 41, 42, 43, 44, 45, 46, 47 ]
          }
        },
        "$procmux$37_CMP0": {
          "type": "$eq",
          "port_directions": {
            "A": "input",
            "B": "input",
            "Y": "output"
          },
          "connections": {
            "A": [ 13, 12 ],
            "B": [ "0", "1" ],
            "Y": [ 58 ]
          }
        },
        "$procmux$38_CMP0": {
          "type": "$eq",
          "port_directions": {
            "A": "input",
            "B": "input",
            "Y": "output"
          },
          "connections": {
            "A": [ 13, 12 ],
            "B": [ "1", "0" ],
            "Y": [ 59 ]
          }
        },
        "$procmux$39_CMP0": {
          "type": "$eq",
          "port_directions": {
            "A": "input",
            "B": "input",
            "Y": "output"
          },
          "connections": {
            "A": [ 13, 12 ],
            "B": [ "0", "0" ],
            "Y": [ 60 ]
          }
        },
        "$reduce_xor$input.v:27$4": {
          "type": "$reduce_xor",
          "port_directions": {
            "A": "input",
            "Y": "output"
          },
          "connections": {
            "A": [ 39, 40, 41, 42, 43, 44, 45, 46, 47 ],
            "Y": [ 48 ]
          }
        },
        "$sub$input.v:16$2": {
          "type": "$sub",
          "port_directions": {
            "A": "input",
            "B": "input",
            "Y": "output"
          },
          "connections": {
            "A": [ 16, 17, 18, 19, 20, 21, 22, 23, 24 ],
            "B": [ "1", "0", "1" ],
            "Y": [ 49, 50, 51, 52, 53, 54, 55, 56, 57, 37 ]
          }
        }
      }
    }
  }
}

example

You can also write out the JSON by hand, of course. We support JSON5 syntax.

Here's an analog example.

JSON Source
{
  "modules": {
    "resistor_divider": {
      "ports": {
        "A": {
          "direction": "input",
          "bits": [2]
        },
        "B": {
          "direction": "input",
          "bits": [3]
        },
        "A AND B": {
          "direction": "output",
          "bits": [4]
        }
      },
      "cells": {
        "R1": {
          "type": "r_v",
          "connections": {
            "A": [2],
            "B": [5]
          },
          "attributes": {
            "value":"10k"
          }
        },
        "R2": {
          "type": "r_v",
          "connections": {
            "A": [3],
            "B": [5]
          },
          "attributes": {
            "value":"10k"
          }
        },
        "Q1": {
          "type": "q_pnp",
          "port_directions": {
            "C": "input",
            "B": "input",
            "E": "output"
          },
          "connections": {
            "C": [6],
            "B": [5],
            "E": [7]
          }
        },
        "R3": {
          "type": "r_v",
          "connections": {
            "A": [7],
            "B": [8]
          },
          "attributes": {
            "value":"10k"
          }
        },
        "R4": {
          "type": "r_v",
          "connections": {
            "A": [7],
            "B": [9]
          },
          "attributes": {
            "value":"10k"
          }
        },
        "R5": {
          "type": "r_v",
          "connections": {
            "A": [4],
            "B": [12]
          },
          "attributes": {
            "value":"10k"
          }
        },
        "Q2": {
          "type": "q_pnp",
          "port_directions": {
            "C": "input",
            "B": "input",
            "E": "output"
          },
          "connections": {
            "C": [10],
            "B": [9],
            "E": [4]
          }
        },
        "vcc": {
          "type": "vcc",
          "connections": {
            "A": [6]
          },
          "attributes": {
            "name":"VCC"
          }
        },
        "vcc2": {
          "type": "vcc",
          "connections": {
            "A": [10]
          },
          "attributes": {
            "name":"VCC"
          }
        },
        "gnd": {
          "type": "gnd",
          "port_directions": {
            "A": "input"
          },
          "connections": {
            "A": [8]
          },
          "attributes": {
            "name":"DGND"
          }
        },
        "gnd2": {
          "type": "gnd",
          "port_directions": {
            "A": "input"
          },
          "connections": {
            "A": [12]
          },
          "attributes": {
            "name":"DGND"
          }
        }
      }
    }
  }
}

example

Skin File

It pulls the node icons and configuration options from a SVG skin file. This our default digital skin file.

This is our analog skin file.

A skin file can use style tags or inline CSS to style the elements. That will be copied onto the output file. A skin file also defines a library of components to use. Each component has an alias list. It will use that component as a template for any cell with that type that it encounters. Each component defines the position and id of each of its ports so we know where to attach the wires to.

For example, here is a mux definition. It has two aliases: "$pmux" and "$mux". It defines a type name, and a width and height, as well as the position and id of each of it's ports. In general you can rearrange them however you like, and add whatever SVG elements you like inside the template.

<g s:type="mux" transform="translate(50, 50)" s:width="20" s:height="40">
  <s:alias val="$pmux"/>
  <s:alias val="$mux"/>

  <path d="M0,0 L20,10 L20,30 L0,40 Z"/>

  <g s:x="0" s:y="10" s:pid="A"/>
  <g s:x="0" s:y="30" s:pid="B"/>
  <g s:x="10" s:y="35" s:pid="S"/>
  <g s:x="20" s:y="20" s:pid="Y"/>
</g>

In addition to the library of components that are matched to cells, a skin file defines some special nodes. Input/Output ports, constants, Splits/Joins, and the generic node. Splits/Joins and the generic nodes are resized and ports are added or removed to adjust to the cell.

The elkjs layout properties are also defined in the skin file.

<s:layoutEngine
      org.eclipse.elk.layered.spacing.nodeNodeBetweenLayers="5"
      org.eclipse.elk.spacing.nodeNode= "35"
      org.eclipse.elk.direction="DOWN"
    />

Any properties specified here will get passed along to the layout engine. Node and edge properties aren't configurable (yet).

Input JSON

Yosys JSON includes more information than we need. We only render one module (either the first or the module with an attribute "top"). If the cell name matches one of the aliases of a template from the skin, then it will use it as a template for the SVG file. Port directions are optional for cells that are defined in the skin (not generic cells).

So it should look something like this.

{
  "modules": {
    "<dont care>": {
      "ports": {
        "<port name>": {
          "direction": "<input|output",
          "bits": [ 2, "1", ... ]
        },
        ...
      },
      "cells": {
        "<cell name>": {
          "type": "<type name",
          "port_directions": {
            "<port name>": "<input|output>",
            ...
          },
          "connections": {
            "<port name>": [ 3, "0", ... ],
            ...
          }
      },
      ...
    }
  }
}

ElkJS

ELK is using a layered approach (Sugiyama, Ganser), similar to dot in the Graphviz package. You can read about their algorithm here: https://rtsys.informatik.uni-kiel.de/%7Ebiblio/downloads/papers/jvlc13.pdf

Status

We are getting close to the 1.0 release. At that point, the skin file format will be considered specified and breaking changes will only happen on major version bumps.

Generating input_json_file with Yosys

Yosys from Clifford Wolf can be used to generate the input_json_file using the write_json command.

Unless you are doing something special you will want to use the prep command. Some examples are provided below and you can find some runnable examples which go from Verilog to diagrams in the examples directory (with example Makefile).

Generate top level diagram

This command will generate a diagram of the top module with all the inner modules shown as boxes.

yosys -p "prep -top my_top_module; write_json output.json" input.v

Generate logic diagram

You can give it the -flatten argument to the prep command if you want Yosys to convert everything into low level logic. Only basic logic cells and black boxes will exist after flattening.

yosys -p "prep -top my_top_module -flatten; write_json output.json" input.v

Generate AND (or not) and inverter (NOT) diagram

It is also frequently common that you want to create a diagram only using AND and NOT (or NAND and NOT) cells. (This is called an AIG.) This can be done with Yosys' aigmap command.

yosys -p "prep -top my_top_module; aigmap; write_json output.json" input.v
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].