Gordon  Murray

Gordon Murray

1679141476

Librealsense: Intel® RealSense™ SDK

Intel® RealSense™ SDK


Overview

Intel® RealSense™ SDK 2.0 is a cross-platform library for Intel® RealSense™ depth cameras (D400 & L500 series and the SR300) and the T265 tracking camera.

📌 For other Intel® RealSense™ devices (F200, R200, LR200 and ZR300), please refer to the latest legacy release.

The SDK allows depth and color streaming, and provides intrinsic and extrinsic calibration information. The library also offers synthetic streams (pointcloud, depth aligned to color and vise-versa), and a built-in support for record and playback of streaming sessions.

Developer kits containing the necessary hardware to use this library are available for purchase at store.intelrealsense.com. Information about the Intel® RealSense™ technology at www.intelrealsense.com

📂 Don't have access to a RealSense camera? Check-out sample data

Update on Recent Changes to the RealSense Product Line

Intel has EOLed the LiDAR, Facial Authentication, and Tracking product lines. These products have been discontinued and will no longer be available for new orders.

Intel WILL continue to sell and support stereo products including the following: D410, D415, D430, , D401 ,D450 modules and D415, D435, D435i, D435f, D405, D455, D457 depth cameras. We will also continue the work to support and develop our LibRealSense open source SDK.

In the future, Intel and the RealSense team will focus our new development on advancing innovative technologies that better support our core businesses and IDM 2.0 strategy.

Building librealsense - Using vcpkg

You can download and install librealsense using the vcpkg dependency manager:

git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install realsense2

The librealsense port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please create an issue or pull request on the vcpkg repository.

Download and Install

Download - The latest releases including the Intel RealSense SDK, Viewer and Depth Quality tools are available at: latest releases. Please check the release notes for the supported platforms, new features and capabilities, known issues, how to upgrade the Firmware and more.

Install - You can also install or build from source the SDK (on Linux \ Windows \ Mac OS \ Android \ Docker), connect your D400 depth camera and you are ready to start writing your first application.

Support & Issues: If you need product support (e.g. ask a question about / are having problems with the device), please check the FAQ & Troubleshooting section. If not covered there, please search our Closed GitHub Issues page, Community and Support sites. If you still cannot find an answer to your question, please open a new issue.

What’s included in the SDK:

WhatDescriptionDownload link
Intel® RealSense™ ViewerWith this application, you can quickly access your Intel® RealSense™ Depth Camera to view the depth stream, visualize point clouds, record and playback streams, configure your camera settings, modify advanced controls, enable depth visualization and post processing and much more.Intel.RealSense.Viewer.exe
Depth Quality ToolThis application allows you to test the camera’s depth quality, including: standard deviation from plane fit, normalized RMS – the subpixel accuracy, distance accuracy and fill rate. You should be able to easily get and interpret several of the depth quality metrics and record and save the data for offline analysis.Depth.Quality.Tool.exe
Debug ToolsDevice enumeration, FW logger, etc as can be seen at the tools directoryIncluded in Intel.RealSense.SDK.exe
Code SamplesThese simple examples demonstrate how to easily use the SDK to include code snippets that access the camera into your applications. Check some of the C++ examples including capture, pointcloud and more and basic C examplesIncluded in Intel.RealSense.SDK.exe
WrappersPython, C#/.NET API, as well as integration with the following 3rd-party technologies: ROS1, ROS2, LabVIEW, OpenCV, PCL, Unity, Matlab, OpenNI, UnrealEngine4 and more to come. 

Ready to Hack!

Our library offers a high level API for using Intel RealSense depth cameras (in addition to lower level ones). The following snippet shows how to start streaming frames and extracting the depth value of a pixel:

// Create a Pipeline - this serves as a top-level API for streaming and processing frames
rs2::pipeline p;

// Configure and start the pipeline
p.start();

while (true)
{
    // Block program until frames arrive
    rs2::frameset frames = p.wait_for_frames();

    // Try to get a frame of a depth image
    rs2::depth_frame depth = frames.get_depth_frame();

    // Get the depth frame's dimensions
    float width = depth.get_width();
    float height = depth.get_height();

    // Query the distance from the camera to the object in the center of the image
    float dist_to_center = depth.get_distance(width / 2, height / 2);

    // Print the distance
    std::cout << "The camera is facing an object " << dist_to_center << " meters away \r";
}

For more information on the library, please follow our examples, and read the documentation to learn more.

Contributing

In order to contribute to Intel RealSense SDK, please follow our contribution guidelines.


Download Details:

Author: IntelRealSense
Source Code: https://github.com/IntelRealSense/librealsense 
License: Apache-2.0 license

#cpluplus #library #sdk #computervision #hardware 

Librealsense: Intel® RealSense™ SDK

8 Best Libraries, Tools, Tutorials for interacting with Hardware in Go

In today's post we will learn about 8 Best Libraries, Tools, Tutorials for interacting with Hardware in Go. 

What is a Hardware?

Abbreviated as HW, hardware is best described as any physical component of a computer system containing a circuit board, ICs, or other electronics. A perfect example of hardware is the screen on which you are viewing this page. Whether it be a monitor, tablet, or smartphone, it is hardware.

Table of contents:

  • Arduino-cli - Official Arduino CLI and library. Can run standalone, or be incorporated into larger Go projects.
  • Emgo - Go-like language for programming embedded systems (e.g. STM32 MCU).
  • Ghw - Golang hardware discovery/inspection library.
  • Go-osc - Open Sound Control (OSC) bindings for Go.
  • Go-rpio - GPIO for Go, doesn't require cgo.
  • Goroslib - Robot Operating System (ROS) library for Go.
  • Joystick - a polled API to read the state of an attached joystick.
  • Sysinfo - A pure Go library providing Linux OS / kernel / hardware system information.

1 - Arduino-cli: Official Arduino CLI and library. Can run standalone, or be incorporated into larger Go projects.

Arduino CLI is an all-in-one solution that provides Boards/Library Managers, sketch builder, board detection, uploader, and many other tools needed to use any Arduino compatible board and platform from command line or machine interfaces.

Note: this software is currently under active development: anything can change at any time, API and UI must be considered unstable until we release version 1.0.0.

Docs

For guidance on installation and development, see the User documentation.

Quickstart

  1. Install the Arduino CLI
  2. Follow the Getting Started guide to check out what the CLI can do
  3. Browse the Commands reference to see all the available commands
  4. Should you have an issue, read the FAQ page

How to contribute

Contributions are welcome!

Please read the document How to contribute which will show you how to build the source code, run the tests, and contribute your changes to the project.

✨ Thanks to all our contributors! ✨

Beta testing

Nightly builds are available for beta testing.

Security

If you think you found a vulnerability or other security-related bug in the Arduino CLI, please read our security policy and report the bug to our Security Team 🛡️ Thank you!

e-mail contact: security@arduino.cc

View on Github

2 - Emgo: Go-like language for programming embedded systems (e.g. STM32 MCU).

Emgo consist of a compiler and the set of packages that allows you to run Go programs on small 32-bit microcontrollers. The compiler generates C as an intermediate code and uses C compiler to produce loadable binaries.

There is Embedded Go project that evolved from Emgo which is based on the reference Go compiler. It has much higher hardware requirements but it is also 100% compatible with the Go language specification. The main development process has moved to Embeadded Go but I still use Emgo for small MCUs so some things can be backported here.

How to start

First of all, to try Emgo you need the Go compiler installed. The current Emgo compiler and whole process described below requires also some kind of Unix-like operating system. There is a chance that Windows with Cygwin can be used but this was not tested.

You can probably use go get to install Emgo but the preferred way is to clone this repository using the git command:

git clone https://github.com/ziutek/emgo.git

Next you need to build and install egc (Emgo compiler):

cd emgo/egc
go install

For now, Emgo supports only ARM Cortex-M based MCUs. To build code for Cortex-M architecture, you need to install ARM embedded toolchain. You have two options: install a package included in your OS distribution (in case of Debian/Ubuntu Linux):

apt-get install gcc-arm-none-eabi

or better go to the GNU ARM Embedded Toolchain website and download most recent toolchain. This is preferred version of toolchain, try use it before report any bug with compilation.

Installed toolchain contains set of arm-none-eabi-* binaries. Find their location and set required enviroment variables:

export EGCC=path_to_arm_gcc            # eg. /usr/local/arm/bin/arm-none-eabi-gcc
export EGLD=path_to_arm_linker         # eg. /usr/local/arm/bin/arm-none-eabi-ld
export EGAR=path_to_arm_archiver       # eg. /usr/local/arm/bin/arm-none-eabi-ar

export EGROOT=path_to_egroot_directory # eg. $HOME/emgo/egroot
export EGPATH=path_to_egpath_directory # eg. $HOME/emgo/egpath

Load/debug helper scripts use also some other tools from the ARM toolchain (eg. arm-none-eabi-objcopy). If you downloaded the toolchain manually, you probably need also to add its bin directory to the PATH enviroment variable:

export PATH=$PATH:path_to_arm_bin_dir  # eg. /usr/local/arm/bin

View on Github

3 - Ghw: Golang hardware discovery/inspection library.

ghw is a small Golang library providing hardware inspection and discovery for Linux and Windows. There currently exists partial support for MacOSX.

Design Principles

No root privileges needed for discovery

ghw goes the extra mile to be useful without root priveleges. We query for host hardware information as directly as possible without relying on shellouts to programs like dmidecode that require root privileges to execute.

Elevated privileges are indeed required to query for some information, but ghw will never error out if blocked from reading that information. Instead, ghw will print a warning message about the information that could not be retrieved. You may disable these warning messages with GHW_DISABLE_WARNINGS environment variable.

Well-documented code and plenty of example code

The code itself should be well-documented with lots of usage examples.

Interfaces should be consistent across modules

Each module in the library should be structured in a consistent fashion, and the structs returned by various library functions should have consistent attribute and method names.

Inspecting != Monitoring

ghw is a tool for gathering information about your hardware's capacity and capabilities.

It is important to point out that ghw does NOT report information that is temporary or variable. It is NOT a system monitor nor is it an appropriate tool for gathering data points for metrics that change over time. If you are looking for a system that tracks usage of CPU, memory, network I/O or disk I/O, there are plenty of great open source tools that do this! Check out the Prometheus project for a great example.

Overriding the root mountpoint ghw uses

The default root mountpoint that ghw uses when looking for information about the host system is /. So, for example, when looking up CPU information on a Linux system, ghw.CPU() will use the path /proc/cpuinfo.

If you are calling ghw from a system that has an alternate root mountpoint, you can either set the GHW_CHROOT environment variable to that alternate path, or call the module constructor function with the ghw.WithChroot() modifier.

For example, if you are executing from within an application container that has bind-mounted the root host filesystem to the mount point /host, you would set GHW_CHROOT to /host so that ghw can find /proc/cpuinfo at /host/proc/cpuinfo.

Alternately, you can use the ghw.WithChroot() function like so:

cpu, err := ghw.CPU(ghw.WithChroot("/host"))

Overriding the per-mountpoint ghw uses

When running inside containers, it could be a bit cumbersome to just override the root mountpoint. Inside containers, when granting access to the host file systems, is more common to bind-mount them in non standard location, like /sys on /host-sys or /proc on /host-proc. Is rarer to mount them in a common subtree (e.g. /sys on /host/sys and /proc on /host/proc...)

To better cover this use case, ghw allows to programmatically override the initial component of filesystems subtrees, allowing to access sysfs (or procfs or...) mounted on non-standard locations.

cpu, err := ghw.CPU(ghw.WithPathOverrides(ghw.PathOverrides{
	"/proc": "/host-proc",
	"/sys": "/host-sys",
}))

Please note

  • this feature works in addition and is composable with the WithChroot/GHW_CHROOT feature.
  • ghw doesn't support yet environs variable to override individual mountpoints, because this could lead to significant environs variables proliferation.

View on Github

4 - Go-osc: Open Sound Control (OSC) bindings for Go.

Open Sound Control (OSC) library for Golang. Implemented in pure Go.

Features

  • OSC Bundles, including timetags
  • OSC Messages
  • OSC Client
  • OSC Server
  • Supports the following OSC argument types:
    • 'i' (Int32)
    • 'f' (Float32)
    • 's' (string)
    • 'b' (blob / binary data)
    • 'h' (Int64)
    • 't' (OSC timetag)
    • 'd' (Double/int64)
    • 'T' (True)
    • 'F' (False)
    • 'N' (Nil)
  • Support for OSC address pattern including '*', '?', '{,}' and '[]' wildcards

Install

go get github.com/hypebeast/go-osc

Usage

Client

import "github.com/hypebeast/go-osc/osc"

func main() {
    client := osc.NewClient("localhost", 8765)
    msg := osc.NewMessage("/osc/address")
    msg.Append(int32(111))
    msg.Append(true)
    msg.Append("hello")
    client.Send(msg)
}

Server

package main

import "github.com/hypebeast/go-osc/osc"

func main() {
    addr := "127.0.0.1:8765"
    d := osc.NewStandardDispatcher()
    d.AddMsgHandler("/message/address", func(msg *osc.Message) {
        osc.PrintMessage(msg)
    })

    server := &osc.Server{
        Addr: addr,
        Dispatcher:d,
    }
    server.ListenAndServe()
}

Tests

make test

View on Github

5 - Go-rpio: GPIO for Go, doesn't require cgo.

go-rpio is a Go library for accessing GPIO-pins on the Raspberry Pi.

It requires no external c libraries such as WiringPI or bcm2835.

There's a tiny bit of additional information over at my blog.

Releases

  • 1.0.0 - Supports original rpi A/B/B+
  • 2.0.0 - Adds support for rpi 2, by @akramer
  • 3.0.0 - Adds support for /dev/gpiomem, by @dotdoom
  • 4.0.0 - Adds support for PWM and Clock modes, by @drahoslove
  • 4.1.0 - Adds support for edge detection, by @drahoslove
  • 4.2.0 - Faster write and toggle of output pins, by @drahoslove
  • 4.3.0 - Adds support for SPI, by @drahoslove
  • 4.4.0 - Support for disabling interrupts (workaround for #35), by @drahoslove
  • 4.5.0 - Improve rpi 4 support, by @wfd3
  • 4.6.0 - Adds Balanced PWM mode, by @youngkin

Usage

import "github.com/stianeikeland/go-rpio/v4"

If you're using an older go.mod incompatible you should instead use:

import "github.com/stianeikeland/go-rpio"

Open memory range for GPIO access in /dev/mem

err := rpio.Open()

Initialize a pin, run basic operations. Pin refers to the bcm2835 pin, not the physical pin on the raspberry pi header. Pin 10 here is exposed on the pin header as physical pin 19.

pin := rpio.Pin(10)

pin.Output()       // Output mode
pin.High()         // Set pin High
pin.Low()          // Set pin Low
pin.Toggle()       // Toggle pin (Low -> High -> Low)

pin.Input()        // Input mode
res := pin.Read()  // Read state from pin (High / Low)

pin.Mode(rpio.Output)   // Alternative syntax
pin.Write(rpio.High)    // Alternative syntax

Pull up/down/off can be set using:

pin.PullUp()
pin.PullDown()
pin.PullOff()

pin.Pull(rpio.PullUp)

Unmap memory when done

rpio.Close()

Also see example examples/blinker/blinker.go

View on Github

6 - Goroslib: Robot Operating System (ROS) library for Go.

goroslib is a library in pure Go that allows to build clients (nodes) for the Robot Operating System (ROS).

The Robot Operating System (ROS) is a project that provides a specification to make multiple programs communicate with each other over time, exchanging structured data with topics, services, actions and parameters. It was conceived to link sensors, algorithms and actuators in unmanned ground vehicles (UGVs) and robots, but it is not bounded to the robot world and can be used anywhere there's the need of building streams of data (for example in video processing).

Features:

  • publish and subscribe to topics with TCP or UDP
  • provide and call services
  • provide and call actions
  • provide and call simple actions
  • get and set parameters
  • support namespaces and relative topics
  • support IPv6 (stateful addresses only)
  • support time API
  • compilation of .msg files is not necessary, message definitions are extracted from code
  • compile or cross-compile for all Go supported OSs (Linux, Windows, Mac OS X) and architectures
  • examples provided for every feature, comprehensive test suite, continuous integration

Installation

Install Go ≥ 1.17.

Create an empty folder, open a terminal in it and initialize the Go modules system:

go mod init main

Download one of the example files and place it in the folder:

Compile and run (a ROS master must be already running in the background)

go run name-of-the-go-file.go

FAQs

Comparison with other libraries

goroslib vs official C++/Python libraries

The official project provides libraries to write nodes in C++ and Python, but they require the download of over 1GB of data and work only with a fixed buildchain. This library allows to write lightweight nodes that can be built with the standard Go compiler, do not need any runtime library and have a size of some megabytes. Another advantage lies in the possibility of compiling nodes for all the Golang supported operating systems (Linux, Windows, Mac OS X, etc) and architectures.

goroslib vs rosgo

rosgo is currently unmaintained; furthermore, it requires compilation of .msg files, doesn't support UDP, doesn't support actions, doesn't support simulated clocks.

View on Github

7 - Joystick: a polled API to read the state of an attached joystick.

Package joystick implements a Polled API to read the state of an attached joystick. Windows, Linux & OSX are supported. Package requires no external dependencies to be installed.

Installation:

$ go get github.com/0xcafed00d/joystick/...

Sample Program

$ go install github.com/0xcafed00d/joystick/joysticktest
$ joysticktest 0

Displays the state of the specified joystick

Example:

import "github.com/0xcafed00d/joystick"
js, err := joystick.Open(jsid)
if err != nil {
  panic(err)
}

fmt.Printf("Joystick Name: %s", js.Name())
fmt.Printf("   Axis Count: %d", js.AxisCount())
fmt.Printf(" Button Count: %d", js.ButtonCount())

state, err := joystick.Read()
if err != nil {
  panic(err)
}

fmt.Printf("Axis Data: %v", state.AxisData)
js.Close()

View on Github

8 - Sysinfo: A pure Go library providing Linux OS / kernel / hardware system information.

Package sysinfo is a Go library providing Linux OS / kernel / hardware system information. It's completely standalone, has no dependencies on the host system, doesn't execute external programs, doesn't even import other Go libraries. It collects only "inventory type" information, things that don't change often.

Code Example

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"os/user"

	"github.com/zcalusic/sysinfo"
)

func main() {
	current, err := user.Current()
	if err != nil {
		log.Fatal(err)
	}

	if current.Uid != "0" {
		log.Fatal("requires superuser privilege")
	}

	var si sysinfo.SysInfo

	si.GetSysInfo()

	data, err := json.MarshalIndent(&si, "", "  ")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(string(data))
}

Motivation

I couldn't find any self-contained library that would provide set of data/features I needed. So another sysinfo was born.

The purpose of the library is to collect only inventory info. No metrics like CPU usage or load average will be added. The rule of thumb is, if it's changing during the day, every day, it doesn't belong in the library.

The library should work well on any modern/supported Linux distribution. There are no plans to add support for older unsupported Linux distributions/kernels, to keep the code clean and robust and reduce the maintenance burden.

Requirements

Sysinfo requires:

  • Linux kernel 4.2 or later
  • access to /sys & /proc Linux virtual file systems
  • access to various files in /etc, /var, /run FS hierarchy
  • superuser privileges (to access SMBIOS/DMI table and detect RAM size and properties)

Sysinfo doesn't require ANY other external utility on the target system, which is its primary strength, IMHO.

It depends on Linux internals heavily, so there are no plans to support other operating systems.

Installation

Just use go get.

go get github.com/zcalusic/sysinfo

There's also a very simple utility demonstrating sysinfo library capabilities. Start it (as superuser) to get pretty formatted JSON output of all the info that sysinfo library provides. Due to its simplicity, the source code of the utility also doubles down as an example of how to use the library.

go get github.com/zcalusic/sysinfo/cmd/sysinfo

--

Build demo utility in Docker container: https://github.com/mattscilipoti/compile_sysinfo

View on Github

Thank you for following this article.

Related videos:

Learn Go Programming by Building 11 Projects – Full Course

#go #golang #tools #hardware 

8 Best Libraries, Tools, Tutorials for interacting with Hardware in Go
Desmond  Gerber

Desmond Gerber

1652095740

Wifi: NodeJS tool To Manage Wifi (Connections, Scans)

We think about switching to ES Modules only for next major release. We would like to have your opinion on this. Please consider leave a comment in the discussion thread.

I am looking for maintainers who could help me to handle all improvements and bug fixes about this project because the hardware/os dependencies make it quite hard to test.

The node-wifi module allows macOS, windows and linux users to interact with surrounding wifi networks through various methods. These methods include scanning for wifi access points and connecting to these access points.

FeaturesLinuxMacWindows
Connect
Scan
List current wifi connections
Disconnect 
Delete connection information 

We wish to be clear in saying that this module is inspired from node-wifi-control but with some slight modifications to certain functions such as the various OS-specific parsers for terminal output as we noticed that these parsers did not work well on certain operating systems.

As everything with hardware dependencies, weird behaviors may happen depending of your configuration. You should never hesitate to notify us about a specificity of your OS/Hardware/Wifi card/whatever.


Install

# Use as a module
npm install node-wifi

Getting started

const wifi = require('node-wifi');

// Initialize wifi module
// Absolutely necessary even to set interface to null
wifi.init({
  iface: null // network interface, choose a random wifi interface if set to null
});

// Scan networks
wifi.scan((error, networks) => {
  if (error) {
    console.log(error);
  } else {
    console.log(networks);
    /*
        networks = [
            {
              ssid: '...',
              bssid: '...',
              mac: '...', // equals to bssid (for retrocompatibility)
              channel: <number>,
              frequency: <number>, // in MHz
              signal_level: <number>, // in dB
              quality: <number>, // same as signal level but in %
              security: 'WPA WPA2' // format depending on locale for open networks in Windows
              security_flags: '...' // encryption protocols (format currently depending of the OS)
              mode: '...' // network mode like Infra (format currently depending of the OS)
            },
            ...
        ];
        */
  }
});

// Connect to a network
wifi.connect({ ssid: 'ssid', password: 'password' }, () => {
  console.log('Connected'); 
  // on windows, the callback is called even if the connection failed due to netsh limitations
  // if your software may work on windows, you should use `wifi.getCurrentConnections` to check if the connection succeeded
});

// Disconnect from a network
// not available on all os for now
wifi.disconnect(error => {
  if (error) {
    console.log(error);
  } else {
    console.log('Disconnected');
  }
});

// Delete a saved network
// not available on all os for now
wifi.deleteConnection({ ssid: 'ssid' }, error => {
  if (error) {
    console.log(error);
  } else {
    console.log('Deleted');
  }
});

// List the current wifi connections
wifi.getCurrentConnections((error, currentConnections) => {
  if (error) {
    console.log(error);
  } else {
    console.log(currentConnections);
    /*
    // you may have several connections
    [
        {
            iface: '...', // network interface used for the connection, not available on macOS
            ssid: '...',
            bssid: '...',
            mac: '...', // equals to bssid (for retrocompatibility)
            channel: <number>,
            frequency: <number>, // in MHz
            signal_level: <number>, // in dB
            quality: <number>, // same as signal level but in %
            security: '...' //
            security_flags: '...' // encryption protocols (format currently depending of the OS)
            mode: '...' // network mode like Infra (format currently depending of the OS)
        }
    ]
    */
  }
});

// All functions also return promise if there is no callback given
wifi
  .scan()
  .then(networks => {
    // networks
  })
  .catch(error => {
    // error
  });

Use as CLI

node-wifi is also usable as a CLI tool with the library node-wifi-cli.

Platforms compatibility

This project is tested with operating systems:

  • macOS Catalina 10.15.5
  • macOS Big Sur 11.5.1
  • linux Ubuntu 18.04.3 LTS

Do not hesitate to create a pull request to add the OS you are using.

Dependencies

Linux:

  • network-manager (nmcli)

Windows:

  • netsh

MacOS:

  • airport
  • networksetup

Contribute

Please read development guidelines before proposing a pull request.

Roadmap

  •  add conventional commits
  •  plug to travis
  •  add github templates
  •  add eslint
  •  add prettier
  •  switch to MIT license
  •  generate changelog and release note
  •  stdout how to reproduce bug
  •  use github actions
  •  add unit tests (in progress)
  •  rewrite the library using ES7 (in progress)
  •  harmonize security flags and modes
  •  install commitizen
  •  use xml to stabilize parsers

Author: Friedrith
Source Code: https://github.com/friedrith/node-wifi 
License: MIT license

#node #hardware #wifi 

Wifi: NodeJS tool To Manage Wifi (Connections, Scans)

Awesome Python: Libraries for Programming with Hardware

Hardware

Libraries for programming with hardware.

  • ino - Command line toolkit for working with Arduino.
  • keyboard - Hook and simulate global keyboard events on Windows and Linux.
  • mouse - Hook and simulate global mouse events on Windows and Linux.
  • Pingo - Pingo provides a uniform API to program devices like the Raspberry Pi, pcDuino, Intel Galileo, etc.
  • PyUserInput - A module for cross-platform control of the mouse and keyboard.
  • scapy - A brilliant packet manipulation library.

Author: vinta
Source Code: https://github.com/vinta/awesome-python
License: View license

#python #hardware 

Awesome Python: Libraries for Programming with Hardware

Mouse: Take Full Control Of Your Mouse with This Small Python Library

Hook and simulate global mouse events in pure Python.

Take full control of your mouse with this small Python library. Hook global events, register hotkeys, simulate mouse movement and clicks, and much more.

Huge thanks to Kirill Pavlov for donating the package name. If you are looking for the Cheddargetter.com client implementation, pip install mouse==0.5.0.

Features

  • Global event hook on all mice devices (captures events regardless of focus).
  • Listen and sends mouse events.
  • Works with Windows and Linux (requires sudo).
  • Works with MacOS (requires granting accessibility permissions to terminal/python in System Preferences -> Security & Privacy)
  • Pure Python, no C modules to be compiled.
  • Zero dependencies on Windows and Linux. Trivial to install and deploy, just copy the files.
  • Python 2 and 3.
  • Includes high level API (e.g. record and play.
  • Events automatically captured in separate thread, doesn't block main program.
  • Tested and documented.

This program makes no attempt to hide itself, so don't use it for keyloggers.

Usage

Install the PyPI package:

$ sudo pip install mouse

or clone the repository (no installation required, source files are sufficient):

$ git clone https://github.com/boppreh/mouse

Then check the API docs to see what features are available.

Known limitations:

  • Events generated under Windows don't report device id (event.device == None). #21
  • To avoid depending on X the Linux parts reads raw device files (/dev/input/input*) but this requries root.
  • Other applications, such as some games, may register hooks that swallow all key events. In this case mouse will be unable to report events.

API

Table of Contents

class mouse.ButtonEvent

ButtonEvent(event_type, button, time)

ButtonEvent.button

Alias for field number 1

ButtonEvent.count(self, value, /)

Return number of occurrences of value.

ButtonEvent.event_type

Alias for field number 0

ButtonEvent.index(self, value, start=0, stop=9223372036854775807, /)

Return first index of value.

Raises ValueError if the value is not present.

ButtonEvent.time

Alias for field number 2

mouse.DOUBLE

= 'double'

mouse.DOWN

= 'down'

mouse.LEFT

= 'left'

mouse.MIDDLE

= 'middle'

class mouse.MoveEvent

MoveEvent(x, y, time)

MoveEvent.count(self, value, /)

Return number of occurrences of value.

MoveEvent.index(self, value, start=0, stop=9223372036854775807, /)

Return first index of value.

Raises ValueError if the value is not present.

MoveEvent.time

Alias for field number 2

MoveEvent.x

Alias for field number 0

MoveEvent.y

Alias for field number 1

mouse.RIGHT

= 'right'

mouse.UP

= 'up'

class mouse.WheelEvent

WheelEvent(delta, time)

WheelEvent.count(self, value, /)

Return number of occurrences of value.

WheelEvent.delta

Alias for field number 0

WheelEvent.index(self, value, start=0, stop=9223372036854775807, /)

Return first index of value.

Raises ValueError if the value is not present.

WheelEvent.time

Alias for field number 1

mouse.X

= 'x'

mouse.X2

= 'x2'

mouse.version

= '0.7.1'

mouse.is_pressed(button='left')

[source]

Returns True if the given button is currently pressed.

mouse.press(button='left')

[source]

Presses the given button (but doesn't release).

mouse.release(button='left')

[source]

Releases the given button.

mouse.click(button='left')

[source]

Sends a click with the given button.

mouse.double_click(button='left')

[source]

Sends a double click with the given button.

mouse.right_click()

[source]

Sends a right click with the given button.

mouse.wheel(delta=1)

[source]

Scrolls the wheel delta clicks. Sign indicates direction.

mouse.move(x, y, absolute=True, duration=0, steps_per_second=120.0)

[source]

Moves the mouse. If absolute, to position (x, y), otherwise move relative to the current position. If duration is non-zero, animates the movement. The fps of the animation is determined by 'steps_per_second', default is 120.

mouse.drag(start_x, start_y, end_x, end_y, absolute=True, duration=0)

[source]

Holds the left mouse button, moving from start to end position, then releases. absolute and duration are parameters regarding the mouse movement.

mouse.on_button(callback, args=(), buttons=('left', 'middle', 'right', 'x', 'x2'), types=('up', 'down', 'double'))

[source]

Invokes callback with args when the specified event happens.

mouse.on_click(callback, args=())

[source]

Invokes callback with args when the left button is clicked.

mouse.on_double_click(callback, args=())

[source]

Invokes callback with args when the left button is double clicked.

mouse.on_right_click(callback, args=())

[source]

Invokes callback with args when the right button is clicked.

mouse.on_middle_click(callback, args=())

[source]

Invokes callback with args when the middle button is clicked.

mouse.wait(button='left', target_types=('up', 'down', 'double'))

[source]

Blocks program execution until the given button performs an event.

mouse.get_position()

[source]

Returns the (x, y) mouse position.

mouse.hook(callback)

[source]

Installs a global listener on all available mouses, invoking callback each time it is moved, a key status changes or the wheel is spun. A mouse event is passed as argument, with type either mouse.ButtonEvent, mouse.WheelEvent or mouse.MoveEvent.

Returns the given callback for easier development.

mouse.unhook(callback)

[source]

Removes a previously installed hook.

mouse.unhook_all()

[source]

Removes all hooks registered by this application. Note this may include hooks installed by high level functions, such as record.

mouse.record(button='right', target_types=('down',))

[source]

Records all mouse events until the user presses the given button. Then returns the list of events recorded. Pairs well with play(events).

Note: this is a blocking function. Note: for more details on the mouse hook and events see hook.

mouse.play(events, speed_factor=1.0, include_clicks=True, include_moves=True, include_wheel=True)

[source]

Plays a sequence of recorded events, maintaining the relative time intervals. If speed_factor is <= 0 then the actions are replayed as fast as the OS allows. Pairs well with record().

The parameters include_* define if events of that type should be inluded in the replay or ignored.

Author: boppreh
Source Code: https://github.com/boppreh/mouse
License: MIT License

#python #hardware 

Mouse: Take Full Control Of Your Mouse with This Small Python Library

Ino: Command Line Toolkit for Working with Arduino Hardware

Ino

Ino is a command line toolkit for working with Arduino hardware

It allows you to:

  • Quickly create new projects
  • Build a firmware from multiple source files and libraries
  • Upload the firmware to a device
  • Perform serial communication with a device (aka serial monitor)

Ino may replace Arduino IDE UI if you prefer to work with command line and an editor of your choice or if you want to integrate Arduino build process to 3-rd party IDE.

Ino is based on make to perform builds. However Makefiles are generated automatically and you'll never see them if you don't want to.

Features

  • Simple. No build scripts are necessary.
  • Out-of-source builds. Directories with source files are not cluttered with intermediate object files.
  • Support for *.ino and *.pde sketches as well as raw *.c and *.cpp.
  • Support for Arduino Software versions 1.x as well as 0.x.
  • Automatic dependency tracking. Referred libraries are automatically included in the build process. Changes in *.h files lead to recompilation of sources which include them.
  • Pretty colorful output.
  • Support for all boards that are supported by Arduino IDE.
  • Fast. Discovered tool paths and other stuff is cached across runs. If nothing has changed, nothing is build.
  • Flexible. Support for simple ini-style config files to setup machine-specific info like used Arduino model, Arduino distribution path, etc just once.

Installation

From source:

  • Download latest source tarball
  • Or clone it from GitHub: git clone git://github.com/amperka/ino.git
  • Do make install to perform installation under /usr/local
  • Or see INSTALL for instructions on changing destination directory

With Python setup tools:

  • Either pip install ino
  • Or easy_install ino

Requirements

  • Python 2.6+
  • Arduino IDE distribution
  • picocom for serial communication

Limitations

  • As for current version, ino works only in Linux and MacOS. However it was created with other OS users in mind, so it will eventually get full cross-platform support. Help from Windows-developers is much appreciated.

Getting Help

License

If not stated otherwise ino is distributed in terms of MIT software license. See MIT-LICENSE.txt in the distribution for details.

Contributors

Changelog

0.3.6

  • Fix #74, #107, #108: Use of types declared in included files is allowed in function definitions. Previously it led to: '<enum|struct|typedef>' not declared in this scope.
  • Fix #105: Search for avrdude.conf in /etc/avrdude to be compatible with Fedora.
  • Fix #99: Check for an existing project before building or creating directories
  • Fix #93, #57, #8: Custom compile and link flags can be passed as ino build arguments
  • Fix #60, #63: Custom make tool command can be passed as ino build argument
  • Fix #23, #28: make is searched within Arduino IDE binaries as well
  • Fix #88, #103: Correct version parsing for some distributions that mangle it
  • Fix #46: Taking build number into account in version string
  • Fix #19, #81, #82: Custom command line arguments for picocom can be passed while running ino serial

0.3.5

  • Fix #62: Include MIT-LICENSE.txt in the tarball.

0.3.4

  • Fix #44, #45: Building and uploading for Arduino Leonardo is fully supported.
  • Fix #3, #29: Build artifacts for different board models and Arduino distributions go in different build subdirectories, so you haven't to run ino clean and rebuild if you switch to another Arduino model or software distribution.
  • The version of avr gcc toolset that is bundled with Arduino Software is now always preferred over system-wide. So that users with edge-versions of software (such as Arch Linux) able to produce expected results.

0.3.3

  • Fix #16: *.ino and *.pde sketches are now populated with function prototypes while preprocessing step in the same way as it done by Arduino IDE, so it is now possible to use functions before they're declared or defined.

0.3.2

  • Fix #13: Local header #includes from sketch files are no longer lead to 'No such file or directory' error. Now GCC is given an additional include path pointing to the sketch origin while compiling processed source.
  • Fix #18: Proper scanning of dependency files when multiple library dependencies are found on the same line. Now all of them are taken into account, not just first one.
  • Add: Processed sketch files now have #line directive so that they appear as original source in GCC output in case of syntax errors.
  • Add: Automatic dependency tracking for included header files. Now a sketch or cpp source get rebuild once an included (directly or indirectly) header changes.

0.3.1

  • Support for ino build --verbose

0.3.0

  • MacOS support
  • Serial port guess

0.2.0

  • Support for Arduino Software version 1.0

0.1.x

  • Initial release
  • Various bug fixes

Author: amperka
Source Code: https://github.com/amperka/ino
License: MIT License

#python #hardware 

Ino: Command Line Toolkit for Working with Arduino Hardware
Diego  Elizondo

Diego Elizondo

1650950340

Cómo Superar 4 Desafíos En Hardware IoT

Obtener un nuevo producto de Internet de las cosas (IoT) en el mercado requiere comprender los desafíos de diseño que podrían presentar obstáculos en el camino o significar que el dispositivo no funciona tan bien como se esperaba. Estas son algunas de las principales preocupaciones relacionadas con el hardware y cómo resolverlas. 

1. Batería de larga duración

Muchos de los usuarios de dispositivos IoT de hoy en día necesitan que tengan baterías que puedan durar años. Eso es particularmente importante si alguien planea implementar algo en un área remota a la que no puede acceder fácilmente para cambiar la batería. Supongamos que el producto es un dispositivo médico conectado que se usa dentro del cuerpo de un paciente. Los reemplazos frecuentes de la batería podrían requerir operaciones o poner a alguien en un riesgo elevado de complicaciones. 

Los diseñadores de hardware deben considerar qué aspectos consumirán más energía y luego evaluar si son críticos para el diseño. Si es así, el siguiente paso es descubrir cómo prolongar la vida útil de la batería.

Una forma de resolver este desafío de diseño de IoT es usar circuitos integrados con modos de suspensión profunda que consumen muy poca corriente. Además, los diseñadores pueden buscar oportunidades para usar voltajes de batería bajos. La idea es minimizar el consumo de corriente dentro del producto. Los diseñadores pueden alcanzar ese objetivo utilizando componentes de bajo consumo y asegurándose de que las piezas no sigan consumiendo demasiada energía cuando no se utilizan. 

Un proyecto financiado por la Unión Europea indicó que se desecharán hasta 78 millones de baterías IoT para 2025 si los ingenieros no toman medidas para mejorar su vida útil. Los investigadores que comentaron sobre el proyecto creen que se producirán grandes avances mediante el desarrollo de baterías que puedan recargarse de forma sostenible. Sin embargo, por ahora, dicen que los diseñadores deben priorizar la duración de la batería desde el principio cuando planifiquen dispositivos IoT. 

2. Fallas de seguridad

Los titulares actuales suelen presentar detalles preocupantes de fallas de seguridad que podrían afectar a los dispositivos IoT en todo el mundo. Resolver este desafío de diseño de IoT desde una perspectiva de hardware requiere un enfoque múltiple. 

En primer lugar, los diseñadores deben considerar una gestión de claves segura que impida que las partes accedan a las claves en estados no cifrados. Deben diseñar el producto para generar y almacenar claves de forma segura. También deberían explorar el uso de cifrado acelerado por hardware para mantener el dispositivo más seguro y ahorrar energía. 

Otra práctica recomendada es tener dominios de memoria separados para aislar el código y los datos de IoT confidenciales y no confidenciales. El uso de acceso seguro a la memoria puede proteger la RAM y la memoria flash del acceso no autorizado. Los diseñadores de hardware también deben implementar protecciones para la depuración y la programación. Hacer eso hace que sea más difícil para los piratas informáticos usar interfaces de programación y depuradores para lanzar ataques.

Los diseñadores de hardware también deben participar o alentar discusiones sobre programas para revelar nuevas vulnerabilidades de seguridad cibernética en un producto. Un estudio encontró que solo el 21% de los proveedores de IoT actualmente tienen tales iniciativas. Sin embargo, son esenciales para ayudar a los diseñadores y a todos los demás interesados ​​en la seguridad de IoT a ser conscientes de los problemas que, de otro modo, pasarían desapercibidos. 

3. El impulso de dispositivos más pequeños y livianos

Otro desafío de diseño de IoT proviene del hecho de que existe una creciente demanda de dispositivos que son progresivamente más pequeños y livianos. El deseo de esas características tiene sentido porque permite flexibilidad en la implementación. 

Una posibilidad es ver si el dispositivo garantiza el uso de una placa de circuito impreso (PCB) flexible en lugar de una rígida. Los PCB flexibles son un  95 % más livianos y permiten que quepan más componentes en un espacio más pequeño. También suelen ser más duraderos que los rígidos y pueden tolerar mejor los golpes en entornos hostiles, lo que les da una vida útil más larga en general. 

Si el dispositivo IoT funcionará con inteligencia artificial (IA) o manejará el procesamiento de datos en el dispositivo, los diseñadores de hardware deben comprender que esas necesidades también pueden afectar el factor de forma. Los investigadores han avanzado recientemente al ejecutar algoritmos en una unidad de microcontrolador (MCU) que ya se usa en miles de millones de dispositivos IoT. Dijeron que su técnica reduciría aún más la memoria necesaria para ejecutar algoritmos de IA y mejoraría el rendimiento. 

Los fabricantes de componentes para dispositivos IoT también tienen como objetivo hacer elementos como los módulos Wi-Fi progresivamente más pequeños para que sean más adecuados para productos miniaturizados. Los diseñadores de hardware de IoT deben mantenerse al tanto de esos desarrollos y aprender cómo las opciones más nuevas podrían respaldar sus próximos productos. 

4. Dedicar suficiente tiempo a las pruebas

Los diseñadores suelen operar con horarios ajustados. Aun así, deben reservar el tiempo suficiente para realizar pruebas de hardware y realizar los ajustes necesarios después de obtener los resultados respectivos. Las evaluaciones de los fabricantes cubren áreas que van desde las pruebas mecánicas hasta la resistencia ambiental. 

En esta fase, los diseñadores se asegurarán de que aspectos como la conectividad, la duración de la batería y la facilidad de uso cumplan con los requisitos mínimos que esperan. Las pruebas que se realizan antes de que un producto llegue al mercado también pueden prevenir problemas relacionados con la seguridad. Por ejemplo, las pruebas de fuzz implican someter los dispositivos IoT a cadenas de bytes aleatorios y rastrear comportamientos anormales que podrían indicar errores. Esto sucede más comúnmente cuando se prueban aplicaciones informáticas. Sin embargo, también es una opción útil para verificar dispositivos IoT. 

La comunicación efectiva entre los equipos es esencial para obtener resultados valiosos en las pruebas. El desarrollador de software que trabajó en un dispositivo podría descubrir un error que afecta parcialmente al hardware. En esos casos, los desarrolladores de software y los diseñadores de hardware tendrían que trabajar juntos en posibles soluciones. 

Mantenerse en contacto con los probadores también es esencial. Es posible que muchas de esas partes no comprendan de inmediato que experimentaron un problema debido a un problema de hardware. Sin embargo, después de que las personas involucradas en las pruebas brinden comentarios detallados, los diseñadores de hardware y otras personas involucradas con el producto IoT pueden comenzar a detectar qué salió mal y colaborar para solucionarlo. 

Los diseñadores de hardware siempre deben planificar que las pruebas tomen más tiempo del previsto. De esa manera, no habrá presión para apresurarse y potencialmente pasar por alto problemas que podrían interferir con la funcionalidad o la seguridad del producto más adelante. 

La previsión evita muchos desafíos de diseño de IoT

No existe una forma universal de evitar todos los desafíos de diseño de IoT con los que se pueda encontrar. Sin embargo, como muestran estos ejemplos, es vital pensar en los buenos y malos resultados de cada decisión de diseño. Hacer eso ayudará a los diseñadores a tomar las decisiones más adecuadas durante cada etapa y evitar problemas costosos y que consumen mucho tiempo.

Fuente: https://dzone.com/articles/how-to-overcome-4-challenges-in-iot-hardware-design

#iot #hardware #design-pattern 

Cómo Superar 4 Desafíos En Hardware IoT

IoTハードウェアの4つの課題を克服する方法

新しいモノのインターネット(IoT)製品を市場に出すには、途中で障害を引き起こしたり、デバイスが期待どおりに機能しないことを意味する可能性のある設計上の課題を理解する必要があります。ここでは、ハードウェアに関連する主な懸念事項とその解決方法について説明します。 

1.長いバッテリー寿命

今日のIoTデバイスユーザーの多くは、何年も使用できるバッテリーを持っている必要があります。これは、誰かがバッテリー交換のために簡単にアクセスできない遠隔地に何かを配備することを計画している場合に特に重要です。製品が、患者の体内で使用される接続された医療機器であるとします。頻繁なバッテリー交換は、操作を必要とするか、さもなければ誰かを合併症のリスクを高める可能性があります。 

ハードウェア設計者は、どの側面が最も電力を消費するかを検討し、それらが設計にとって重要であるかどうかを評価する必要があります。もしそうなら、次のステップはバッテリーの寿命を延ばす方法を見つけることです。

このIoT設計の課題を解決する1つの方法は、電流をほとんど消費しないディープスリープモードの集積回路を使用することです。さらに、設計者は低バッテリ電圧を使用する機会を探すことができます。アイデアは、製品内の電流引き込みを最小限に抑えることです。設計者は、低電力のコンポーネントを使用し、使用されていないときに部品が過度の電力を消費し続けないようにすることで、その目標を達成できます。 

欧州連合が資金提供したプロジェクトでは、エンジニアが寿命を延ばすための措置を講じない場合、2025年までに最大7,800万個のIoTバッテリーが廃棄されることが示されました。このプロジェクトについてコメントした研究者たちは、持続的に充電できるバッテリーを開発することで大きな進歩が見られると信じています。ただし、今のところ、設計者はIoTデバイスを計画する際にバッテリー寿命を早期に優先する必要があると彼らは言います。 

2.セキュリティ上の欠陥

現在のヘッドラインには、世界中のIoTデバイスに影響を与える可能性のあるセキュリティ上の欠陥の気になる詳細が頻繁に掲載されています。ハードウェアの観点からこのIoT設計の課題を解決するには、多面的なアプローチが必要です。 

まず、設計者は、当事者が暗号化されていない状態のキーにアクセスできないようにする安全なキー管理を検討する必要があります。キーを安全に生成して保存するように製品を設計する必要があります。また、ハードウェアアクセラレーションによる暗号化を使用して、電力を節約しながらデバイスをより安全に保つことも検討する必要があります。 

もう1つのベストプラクティスは、機密性の高いIoTコードと機密性の低いIoTコードとデータを分離するために、別々のメモリドメインを用意することです。安全なメモリアクセスを使用すると、RAMとフラッシュメモリを不正アクセスから保護できます。ハードウェア設計者は、デバッグとプログラミングの保護も実装する必要があります。そうすることで、ハッカーがプログラミングインターフェイスやデバッガーを使用して攻撃を開始することがより困難になります。

ハードウェア設計者は、製品に新たに発見されたサイバーセキュリティの脆弱性を開示するためのプログラムに関する議論にも参加または奨励する必要があります。ある調査によると、現在IoTベンダーの21%だけがそのようなイニシアチブを持っています。ただし、これらは、設計者やIoTセキュリティに関係する他のすべての人が、他の方法では見過ごされがちな問題に気付くのを支援するために不可欠です。 

3.より軽く、より小さなデバイスの推進

もう1つのIoT設計の課題は、徐々に小型化および軽量化されたデバイスに対する需要が高まっているという事実にあります。これらの特性に対する要望は、実装の柔軟性を可能にするため、理にかなっています。 

1つの可能性は、デバイスがリジッドではなくフレキシブルプリント回路基板(PCB)の使用を保証するかどうかを確認することです。フレキシブルPCBは 95%軽量であり、より多くのコンポーネントをより小さなスペースに収めることができます。また、通常、剛性のあるものよりも耐久性があり、過酷な環境での衝撃に耐えることができるため、全体的な寿命が長くなります。 

IoTデバイスが人工知能(AI)で動作するか、デバイス上のデータ処理を処理する場合、ハードウェア設計者は、これらの必需品がフォームファクターにも影響を与える可能性があることを理解する必要があります。研究者は最近、数十億のIoTデバイスですでに使用されているマイクロコントローラーユニット(MCU)でアルゴリズムを実行することで進歩を遂げました。彼らは、彼らの技術は、パフォーマンスを向上させながら、AIアルゴリズムを実行するために必要なメモリをさらに削減すると述べました。 

IoTデバイスのコンポーネントのメーカーも、Wi-Fiモジュールなどのアイテムを徐々に小さくして、小型化された製品により適したものにすることを目指しています。IoTハードウェア設計者は、これらの開発に遅れずについていき、新しいオプションが今後の製品をどのようにサポートできるかを学ぶ必要があります。 

4.テストに十分な時間を割く

設計者は通常、厳しいスケジュールで作業します。それでも、ハードウェアテストを実行し、それぞれの結果を得た後に必要な調整を行うために十分な時間を確保する必要があります。メーカーの評価は、機械的試験から耐環境性に 至るまでの領域をカバーしています。

このフェーズでは、設計者は、接続性、バッテリ寿命、使いやすさなどの側面が、期待する最小要件を満たしていることを確認します。製品が市場に出る前に行われるテストは、セキュリティ関連の問題を防ぐこともできます。たとえば、ファズテストでは、IoTデバイスをランダムなバイト文字列にさらし、バグを示す可能性のある異常な動作を追跡します。これは、コンピュータアプリケーションをテストするときに最も一般的に発生します。ただし、IoTデバイスをチェックする場合にも便利なオプションです。 

貴重なテスト結果を得るには、チーム間の効果的なコミュニケーションが不可欠です。デバイスで作業したソフトウェア開発者は、ハードウェアに部分的に影響するバグを発見する可能性があります。そのような場合、ソフトウェア開発者とハードウェア設計者は、潜在的なソリューションに協力する必要があります。 

テスターと連絡を取り合うことも不可欠です。これらの関係者の多くは、ハードウェアの問題が原因で問題が発生したことをすぐには理解できない場合があります。ただし、テストに関係する人々が詳細なフィードバックを提供した後、ハードウェア設計者やIoT製品に関係する他の人々は、問題のあるものをターゲットにして、協力して修正することができます。 

ハードウェア設計者は、常に予想よりも多くの時間をかけてテストを計画する必要があります。そうすれば、急いで製品の機能やセキュリティを妨げる可能性のある問題を見逃す可能性がなくなります。 

Foresightは多くのIoT設計の課題を防ぎます

遭遇する可能性のあるすべてのIoT設計の課題を回避する普遍的な方法はありません。ただし、これらの例が示すように、すべての設計決定の良い結果と悪い結果を考えることが重要です。そうすることで、設計者はすべての段階で最も適切な選択を行い、コストと時間のかかる問題を回避することができます。

ソース:https ://dzone.com/articles/how-to-overcome-4-challenges-in-iot-hardware-design

#iot #hardware #design-pattern 

IoTハードウェアの4つの課題を克服する方法

¿Qué Es Firmware? Definición Y Ejemplos

¿Sabías que el firmware está literalmente en todas partes? Puede resultar extraño pensar en ello, pero es tan común como el hardware y el software.

De hecho, es gracias al firmware que:

  • Las impresoras funcionan
  • Los desfibriladores funcionan
  • Funciona la radio del coche
  • y más …

Según los ejemplos anteriores, probablemente ya tenga una idea de qué es el firmware. Pero no tienes una definición clara de ello.

Para comprender realmente qué es el firmware, primero debemos comprender el software, luego el hardware y, finalmente, podemos saltar al firmware.

En este tutorial, explicaré cada tema con una analogía. Al hacerlo, todos pueden entender.

¡No importa si te estás iniciando en la tecnología!

Con eso, me gustaría asegurarme de que todos entiendan qué es el software, el hardware y el firmware. No daré más detalles sobre los términos técnicos.

En este artículo exploraremos:

  • ¿Qué es exactamente el software?
  • ¿Qué es exactamente el hardware?
  • ¿Qué es exactamente el firmware?

¿Qué es el software?

libro

Foto de Kübra Doğu de Pexels

Imagina, si quieres, que no tienes idea de qué hacer para cenar hoy.

Por suerte, encuentras un viejo libro de cocina que tienes y decides cocinar una de las recetas que contiene.

El libro de cocina tiene muchas recetas. Cada una de estas recetas tiene sus propias instrucciones.

En el libro de cocina , una receta puede verse como un conjunto de pasos (o instrucciones) que juntos hacen una comida .

instrucciones de cocina

Foto de Luis Quintero en Pexels

También puede crear sus propias comidas en función de su experiencia en la cocina de muchas recetas diferentes, ¿verdad?

El software no es diferente.

Los programas de software pueden verse como un conjunto de instrucciones que trabajan juntas para formar un programa .

 global  _main
    extern  _printf

    section .text
_main:
    push    message
    call    _printf
    add     esp, 4
    ret
message:
    db  'Hello, World', 10, 0

Imprimir hola mundo en código máquina (Asamblea)HolaMundo.asm

Entonces, las aplicaciones son un gran conjunto de instrucciones que realizan tareas específicas.

Los sistemas operativos son grandes conjuntos de instrucciones que coordinan los recursos de software y hardware.

  • libro de cocina = software
  • Libro de cocina de la cena = tipo de software (aplicación o sistema operativo)
  • receta = programa

Necesitas una receta para hacer la cena. Debe seguir cada paso del libro de cocina para crear una receta.

Una vez que hayas completado todos los pasos, tu cena estará lista.

Necesita software para realizar una tarea en particular. Una computadora tiene que seguir todas las instrucciones para que el software funcione.

Por lo tanto, el software se ejecuta mientras se siguen las instrucciones o después de que se hayan completado.

receta---instrucciones-de-cocina

¿Qué es la ferretería?

alimento

Foto de ELEVATE de Pexels

Para preparar la cena, necesita una serie de pasos del libro de cocina que le indiquen cómo preparar una comida en particular.

También necesita varias herramientas para cocinar, como ollas y sartenes, cuchillos y la comida misma. Esto es como el hardware.

Entonces, un libro de cocina te da instrucciones que te permiten cocinar.

proceso-de-coccion-1

Para que el hardware funcione, necesita un software (un conjunto de instrucciones) que le diga qué hacer.

CPU-proceso-2

Entonces, el software le da instrucciones al hardware que le permite funcionar.

  • Herramientas de preparación de comidas = hardware
  • Receta = software

Sin software, no puede hacer que el hardware funcione.

Sin una receta, no sabrá qué hacer con sus diversas herramientas e ingredientes para preparar una comida.

Al igual que el hardware sin software, también puede comer solo alimentos crudos. Bruto.

De la misma manera que hay varios tipos de comidas, también hay varios tipos de hardware informático.

Por ejemplo:

  • UPC
  • RAM
  • GPU
  • y mucho más…

comparación de procesos

Comparación de procesos

¿Qué es Firmware?

postre

Foto de Ella Olsson de Pexels

Un programa es un conjunto de instrucciones leídas por una computadora.

Digamos que solo quieres hacer un refrigerio o un postre. Probablemente no necesites tantos ingredientes como cuando preparas una cena para tu familia, ¿verdad?

Supongamos que desea un software que se ejecute en un microondas. No necesitas todo el hardware que tiene la computadora para que el microondas funcione, ¿verdad? Solo necesita eso específico para hacer que el microondas funcione.

O diga que desea que el software se ejecute en una impresora. No necesita todo el hardware que tiene la computadora para que la impresora funcione, ¿verdad? Solo el software para la impresora.

  • Software de microondas = firmware
  • Software de impresoras = firmware

Entonces, esto significa que el firmware no es más que un software, pero en un dispositivo de hardware. No en una computadora.

El firmware permite que hardware muy específico complete tareas muy específicas.

Terminando

¡Gracias por leer! Ahora sabes más sobre:

  • Software
  • Hardware
  • firmware

Foto del microprocesador de Pok Rie de Pexels

Fuente: https://www.freecodecamp.org/news/what-is-firmware/

#firmware  #softwares  #hardware 

¿Qué Es Firmware? Definición Y Ejemplos
伊藤  直子

伊藤 直子

1650659580

ファームウェア (Firmware) とは何ですか?定義と例

ファームウェアが文字通りどこにでもあることをご存知ですか?考えるのは奇妙かもしれませんが、ハードウェアやソフトウェアと同じくらい一般的です。

実際、ファームウェアのおかげで次のことが可能になります。

  • プリンターは動作します
  • 除細動器は機能します
  • カーラジオは動作します
  • もっと …

上記の例に基づいて、おそらくファームウェアが何であるかについてすでにある程度の知識があります。しかし、あなたはそれの明確な定義を持っていません。

ファームウェアとは何かを真に理解するには、まずソフトウェア、次にハードウェアを理解し、最後にファームウェアに飛び込む必要があります。

このチュートリアルでは、各トピックを類推して説明します。そうすることで、誰もが理解できるようになります。

テクノロジーを始めたばかりかどうかは関係ありません。

それで、ソフトウェア、ハードウェア、ファームウェアが何であるかをみんなに理解してもらいたいと思います。専門用語については詳しく説明しません。

この記事では、以下について説明します。

  • ソフトウェアとは正確には何ですか?
  • ハードウェアとは正確には何ですか?
  • ファームウェアとは正確には何ですか?

ソフトウェアとは何ですか?

本

PexelsKübraDoğuによる写真

もしそうなら、今日の夕食に何を作ればいいのかわからないと想像してみてください。

幸いなことに、あなたはあなたが持っている古い料理本を見つけて、その中のレシピの1つを料理することに決めました。

クックブックには多くのレシピがあります。これらのレシピにはそれぞれ独自の手順があります。

クックブックでは、レシピは一緒に食事を作る一連のステップ(または指示)として見ることができます。

料理指導

PexelsのLuisQuinteroによる写真

また、さまざまなレシピを調理した経験に基づいて、独自の食事を作成することもできますよね?

ソフトウェアも例外ではありません。

ソフトウェアプログラムは、連携してプログラムを形成する一連の命令と見なすことができます。

 global  _main
    extern  _printf

    section .text
_main:
    push    message
    call    _printf
    add     esp, 4
    ret
message:
    db  'Hello, World', 10, 0

hello worldをマシンコードで出力する(アセンブリ)HelloWorld.asm

次に、アプリケーションは特定のタスクを実行する一連の大きな命令です。

オペレーティングシステムは、ソフトウェアとハ​​ードウェアのリソースを調整する一連の大きな命令です。

  • クックブック=ソフトウェア
  • ディナークックブック=ソフトウェアの種類(アプリケーションまたはオペレーティングシステム)
  • レシピ=プログラム

あなたは夕食を作るためのレシピが必要です。レシピを作成するには、クックブックの各ステップに従う必要があります。

すべての手順を完了すると、夕食の準備が整います。

特定のタスクを実行するにはソフトウェアが必要です。コンピュータは、ソフトウェアが機能するためにすべての指示に従う必要があります。

したがって、ソフトウェアは、指示に従っている間、または指示が完了した後に実行されます。

レシピ---調理-指示

ハードウェアとは何ですか?

食物

PexelsELEVATEによる写真

夕食を作るために、あなたは特定の食事を作る方法をあなたに教える料理本からの一連のステップを必要とします。

また、鍋やフライパン、ナイフ、食べ物自体など、さまざまな調理器具が必要です。これはハードウェアのようなものです。

したがって、クックブックには、料理を可能にする手順が記載されています。

調理プロセス-1

ハードウェアが機能するには、何をすべきかを指示するソフトウェア(一連の命令)が必要です。

CPUプロセス-2

次に、ソフトウェアは、それを機能させるハードウェアに指示を与えます。

  • 食事準備ツール=ハードウェア
  • レシピ=ソフトウェア

ソフトウェアがなければ、ハードウェアを機能させることはできません。

レシピがなければ、食事を作るためにさまざまな道具や材料をどうするかがわかりません。

ソフトウェアのないハードウェアのように、生の食品だけで食事をすることもできます。キモい。

さまざまな種類の食事があるのと同じように、さまざまな種類のコンピュータハードウェアもあります。

例えば:

  • CPU
  • GPU
  • そしてもっと…

プロセスの比較

プロセスの比較

ファームウェアとは何ですか?

デザート

PexelsEllaOlssonによる写真

プログラムは、コンピューターによって読み取られる一連の命令です。

おやつやデザートを作りたいだけだとしましょう。家族で夕食を作るときほど多くの材料は必要ないでしょう?

電子レンジで動作するソフトウェアが必要だとしましょう。コンピュータが電子レンジを機能させるために必要なすべてのハードウェアは必要ありませんよね?あなたはただマイクロ波を機能させるためにそれを必要とします。

または、ソフトウェアをプリンターで実行したいとします。コンピューターがプリンターを正しく動作させるために必要なすべてのハードウェアは必要ありませんか?プリンタ用のソフトウェアだけです。

  • マイクロ波ソフトウェア=ファームウェア
  • プリンターソフトウェア=ファームウェア

つまり、これはファームウェアがソフトウェアにすぎず、ハードウェアデバイスにあることを意味します。コンピューターではありません。

ファームウェアにより、非常に特定のハードウェアが非常に特定のタスクを完了できます。

まとめ

読んでくれてありがとう!今、あなたはもっと知っています:

  • ソフトウェア
  • ハードウェア
  • ファームウェア

PexelsPokRieによるマイクロプロセッサの写真

ソース:https ://www.freecodecamp.org/news/what-is-firmware/

#firmware  #softwares  #hardware 

ファームウェア (Firmware) とは何ですか?定義と例

Tipos De Discos Duros: SATA, PATA, SCSI Y SSD

Un disco duro es un componente de hardware no volátil en una computadora que actúa como almacenamiento para todo el contenido digital. Contiene archivos de programa, documentos, imágenes, videos, música y más.

La naturaleza no volátil de los discos duros significa que no pierden datos, incluso si se pierde la energía. Debido a esto, ayudan a las computadoras a almacenar archivos y otros datos durante mucho tiempo, siempre que no se dañen o corrompan.

Desde el primer lanzamiento de discos duros de IBM en 1956, los discos duros han pasado de ser del tamaño de un refrigerador y tener una capacidad de almacenamiento de solo 5 MB a unos de bolsillo y tienen una capacidad de almacenamiento de hasta 4 TB.

En este artículo, cubriré los diferentes tipos de discos duros para que pueda elegir el mejor para su computadora.

1956_RAMAC_P1-1

El primer disco duro

Tipos de discos duros

Actualmente, los discos duros se dividen en 4 tipos principales:

  • Accesorio de tecnología avanzada paralela (PATA)
  • Accesorio de tecnología avanzada en serie (SATA)
  • Interfaz de sistema de computadora pequeña (SCSI)
  • Unidad de estado sólido (SSD)

Estos nombres provienen de la forma en que se conectan a la computadora. En este artículo, ahora voy a elaborar cada uno de estos tipos de discos duros de la manera más concisa posible.

Accesorio de tecnología avanzada paralela (PATA)

Los discos duros PATA fueron introducidos por primera vez en el mercado por Compaq y Western Digital en 1986. Pueden tener una capacidad de hasta 80 GB y transferir datos a una velocidad de hasta 133 MB/S.

Fueron nombrados Adjunto de Tecnología Avanzada Paralela porque utilizan una interfaz ATA paralela para conectarse a la computadora. Además de PATA, también se denominan Integrated Drive Electronics (IDE) y Enhanced Integrated Drive Electronics (EIDE).

Los discos duros PATA están hechos de partes mecánicas móviles y se basan en tecnología de señalización paralela, lo que significa que transmiten múltiples bits de datos simultáneamente.

Accesorio de tecnología avanzada en serie (SATA)

En los últimos tiempos, muchas computadoras de escritorio y portátiles han obtenido discos duros SATA porque han reemplazado a los discos duros PATA en tamaño, consumo de energía e incluso mejores precios.

El modo de conexión a una computadora sigue siendo el mismo que el de PATA, pero en lugar de la tecnología de señalización en paralelo para la transmisión de datos, utilizan la tecnología de señalización en serie. Esto significa que transfieren datos un bit a la vez.

Una ventaja notable que tienen los discos duros SATA sobre los discos duros PATA es la transmisión de datos a una velocidad de 150 a 300 MB/S. Además, tienen cables más finos y un límite de cable de 1 metro.

Interfaz de sistema de computadora pequeña (SCSI)

Los discos duros SCSI son actualizaciones sobre los discos SATA y PATA por muchas razones, como operaciones las 24 horas, velocidad, almacenamiento y muchos otros.

Para la conexión, los discos duros SCSI utilizan una pequeña interfaz de sistema informático, que es un estándar para conectar dispositivos periféricos como impresoras, escáneres y otros.

Lo mejor de todo es que permiten la conexión de dispositivos periféricos como impresoras, escáneres y otros discos duros. Además, transmiten datos a 320 MB/S y puedes conectarlos interna o externamente.

Las conexiones a través de SCSI en las computadoras personales ahora han sido reemplazadas por el Universal Serial BUS (USB). Esto significa que SCSI ya no se utiliza como hardware de consumo.

Unidad de estado sólido (SSD)

Los discos duros SSD son una de las últimas tecnologías de discos duros en el momento de escribir este artículo.

A diferencia de las tecnologías de disco duro anteriores a las unidades SSD, no consisten en partes móviles y no utilizan magnetismo para almacenar datos.

En su lugar, utilizan circuitos integrados (CI) al igual que las computadoras de tercera generación. Esto los hace más duraderos, más rápidos y menos propensos a sufrir daños y corrupción.

Los discos duros SSD tienen la ventaja notable de transferir datos a una velocidad de 550 MB/S y permiten tiempos de arranque más rápidos que los tipos de discos duros anteriores.

Conclusión

Este artículo le mostró diferentes tipos de discos duros y los explicó detalladamente, para que pueda aprender más sobre los discos duros y elegir el mejor para sus necesidades.

Desde PATA hasta SATA, SCSI y SSD, los discos duros siguen evolucionando y se está investigando para fabricar mejores.

De hecho, existe una nueva variación de los discos duros SSD llamados SSD NVMe (Non-volatile Memory Express) que tiene la capacidad de transferir datos a una velocidad de hasta 3,5 GB/S. Esto los convierte en la mejor opción para la edición de video y juegos de alta resolución, aunque requieren más energía que los SSD reales.

Gracias por leer.

Si encuentra útil este artículo, no dude en compartirlo con sus amigos y familiares. 

Fuente: https://www.freecodecamp.org/news/types-of-hard-drives-sata-pata-scsi-and-more-2/

#sata #hardware #ssd 

Tipos De Discos Duros: SATA, PATA, SCSI Y SSD
坂本  健一

坂本 健一

1649461380

ハードドライブの種類– SATA、PATA、SCSI、SSD

ハードドライブは、すべてのデジタルコンテンツのストレージとして機能する、コンピューター上の不揮発性ハードウェアコンポーネントです。プログラムファイル、ドキュメント、写真、ビデオ、音楽などを保持します。

ハードドライブの不揮発性は、電源が失われた場合でもデータが失われないことを意味します。このため、損傷や破損がない限り、コンピューターがファイルやその他のデータを長期間保存するのに役立ちます。

1956年にIBMがハードドライブを最初にリリースして以来、ハードドライブは冷蔵庫のサイズでわずか5MBのストレージ容量から、ポケットサイズで最大4TBのストレージ容量を持つものへと進化してきました。

この記事では、さまざまな種類のハードドライブについて説明し、コンピューターに最適なものを選択できるようにします。

1956_RAMAC_P1-1

最初のハードドライブ

ハードドライブの種類

現在、ハードドライブは4つの主要なタイプに分けられます。

  • Parallel Advanced Technology Attachment(PATA)
  • シリアルアドバンストテクノロジーアタッチメント(SATA)
  • Small Computer System Interface(SCSI)
  • ソリッドステートドライブ(SSD)

これらの名前は、コンピューターへの接続方法に由来しています。この記事では、これらのタイプのハードドライブのそれぞれについて可能な限り簡潔に説明します。

Parallel Advanced Technology Attachment(PATA)

PATAハードドライブは、1986年にCompaqとWestern Digitalによって最初に市場に導入されました。最大80GBの容量を持ち、133 MB/Sの速度でデータを転送できます。

これらは、パラレルATAインターフェイスを使用してコンピュータに接続するため、Parallel AdvancedTechnologyAttachmentと名付けられました。PATAとは別に、Integrated Drive Electronics(IDE)およびEnhanced Integrated Drive Electronics(EIDE)とも呼ばれます。

PATAハードドライブは機械的な可動部品でできており、パラレルシグナリングテクノロジーに基づいています。つまり、複数ビットのデータを同時に送信します。

シリアルアドバンストテクノロジーアタッチメント(SATA)

最近では、多くのデスクトップおよびラップトップコンピュータが、サイズ、消費電力、およびさらに優れた価格設定でPATAハードドライブに取って代わったため、SATAハードドライブを取得しています。

コンピュータへの接続モードはPATAと同じですが、データ伝送用の並列シグナリングテクノロジの代わりに、シリアルシグナリングテクノロジを使用します。これは、一度に1ビットずつデータを転送することを意味します。

SATAハードドライブがPATAハードドライブよりも優れている注目すべき利点は、150〜300 MB/Sの速度でデータを送信できることです。さらに、ケーブルが細く、ケーブル制限が1メートルです。

Small Computer System Interface(SCSI)

SCSIハードドライブは、24時間稼働、速度、ストレージなどの多くの理由から、SATAおよびPATAドライブをアップグレードしたものです。

接続には、SCSIハードドライブは小さなコンピューターシステムインターフェイスを使用します。これは、プリンター、スキャナーなどの周辺機器を接続するための標準です。

何よりも、プリンター、スキャナー、その他のハードドライブなどの周辺機器を接続できます。さらに、320 MB / Sでデータを送信し、内部または外部に接続できます。

パーソナルコンピュータ上のSCSIを介した接続は、ユニバーサルシリアルバス(USB)に置き換えられました。これは、SCSIがコンシューマーハードウェアとして使用されなくなったことを意味します。

ソリッドステートドライブ(SSD)

SSDハードドライブは、この記事の執筆時点での最新のハードドライブ技術の1つです。

SSDドライブ以前のハードドライブテクノロジーとは異なり、可動部品で構成されておらず、データの保存に磁気を使用していません。

代わりに、第3世代のコンピューターと同じように集積回路(IC)を使用します。これにより、耐久性が向上し、速度が向上し、損傷や破損が発生しにくくなります。

SSDハードドライブには、550 MB / Sの速度でデータを転送するという顕著な利点があり、以前のタイプのハードドライブよりも起動時間を短縮できます。

結論

この記事では、さまざまな種類のハードドライブを紹介し、それらについて詳しく説明したので、ハードドライブについて詳しく学び、ニーズに最適なものを選択できます。

PATAからSATA、SCSI、SSDに至るまで、ハードドライブは進化を続けており、より優れたものを作るための研究が進行中です。

実際、NVMe(Non-volatile Memory Express)SSDと呼ばれるSSDハードドライブの新しいバリエーションがあり、3.5 GB/Sの速度でデータを転送できます。これにより、実際のSSDよりも多くの電力を必要としますが、ビデオ編集や高解像度ゲームに最適です。

読んでくれてありがとう。

この記事が役に立ったら、お友達やご家族と共有することを躊躇しないでください。 

ソース:https ://www.freecodecamp.org/news/types-of-hard-drives-sata-pata-scsi-and-more-2/

#sata #hardware #ssd 

ハードドライブの種類– SATA、PATA、SCSI、SSD
Waylon  Bruen

Waylon Bruen

1649319480

Ghw: Golang Hardware Discovery/inspection Library

ghw - Golang HardWare discovery/inspection library 

ghw mascot

ghw is a small Golang library providing hardware inspection and discovery for Linux and Windows. There currently exists partial support for MacOSX.

Design Principles

No root privileges needed for discovery

ghw goes the extra mile to be useful without root priveleges. We query for host hardware information as directly as possible without relying on shellouts to programs like dmidecode that require root privileges to execute.

Elevated privileges are indeed required to query for some information, but ghw will never error out if blocked from reading that information. Instead, ghw will print a warning message about the information that could not be retrieved. You may disable these warning messages with GHW_DISABLE_WARNINGS environment variable.

Well-documented code and plenty of example code

The code itself should be well-documented with lots of usage examples.

Interfaces should be consistent across modules

Each module in the library should be structured in a consistent fashion, and the structs returned by various library functions should have consistent attribute and method names.

Inspecting != Monitoring

ghw is a tool for gathering information about your hardware's capacity and capabilities.

It is important to point out that ghw does NOT report information that is temporary or variable. It is NOT a system monitor nor is it an appropriate tool for gathering data points for metrics that change over time. If you are looking for a system that tracks usage of CPU, memory, network I/O or disk I/O, there are plenty of great open source tools that do this! Check out the Prometheus project for a great example.

Usage

You can use the functions in ghw to determine various hardware-related information about the host computer:

Overriding the root mountpoint ghw uses

The default root mountpoint that ghw uses when looking for information about the host system is /. So, for example, when looking up CPU information on a Linux system, ghw.CPU() will use the path /proc/cpuinfo.

If you are calling ghw from a system that has an alternate root mountpoint, you can either set the GHW_CHROOT environment variable to that alternate path, or call the module constructor function with the ghw.WithChroot() modifier.

For example, if you are executing from within an application container that has bind-mounted the root host filesystem to the mount point /host, you would set GHW_CHROOT to /host so that ghw can find /proc/cpuinfo at /host/proc/cpuinfo.

Alternately, you can use the ghw.WithChroot() function like so:

cpu, err := ghw.CPU(ghw.WithChroot("/host"))

Overriding the per-mountpoint ghw uses

When running inside containers, it could be a bit cumbersome to just override the root mountpoint. Inside containers, when granting access to the host file systems, is more common to bind-mount them in non standard location, like /sys on /host-sys or /proc on /host-proc. Is rarer to mount them in a common subtree (e.g. /sys on /host/sys and /proc on /host/proc...)

To better cover this use case, ghw allows to programmatically override the initial component of filesystems subtrees, allowing to access sysfs (or procfs or...) mounted on non-standard locations.

cpu, err := ghw.CPU(ghw.WithPathOverrides(ghw.PathOverrides{
    "/proc": "/host-proc",
    "/sys": "/host-sys",
}))

Please note

  • this feature works in addition and is composable with the WithChroot/GHW_CHROOT feature.
  • ghw doesn't support yet environs variable to override individual mountpoints, because this could lead to significant environs variables proliferation.

Consuming snapshots

You can make ghw read from snapshots (created with ghw-snapshot) using environment variables or programmatically. Please check SNAPSHOT.md to learn more about how ghw creates and consumes snapshots.

The environment variable GHW_SNAPSHOT_PATH let users specify a snapshot that ghw will automatically consume. All the needed chroot changes will be automatically performed. By default, the snapshot is unpacked on a temporary directory managed by ghw, and cleaned up when no longer needed, avoiding leftovers.

The rest of the environment variables are relevant iff GHW_SNAPSHOT_PATH is given. GHW_SNAPSHOT_ROOT let users specify the directory on which the snapshot should be unpacked. This moves the ownership of that directory from ghw to users. For this reason, ghw will not clean up automatically the content unpacked in GHW_SNAPSHOT_ROOT.

GHW_SNAPSHOT_EXCLUSIVE is relevant iff GHW_SNAPSHOT_ROOT is given. Set it to any value to toggle it on. This tells ghw that the directory is meant only to contain the given snapshot, thus ghw will not attempt to unpack it (and will go ahead silently!) unless the directory is empty. You can use both GHW_SNAPSHOT_ROOT and GHW_SNAPSHOT_EXCLUSIVE to make sure ghw unpacks the snapshot only once regardless of how many ghw packages (e.g. cpu, memory) access it.

Set GHW_SNAPSHOT_PRESERVE to any value to enable it. If set, ghw will not clean up the unpacked snapshot once done, leaving it into the system.

cpu, err := ghw.CPU(ghw.WithSnapshot(ghw.SnapshotOptions{
    Path: "/path/to/linux-amd64-d4771ed3300339bc75f856be09fc6430.tar.gz",
}))


myRoot := "/my/safe/directory"
cpu, err := ghw.CPU(ghw.WithSnapshot(ghw.SnapshotOptions{
    Path: "/path/to/linux-amd64-d4771ed3300339bc75f856be09fc6430.tar.gz",
    Root: &myRoot,
}))

myOtherRoot := "/my/other/safe/directory"
cpu, err := ghw.CPU(ghw.WithSnapshot(ghw.SnapshotOptions{
    Path:      "/path/to/linux-amd64-d4771ed3300339bc75f856be09fc6430.tar.gz",
    Root:      &myOtherRoot,
    Exclusive: true,
}))

Creating snapshots

You can create ghw snapshots in two ways. You can just consume the ghw-snapshot tool, or you can create them programmatically from your golang code. We explore now the latter case.

Snapshotting takes two phases:

  1. clone the relevant pseudofiles/pseudodirectories into a temporary tree This tree is usually deleted once the packing is successful.
  2. pack the cloned tree into a tar.gz

import (
    "fmt"
    "io/ioutil"
    "os"

    "github.com/jaypipes/ghw/pkg/snapshot"
)

// ...

scratchDir, err := ioutil.TempDir("", "ghw-snapshot-*")
if err != nil {
    fmt.Printf("Error creating clone directory: %v", err)
}
defer os.RemoveAll(scratchDir)

// this step clones all the files and directories ghw cares about
if err := snapshot.CloneTreeInto(scratchDir); err != nil {
    fmt.Printf("error cloning into %q: %v", scratchDir, err)
}

// optionally, you may add extra content into your snapshot.
// ghw will ignore the extra content.
// Glob patterns like `filepath.Glob` are supported.
fileSpecs := []string{
    "/proc/cmdline",
}

// options allows the client code to optionally deference symlinks, or copy
// them into the cloned tree as symlinks
var opts *snapshot.CopyFileOptions
if err := snapshot.CopyFilesInto(fileSpecs, scratchDir, opts); err != nil {
    fmt.Printf("error cloning extra files into %q: %v", scratchDir, err)
}

// automates the creation of the gzipped tarball out of the given tree.
if err := snapshot.PackFrom("my-snapshot.tgz", scratchDir); err != nil {
    fmt.Printf("error packing %q into %q: %v", scratchDir, *output, err)
}

Disabling warning messages

When ghw isn't able to retrieve some information, it may print certain warning messages to stderr. To disable these warnings, simply set the GHW_DISABLE_WARNINGS environs variable:

$ ghwc memory
WARNING:
Could not determine total physical bytes of memory. This may
be due to the host being a virtual machine or container with no
/var/log/syslog file, or the current user may not have necessary
privileges to read the syslog. We are falling back to setting the
total physical amount of memory to the total usable amount of memory
memory (24GB physical, 24GB usable)
$ GHW_DISABLE_WARNINGS=1 ghwc memory
memory (24GB physical, 24GB usable)

You can disable warning programmatically using the WithDisableWarnings option:


import (
    "github.com/jaypipes/ghw"
)

mem, err := ghw.Memory(ghw.WithDisableWarnings())

WithDisableWarnings is a alias for the WithNullAlerter option, which in turn leverages the more general Alerter feature of ghw.

You may supply a Alerter to ghw to redirect all the warnings there, like logger objects (see for example golang's stdlib log.Logger). Alerter is in fact the minimal logging interface ghw needs. To learn more, please check the option.Alerterinterface and theghw.WithAlerter()` function.

Memory

The basic building block of the memory support in ghw is the ghw.MemoryArea struct. A "memory area" is a block of memory which share common properties. In the simplest case, the whole system memory fits in a single memory area; in more complex scenarios, like multi-NUMA systems, many memory areas may be present in the system (e.g. one for each NUMA cell).

The ghw.MemoryArea struct contains the following fields:

  • ghw.MemoryInfo.TotalPhysicalBytes contains the amount of physical memory on the host
  • ghw.MemoryInfo.TotalUsableBytes contains the amount of memory the system can actually use. Usable memory accounts for things like the kernel's resident memory size and some reserved system bits

Information about the host computer's memory can be retrieved using the ghw.Memory() function which returns a pointer to a ghw.MemoryInfo struct. ghw.MemoryInfo is a superset of ghw.MemoryArea. Thus, it contains all the fields found in the ghw.MemoryArea (replicated for clarity) plus some:

  • ghw.MemoryInfo.TotalPhysicalBytes contains the amount of physical memory on the host
  • ghw.MemoryInfo.TotalUsableBytes contains the amount of memory the system can actually use. Usable memory accounts for things like the kernel's resident memory size and some reserved system bits
  • ghw.MemoryInfo.SupportedPageSizes is an array of integers representing the size, in bytes, of memory pages the system supports
  • ghw.MemoryInfo.Modules is an array of pointers to ghw.MemoryModule structs, one for each physical DIMM. Currently, this information is only included on Windows, with Linux support planned.
package main

import (
    "fmt"

    "github.com/jaypipes/ghw"
)

func main() {
    memory, err := ghw.Memory()
    if err != nil {
        fmt.Printf("Error getting memory info: %v", err)
    }

    fmt.Println(memory.String())
}

Example output from my personal workstation:

memory (24GB physical, 24GB usable)

Physical versus Usable Memory

There has been some confusion regarding the difference between the total physical bytes versus total usable bytes of memory.

Some of this confusion has been due to a misunderstanding of the term "usable". As mentioned above, ghw does inspection of the system's capacity.

A host computer has two capacities when it comes to RAM. The first capacity is the amount of RAM that is contained in all memory banks (DIMMs) that are attached to the motherboard. ghw.MemoryInfo.TotalPhysicalBytes refers to this first capacity.

There is a (usually small) amount of RAM that is consumed by the bootloader before the operating system is started (booted). Once the bootloader has booted the operating system, the amount of RAM that may be used by the operating system and its applications is fixed. ghw.MemoryInfo.TotalUsableBytes refers to this second capacity.

You can determine the amount of RAM that the bootloader used (that is not made available to the operating system) by subtracting ghw.MemoryInfo.TotalUsableBytes from ghw.MemoryInfo.TotalPhysicalBytes:

package main

import (
    "fmt"

    "github.com/jaypipes/ghw"
)

func main() {
    memory, err := ghw.Memory()
    if err != nil {
        fmt.Printf("Error getting memory info: %v", err)
    }

        phys := memory.TotalPhysicalBytes
        usable := memory.TotalUsableBytes

    fmt.Printf("The bootloader consumes %d bytes of RAM\n", phys - usable)
}

Example output from my personal workstation booted into a Windows10 operating system with a Linux GRUB bootloader:

The bootloader consumes 3832720 bytes of RAM

CPU

The ghw.CPU() function returns a ghw.CPUInfo struct that contains information about the CPUs on the host system.

ghw.CPUInfo contains the following fields:

  • ghw.CPUInfo.TotalCores has the total number of physical cores the host system contains
  • ghw.CPUInfo.TotalThreads has the total number of hardware threads the host system contains
  • ghw.CPUInfo.Processors is an array of ghw.Processor structs, one for each physical processor package contained in the host

Each ghw.Processor struct contains a number of fields:

  • ghw.Processor.ID is the physical processor uint32 ID according to the system
  • ghw.Processor.NumCores is the number of physical cores in the processor package
  • ghw.Processor.NumThreads is the number of hardware threads in the processor package
  • ghw.Processor.Vendor is a string containing the vendor name
  • ghw.Processor.Model is a string containing the vendor's model name
  • ghw.Processor.Capabilities is an array of strings indicating the features the processor has enabled
  • ghw.Processor.Cores is an array of ghw.ProcessorCore structs that are packed onto this physical processor

A ghw.ProcessorCore has the following fields:

  • ghw.ProcessorCore.ID is the uint32 identifier that the host gave this core. Note that this does not necessarily equate to a zero-based index of the core within a physical package. For example, the core IDs for an Intel Core i7 are 0, 1, 2, 8, 9, and 10
  • ghw.ProcessorCore.Index is the zero-based index of the core on the physical processor package
  • ghw.ProcessorCore.NumThreads is the number of hardware threads associated with the core
  • ghw.ProcessorCore.LogicalProcessors is an array of logical processor IDs assigned to any processing unit for the core
package main

import (
    "fmt"
    "math"
    "strings"

    "github.com/jaypipes/ghw"
)

func main() {
    cpu, err := ghw.CPU()
    if err != nil {
        fmt.Printf("Error getting CPU info: %v", err)
    }

    fmt.Printf("%v\n", cpu)

    for _, proc := range cpu.Processors {
        fmt.Printf(" %v\n", proc)
        for _, core := range proc.Cores {
            fmt.Printf("  %v\n", core)
        }
        if len(proc.Capabilities) > 0 {
            // pretty-print the (large) block of capability strings into rows
            // of 6 capability strings
            rows := int(math.Ceil(float64(len(proc.Capabilities)) / float64(6)))
            for row := 1; row < rows; row = row + 1 {
                rowStart := (row * 6) - 1
                rowEnd := int(math.Min(float64(rowStart+6), float64(len(proc.Capabilities))))
                rowElems := proc.Capabilities[rowStart:rowEnd]
                capStr := strings.Join(rowElems, " ")
                if row == 1 {
                    fmt.Printf("  capabilities: [%s\n", capStr)
                } else if rowEnd < len(proc.Capabilities) {
                    fmt.Printf("                 %s\n", capStr)
                } else {
                    fmt.Printf("                 %s]\n", capStr)
                }
            }
        }
    }
}

Example output from my personal workstation:

cpu (1 physical package, 6 cores, 12 hardware threads)
 physical package #0 (6 cores, 12 hardware threads)
  processor core #0 (2 threads), logical processors [0 6]
  processor core #1 (2 threads), logical processors [1 7]
  processor core #2 (2 threads), logical processors [2 8]
  processor core #3 (2 threads), logical processors [3 9]
  processor core #4 (2 threads), logical processors [4 10]
  processor core #5 (2 threads), logical processors [5 11]
  capabilities: [msr pae mce cx8 apic sep
                 mtrr pge mca cmov pat pse36
                 clflush dts acpi mmx fxsr sse
                 sse2 ss ht tm pbe syscall
                 nx pdpe1gb rdtscp lm constant_tsc arch_perfmon
                 pebs bts rep_good nopl xtopology nonstop_tsc
                 cpuid aperfmperf pni pclmulqdq dtes64 monitor
                 ds_cpl vmx est tm2 ssse3 cx16
                 xtpr pdcm pcid sse4_1 sse4_2 popcnt
                 aes lahf_lm pti retpoline tpr_shadow vnmi
                 flexpriority ept vpid dtherm ida arat]

Block storage

Information about the host computer's local block storage is returned from the ghw.Block() function. This function returns a pointer to a ghw.BlockInfo struct.

The ghw.BlockInfo struct contains two fields:

  • ghw.BlockInfo.TotalPhysicalBytes contains the amount of physical block storage on the host
  • ghw.BlockInfo.Disks is an array of pointers to ghw.Disk structs, one for each disk drive found by the system

Each ghw.Disk struct contains the following fields:

  • ghw.Disk.Name contains a string with the short name of the disk, e.g. "sda"
  • ghw.Disk.SizeBytes contains the amount of storage the disk provides
  • ghw.Disk.PhysicalBlockSizeBytes contains the size of the physical blocks used on the disk, in bytes
  • ghw.Disk.IsRemovable contains a boolean indicating if the disk drive is removable
  • ghw.Disk.DriveType is the type of drive. It is of type ghw.DriveType which has a ghw.DriveType.String() method that can be called to return a string representation of the bus. This string will be "HDD", "FDD", "ODD", or "SSD", which correspond to a hard disk drive (rotational), floppy drive, optical (CD/DVD) drive and solid-state drive.
  • ghw.Disk.StorageController is the type of storage controller/drive. It is of type ghw.StorageController which has a ghw.StorageController.String() method that can be called to return a string representation of the bus. This string will be "SCSI", "IDE", "virtio", "MMC", or "NVMe"
  • ghw.Disk.NUMANodeID is the numeric index of the NUMA node this disk is local to, or -1
  • ghw.Disk.Vendor contains a string with the name of the hardware vendor for the disk drive
  • ghw.Disk.Model contains a string with the vendor-assigned disk model name
  • ghw.Disk.SerialNumber contains a string with the disk's serial number
  • ghw.Disk.WWN contains a string with the disk's World Wide Name
  • ghw.Disk.Partitions contains an array of pointers to ghw.Partition structs, one for each partition on the disk

Each ghw.Partition struct contains these fields:

  • ghw.Partition.Name contains a string with the short name of the partition, e.g. "sda1"
  • ghw.Partition.SizeBytes contains the amount of storage the partition provides
  • ghw.Partition.MountPoint contains a string with the partition's mount point, or "" if no mount point was discovered
  • ghw.Partition.Type contains a string indicated the filesystem type for the partition, or "" if the system could not determine the type
  • ghw.Partition.IsReadOnly is a bool indicating the partition is read-only
  • ghw.Partition.Disk is a pointer to the ghw.Disk object associated with the partition. This will be nil if the ghw.Partition struct was returned by the ghw.DiskPartitions() library function.
  • ghw.Partition.UUID is a string containing the volume UUID on Linux, the partition UUID on MacOS and nothing on Windows.
package main

import (
    "fmt"

    "github.com/jaypipes/ghw"
)

func main() {
    block, err := ghw.Block()
    if err != nil {
        fmt.Printf("Error getting block storage info: %v", err)
    }

    fmt.Printf("%v\n", block)

    for _, disk := range block.Disks {
        fmt.Printf(" %v\n", disk)
        for _, part := range disk.Partitions {
            fmt.Printf("  %v\n", part)
        }
    }
}

Example output from my personal workstation:

block storage (1 disk, 2TB physical storage)
 sda HDD (2TB) SCSI [@pci-0000:04:00.0-scsi-0:1:0:0 (node #0)] vendor=LSI model=Logical_Volume serial=600508e000000000f8253aac9a1abd0c WWN=0x600508e000000000f8253aac9a1abd0c
  /dev/sda1 (100MB)
  /dev/sda2 (187GB)
  /dev/sda3 (449MB)
  /dev/sda4 (1KB)
  /dev/sda5 (15GB)
  /dev/sda6 (2TB) [ext4] mounted@/

Note that ghw looks in the udev runtime database for some information. If you are using ghw in a container, remember to bind mount /dev/disk and /run into your container, otherwise ghw won't be able to query the udev DB or sysfs paths for information.

Topology

NOTE: Topology support is currently Linux-only. Windows support is planned.

Information about the host computer's architecture (NUMA vs. SMP), the host's node layout and processor caches can be retrieved from the ghw.Topology() function. This function returns a pointer to a ghw.TopologyInfo struct.

The ghw.TopologyInfo struct contains two fields:

  • ghw.TopologyInfo.Architecture contains an enum with the value ghw.NUMA or ghw.SMP depending on what the topology of the system is
  • ghw.TopologyInfo.Nodes is an array of pointers to ghw.TopologyNode structs, one for each topology node (typically physical processor package) found by the system

Each ghw.TopologyNode struct contains the following fields:

  • ghw.TopologyNode.ID is the system's uint32 identifier for the node
  • ghw.TopologyNode.Cores is an array of pointers to ghw.ProcessorCore structs that are contained in this node
  • ghw.TopologyNode.Caches is an array of pointers to ghw.MemoryCache structs that represent the low-level caches associated with processors and cores on the system
  • ghw.TopologyNode.Distance is an array of distances between NUMA nodes as reported by the system.
  • ghw.TopologyNode.Memory is a struct describing the memory attached to this node. Please refer to the documentation of ghw.MemoryArea.

See above in the CPU section for information about the ghw.ProcessorCore struct and how to use and query it.

Each ghw.MemoryCache struct contains the following fields:

  • ghw.MemoryCache.Type is an enum that contains one of ghw.DATA, ghw.INSTRUCTION or ghw.UNIFIED depending on whether the cache stores CPU instructions, program data, or both
  • ghw.MemoryCache.Level is a positive integer indicating how close the cache is to the processor
  • ghw.MemoryCache.SizeBytes is an integer containing the number of bytes the cache can contain
  • ghw.MemoryCache.LogicalProcessors is an array of integers representing the logical processors that use the cache
package main

import (
    "fmt"

    "github.com/jaypipes/ghw"
)

func main() {
    topology, err := ghw.Topology()
    if err != nil {
        fmt.Printf("Error getting topology info: %v", err)
    }

    fmt.Printf("%v\n", topology)

    for _, node := range topology.Nodes {
        fmt.Printf(" %v\n", node)
        for _, cache := range node.Caches {
            fmt.Printf("  %v\n", cache)
        }
    }
}

Example output from my personal workstation:

topology SMP (1 nodes)
 node #0 (6 cores)
  L1i cache (32 KB) shared with logical processors: 3,9
  L1i cache (32 KB) shared with logical processors: 2,8
  L1i cache (32 KB) shared with logical processors: 11,5
  L1i cache (32 KB) shared with logical processors: 10,4
  L1i cache (32 KB) shared with logical processors: 0,6
  L1i cache (32 KB) shared with logical processors: 1,7
  L1d cache (32 KB) shared with logical processors: 11,5
  L1d cache (32 KB) shared with logical processors: 10,4
  L1d cache (32 KB) shared with logical processors: 3,9
  L1d cache (32 KB) shared with logical processors: 1,7
  L1d cache (32 KB) shared with logical processors: 0,6
  L1d cache (32 KB) shared with logical processors: 2,8
  L2 cache (256 KB) shared with logical processors: 2,8
  L2 cache (256 KB) shared with logical processors: 3,9
  L2 cache (256 KB) shared with logical processors: 0,6
  L2 cache (256 KB) shared with logical processors: 10,4
  L2 cache (256 KB) shared with logical processors: 1,7
  L2 cache (256 KB) shared with logical processors: 11,5
  L3 cache (12288 KB) shared with logical processors: 0,1,10,11,2,3,4,5,6,7,8,9

Network

Information about the host computer's networking hardware is returned from the ghw.Network() function. This function returns a pointer to a ghw.NetworkInfo struct.

The ghw.NetworkInfo struct contains one field:

  • ghw.NetworkInfo.NICs is an array of pointers to ghw.NIC structs, one for each network interface controller found for the systen

Each ghw.NIC struct contains the following fields:

  • ghw.NIC.Name is the system's identifier for the NIC
  • ghw.NIC.MacAddress is the MAC address for the NIC, if any
  • ghw.NIC.IsVirtual is a boolean indicating if the NIC is a virtualized device
  • ghw.NIC.Capabilities is an array of pointers to ghw.NICCapability structs that can describe the things the NIC supports. These capabilities match the returned values from the ethtool -k <DEVICE> call on Linux
  • ghw.NIC.PCIAddress is the PCI device address of the device backing the NIC. this is not-nil only if the backing device is indeed a PCI device; more backing devices (e.g. USB) will be added in future versions.

The ghw.NICCapability struct contains the following fields:

  • ghw.NICCapability.Name is the string name of the capability (e.g. "tcp-segmentation-offload")
  • ghw.NICCapability.IsEnabled is a boolean indicating whether the capability is currently enabled/active on the NIC
  • ghw.NICCapability.CanEnable is a boolean indicating whether the capability may be enabled
package main

import (
    "fmt"

    "github.com/jaypipes/ghw"
)

func main() {
    net, err := ghw.Network()
    if err != nil {
        fmt.Printf("Error getting network info: %v", err)
    }

    fmt.Printf("%v\n", net)

    for _, nic := range net.NICs {
        fmt.Printf(" %v\n", nic)

        enabledCaps := make([]int, 0)
        for x, cap := range nic.Capabilities {
            if cap.IsEnabled {
                enabledCaps = append(enabledCaps, x)
            }
        }
        if len(enabledCaps) > 0 {
            fmt.Printf("  enabled capabilities:\n")
            for _, x := range enabledCaps {
                fmt.Printf("   - %s\n", nic.Capabilities[x].Name)
            }
        }
    }
}

Example output from my personal laptop:

net (3 NICs)
 docker0
  enabled capabilities:
   - tx-checksumming
   - tx-checksum-ip-generic
   - scatter-gather
   - tx-scatter-gather
   - tx-scatter-gather-fraglist
   - tcp-segmentation-offload
   - tx-tcp-segmentation
   - tx-tcp-ecn-segmentation
   - tx-tcp-mangleid-segmentation
   - tx-tcp6-segmentation
   - udp-fragmentation-offload
   - generic-segmentation-offload
   - generic-receive-offload
   - tx-vlan-offload
   - highdma
   - tx-lockless
   - netns-local
   - tx-gso-robust
   - tx-fcoe-segmentation
   - tx-gre-segmentation
   - tx-gre-csum-segmentation
   - tx-ipxip4-segmentation
   - tx-ipxip6-segmentation
   - tx-udp_tnl-segmentation
   - tx-udp_tnl-csum-segmentation
   - tx-gso-partial
   - tx-sctp-segmentation
   - tx-esp-segmentation
   - tx-vlan-stag-hw-insert
 enp58s0f1
  enabled capabilities:
   - rx-checksumming
   - generic-receive-offload
   - rx-vlan-offload
   - tx-vlan-offload
   - highdma
 wlp59s0
  enabled capabilities:
   - scatter-gather
   - tx-scatter-gather
   - generic-segmentation-offload
   - generic-receive-offload
   - highdma
   - netns-local

PCI

ghw contains a PCI database inspection and querying facility that allows developers to not only gather information about devices on a local PCI bus but also query for information about hardware device classes, vendor and product information.

NOTE: Parsing of the PCI-IDS file database is provided by the separate github.com/jaypipes/pcidb library. You can read that library's README for more information about the various structs that are exposed on the ghw.PCIInfo struct.

The ghw.PCI() function returns a ghw.PCIInfo struct. The ghw.PCIInfo struct contains a number of fields that may be queried for PCI information:

  • ghw.PCIInfo.Devices is a slice of pointers to ghw.PCIDevice structs that describe the PCI devices on the host system
  • ghw.PCIInfo.Classes is a map, keyed by the PCI class ID (a hex-encoded string) of pointers to pcidb.Class structs, one for each class of PCI device known to ghw (DEPRECATED, will be removed in ghw v1.0. Use the github.com/jaypipes/pcidb library for exploring PCI database information)
  • ghw.PCIInfo.Vendors is a map, keyed by the PCI vendor ID (a hex-encoded string) of pointers to pcidb.Vendor structs, one for each PCI vendor known to ghw (DEPRECATED, will be removed in ghw v1.0. Use the github.com/jaypipes/pcidb library for exploring PCI database information)
  • ghw.PCIInfo.Products is a map, keyed by the PCI product ID (a hex-encoded string) of pointers to pcidb.Product structs, one for each PCI product known to ghw (DEPRECATED, will be removed in ghw v1.0. Use the github.com/jaypipes/pcidb library for exploring PCI database information)

NOTE: PCI products are often referred to by their "device ID". We use the term "product ID" in ghw because it more accurately reflects what the identifier is for: a specific product line produced by the vendor.

The ghw.PCIDevice struct has the following fields:

  • ghw.PCIDevice.Vendor is a pointer to a pcidb.Vendor struct that describes the device's primary vendor. This will always be non-nil.
  • ghw.PCIDevice.Product is a pointer to a pcidb.Product struct that describes the device's primary product. This will always be non-nil.
  • ghw.PCIDevice.Subsystem is a pointer to a pcidb.Product struct that describes the device's secondary/sub-product. This will always be non-nil.
  • ghw.PCIDevice.Class is a pointer to a pcidb.Class struct that describes the device's class. This will always be non-nil.
  • ghw.PCIDevice.Subclass is a pointer to a pcidb.Subclass struct that describes the device's subclass. This will always be non-nil.
  • ghw.PCIDevice.ProgrammingInterface is a pointer to a pcidb.ProgrammingInterface struct that describes the device subclass' programming interface. This will always be non-nil.
  • ghw.PCIDevice.Driver is a string representing the device driver the system is using to handle this device. Can be empty string if this information is not available. If the information is not available, this doesn't mean at all the device is not functioning, but only the fact ghw was not able to retrieve this information.

The ghw.PCIAddress (which is an alias for the ghw.pci.address.Address struct) contains the PCI address fields. It has a ghw.PCIAddress.String() method that returns the canonical Domain:Bus:Device.Function ([D]BDF) representation of this Address.

The ghw.PCIAddress struct has the following fields:

  • ghw.PCIAddress.Domain is a string representing the PCI domain component of the address.
  • ghw.PCIAddress.Bus is a string representing the PCI bus component of the address.
  • ghw.PCIAddress.Device is a string representing the PCI device component of the address.
  • ghw.PCIAddress.Function is a string representing the PCI function component of the address.

NOTE: Older versions (pre-v0.9.0) erroneously referred to the Device field as the Slot field. As noted by @pearsonk in #220, this was a misnomer.

Finding a PCI device by PCI address

In addition to the above information, the ghw.PCIInfo struct has the following method:

  • ghw.PCIInfo.GetDevice(address string)

The following code snippet shows how to call the ghw.PCIInfo.ListDevices() method and output a simple list of PCI address and vendor/product information:

package main

import (
    "fmt"

    "github.com/jaypipes/ghw"
)

func main() {
    pci, err := ghw.PCI()
    if err != nil {
        fmt.Printf("Error getting PCI info: %v", err)
    }
    fmt.Printf("host PCI devices:\n")
    fmt.Println("====================================================")

    for _, device := range pci.Devices {
        vendor := device.Vendor
        vendorName := vendor.Name
        if len(vendor.Name) > 20 {
            vendorName = string([]byte(vendorName)[0:17]) + "..."
        }
        product := device.Product
        productName := product.Name
        if len(product.Name) > 40 {
            productName = string([]byte(productName)[0:37]) + "..."
        }
        fmt.Printf("%-12s\t%-20s\t%-40s\n", device.Address, vendorName, productName)
    }
}

on my local workstation the output of the above looks like the following:

host PCI devices:
====================================================
0000:00:00.0    Intel Corporation       5520/5500/X58 I/O Hub to ESI Port
0000:00:01.0    Intel Corporation       5520/5500/X58 I/O Hub PCI Express Roo...
0000:00:02.0    Intel Corporation       5520/5500/X58 I/O Hub PCI Express Roo...
0000:00:03.0    Intel Corporation       5520/5500/X58 I/O Hub PCI Express Roo...
0000:00:07.0    Intel Corporation       5520/5500/X58 I/O Hub PCI Express Roo...
0000:00:10.0    Intel Corporation       7500/5520/5500/X58 Physical and Link ...
0000:00:10.1    Intel Corporation       7500/5520/5500/X58 Routing and Protoc...
0000:00:14.0    Intel Corporation       7500/5520/5500/X58 I/O Hub System Man...
0000:00:14.1    Intel Corporation       7500/5520/5500/X58 I/O Hub GPIO and S...
0000:00:14.2    Intel Corporation       7500/5520/5500/X58 I/O Hub Control St...
0000:00:14.3    Intel Corporation       7500/5520/5500/X58 I/O Hub Throttle R...
0000:00:19.0    Intel Corporation       82567LF-2 Gigabit Network Connection
0000:00:1a.0    Intel Corporation       82801JI (ICH10 Family) USB UHCI Contr...
0000:00:1a.1    Intel Corporation       82801JI (ICH10 Family) USB UHCI Contr...
0000:00:1a.2    Intel Corporation       82801JI (ICH10 Family) USB UHCI Contr...
0000:00:1a.7    Intel Corporation       82801JI (ICH10 Family) USB2 EHCI Cont...
0000:00:1b.0    Intel Corporation       82801JI (ICH10 Family) HD Audio Contr...
0000:00:1c.0    Intel Corporation       82801JI (ICH10 Family) PCI Express Ro...
0000:00:1c.1    Intel Corporation       82801JI (ICH10 Family) PCI Express Po...
0000:00:1c.4    Intel Corporation       82801JI (ICH10 Family) PCI Express Ro...
0000:00:1d.0    Intel Corporation       82801JI (ICH10 Family) USB UHCI Contr...
0000:00:1d.1    Intel Corporation       82801JI (ICH10 Family) USB UHCI Contr...
0000:00:1d.2    Intel Corporation       82801JI (ICH10 Family) USB UHCI Contr...
0000:00:1d.7    Intel Corporation       82801JI (ICH10 Family) USB2 EHCI Cont...
0000:00:1e.0    Intel Corporation       82801 PCI Bridge
0000:00:1f.0    Intel Corporation       82801JIR (ICH10R) LPC Interface Contr...
0000:00:1f.2    Intel Corporation       82801JI (ICH10 Family) SATA AHCI Cont...
0000:00:1f.3    Intel Corporation       82801JI (ICH10 Family) SMBus Controller
0000:01:00.0    NEC Corporation         uPD720200 USB 3.0 Host Controller
0000:02:00.0    Marvell Technolog...    88SE9123 PCIe SATA 6.0 Gb/s controller
0000:02:00.1    Marvell Technolog...    88SE912x IDE Controller
0000:03:00.0    NVIDIA Corporation      GP107 [GeForce GTX 1050 Ti]
0000:03:00.1    NVIDIA Corporation      UNKNOWN
0000:04:00.0    LSI Logic / Symbi...    SAS2004 PCI-Express Fusion-MPT SAS-2 ...
0000:06:00.0    Qualcomm Atheros        AR5418 Wireless Network Adapter [AR50...
0000:08:03.0    LSI Corporation         FW322/323 [TrueFire] 1394a Controller
0000:3f:00.0    Intel Corporation       UNKNOWN
0000:3f:00.1    Intel Corporation       Xeon 5600 Series QuickPath Architectu...
0000:3f:02.0    Intel Corporation       Xeon 5600 Series QPI Link 0
0000:3f:02.1    Intel Corporation       Xeon 5600 Series QPI Physical 0
0000:3f:02.2    Intel Corporation       Xeon 5600 Series Mirror Port Link 0
0000:3f:02.3    Intel Corporation       Xeon 5600 Series Mirror Port Link 1
0000:3f:03.0    Intel Corporation       Xeon 5600 Series Integrated Memory Co...
0000:3f:03.1    Intel Corporation       Xeon 5600 Series Integrated Memory Co...
0000:3f:03.4    Intel Corporation       Xeon 5600 Series Integrated Memory Co...
0000:3f:04.0    Intel Corporation       Xeon 5600 Series Integrated Memory Co...
0000:3f:04.1    Intel Corporation       Xeon 5600 Series Integrated Memory Co...
0000:3f:04.2    Intel Corporation       Xeon 5600 Series Integrated Memory Co...
0000:3f:04.3    Intel Corporation       Xeon 5600 Series Integrated Memory Co...
0000:3f:05.0    Intel Corporation       Xeon 5600 Series Integrated Memory Co...
0000:3f:05.1    Intel Corporation       Xeon 5600 Series Integrated Memory Co...
0000:3f:05.2    Intel Corporation       Xeon 5600 Series Integrated Memory Co...
0000:3f:05.3    Intel Corporation       Xeon 5600 Series Integrated Memory Co...
0000:3f:06.0    Intel Corporation       Xeon 5600 Series Integrated Memory Co...
0000:3f:06.1    Intel Corporation       Xeon 5600 Series Integrated Memory Co...
0000:3f:06.2    Intel Corporation       Xeon 5600 Series Integrated Memory Co...
0000:3f:06.3    Intel Corporation       Xeon 5600 Series Integrated Memory Co...

The following code snippet shows how to call the ghw.PCIInfo.GetDevice() method and use its returned ghw.PCIDevice struct pointer:

package main

import (
    "fmt"
    "os"

    "github.com/jaypipes/ghw"
)

func main() {
    pci, err := ghw.PCI()
    if err != nil {
        fmt.Printf("Error getting PCI info: %v", err)
    }

    addr := "0000:00:00.0"
    if len(os.Args) == 2 {
        addr = os.Args[1]
    }
    fmt.Printf("PCI device information for %s\n", addr)
    fmt.Println("====================================================")
    deviceInfo := pci.GetDevice(addr)
    if deviceInfo == nil {
        fmt.Printf("could not retrieve PCI device information for %s\n", addr)
        return
    }

    vendor := deviceInfo.Vendor
    fmt.Printf("Vendor: %s [%s]\n", vendor.Name, vendor.ID)
    product := deviceInfo.Product
    fmt.Printf("Product: %s [%s]\n", product.Name, product.ID)
    subsystem := deviceInfo.Subsystem
    subvendor := pci.Vendors[subsystem.VendorID]
    subvendorName := "UNKNOWN"
    if subvendor != nil {
        subvendorName = subvendor.Name
    }
    fmt.Printf("Subsystem: %s [%s] (Subvendor: %s)\n", subsystem.Name, subsystem.ID, subvendorName)
    class := deviceInfo.Class
    fmt.Printf("Class: %s [%s]\n", class.Name, class.ID)
    subclass := deviceInfo.Subclass
    fmt.Printf("Subclass: %s [%s]\n", subclass.Name, subclass.ID)
    progIface := deviceInfo.ProgrammingInterface
    fmt.Printf("Programming Interface: %s [%s]\n", progIface.Name, progIface.ID)
}

Here's a sample output from my local workstation:

PCI device information for 0000:03:00.0
====================================================
Vendor: NVIDIA Corporation [10de]
Product: GP107 [GeForce GTX 1050 Ti] [1c82]
Subsystem: UNKNOWN [8613] (Subvendor: ASUSTeK Computer Inc.)
Class: Display controller [03]
Subclass: VGA compatible controller [00]
Programming Interface: VGA controller [00]

GPU

Information about the host computer's graphics hardware is returned from the ghw.GPU() function. This function returns a pointer to a ghw.GPUInfo struct.

The ghw.GPUInfo struct contains one field:

  • ghw.GPUInfo.GraphicCards is an array of pointers to ghw.GraphicsCard structs, one for each graphics card found for the systen

Each ghw.GraphicsCard struct contains the following fields:

  • ghw.GraphicsCard.Index is the system's numeric zero-based index for the card on the bus
  • ghw.GraphicsCard.Address is the PCI address for the graphics card
  • ghw.GraphicsCard.DeviceInfo is a pointer to a ghw.PCIDevice struct describing the graphics card. This may be nil if no PCI device information could be determined for the card.
  • ghw.GraphicsCard.Node is an pointer to a ghw.TopologyNode struct that the GPU/graphics card is affined to. On non-NUMA systems, this will always be nil.
package main

import (
    "fmt"

    "github.com/jaypipes/ghw"
)

func main() {
    gpu, err := ghw.GPU()
    if err != nil {
        fmt.Printf("Error getting GPU info: %v", err)
    }

    fmt.Printf("%v\n", gpu)

    for _, card := range gpu.GraphicsCards {
        fmt.Printf(" %v\n", card)
    }
}

Example output from my personal workstation:

gpu (1 graphics card)
 card #0 @0000:03:00.0 -> class: 'Display controller' vendor: 'NVIDIA Corporation' product: 'GP107 [GeForce GTX 1050 Ti]'

NOTE: You can read more about the fields of the ghw.PCIDevice struct if you'd like to dig deeper into PCI subsystem and programming interface information

NOTE: You can read more about the fields of the ghw.TopologyNode struct if you'd like to dig deeper into the NUMA/topology subsystem

Chassis

The host's chassis information is accessible with the ghw.Chassis() function. This function returns a pointer to a ghw.ChassisInfo struct.

The ghw.ChassisInfo struct contains multiple fields:

  • ghw.ChassisInfo.AssetTag is a string with the chassis asset tag
  • ghw.ChassisInfo.SerialNumber is a string with the chassis serial number
  • ghw.ChassisInfo.Type is a string with the chassis type code
  • ghw.ChassisInfo.TypeDescription is a string with a description of the chassis type
  • ghw.ChassisInfo.Vendor is a string with the chassis vendor
  • ghw.ChassisInfo.Version is a string with the chassis version

NOTE: These fields are often missing for non-server hardware. Don't be surprised to see empty string or "None" values.

package main

import (
    "fmt"

    "github.com/jaypipes/ghw"
)

func main() {
    chassis, err := ghw.Chassis()
    if err != nil {
        fmt.Printf("Error getting chassis info: %v", err)
    }

    fmt.Printf("%v\n", chassis)
}

Example output from my personal workstation:

chassis type=Desktop vendor=System76 version=thelio-r1

NOTE: Some of the values such as serial numbers are shown as unknown because the Linux kernel by default disallows access to those fields if you're not running as root. They will be populated if it runs as root or otherwise you may see warnings like the following:

WARNING: Unable to read chassis_serial: open /sys/class/dmi/id/chassis_serial: permission denied

You can ignore them or use the Disabling warning messages feature to quiet things down.

BIOS

The host's basis input/output system (BIOS) information is accessible with the ghw.BIOS() function. This function returns a pointer to a ghw.BIOSInfo struct.

The ghw.BIOSInfo struct contains multiple fields:

  • ghw.BIOSInfo.Vendor is a string with the BIOS vendor
  • ghw.BIOSInfo.Version is a string with the BIOS version
  • ghw.BIOSInfo.Date is a string with the date the BIOS was flashed/created
package main

import (
    "fmt"

    "github.com/jaypipes/ghw"
)

func main() {
    bios, err := ghw.BIOS()
    if err != nil {
        fmt.Printf("Error getting BIOS info: %v", err)
    }

    fmt.Printf("%v\n", bios)
}

Example output from my personal workstation:

bios vendor=System76 version=F2 Z5 date=11/14/2018

Baseboard

The host's baseboard information is accessible with the ghw.Baseboard() function. This function returns a pointer to a ghw.BaseboardInfo struct.

The ghw.BaseboardInfo struct contains multiple fields:

  • ghw.BaseboardInfo.AssetTag is a string with the baseboard asset tag
  • ghw.BaseboardInfo.SerialNumber is a string with the baseboard serial number
  • ghw.BaseboardInfo.Vendor is a string with the baseboard vendor
  • ghw.BaseboardInfo.Product is a string with the baseboard name on Linux and Product on Windows
  • ghw.BaseboardInfo.Version is a string with the baseboard version

NOTE: These fields are often missing for non-server hardware. Don't be surprised to see empty string or "None" values.

package main

import (
    "fmt"

    "github.com/jaypipes/ghw"
)

func main() {
    baseboard, err := ghw.Baseboard()
    if err != nil {
        fmt.Printf("Error getting baseboard info: %v", err)
    }

    fmt.Printf("%v\n", baseboard)
}

Example output from my personal workstation:

baseboard vendor=System76 version=thelio-r1

NOTE: Some of the values such as serial numbers are shown as unknown because the Linux kernel by default disallows access to those fields if you're not running as root. They will be populated if it runs as root or otherwise you may see warnings like the following:

WARNING: Unable to read board_serial: open /sys/class/dmi/id/board_serial: permission denied

You can ignore them or use the Disabling warning messages feature to quiet things down.

Product

The host's product information is accessible with the ghw.Product() function. This function returns a pointer to a ghw.ProductInfo struct.

The ghw.ProductInfo struct contains multiple fields:

  • ghw.ProductInfo.Family is a string describing the product family
  • ghw.ProductInfo.Name is a string with the product name
  • ghw.ProductInfo.SerialNumber is a string with the product serial number
  • ghw.ProductInfo.UUID is a string with the product UUID
  • ghw.ProductInfo.SKU is a string with the product stock unit identifier (SKU)
  • ghw.ProductInfo.Vendor is a string with the product vendor
  • ghw.ProductInfo.Version is a string with the product version

NOTE: These fields are often missing for non-server hardware. Don't be surprised to see empty string, "Default string" or "None" values.

package main

import (
    "fmt"

    "github.com/jaypipes/ghw"
)

func main() {
    product, err := ghw.Product()
    if err != nil {
        fmt.Printf("Error getting product info: %v", err)
    }

    fmt.Printf("%v\n", product)
}

Example output from my personal workstation:

product family=Default string name=Thelio vendor=System76 sku=Default string version=thelio-r1

NOTE: Some of the values such as serial numbers are shown as unknown because the Linux kernel by default disallows access to those fields if you're not running as root. They will be populated if it runs as root or otherwise you may see warnings like the following:

WARNING: Unable to read product_serial: open /sys/class/dmi/id/product_serial: permission denied

You can ignore them or use the Disabling warning messages feature to quiet things down.

Serialization

All of the ghw XXXInfo structs -- e.g. ghw.CPUInfo -- have two methods for producing a serialized JSON or YAML string representation of the contained information:

  • JSONString() returns a string containing the information serialized into JSON. It accepts a single boolean parameter indicating whether to use indentation when outputting the string
  • YAMLString() returns a string containing the information serialized into YAML
package main

import (
    "fmt"

    "github.com/jaypipes/ghw"
)

func main() {
    mem, err := ghw.Memory()
    if err != nil {
        fmt.Printf("Error getting memory info: %v", err)
    }

    fmt.Printf("%s", mem.YAMLString())
}

the above example code prints the following out on my local workstation:

memory:
  supported_page_sizes:
  - 1073741824
  - 2097152
  total_physical_bytes: 25263415296
  total_usable_bytes: 25263415296

Calling external programs

By default ghw may call external programs, for example ethtool, to learn about hardware capabilities. In some rare circumstances it may be useful to opt out from this behaviour and rely only on the data provided by pseudo-filesystems, like sysfs. The most common use case is when we want to consume a snapshot from ghw. In these cases the information provided by tools will be most likely inconsistent with the data from the snapshot - they will run on a different host! To prevent ghw from calling external tools, set the environs variable GHW_DISABLE_TOOLS to any value, or, programmatically, check the WithDisableTools function. The default behaviour of ghw is to call external tools when available.

WARNING:

  • on all platforms, disabling external tools make ghw return less data. Unless noted otherwise, there is no fallback flow if external tools are disabled.
  • on darwin, disabling external tools disable block support entirely

Developers

Contributions to ghw are welcomed! Fork the repo on GitHub and submit a pull request with your proposed changes. Or, feel free to log an issue for a feature request or bug report.

Running tests

You can run unit tests easily using the make test command, like so:

[jaypipes@uberbox ghw]$ make test
go test github.com/jaypipes/ghw github.com/jaypipes/ghw/cmd/ghwc
ok      github.com/jaypipes/ghw 0.084s
?       github.com/jaypipes/ghw/cmd/ghwc    [no test files]

Author: Jaypipes
Source Code: https://github.com/jaypipes/ghw 
License: Apache-2.0 License

#go #golang #hardware 

Ghw: Golang Hardware Discovery/inspection Library

Montando um PC COMPLETO por MENOS de R$ 1.500 💸 - Raspberry Pi 4 com Teclado e Mouse

Montando um PC COMPLETO por MENOS de R$ 1.500 💸 - Raspberry Pi 4 com Teclado e Mouse

Montar um PC completo, com teclado e mouse pode ser um grande desafio nos dias de hoje quando o orçamento é apertado. O Raspberry Pi é considerado por muitos uma ferramenta de acessibilidade, e apesar de ser mais caro no Brasil do que no exterior, o Raspberry Pi 4 Modelo B pode ser uma ótima alternativa para quem precisa de computador funcional, para estudar, navegar na internet e até mesmo jogar.

📎 𝗙𝗼𝗻𝘁𝗲𝘀 𝗲 𝗟𝗶𝗻𝗸𝘀:
‣ Download do Rasbperry Pi Imager: https://www.raspberrypi.com/software/

#hardware #software #raspberrypi #linux 

Montando um PC COMPLETO por MENOS de R$ 1.500 💸 - Raspberry Pi 4 com Teclado e Mouse

Rapid Open Hardware Development (ROHD) Framework

Rapid Open Hardware Development (ROHD) Framework

Describing Hardware in Dart with ROHD

ROHD (pronounced like "road") is a framework for describing and verifying hardware in the Dart programming language. ROHD enables you to build and traverse a graph of connectivity between module objects using unrestricted software.

Features of ROHD include:

  • Full power of the modern Dart language for hardware design and verification
  • Makes validation collateral simpler to develop and debug. The ROHD Verification Framework helps build well-structured testbenches.
  • Develop layers of abstraction within a hardware design, making it more flexible and powerful
  • Easy IP integration and interfaces; using an IP is as easy as an import. Reduces tedious, redundant, and error prone aspects of integration
  • Simple and fast build, free of complex build systems and EDA vendor tools
  • Can use the excellent pub.dev package manager and all the packages it has to offer
  • Built-in event-based fast simulator with 4-value (0, 1, X, and Z) support and a waveform dumper to .vcd file format
  • Conversion of modules to equivalent, human-readable, structurally similar SystemVerilog for integration or downstream tool consumption
  • Run-time dynamic module port definitions (numbers, names, widths, etc.) and internal module logic, including recursive module contents
  • Simple, free, open source tool stack without any headaches from library dependencies, file ordering, elaboration/analysis options, +defines, etc.
  • Excellent, simple, fast unit-testing framework
  • Less verbose than alternatives (fewer lines of code)
  • Enables higher quality development
  • Replaces hacky perl/python scripting for automation with powerful native control of design generation
  • Fewer bugs and lines of code means shorter development schedule
  • Support for cosimulation with verilog modules and instantiation of verilog modules in generated SystemVerilog code
  • Use modern IDEs like Visual Studio Code, with excellent static analysis, fast autocomplete, built-in debugger, linting, git integration, extensions, and much more
  • Simulate with various abstraction levels of models from architectural, to functional, to cycle-accurate, to RTL levels in the same language and environment.

ROHD is not a new language, it is not a hardware description language (HDL), and it is not a version of High-Level Synthesis (HLS). ROHD can be classified as a generator framework.

You can think of this project as an attempt to replace SystemVerilog and related build systems as the front-end methodology of choice in the industry.

One of ROHD's goals is to help grow an open-source community around reusable hardware designs and verification components.

Why Dart?

Dart is a modern, relatively new language developed by Google. It is designed with client-side application development in mind (e.g. apps and websites), but also has great performance for general tasks. It adopts some of the most loved syntax and features from languages like C++, Java, C#, JavaScript/TypeScript, and Kotlin. Dart is extremely user-friendly, fun to use, and easy to learn. The excellent, fast static analysis with a modern IDE with autocomplete makes it easy to learn as you work. Dart has a lot of great modern language features, including null safety.

Because it is designed with asynchronous requests in mind (i.e. sending a request to a server and not freezing the application while it waits for a response), Dart has async/await and Futures built in, with concurrent programming using isolates. These constructs enable code to execute in parallel without multithreading. These chacteristics make modelling hardware very easy.

Dart can compile to native machine code, but also includes its own high-performance VM and a JIT compiler. During development, you can use a feature called "hot reload" to change code while the program is actively executing.

Dart has an excellent package manager called "pub" (https://pub.dev). It is possible to host a private Dart Pub server for packages that shouldn't be shared broadly (e.g. Top-Secret IP).

The Challenge of Justifying Trying a New Language

This StackOverflow answer about why it's worth trying Chisel (an alternative to ROHD) contains valuable insight into why it is difficult in general to justify a new language to someone who hasn't used it before:

Language power is notoriously difficult to objectively evaluate. Paul Graham describes this as the "Blub Paradox" in his "Beating the Averages" essay. Graham's thesis is that an engineer proficient in a less powerful language cannot evaluate the utility of a more powerful language.

If you're thinking "SystemVerilog is just fine, I don't need something new", it is worth reading either or both of the StackOverflow answer and the Paul Graham essay.

More Information on Dart

Try out Dart instantly from your browser here: https://dartpad.dev/?null_safety=true

See some Dart language samples here: https://dart.dev/samples

For more information on Dart and tutorials, see https://dart.dev/ and https://dart.dev/overview

Development Recommendations

Getting started

Once you have Dart installed, if you don't already have a project, you can create one using dart create: https://dart.dev/tools/dart-tool

Then add ROHD as a dependency to your pubspec.yaml file. ROHD is registered on pub.dev. The easiest way to add ROHD as a dependency is following the instructions here https://pub.dev/packages/rohd/install.

Now you can import it in your project using:

import 'package:rohd/rohd.dart';

There are complete API docs available at https://intel.github.io/rohd/rohd/rohd-library.html.

If you need some help, you can visit our Discussions page. This is a friendly place where you can ask questions, share ideas, or just discuss openly! You could also head to StackOverflow.com (use the tag rohd) to ask questions or look for answers.

You also may be interested to join the ROHD Forum periodic meetings with other users and developers in the ROHD community. The meetings are open to anyone interested!

Be sure to note the minimum Dart version required for ROHD specified in pubspec.yaml (at least 2.14.0). If you're using the version of Dart that came with Flutter, it might be older than that.

Package Managers for Hardware

In the Dart ecosystem, you can use a package manager to define all package dependencies. A package manager allows you to define constrainted subsets of versions of all your direct dependencies, and then the tool will solve for a coherent set of all (direct and indirect) dependencies required to build your project. There's no need to manually figure out tool versions, build flags and options, environment setup, etc. because it is all guaranteed to work. Integration of other packages (whether a tool or a hardware IP) become as simple as an import statment. Compare that to SystemVerilog IP integration!

Read more about package managers here: https://en.wikipedia.org/wiki/Package_manager
Take a look at Dart's package manager, pub.dev, here: https://pub.dev

ROHD Syntax and Examples

The below subsections offer some examples of implementations and syntax in ROHD.

A full example of a counter module

To get a quick feel for what ROHD looks like, below is an example of what a simple counter module looks like in ROHD.

// Import the ROHD package
import 'package:rohd/rohd.dart';

// Define a class Counter that extends ROHD's abstract Module class
class Counter extends Module {

  // For convenience, map interesting outputs to short variable names for consumers of this module
  Logic get val => output('val');

  // This counter supports any width, determined at run-time
  final int width;
  Counter(Logic en, Logic reset, Logic clk, {this.width=8, String name='counter'}) : super(name: name) {
    // Register inputs and outputs of the module in the constructor.
    // Module logic must consume registered inputs and output to registered outputs.
    en    = addInput('en', en);
    reset = addInput('reset', reset);
    clk   = addInput('clk', clk);

    var val = addOutput('val', width: width);

    // A local signal named 'nextVal'
    var nextVal = Logic(name: 'nextVal', width: width);
    
    // Assignment statement of nextVal to be val+1 (<= is the assignment operator)
    nextVal <= val + 1;

    // `Sequential` is like SystemVerilog's always_ff, in this case trigger on the positive edge of clk
    Sequential(clk, [
      // `If` is a conditional if statement, like `if` in SystemVerilog always blocks
      If(reset, then:[
        // the '<' operator is a conditional assignment
        val < 0
      ], orElse: [If(en, then: [
        val < nextVal
      ])])
    ]);
  }
}

You can find an executable version of this counter example in example/example.dart.

A more complex example

See a more advanced example of a logarithmic-depth tree of arbitrary functionality at doc/TreeExample.md.

You can find an executable version of the tree example in example/tree.dart.

Logical signals

The fundamental signal building block in ROHD is called Logic.

// a one bit, unnamed signal
var x = Logic();

// an 8-bit bus named 'b'
var bus = Logic(name: 'b', width: 8)

The value of a signal

You can access the current value of a signal using value. You cannot access this as part of synthesizable ROHD code. ROHD supports X and Z values and propogation. If the signal is valid (no X or Z in it), you can also convert it to an int with valueInt (ROHD will throw an exception otherwise). If the signal has more bits than a dart int (64 bits, usually), you need to use valueBigInt to get a BigInt (again, ROHD will throw an exception otherwise).

Bits of a Logic are of type LogicValue, with pre-defined constant enum values x, z, one, and zero. The value of a Logic is represented by a LogicValues, which behaves like a collection of LogicValues. Both LogicValue and LogicValues have a number of built-in logical operations (like &, |, ^, +, -, etc.).

var x = Logic(width:2);

// a LogicValues
x.value

// an int
x.valueInt

// a BigInt
x.valueBigInt

You can create LogicValuess using a variety of constructors including fromInt, fromBigInt, filled (like '0, '1, 'x, etc. in SystemVerilog), and from (which takes any Iterable<LogicValue>).

Listening to and waiting for changes

You can trigger on changes of Logics with some built in events. ROHD uses dart synchronous streams for events.

There are three testbench-consumable streams built-in to ROHD Logics: changed, posedge, and negedge. You can use listen to trigger something every time the edge transitions. Note that this is not synthesizable by ROHD and should not be confused with a synthesizable always(@) type of statement. Event arguments passed to listeners are of type LogicValueChanged, which has information about the previousValue and newValue.

Logic mySignal;
...
mySignal.posedge.listen((args) {
  print("mySignal was ${args.previousValue} before, but there was a positive edge and the new value is ${args.newValue}");
});

You can also use helper getters nextChanged, nextPosedge, and nextNegedge which return Future<LogicValueChanged>. You can think of these as similar to something like @(posedge mySignal); in SystemVerilog testbench code. Again, these are not something that should be included in synthesizable ROHD hardware.

Constants

Constants can often be inferred by ROHD automatically, but can also be explicitly defined using Const, which extends Logic.

// a 16 bit constant with value 5
var x = Const(5, width:16);

There is a convenience function for converting binary to an integer:

// this is equvialent to and shorter than int.parse('010101', radix:2)
bin('010101')

Assignment

To assign one signal to the value of another signal, use the <= operator. This is a hardware synthesizable assignment connecting two wires together.

var a = Logic(), b = Logic();
// assign a to always have the same value as b
a <= b;

Simple logical, mathematical, and comparison operations

Logical operations on signals are very similar to those in SystemVerilog.

a_bar     <=  ~a;      // not
a_and_b   <=  a & b;   // and
a_or_b    <=  a | b;   // or
a_xor_b   <=  a ^ b;   // xor
and_a     <=  a.and(); // unary and
or_a      <=  a.or();  // unary or
xor_a     <=  a.xor(); // unary xor
a_plus_b  <=  a + b;   // addition
a_sub_b   <=  a - b;   // subtraction
a_times_b <=  a * b;   // multiplication
a_div_b   <=  a / b;   // division
a_eq_b    <=  a.eq(b)  // equality              NOTE: == is for Object equality of Logic's
a_lt_b    <=  a.lt(b)  // less than             NOTE: <  is for conditional assignment
a_lte_b   <=  a.lte(b) // less than or equal    NOTE: <= is for assignment
a_gt_b    <=  (a > b)  // greater than          NOTE: careful with order of operations, > needs parentheses in this case
a_gte_b   <=  (a >= b) // greater than or equal NOTE: careful with order of operations, >= needs parentheses in this case

Shift Operations

Dart has implemented the triple shift operator (>>>) in the opposite way as is implemented in SystemVerilog. That is to say in Dart, >>> means logical shift right (fill with 0's), and >> means arithmetic shift right (maintaining sign). ROHD keeps consistency with Dart's implementation to avoid introducing confusion within Dart code you write (whether ROHD or plain Dart).

a << b    // logical shift left
a >> b    // arithmetic shift right
a >>> b   // logical shift right

Bus ranges and swizzling

Multi-bit busses can be accessed by single bits and ranges or composed from multiple other signals.

var a = Logic(width:8),
    b = Logic(width:3),
    c = Const(7, width:5),
    d = Logic(),
    e = Logic(width: 9);


// assign b to the bottom 3 bits of a
b <= a.slice(2,0);

// assign d to the top bit of a
d <= a[7];

// construct e by swizzling bits from b, c, and d
// here, the MSB is on the left, LSB is on the right
e <= [d, c, b].swizzle();

// alternatively, do a reverse swizzle (useful for lists where 0-index is actually the 0th element)
// here, the LSB is on the left, the MSB is on the right
e <= [b, c, d].rswizzle();

ROHD does not (currently) support assignment to a subset of a bus. That is, you cannot do something like e[3] <= d. If you need to build a bus from a collection of other signals, use swizzling.

Modules

Modules are similar to modules in SystemVerilog. They have inputs and outputs and logic that connects them. There are a handful of rules that must be followed when implementing a module.

  1. All logic within a Module must consume only inputs (from the input or addInput methods) to the Module either directly or indirectly.
  2. Any logic outside of a Module must consume the signals only via outputs (from the output or addOutput methods) of the Module.
  3. Logic must be defined before the call to super.build(), which always must be called at the end of the build() method if it is overidden.

The reasons for these rules have to do with how ROHD is able to determine which logic and Modules exist within a given Module and how ROHD builds connectivity. If these rules are not followed, generated outputs (including waveforms and SystemVerilog) may be unpredictable.

You should strive to build logic within the constructor of your Module (directly or via method calls within the constructor). This way any code can utilize your Module immediately after creating it. Be careful to consume the registered inputs and drive the registered outputs of your module, and not the "raw" parameters.

It is legal to put logic within an override of the build function, but that forces users of your module to always call build before it will be functionally usable for simple simulation. If you put logic in build(), ensure you put the call to super.build() at the end of the method.

Note that the build() method returns a Future<void>, not just void. This is because the build() method is permitted to consume real wallclock time in some cases, for example for setting up cosimulation with another simulator. If you expect your build to consume wallclock time, make sure the Simulator is aware it needs to wait before proceeding.

It is not necessary to put all logic directly within a class that extends Module. You can put synthesizable logic in other functions and classes, as long as the logic eventually connects to an input or output of a module if you hope to convert it to SystemVerilog. Except where there is a desire for the waveforms and SystemVerilog generated to have module hierarchy, it is not necessary to use submodules within modules instead of plain classes or functions.

The Module base class has an optional String argument 'name' which is an instance name.

Modules have the below basic structure:

// class must extend Module to be a Module
class MyModule extends Module {
    
    // constructor
    MyModule(Logic in1, {String name='mymodule'}) : super(name: name) {
        // add inputs in the constructor, passing in the Logic it is connected to
        // it's a good idea to re-set the input parameters so you don't accidentally use the wrong one
        in1 = addInput('in1', in1);

        // add outputs in the constructor as well
        // you can capture the output variable to a local variable for use
        var out = addOutput('out');

        // now you can define your logic
        // this example is just a passthrough from 'in1' to 'out'
        out <= in1;
    }
}

All gates or functionality apart from assign statements in ROHD are implemented using Modules.

Inputs, outputs, widths, and getters

The default width of an input and output is 1. You can control the width of ports using the width argument of addInput() and addOutput(). You may choose to set them to a static number, based on some other variable, or even dynamically based on the width of input parameters. These functions also return the input/output signal.

It can be convenient to use dart getters for signal names so that accessing inputs and outputs of a module doesn't require calling input() and output() every time. It also makes it easier to consume your module.

Below are some examples of inputs and outputs in a Module.

class MyModule extends Module {

    MyModule(Logic a, Logic b, Logic c, {int xWidth=5}) {
        
        // 'a' should always be width 4, throw an exception if its wrong
        if(a.width != 4) throw Exception('Width of a must be 4!');
        addInput('a', a, width: 4);

        // allow 'b' to always be any width, based on what's passed in
        addInput('b', b, width: b.width);

        // default width is 1, so 'c' is 1 bit
        // addInput returns the value of input('c'), if you want it
        var c_input = addInput('c', c)

        // set the width of 'x' based on the constructor argument
        addOutput('x', width: xWidth);

        // you can dynamically set the output width based on an input width, as well
        // addOutput returns the value of output('y'), if you want it
        var y_output = addOutput('y', width: b.width);
    }

    // A verbose getter of the value of input 'a'
    Logic get a {
      return input('a');
    }
    
    // Dart shorthand makes getters less verbose, but the functionality is the same as above
    Logic get b => input('b');
    Logic get x => output('x');
    Logic get y => output('y');

    // it is not necessary to have all signals accessible through getters, here we omit 'c'

}

Sequentials

ROHD has a basic FlipFlop module that can be used as a flip flop. For more complex sequential logic, use the Sequential block described in the Conditionals section.

Dart doesn't have a notion of certain signals being "clocks" vs. "not clocks". You can use any signal as a clock input to sequential logic, and have as many clocks of as many frequencies as you want.

Conditionals

ROHD supports a variety of Conditional type statements that always must fall within a type of _Always block, similar to SystemVerilog. There are two types of _Always blocks: Sequential and Combinational, which map to SystemVerilog's always_ff and always_comb, respectively. Combinational takes a list of Conditional statements. Different kinds of Conditional statement, such as If, may be composed of more Conditional statements. You can create Conditional composition chains as deep as you like.

Conditional statements are executed imperatively and in order, just like the contents of always blocks in SystemVerilog. _Always blocks in ROHD map 1-to-1 with SystemVerilog always statements when converted.

Assignments within an _Always should be executed conditionally, so use the < operator which creates a ConditionalAssign object instead of <=.

If

Below is an example of an If statement in ROHD:

Combinational([
  If(a, then: [
      y < a,
      z < b,
      x < a & b,
      q < d,
  ], orElse: [ If(b, then: [
      y < b,
      z < a,
      q < 13,
  ], orElse: [
      y < 0,
      z < 1,
  ])])
]);

IfBlock

The IfBlock makes syntax for long chains of if / else if / else chains nicer. For example:

Sequential(clk, [
  IfBlock([
    // the first one must be Iff (yes, with 2 f's, to differentiate from If above)
    Iff(a & ~b, [
      c < 1,
      d < 0
    ]),
    ElseIf(b & ~a, [
      c < 1,
      d < 0
    ]),
    // have as many ElseIf's here as you want
    Else([
      c < 0,
      d < 1
    ])
  ])
]);

Case and CaseZ

ROHD supports Case and CaseZ statements, including priority and unique flavors, which are implemented in the same way as SystemVerilog. For example:

Combinational([
  Case([b,a].swizzle(), [
      CaseItem(Const(LogicValues.fromString('01')), [
        c < 1,
        d < 0
      ]),
      CaseItem(Const(LogicValues.fromString('10')), [
        c < 1,
        d < 0,
      ]),
    ], defaultItem: [
      c < 0,
      d < 1,
    ],
    conditionalType: ConditionalType.Unique
  ),
  CaseZ([b,a].swizzle(),[
      CaseItem(Const(LogicValues.fromString('z1')), [
        e < 1,
      ])
    ], defaultItem: [
      e < 0,
    ],
    conditionalType: ConditionalType.Priority
  )
]);

Note that ROHD supports the 'z' syntax, not the '?' syntax (these are equivalent in SystemVerilog).

There is no support for an equivalent of casex from SystemVerilog, since it can easily cause unsynthesizeable code to be generated (see: https://www.verilogpro.com/verilog-case-casez-casex/).

Interfaces

Interfaces make it easier to define port connections of a module in a reusable way. An example of the counter re-implemented using interfaces is shown below.

Interface takes a generic parameter for direction type. This enables you to group signals so make adding them as inputs/outputs easier for different modules sharing this interface.

The Port class extends Logic, but has a constructor that takes width as a positional argument to make interface port definitions a little cleaner.

When connecting an Interface to a Module, you should always create a new instance of the Interface so you don't modify the one being passed in through the constructor. Modifying the same Interface as was passed would have negative consequences if multiple Modules were consuming the same Interface, and also breaks the rules for Module input and output connectivity.

The connectIO function under the hood calls addInput and addOutput directly on the Module and connects those Module ports to the correct ports on the Interfaces. Connection is based on signal names. You can use the uniquify Function argument in connectIO to uniquify inputs and outputs in case you have multiple instances of the same Interface connected to your module. You can also use the setPort function to directly set individual ports on the Interface instead of via tagged set of ports.

// Define a set of legal directions for this interface, and pass as parameter to Interface
enum CounterDirection {IN, OUT}
class CounterInterface extends Interface<CounterDirection> {
  
  // include the getters in the interface so any user can access them
  Logic get en => port('en');
  Logic get reset => port('reset');
  Logic get val => port('val');

  final int width;
  CounterInterface(this.width) {
    // register ports to a specific direction
    setPorts([
      Port('en'), // Port extends Logic
      Port('reset')
    ], [CounterDirection.IN]);  // inputs to the counter

    setPorts([
      Port('val', width),
    ], [CounterDirection.OUT]); // outputs from the counter
  }

}

class Counter extends Module {
  
  late final CounterInterface intf;
  Counter(CounterInterface intf) {
    // define a new interface, and connect it to the interface passed in
    this.intf = CounterInterface(intf.width)
      ..connectIO(this, intf, 
        // map inputs and outputs to appropriate directions
        inputTags: {CounterDirection.IN}, 
        outputTags: {CounterDirection.OUT}
      );
    
    _buildLogic();
  }

  void _buildLogic() {
    var nextVal = Logic(name: 'nextVal', width: intf.width);
    
    // access signals directly from the interface
    nextVal <= intf.val + 1;

    Sequential( SimpleClockGenerator(10).clk, [
      If(intf.reset, then:[
        intf.val < 0
      ], orElse: [If(intf.en, then: [
        intf.val < nextVal
      ])])
    ]);
  }
}

Non-synthesizable signal deposition

For testbench code or other non-synthesizable code, you can use put or inject on any Logic to deposit a value on the signal. The two functions have similar behavior, but inject is shorthand for calling put inside of Simulator.injectAction, which allows the deposited change to propogate within the same Simulator tick.

var a = Logic(), b = Logic(width:4);

// you can put an int directly on a signal
a.put(0);
b.inject(0xf);

// you can also put a `LogicValue` onto a signal
a.put(LogicValue.x);

// you can also put a `LogicValues` onto a signal
b.put(LogicValues([
  LogicValue.one,
  LogicValue.zero,
  LogicValue.x,
  LogicValue.z,
  ].reversed // reverse since arrays start with 0
));

Note: changing a value directly with put() will propogate the value, but it will not trigger flip-flop edge detection or cosim interaction.

Custom module behavior with custom in-line SystemVerilog representation

Many of the basic built-in gates in Dart implement custom behavior. An implementation of the NotGate is shown below as an example. There is different syntax for functions which can be inlined versus those which cannot (the ~ can be inlined). In this case, the InlineSystemVerilog mixin is used, but if it were not inlineable, you could use CustomSystemVerilog. Note that it is mandatory to provide an initial value computation when the module is first created for non-sequential modules.

class NotGate extends Module with InlineSystemVerilog {

  /// Name for a port of this module. 
  late final String _a, _out;
  
  /// The input to this [NotGate].
  Logic get a => input(_a);

  /// The output of this [NotGate].
  Logic get out => output(_out);

  NotGate(Logic a, {String name = 'not'}) : super(name: name) {
    _a = Module.unpreferredName(a.name);
    _out = Module.unpreferredName('${a.name}_b');
    addInput(_a, a, width: a.width);
    addOutput(_out, width: a.width);
    _setup();
  }

  /// Performs setup steps for custom functional behavior.
  void _setup() {
    _execute(); // for initial values

    // Custom behavior should subscribe to 'glitch'
    a.glitch.listen((args) {
      _execute();
    });
  }

  /// Executes the functional behavior of this gate.
  void _execute() {
    out.put(~a.value);
  }

  // specify how to convert this behavior to Verilog
  @override
  String inlineVerilog(Map<String,String> inputs) {
    if(inputs.length != 1) throw Exception('Gate has exactly one input.');
    var a = inputs[_a]!;
    return '~$a';
  }
}

Pipelines

ROHD has a built-in syntax for handling pipelines in a simple & refactorable way. The below example shows a three-stage pipeline which adds 1 three times. Note that Pipeline consumes a clock and a list of stages, which are each a List<Conditional> Function(PipelineStageInfo p), where PipelineStageInfo has information on the value of a given signal in that stage. The List<Conditional> the same type of procedural code that can be placed in Combinational.

Logic a;
var pipeline = Pipeline(clk,
  stages: [
    (p) => [
      // the first time `get` is called, `a` is automatically pipelined
      p.get(a) < p.get(a) + 1
    ],
    (p) => [
      p.get(a) < p.get(a) + 1
    ],
    (p) => [
      p.get(a) < p.get(a) + 1
    ],
  ]
);
var b = pipeline.get(a); // the output of the pipeline

This pipeline is very easy to refactor. If we wanted to merge the last two stages, we could simply rewrite it as:

Logic a;
var pipeline = Pipeline(clk,
  stages: [
    (p) => [
      p.get(a) < p.get(a) + 1
    ],
    (p) => [
      p.get(a) < p.get(a) + 1,
      p.get(a) < p.get(a) + 1
    ],
  ]
);
var b = pipeline.get(a);

You can also optionally add stalls and reset values for signals in the pipeline. Any signal not accessed via the PipelineStageInfo object is just access as normal, so other logic can optionally sit outside of the pipeline object.

ROHD also includes a version of Pipeline that supports a ready/valid protocol called ReadyValidPipeline. The syntax looks the same, but has some additional parameters for readys and valids.

ROHD Simulator

The ROHD simulator is a static class accessible as Simulator which implements a simple event-based simulator. All Logics in Dart have glitch events which propogate values to connected Logics downstream. In this way, ROHD propogates values across the entire graph representation of the hardware (without any Simulator involvement required). The simulator has a concept of (unitless) time, and arbitrary Dart functions can be registered to occur at arbitraty times in the simulator. Asking the simulator to run causes it to iterate through all registered timestamps and execute the functions in chronological order. When these functions deposit signals on Logics, it propogates values across the hardware. The simulator has a number of events surrounding execution of a timestamp tick so that things like FlipFlops can know when clocks and signals are glitch-free.

  • To register a function at an arbitraty timestamp, use Simulator.registerAction
  • To set a maximum simulation time, use Simulator.setMaxSimTime
  • To immediately end the simulation at the end of the current timestamp, use Simulator.endSimulation
  • To run just the next timestamp, use Simulator.tick
  • To run simulator ticks until completion, use Simulator.run
  • To reset the simulator, use Simulator.reset
    • Note that this only resets the Simulator and not any Modules or Logic values
  • To add an action to the Simulator in the current timestep, use Simulator.injectAction.

Instantiation of External Modules

ROHD can instantiate external SystemVerilog modules. The ExternalSystemVerilogModule constructor requires the top level SystemVerilog module name. When ROHD generates SystemVerilog for a model containing an ExternalSystemVerilogModule, it will instantiate instances of the specified topModuleName. This is useful for integration related activities.

There is an upcoming package for SystemVerilog cosimulation with ROHD which adds cosimulation capabilities to an ExternalSystemVerilogModule planned for release soon.

Unit Testing

Dart has a great unit testing package available on pub.dev: https://pub.dev/packages/test

The ROHD package has a great set of examples of how to write unit tests for ROHD Modules in the test/ directory.

Note that when unit testing with ROHD, it is important to reset the Simulator with Simulator.reset().

Contributing

ROHD is under active development. If you're interested in contributing, have feedback or a question, or found a bug, please see CONTRIBUTING.md.

Comparison with Alternatives

There are a lot of options for developing hardware. This section briefly discusses popular alternatives to ROHD and some of their strengths and weaknesses.

SystemVerilog

SystemVerilog is the most popular HDL (hardware descriptive language). It is based on Verilog, with additional software-like constructs added on top of it. Some major drawbacks of SystemVerilog are:

  • SystemVerilog is old, verbose, and limited, which makes code more bug-prone
  • Integration of IPs at SOC level with SystemVerilog is very difficult and time-consuming.
  • Validation collateral is hard to develop, debug, share, and reuse when it is written in SystemVerilog.
  • Building requires building packages with proper `include ordering based on dependencies, ordering of files read by compilers in .f files, correctly specifiying order of package and library dependencies, and correct analysis and elaboration options. This is an area that drains many engineers' time debugging.
  • Build and simulation are dependent on expensive EDA vendor tools or incomplete open-source alternatives. Every tool has its own intricacies, dependencies, licensing, switches, etc. and different tools may synthesize or simulate the same code in a functionally inequivalent way.
  • Designing configurable and flexible modules in pure SystemVerilog usually requires parameterization, compile-time defines, and "generate" blocks, which can be challenging to use, difficult to debug, and restrictive on approaches.
    • People often rely on perl scripts to bridge the gap for iteratively generating more complex hardware or stitching together large numbers of modules.
  • Testbenches are, at the end of the day, software. SystemVerilog is arguably a terrible programming language, since it is primarily focused at hardware description, which makes developing testbenches excessively challenging. Basic software quality-of-life features are missing in SystemVerilog.
    • Mitigating the problem by connecting to other languages through DPI calls (e.g. C++ or SystemC) has it's own complexities with extra header files, difficulty modelling parallel execution and edge events, passing callbacks, etc.
    • UVM throws macros and boilerplate at the problem, which doesn't resolve the underlying limitations.

ROHD aims to enable all the best parts of SystemVerilog, while completely eliminating each of the above issues. Build is automatic and part of Dart, packages and files can just be imported as needed, no vendor tools are required, hardware can be constructed using all available software constructs, and Dart is a fully-featured modern software language with modern features.

You can read more about SystemVerilog here: https://en.wikipedia.org/wiki/SystemVerilog

Chisel

Chisel is a domain specific language (DSL) built on top of Scala, which is built on top of the Java virtual machine (JVM). The goals of Chisel are somewhat aligned with the goals of ROHD. Chisel can also convert to SystemVerilog.

  • The syntax of Scala (and thus Chisel) is probably less familiar-feeling to most hardware engineers, and is arguably more verbose and subjectively uglier than ROHD with Dart.
  • Scala and the JVM are arguably less user friendly to debug than Dart code.
  • Chisel is focused mostly on the hardware designer rather than the validator. Many of the design choices for the language are centered around making it easier to parameterize and synthesize logic. ROHD was created with validators in mind.
  • Chisel generates logic that's closer to a netlist than what a similar implementation in SystemVerilog would look like. This can make it difficult to debug or validate generated code. ROHD generates structurally similar SystemVerilog that looks close to how you might write it.

Read more about Chisel here: https://www.chisel-lang.org/

MyHDL (Python)

There have been a number of attempts to create a HDL on top of Python, but it appears the MyHDL is one of the most mature options. MyHDL has many similar goals to ROHD, but chose to develop in Python instead of Dart. MyHDL can also convert to SystemVerilog.

  • MyHDL uses "generators" and decorators to help model concurrent behavior of hardware, which is arguably less user-friendly and intuitive than async/await and event based simulation in ROHD.
  • While Python is a great programming langauge for the right purposes, some language features of Dart make it better for representing hardware. Above is already mentioned Dart's isolates and async/await, which don't exist in the same way in Python. Dart is statically typed with null safety while Python is dynamically typed, which can make static analysis (including intellisense, type safety, etc.) more challenging in Python. Python can also be challenging to scale to large programs without careful architecting.
  • Python is inherently slower to execute than Dart.
  • MyHDL has support for cosimulation via VPI calls to SystemVerilog simulators. The MyHDL C/VPI implementation is gratefully reused within a separate package in the ROHD ecosystem for cosimulation.

Read more about MyHDL here: http://www.myhdl.org/

High-Level Synthesis (HLS)

High-Level Synthesis (HLS) uses a subset of C++ and SystemC to describe algorithms and functionality, which EDA vendor tools can compile into SystemVerilog. The real strength of HLS is that it enables design exploration to optimize a higher-level functional intent for area, power, and/or performance through proper staging and knowledge of the characteristics of the targeted process.

  • HLS is a step above/away from RTL-level modelling, which is a strength in some situations but might not be the right level in others.
  • HLS uses C++/SystemC, which is arguably a less "friendly" language to use than Dart.

Read more about one example of an HLS tool (Cadence's Stratus tool) here: https://www.cadence.com/en_US/home/tools/digital-design-and-signoff/synthesis/stratus-high-level-synthesis.html

There are a number of other attempts to make HLS better, including XLS and Dahlia & Calyx. There are discussions on ways to reasonably incorporate some of the strengths of HLS approaches into ROHD.

Transaction Level Verilog (TL-Verilog)

Transaction Level Verilog (TL-Verilog) is like an extension on top of SystemVerilog that makes pipelining simpler and more concise.

  • TL-Verilog makes RTL design easier, but doesn't really add much in terms of verification
  • Abstraction of pipelining is something that could be achievable with ROHD, but is not (yet) implemented in base ROHD.

Read more about TL-Verilog here: https://www.redwoodeda.com/tl-verilog

PyMTL

PyMTL is another attempt at creating an HDL in Python. It is developed at Cornell University and the third version (PyMTL 3) is currently in Beta. PyMTL aims to resolve a lot of the same things as ROHD, but with Python. It supports conversion to SystemVerilog and simulation.

  • The Python language trade-offs described in the above section on MyHDL apply to PyMTL as well.

Read more about PyMTL here: https://github.com/pymtl/pymtl3 or https://pymtl3.readthedocs.io/en/latest/

cocotb

cocotb is a Python-based testbench framework for testing SystemVerilog and VHDL designs. It makes no attempt to represent hardware or create a simulator, but rather connects to other hardware simulators via things like VPI calls.

Read more about cocotb here: https://github.com/cocotb/cocotb or https://docs.cocotb.org/en/stable/

Author: intel
Source Code: https://github.com/intel/rohd 
License: View license

#flutter #frameworks #hardware 

Rapid Open Hardware Development (ROHD) Framework