1679141476
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
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.
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 - 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 | Description | Download link |
---|---|---|
Intel® RealSense™ Viewer | With 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 Tool | This 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 Tools | Device enumeration, FW logger, etc as can be seen at the tools directory | Included in Intel.RealSense.SDK.exe |
Code Samples | These 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 examples | Included in Intel.RealSense.SDK.exe |
Wrappers | Python, 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. |
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.
In order to contribute to Intel RealSense SDK, please follow our contribution guidelines.
Author: IntelRealSense
Source Code: https://github.com/IntelRealSense/librealsense
License: Apache-2.0 license
1663311780
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 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.
For guidance on installation and development, see the User documentation.
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! ✨
Nightly builds are available for beta testing.
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
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.
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
ghw
is a small Golang library providing hardware inspection and discovery for Linux and Windows. There currently exists partial support for MacOSX.
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.
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.
ghw
usesThe 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"))
ghw
usesWhen 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
WithChroot
/GHW_CHROOT
feature.ghw
doesn't support yet environs variable to override individual mountpoints, because this could lead to significant environs variables proliferation.Open Sound Control (OSC) library for Golang. Implemented in pure Go.
go get github.com/hypebeast/go-osc
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)
}
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()
}
make test
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.
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
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:
.msg
files is not necessary, message definitions are extracted from codeInstall 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
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.
rosgo is currently unmaintained; furthermore, it requires compilation of .msg
files, doesn't support UDP, doesn't support actions, doesn't support simulated clocks.
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.
$ go get github.com/0xcafed00d/joystick/...
$ go install github.com/0xcafed00d/joystick/joysticktest
$ joysticktest 0
Displays the state of the specified joystick
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()
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.
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))
}
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.
Sysinfo requires:
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.
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
Thank you for following this article.
Learn Go Programming by Building 11 Projects – Full Course
1652095740
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.
Features | Linux | Mac | Windows |
---|---|---|---|
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.
# Use as a module
npm install node-wifi
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
});
node-wifi
is also usable as a CLI tool with the library node-wifi-cli.
This project is tested with operating systems:
Do not hesitate to create a pull request to add the OS you are using.
Linux:
Windows:
MacOS:
Please read development guidelines before proposing a pull request.
Author: Friedrith
Source Code: https://github.com/friedrith/node-wifi
License: MIT license
1651088400
Libraries for programming with hardware.
Author: vinta
Source Code: https://github.com/vinta/awesome-python
License: View license
1651046640
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
.
This program makes no attempt to hide itself, so don't use it for keyloggers.
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.
event.device == None
). #21/dev/input/input*
) but this requries root.mouse
will be unable to report events.API
hold
)replay
)ButtonEvent(event_type, button, time)
Alias for field number 1
Return number of occurrences of value.
Alias for field number 0
Return first index of value.
Raises ValueError if the value is not present.
Alias for field number 2
= 'double'
= 'down'
= 'left'
= 'middle'
MoveEvent(x, y, time)
Return number of occurrences of value.
Return first index of value.
Raises ValueError if the value is not present.
Alias for field number 2
Alias for field number 0
Alias for field number 1
= 'right'
= 'up'
WheelEvent(delta, time)
Return number of occurrences of value.
Alias for field number 0
Return first index of value.
Raises ValueError if the value is not present.
Alias for field number 1
= 'x'
= 'x2'
= '0.7.1'
Returns True if the given button is currently pressed.
Presses the given button (but doesn't release).
Releases the given button.
Sends a click with the given button.
Sends a double click with the given button.
Sends a right click with the given button.
Scrolls the wheel delta
clicks. Sign indicates direction.
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.
Holds the left mouse button, moving from start to end position, then releases. absolute
and duration
are parameters regarding the mouse movement.
Invokes callback
with args
when the specified event happens.
Invokes callback
with args
when the left button is clicked.
Invokes callback
with args
when the left button is double clicked.
Invokes callback
with args
when the right button is clicked.
Invokes callback
with args
when the middle button is clicked.
Blocks program execution until the given button performs an event.
Returns the (x, y) mouse position.
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.
Removes a previously installed hook.
Removes all hooks registered by this application. Note this may include hooks installed by high level functions, such as record
.
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
.
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
1651028160
Ino
Ino is a command line toolkit for working with Arduino hardware
It allows you to:
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.
*.ino
and *.pde
sketches as well as raw *.c
and *.cpp
.*.h
files lead to recompilation of sources which include them.From source:
git clone git://github.com/amperka/ino.git
make install
to perform installation under /usr/local
INSTALL
for instructions on changing destination directoryWith Python setup tools:
pip install ino
easy_install ino
picocom
for serial communicationino --help
.If not stated otherwise ino is distributed in terms of MIT software license. See MIT-LICENSE.txt in the distribution for details.
0.3.6
0.3.5
0.3.4
ino clean
and rebuild if you switch to another Arduino model or software distribution.0.3.3
*.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
0.3.1
ino build --verbose
0.3.0
0.2.0
0.1.x
Author: amperka
Source Code: https://github.com/amperka/ino
License: MIT License
1650950340
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.
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.
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.
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.
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.
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
1650906840
新しいモノのインターネット(IoT)製品を市場に出すには、途中で障害を引き起こしたり、デバイスが期待どおりに機能しないことを意味する可能性のある設計上の課題を理解する必要があります。ここでは、ハードウェアに関連する主な懸念事項とその解決方法について説明します。
今日のIoTデバイスユーザーの多くは、何年も使用できるバッテリーを持っている必要があります。これは、誰かがバッテリー交換のために簡単にアクセスできない遠隔地に何かを配備することを計画している場合に特に重要です。製品が、患者の体内で使用される接続された医療機器であるとします。頻繁なバッテリー交換は、操作を必要とするか、さもなければ誰かを合併症のリスクを高める可能性があります。
ハードウェア設計者は、どの側面が最も電力を消費するかを検討し、それらが設計にとって重要であるかどうかを評価する必要があります。もしそうなら、次のステップはバッテリーの寿命を延ばす方法を見つけることです。
このIoT設計の課題を解決する1つの方法は、電流をほとんど消費しないディープスリープモードの集積回路を使用することです。さらに、設計者は低バッテリ電圧を使用する機会を探すことができます。アイデアは、製品内の電流引き込みを最小限に抑えることです。設計者は、低電力のコンポーネントを使用し、使用されていないときに部品が過度の電力を消費し続けないようにすることで、その目標を達成できます。
欧州連合が資金提供したプロジェクトでは、エンジニアが寿命を延ばすための措置を講じない場合、2025年までに最大7,800万個のIoTバッテリーが廃棄されることが示されました。このプロジェクトについてコメントした研究者たちは、持続的に充電できるバッテリーを開発することで大きな進歩が見られると信じています。ただし、今のところ、設計者はIoTデバイスを計画する際にバッテリー寿命を早期に優先する必要があると彼らは言います。
現在のヘッドラインには、世界中のIoTデバイスに影響を与える可能性のあるセキュリティ上の欠陥の気になる詳細が頻繁に掲載されています。ハードウェアの観点からこのIoT設計の課題を解決するには、多面的なアプローチが必要です。
まず、設計者は、当事者が暗号化されていない状態のキーにアクセスできないようにする安全なキー管理を検討する必要があります。キーを安全に生成して保存するように製品を設計する必要があります。また、ハードウェアアクセラレーションによる暗号化を使用して、電力を節約しながらデバイスをより安全に保つことも検討する必要があります。
もう1つのベストプラクティスは、機密性の高いIoTコードと機密性の低いIoTコードとデータを分離するために、別々のメモリドメインを用意することです。安全なメモリアクセスを使用すると、RAMとフラッシュメモリを不正アクセスから保護できます。ハードウェア設計者は、デバッグとプログラミングの保護も実装する必要があります。そうすることで、ハッカーがプログラミングインターフェイスやデバッガーを使用して攻撃を開始することがより困難になります。
ハードウェア設計者は、製品に新たに発見されたサイバーセキュリティの脆弱性を開示するためのプログラムに関する議論にも参加または奨励する必要があります。ある調査によると、現在IoTベンダーの21%だけがそのようなイニシアチブを持っています。ただし、これらは、設計者やIoTセキュリティに関係する他のすべての人が、他の方法では見過ごされがちな問題に気付くのを支援するために不可欠です。
もう1つのIoT設計の課題は、徐々に小型化および軽量化されたデバイスに対する需要が高まっているという事実にあります。これらの特性に対する要望は、実装の柔軟性を可能にするため、理にかなっています。
1つの可能性は、デバイスがリジッドではなくフレキシブルプリント回路基板(PCB)の使用を保証するかどうかを確認することです。フレキシブルPCBは 95%軽量であり、より多くのコンポーネントをより小さなスペースに収めることができます。また、通常、剛性のあるものよりも耐久性があり、過酷な環境での衝撃に耐えることができるため、全体的な寿命が長くなります。
IoTデバイスが人工知能(AI)で動作するか、デバイス上のデータ処理を処理する場合、ハードウェア設計者は、これらの必需品がフォームファクターにも影響を与える可能性があることを理解する必要があります。研究者は最近、数十億のIoTデバイスですでに使用されているマイクロコントローラーユニット(MCU)でアルゴリズムを実行することで進歩を遂げました。彼らは、彼らの技術は、パフォーマンスを向上させながら、AIアルゴリズムを実行するために必要なメモリをさらに削減すると述べました。
IoTデバイスのコンポーネントのメーカーも、Wi-Fiモジュールなどのアイテムを徐々に小さくして、小型化された製品により適したものにすることを目指しています。IoTハードウェア設計者は、これらの開発に遅れずについていき、新しいオプションが今後の製品をどのようにサポートできるかを学ぶ必要があります。
設計者は通常、厳しいスケジュールで作業します。それでも、ハードウェアテストを実行し、それぞれの結果を得た後に必要な調整を行うために十分な時間を確保する必要があります。メーカーの評価は、機械的試験から耐環境性に 至るまでの領域をカバーしています。
このフェーズでは、設計者は、接続性、バッテリ寿命、使いやすさなどの側面が、期待する最小要件を満たしていることを確認します。製品が市場に出る前に行われるテストは、セキュリティ関連の問題を防ぐこともできます。たとえば、ファズテストでは、IoTデバイスをランダムなバイト文字列にさらし、バグを示す可能性のある異常な動作を追跡します。これは、コンピュータアプリケーションをテストするときに最も一般的に発生します。ただし、IoTデバイスをチェックする場合にも便利なオプションです。
貴重なテスト結果を得るには、チーム間の効果的なコミュニケーションが不可欠です。デバイスで作業したソフトウェア開発者は、ハードウェアに部分的に影響するバグを発見する可能性があります。そのような場合、ソフトウェア開発者とハードウェア設計者は、潜在的なソリューションに協力する必要があります。
テスターと連絡を取り合うことも不可欠です。これらの関係者の多くは、ハードウェアの問題が原因で問題が発生したことをすぐには理解できない場合があります。ただし、テストに関係する人々が詳細なフィードバックを提供した後、ハードウェア設計者やIoT製品に関係する他の人々は、問題のあるものをターゲットにして、協力して修正することができます。
ハードウェア設計者は、常に予想よりも多くの時間をかけてテストを計画する必要があります。そうすれば、急いで製品の機能やセキュリティを妨げる可能性のある問題を見逃す可能性がなくなります。
遭遇する可能性のあるすべてのIoT設計の課題を回避する普遍的な方法はありません。ただし、これらの例が示すように、すべての設計決定の良い結果と悪い結果を考えることが重要です。そうすることで、設計者はすべての段階で最も適切な選択を行い、コストと時間のかかる問題を回避することができます。
ソース:https ://dzone.com/articles/how-to-overcome-4-challenges-in-iot-hardware-design
1650659820
¿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:
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.
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 .
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)
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.
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.
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.
Para que el hardware funcione, necesita un software (un conjunto de instrucciones) que le diga qué hacer.
Entonces, el software le da instrucciones al hardware que le permite funcionar.
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:
Comparación de procesos
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.
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.
¡Gracias por leer! Ahora sabes más sobre:
Foto del microprocesador de Pok Rie de Pexels
1650659580
ファームウェアが文字通りどこにでもあることをご存知ですか?考えるのは奇妙かもしれませんが、ハードウェアやソフトウェアと同じくらい一般的です。
実際、ファームウェアのおかげで次のことが可能になります。
上記の例に基づいて、おそらくファームウェアが何であるかについてすでにある程度の知識があります。しかし、あなたはそれの明確な定義を持っていません。
ファームウェアとは何かを真に理解するには、まずソフトウェア、次にハードウェアを理解し、最後にファームウェアに飛び込む必要があります。
このチュートリアルでは、各トピックを類推して説明します。そうすることで、誰もが理解できるようになります。
テクノロジーを始めたばかりかどうかは関係ありません。
それで、ソフトウェア、ハードウェア、ファームウェアが何であるかをみんなに理解してもらいたいと思います。専門用語については詳しく説明しません。
もしそうなら、今日の夕食に何を作ればいいのかわからないと想像してみてください。
幸いなことに、あなたはあなたが持っている古い料理本を見つけて、その中のレシピの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をマシンコードで出力する(アセンブリ)
次に、アプリケーションは特定のタスクを実行する一連の大きな命令です。
オペレーティングシステムは、ソフトウェアとハードウェアのリソースを調整する一連の大きな命令です。
あなたは夕食を作るためのレシピが必要です。レシピを作成するには、クックブックの各ステップに従う必要があります。
すべての手順を完了すると、夕食の準備が整います。
特定のタスクを実行するにはソフトウェアが必要です。コンピュータは、ソフトウェアが機能するためにすべての指示に従う必要があります。
したがって、ソフトウェアは、指示に従っている間、または指示が完了した後に実行されます。
夕食を作るために、あなたは特定の食事を作る方法をあなたに教える料理本からの一連のステップを必要とします。
また、鍋やフライパン、ナイフ、食べ物自体など、さまざまな調理器具が必要です。これはハードウェアのようなものです。
したがって、クックブックには、料理を可能にする手順が記載されています。
ハードウェアが機能するには、何をすべきかを指示するソフトウェア(一連の命令)が必要です。
次に、ソフトウェアは、それを機能させるハードウェアに指示を与えます。
ソフトウェアがなければ、ハードウェアを機能させることはできません。
レシピがなければ、食事を作るためにさまざまな道具や材料をどうするかがわかりません。
ソフトウェアのないハードウェアのように、生の食品だけで食事をすることもできます。キモい。
さまざまな種類の食事があるのと同じように、さまざまな種類のコンピュータハードウェアもあります。
例えば:
プロセスの比較
PexelsのEllaOlssonによる写真
プログラムは、コンピューターによって読み取られる一連の命令です。
おやつやデザートを作りたいだけだとしましょう。家族で夕食を作るときほど多くの材料は必要ないでしょう?
電子レンジで動作するソフトウェアが必要だとしましょう。コンピュータが電子レンジを機能させるために必要なすべてのハードウェアは必要ありませんよね?あなたはただマイクロ波を機能させるためにそれを必要とします。
または、ソフトウェアをプリンターで実行したいとします。コンピューターがプリンターを正しく動作させるために必要なすべてのハードウェアは必要ありませんか?プリンタ用のソフトウェアだけです。
つまり、これはファームウェアがソフトウェアにすぎず、ハードウェアデバイスにあることを意味します。コンピューターではありません。
ファームウェアにより、非常に特定のハードウェアが非常に特定のタスクを完了できます。
読んでくれてありがとう!今、あなたはもっと知っています:
1649512860
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.
El primer disco duro
Actualmente, los discos duros se dividen en 4 tipos principales:
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.
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.
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.
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.
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.
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/
1649461380
ハードドライブは、すべてのデジタルコンテンツのストレージとして機能する、コンピューター上の不揮発性ハードウェアコンポーネントです。プログラムファイル、ドキュメント、写真、ビデオ、音楽などを保持します。
ハードドライブの不揮発性は、電源が失われた場合でもデータが失われないことを意味します。このため、損傷や破損がない限り、コンピューターがファイルやその他のデータを長期間保存するのに役立ちます。
1956年にIBMがハードドライブを最初にリリースして以来、ハードドライブは冷蔵庫のサイズでわずか5MBのストレージ容量から、ポケットサイズで最大4TBのストレージ容量を持つものへと進化してきました。
この記事では、さまざまな種類のハードドライブについて説明し、コンピューターに最適なものを選択できるようにします。
最初のハードドライブ
現在、ハードドライブは4つの主要なタイプに分けられます。
これらの名前は、コンピューターへの接続方法に由来しています。この記事では、これらのタイプのハードドライブのそれぞれについて可能な限り簡潔に説明します。
PATAハードドライブは、1986年にCompaqとWestern Digitalによって最初に市場に導入されました。最大80GBの容量を持ち、133 MB/Sの速度でデータを転送できます。
これらは、パラレルATAインターフェイスを使用してコンピュータに接続するため、Parallel AdvancedTechnologyAttachmentと名付けられました。PATAとは別に、Integrated Drive Electronics(IDE)およびEnhanced Integrated Drive Electronics(EIDE)とも呼ばれます。
PATAハードドライブは機械的な可動部品でできており、パラレルシグナリングテクノロジーに基づいています。つまり、複数ビットのデータを同時に送信します。
最近では、多くのデスクトップおよびラップトップコンピュータが、サイズ、消費電力、およびさらに優れた価格設定でPATAハードドライブに取って代わったため、SATAハードドライブを取得しています。
コンピュータへの接続モードはPATAと同じですが、データ伝送用の並列シグナリングテクノロジの代わりに、シリアルシグナリングテクノロジを使用します。これは、一度に1ビットずつデータを転送することを意味します。
SATAハードドライブがPATAハードドライブよりも優れている注目すべき利点は、150〜300 MB/Sの速度でデータを送信できることです。さらに、ケーブルが細く、ケーブル制限が1メートルです。
SCSIハードドライブは、24時間稼働、速度、ストレージなどの多くの理由から、SATAおよびPATAドライブをアップグレードしたものです。
接続には、SCSIハードドライブは小さなコンピューターシステムインターフェイスを使用します。これは、プリンター、スキャナーなどの周辺機器を接続するための標準です。
何よりも、プリンター、スキャナー、その他のハードドライブなどの周辺機器を接続できます。さらに、320 MB / Sでデータを送信し、内部または外部に接続できます。
パーソナルコンピュータ上のSCSIを介した接続は、ユニバーサルシリアルバス(USB)に置き換えられました。これは、SCSIがコンシューマーハードウェアとして使用されなくなったことを意味します。
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/
1649319480
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.
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.
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.
You can use the functions in ghw
to determine various hardware-related information about the host computer:
ghw
usesThe 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"))
ghw
usesWhen 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
WithChroot
/GHW_CHROOT
feature.ghw
doesn't support yet environs variable to override individual mountpoints, because this could lead to significant environs variables proliferation.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,
}))
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:
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)
}
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 the
ghw.WithAlerter()` function.
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 hostghw.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 bitsInformation 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 hostghw.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 bitsghw.MemoryInfo.SupportedPageSizes
is an array of integers representing the size, in bytes, of memory pages the system supportsghw.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)
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
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 containsghw.CPUInfo.TotalThreads
has the total number of hardware threads the host system containsghw.CPUInfo.Processors
is an array of ghw.Processor
structs, one for each physical processor package contained in the hostEach ghw.Processor
struct contains a number of fields:
ghw.Processor.ID
is the physical processor uint32
ID according to the systemghw.Processor.NumCores
is the number of physical cores in the processor packageghw.Processor.NumThreads
is the number of hardware threads in the processor packageghw.Processor.Vendor
is a string containing the vendor nameghw.Processor.Model
is a string containing the vendor's model nameghw.Processor.Capabilities
is an array of strings indicating the features the processor has enabledghw.Processor.Cores
is an array of ghw.ProcessorCore
structs that are packed onto this physical processorA 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 10ghw.ProcessorCore.Index
is the zero-based index of the core on the physical processor packageghw.ProcessorCore.NumThreads
is the number of hardware threads associated with the coreghw.ProcessorCore.LogicalProcessors
is an array of logical processor IDs assigned to any processing unit for the corepackage 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]
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 hostghw.BlockInfo.Disks
is an array of pointers to ghw.Disk
structs, one for each disk drive found by the systemEach 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 providesghw.Disk.PhysicalBlockSizeBytes
contains the size of the physical blocks used on the disk, in bytesghw.Disk.IsRemovable
contains a boolean indicating if the disk drive is removableghw.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 -1ghw.Disk.Vendor
contains a string with the name of the hardware vendor for the disk driveghw.Disk.Model
contains a string with the vendor-assigned disk model nameghw.Disk.SerialNumber
contains a string with the disk's serial numberghw.Disk.WWN
contains a string with the disk's World Wide Nameghw.Disk.Partitions
contains an array of pointers to ghw.Partition
structs, one for each partition on the diskEach 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 providesghw.Partition.MountPoint
contains a string with the partition's mount point, or "" if no mount point was discoveredghw.Partition.Type
contains a string indicated the filesystem type for the partition, or "" if the system could not determine the typeghw.Partition.IsReadOnly
is a bool indicating the partition is read-onlyghw.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 usingghw
in a container, remember to bind mount/dev/disk
and/run
into your container, otherwiseghw
won't be able to query the udev DB or sysfs paths for information.
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 isghw.TopologyInfo.Nodes
is an array of pointers to ghw.TopologyNode
structs, one for each topology node (typically physical processor package) found by the systemEach ghw.TopologyNode
struct contains the following fields:
ghw.TopologyNode.ID
is the system's uint32
identifier for the nodeghw.TopologyNode.Cores
is an array of pointers to ghw.ProcessorCore
structs that are contained in this nodeghw.TopologyNode.Caches
is an array of pointers to ghw.MemoryCache
structs that represent the low-level caches associated with processors and cores on the systemghw.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 bothghw.MemoryCache.Level
is a positive integer indicating how close the cache is to the processorghw.MemoryCache.SizeBytes
is an integer containing the number of bytes the cache can containghw.MemoryCache.LogicalProcessors
is an array of integers representing the logical processors that use the cachepackage 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
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 systenEach ghw.NIC
struct contains the following fields:
ghw.NIC.Name
is the system's identifier for the NICghw.NIC.MacAddress
is the MAC address for the NIC, if anyghw.NIC.IsVirtual
is a boolean indicating if the NIC is a virtualized deviceghw.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 Linuxghw.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 NICghw.NICCapability.CanEnable
is a boolean indicating whether the capability may be enabledpackage 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
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 systemghw.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.
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]
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 systenEach ghw.GraphicsCard
struct contains the following fields:
ghw.GraphicsCard.Index
is the system's numeric zero-based index for the card on the busghw.GraphicsCard.Address
is the PCI address for the graphics cardghw.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
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 tagghw.ChassisInfo.SerialNumber
is a string with the chassis serial numberghw.ChassisInfo.Type
is a string with the chassis type codeghw.ChassisInfo.TypeDescription
is a string with a description of the chassis typeghw.ChassisInfo.Vendor
is a string with the chassis vendorghw.ChassisInfo.Version
is a string with the chassis versionNOTE: 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.
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 vendorghw.BIOSInfo.Version
is a string with the BIOS versionghw.BIOSInfo.Date
is a string with the date the BIOS was flashed/createdpackage 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
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 tagghw.BaseboardInfo.SerialNumber
is a string with the baseboard serial numberghw.BaseboardInfo.Vendor
is a string with the baseboard vendorghw.BaseboardInfo.Product
is a string with the baseboard name on Linux and Product on Windowsghw.BaseboardInfo.Version
is a string with the baseboard versionNOTE: 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.
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 familyghw.ProductInfo.Name
is a string with the product nameghw.ProductInfo.SerialNumber
is a string with the product serial numberghw.ProductInfo.UUID
is a string with the product UUIDghw.ProductInfo.SKU
is a string with the product stock unit identifier (SKU)ghw.ProductInfo.Vendor
is a string with the product vendorghw.ProductInfo.Version
is a string with the product versionNOTE: 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.
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 stringYAMLString()
returns a string containing the information serialized into YAMLpackage 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
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:
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.
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
1646377222
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
1642127160
Rapid Open Hardware Development (ROHD) Framework
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:
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.
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 Future
s 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).
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.
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
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.
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
The below subsections offer some examples of implementations and syntax in ROHD.
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.
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.
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)
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 LogicValue
s. 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 LogicValues
s using a variety of constructors including fromInt
, fromBigInt
, filled
(like '0, '1, 'x, etc. in SystemVerilog), and from
(which takes any Iterable<LogicValue>
).
You can trigger on changes of Logic
s with some built in events. ROHD uses dart synchronous streams for events.
There are three testbench-consumable streams built-in to ROHD Logic
s: 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 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')
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;
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
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
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.
Module
s 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.
Module
must consume only inputs (from the input
or addInput
methods) to the Module either directly or indirectly.Module
must consume the signals only via outputs (from the output
or addOutput
methods) of the Module.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 Module
s 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 input
s and drive the registered output
s 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.
Module
s 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.
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'
}
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.
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 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 Module
s 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 Interface
s. 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
])])
]);
}
}
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.
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';
}
}
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.
The ROHD simulator is a static class accessible as Simulator
which implements a simple event-based simulator. All Logic
s in Dart have glitch
events which propogate values to connected Logic
s 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 Logic
s, it propogates values across the hardware. The simulator has a number of events surrounding execution of a timestamp tick so that things like FlipFlop
s can know when clocks and signals are glitch-free.
Simulator.registerAction
Simulator.setMaxSimTime
Simulator.endSimulation
Simulator.tick
Simulator.run
Simulator.reset
Simulator
and not any Module
s or Logic
valuesSimulator.injectAction
.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.
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 Module
s in the test/ directory.
Note that when unit testing with ROHD, it is important to reset the Simulator
with Simulator.reset()
.
ROHD is under active development. If you're interested in contributing, have feedback or a question, or found a bug, please see CONTRIBUTING.md.
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 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:
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 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.
Read more about Chisel here: https://www.chisel-lang.org/
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.
Read more about MyHDL here: http://www.myhdl.org/
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.
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) is like an extension on top of SystemVerilog that makes pipelining simpler and more concise.
Read more about TL-Verilog here: https://www.redwoodeda.com/tl-verilog
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.
Read more about PyMTL here: https://github.com/pymtl/pymtl3 or https://pymtl3.readthedocs.io/en/latest/
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