class: center, middle # Why Nix Shorts ## Justin Woo ### Berlin FP Group - 20 Apr 2021 --- # Objectives While this is not really a talk about Nix, we'll review Nix Shorts (for those who expected to learn about Nix). Then we will discuss why I wrote Nix Shorts. After, we'll talk about some of the things I expect out of documentation that others might agree with. --- # Nix Shorts Originally written in August - October 2019, Nix Shorts contains six independent posts: * Your First Derivation * Working With Nix Shells * Pinning to a specific Nixpkgs * Installing things to Nix Profile * Installing Packages from Files * Inspecting Values with [Nix] REPL --- # Your First Derivation A Derivation in Nix is a definition of a build, which takes some inputs and produces an output. The inputs are almost always in a `src` attribute, and outputs are almost always some `/nix/store/some-hash-pkg-name` path. ## Basic derivation example Start with some inputs you want to build with. ```bash $ mkdir src $ echo hello > src/hi.txt $ ls src hi.txt ``` --- Then prepare a `default.nix`, which will be used by default when we later run `nix-build`. ```nix # allow our nixpkgs import to be overridden if desired { pkgs ? import
{} }: # let's write an actual basic derivation # this uses the standard nixpkgs mkDerivation function pkgs.stdenv.mkDerivation { # name of our derivation name = "basic-derivation"; # sources that will be used for our derivation. src = ./src; # see https://nixos.org/nixpkgs/manual/#ssec-install-phase # $src is defined as the location of our `src` attribute above installPhase = '' # $out is an automatically generated filepath by nix, # but it's up to you to make it what you need ln -s $src $out ''; } ``` --- ## Building our derivation With our derivation defined, we can build this derivation using `nix-build`. ```bash $ nix-build # or nix-build default.nix # some build logs /nix/store/some-hash-basic-derivation ``` `nix-build` will create a symlink to the output by default in `./result`. ```bash $ readlink result /nix/store/kgjcq77210jkjppc8628vcl27i6f22k8-basic-derivation $ readlink -f result /nix/store/54992nknd3av7j4p7fmsh96ja5hp1vli-src $ ls result hi.txt $ cat result/hi.txt hello ``` --- # Working With Nix Shells ## Shells with `-p` Using `nix-shell` with `-p` can get you quickly set up with a shell with packages from Nixpkgs installed. ```bash # from your top level $ nix-shell -p hello # nix shell with hello installed $ which hello /nix/store/some-hash-hello-2.10/bin/hello $ hello Hello, world! $ exit exit # back to your top level shell ``` --- ## Nixpkgs mkShell You can write an expression in a file using `mkShell`. Note `nix-shell` uses `shell.nix` or `default.nix` implicitly. ```nix # shell.nix { pkgs ? import
{} }: pkgs.mkShell { buildInputs = [ pkgs.hello ]; } ``` And we can see this used like so: ```bash # implicitly does `nix-shell shell.nix --run ...` $ nix-shell --run 'which hello; hello' /nix/store/some-hash-hello-2.10/bin/hello Hello, world! ``` --- # Pinning to a specific Nixpkgs Because you want to be fairly sure what you write today works tomorrow. ```nix # pinned.nix import ( builtins.fetchTarball { url = "https://github.com/nixos/nixpkgs/archive/hash.tar.gz"; sha256 = "some-sha"; } ) ``` This expression uses the GitHub tarballs created for each publicly visible commit, using the builtin fetchTarball in Nix 2.x+. --- ## Usage In your expressions, you can simply replace usages of `
` with your imported Nixpkgs expression. ```diff -{ pkgs ? import
{} }: +{ pkgs ? import ./pinned.nix {} }: ``` ## With `fetchFromGitHub` ```nix let pkgs = import
{}; in import (pkgs.fetchFromGitHub { owner = "nixos"; repo = "nixpkgs"; rev = "some-commit-hash"; sha256 = "some-sha"; }) ``` --- # Installing things to Nix Profile Nix Profile is a symlink location in `~/.nix-profile` when you install Nix. ```bash $ readlink ~/.nix-profile /nix/var/nix/profiles/per-user/your-user/profile $ readlink -f ~/.nix-profile /nix/store/some-hash-user-environment $ ls ~/.nix-profile bin etc include lib manifest.nix share ``` --- ## Installing packages from Nixpkgs To install packages from nixpkgs, you can use the `-A` flag to specify which attribute you want to install. ```bash $ nix-env -iA nixpkgs.python installing 'python-2.7.16' $ which python /home/your-user/.nix-profile/bin/python ``` ## Uninstalling packages The easiest method is to use `nix-env -e` (short for `uninstall`) and tab-complete. ```bash $ nix-env -e python uninstalling 'python-2.7.16' ``` --- ## Looking at what is in the environment To find out what packages you have installed in your environment, you can use `nix-env -q` (short for "query"). ```bash # example, may not match your results $ nix-env -q alacritty autorandr-1.8.1 bash-completion-2.8 bat-0.11.0 colordiff-1.0.18 ``` --- # Installing Packages from Files ## From a file of a single derivation expression Remember that every Nix source file is an expression. You can build and install packages from a file that is a derivation value. ```nix let pkgs = import
{}; in pkgs.stdenv.mkDerivation { name = "test.txt"; # contents: "hello, i am test" src = ./test.txt; phases = ["installPhase"]; installPhase = '' mkdir -p $out/test ln -s $src $out/test/text.txt ''; } ``` --- ### Usage ```bash $ nix-build derivation.nix /nix/store/some-hash-test.txt $ cat result/test/text.txt hello, i am test ``` Outputs of directories can be installed to the profile. ```bash $ nix-env -if derivation.nix installing 'test.txt' building '/nix/store/some-hash-user-environment.drv'... created NNN symlinks in user environment $ cat ~/.nix-profile/test/text.txt hello, i am test ``` --- ## From a set of derivations This is mostly useful if you want to version control packages installed in your profile. ```nix { pkgs ? import
{} }: { inherit (pkgs) python mypy; } ``` ```bash $ nix-env -if some-pkgs.nix installing 'mypy-0.701' installing 'python-2.7.16' building '/nix/store/some-hash-user-environment.drv'... created NNN symlinks in user environment ``` --- # Inspecting Values with [Nix] REPL It can be useful to inspect Nix expressions with the REPL. ```bash bash> nix repl Welcome to Nix version 2.2. Type :? for help. nix-repl> :? The following commands are available:
Evaluate and print expression
=
Bind expression to variable :a
Add attributes from resulting set to scope :b
Build derivation :i
Build derivation, then install result into current profile :l
Load Nix expression and add it to scope # ... ``` --- ### Evaluate The first is the same as an expression evaluation: ```bash nix-repl> 1 1 ``` ### Bind The second is the same as a `let`-bind in an expression: ```bash nix-repl> a = 1 nix-repl> a 1 ``` This is equivalent to `let a = 1; in ...`, but the introduced variables will persist in the session. --- ### Example usage ```bash bash> nix repl '
' # or `nix repl your-pinned-nixpkgs.nix` Loading '
'... Added 10647 variables. nix-repl> pkgs.purescript.outPath "/nix/store/vmwdvr9fcrbvnfdjfrrpb07z8gzbi1q7-purescript-0.13.0" nix-repl> :b pkgs.purescript this derivation produced the following outputs: out -> /nix/store/vmwdvr9fcrbvnfdjfrrpb07z8gzbi1q7-purescript-0.13.0 bash> fd . /nix/store/vmwdvr9fcrbvnfdjfrrpb07z8gzbi1q7-purescript-0.13.0 /nix/store/vmwdvr9fcrbvnfdjfrrpb07z8gzbi1q7-purescript-0.13.0/bin /nix/store/vmwdvr9fcrbvnfdjfrrpb07z8gzbi1q7-purescript-0.13.0/bin/purs /nix/store/vmwdvr9fcrbvnfdjfrrpb07z8gzbi1q7-purescript-0.13.0/etc /nix/store/vmwdvr9fcrbvnfdjfrrpb07z8gzbi1q7-purescript-0.13.0/etc/bash_completion.d /nix/store/vmwdvr9fcrbvnfdjfrrpb07z8gzbi1q7-purescript-0.13.0/etc/bash_completion.d/purs-completion.bash ``` --- # Why Nix Shorts? There are many things I dislike about existing "introduction to Nix" materials. ## Irrelevant Nix implementation details * "How to make a derivation from scratch using `derivation`" * `nix-instantiate` "examples" * GC roots and other implementation details Akin to trying to introduce people to Haskell via GHC Generics and Template Haskell ## Lack of NixPkgs `stdenv/lib` usage * "Introductions" that don't use `mkDerivation` * What the hell kind of Nix code do you think people are going to be working with * Writing custom builders: why is this relevant in an introduction? --- ## Demonstrations and examples do not exist * Show me some code like what I will actually read and write * `callPackage`, formal arguments, expressions in files ## "Read Nix Pills" * People who say this must not actually have even read Nix Pills * Actual quote from Nix Pills: > These articles are not a tutorial on using Nix. Instead, we're going to walk through the Nix system to understand the fundamentals.  * What do people I know ask me over and over? * What do people I work with not know? * How can they start forming their own solutions? * What are the most basic concrete things they need to do? --- # What I aim to do in my articles * Nix Shorts: 6 articles * My Blog Posts: 113 articles
## A single topic Not "philosophical", just one problem Should be fairly independent to consume ## A definition What does the topic mean, literally? --- ## Demonstration, with commands and code Code with explanation of intention and expected/actual output is * more useful than some kind of vague description * provides for the reader to form their own connections * reproducible, physically or not and resistant to API changes ### "The examples will go out of date" Did you explain well enough what is in the input and how it relates to the result? If yes: user can read changelogs and map the new interfaces to what is written If no: then maybe consider putting a bit more effort in this next time ### "The topic will go out of date" Yes, but also no. --- ## Explanations of unfamiliar bits Unfamiliar items are explicitly explained as much as possible If the explanation is insufficient, users can search further from this Fairly similar to the previous point about demonstrations, but this is more about "prerequisite knowledge" ### Don't treat readers like children Analogies should be brief, real details should be properly addressed ### "It's impossible to talk about the real things because it's endlessly complex" What is the difference between popular science news article, an undergrad biology textbook, and a microbiology textbook? Further: next slide --- ## Links to other resources You don't actually need to explain everything ...If you don't trap your users in a closed ecosystem No walled gardens; Almost no ideas are actually novel Referring to existing work saves everyone time Confusing topic might be illuminated by extra resources --- ## Doesn't have to be read Not every word even has to be read Skim through, read code, review when code is not readily understood "Narrative flow" often not even actually a thing Length of writing usually a sign that something is * too vague * too large in scope * overembellished --- .left[ ## No moral messaging "What you have been doing is WRONG/BAD" Only suggestions/starting points Don't put this god damn image in your docs: ] .right[
] --- # The main things I expect from other articles * A single topic * A definition * Demonstration, with commands and code * Explanations of unfamiliar bits * Links to other resources * Doesn't have to be read * No moral messaging In reality, maybe even half of these would be good to meet. --- # Some extra things writings I dislike do ## Long README with no clear structure The solution is not more tooling to generate structure for your README by generating a table of contents. ## TODO Not even a single minute could be spared ## Analogies stretched too far Burritos, Lego ## Lies and misrepresentations Maybe I'm the only one who cares about this though --- # My hopes for articles in the future Everyone should write with their own ideas of what they want from their writing Nobody should be using these reasons to not write: * "I'm bad at writing" * "I don't want to maintain it" * "I'm too lazy" * "I don't know enough about it" But these are some of the reasons why you might not: * "I'm too lazy" * "I'm not motivated to" --- class: middle ## You might write because * writing reinforces what you know * you can review what you have written yourself * you can help others learn * you can help others gain different perspectives --- class: middle # End Thanks for coming and listening to my rambling Nix Shorts
These slides
Advent of food 2020


Before Change
model.load_weights(weights_file)
elif default_size == 331: // large version
if include_top:
weight_path = NASNET_LARGE_WEIGHT_PATH
model_name = "nasnet_large.h5"
else:
weight_path = NASNET_LARGE_WEIGHT_PATH_NO_TOP
model_name = "nasnet_large_no_top.h5"
weights_file = get_file(model_name, weight_path,
cache_subdir="models")
model.load_weights(weights_file)
else:
After Change
// load weights
if weights == "imagenet":
if default_size == 224: // mobile version
if include_top:
weights_path = get_file(
"nasnet_mobile.h5",
NASNET_MOBILE_WEIGHT_PATH,
cache_subdir="models",
file_hash="020fb642bf7360b370c678b08e0adf61")
else:
weights_path = get_file(
"nasnet_mobile_no_top.h5",
NASNET_MOBILE_WEIGHT_PATH_NO_TOP,
cache_subdir="models",
file_hash="1ed92395b5b598bdda52abe5c0dbfd63")
model.load_weights(weights_path)
elif default_size == 331: // large version
if include_top:
weights_path = get_file(


2. HLS in ROS 2
| Source code | |
|---|---|
simple_adder |
|
| adder1 | |
| kernel 1 | adder1.cpp |
| testbench 1 | testbench1.cpp |
| adder2 | |
| kernel 2 | adder2.cpp |
| testbench 2 | testbench2.cpp |
HLS is at the core of C++ hardware acceleration. KRS allows to maintain a ROS 2-centric view while leveraging HLS, optimizing the flow and empowering roboticists toperform everything from the CLI, attaching nicely to the ROS 2 meta build system (ament
) and the ROS 2 meta build tools (colcon
).
This example demonstrates how KRS helps to transition from the Xilinx's Vitis-centric flow to the ROS 2 flow. The source code performs a trivial add operation. HLS is used directly from the ROS 2 CLI build tools. We explore the possiblities of offloading this operation to the Programmable Logic (PL). The latencies derived from the offloading operation are then analyzed both with the ROS 2 CLI tooling, and later, with the Vitis HLS GUI.
Though we'll be targeting KV260 hardware platform, no physical hardware is needed for this example.
Warning
The examples assume you've already installed KRS. If not, refer to install.
Tip
Learn ROS 2 before trying this out first.
Prepare the environment and fetch the example
$ cd ~/krs_ws # head to your KRS workspace
# prepare the environment
$ source /tools/Xilinx/Vitis/2020.2/settings64.sh # source Xilinx tools
$ source /opt/ros/foxy/setup.bash # Sources system ROS 2 installation
$ export PATH="/usr/bin":$PATH # FIXME: adjust path for CMake 3.5+
# fetch the source code of examples
$ git clone https://github.com/ros-acceleration/acceleration_examples src/acceleration_examples
# build the workspace
$ colcon build --merge-install # about 2 mins
# source the workspace as an overlay
$ source install/setup.bash
A bit of background on HLS, RTL and FPGAs
About C simulation
HLS C Simulation performs a pre-synthesis validation and checks that that the C program correctly implements the required functionality. This allows you to compile, simulate, and debug the C/C++ algorithm. C simulation allows for the function to be synthesized (e.g. simple_adder
above) to be validated with a test bench using C simulation. A C test bench includes a main() top-level function, that calls the function to be synthesized by the Vitis HLS project. The test bench can also include other functions.
Refer to Verifying Code with C Simulation for more.
About Synthesis
Synthesis transforms the C or C++ function into RTL code for acceleration in programmable logic. HLS allows you to control synthesis process using optimization pragmas to create high-performance implementations.
Refer to Synthesizing the Code for more.
A further understanding of the synthesis summary view
The synthesis summary view provides lots of information with different fields which may not always be self-explanatory. The list below tries to clarify some of the most relevant ones:
- Slack: displays any timing issues in the implementation.
- Latency(cycles)/Latency(ns): displays the number of cycles it takes to produce the output. The same information is also displayed in ns.
- Iteration Latency: latency of a single iteration for a loop.
- Interval: Interval or Initiation Interval (II) is the number of clock cycles before new inputs can be applied.
- Trip Count: displays the number of iterations of a specific loop in the implemented hardware. This reflects any unrolling of the loop in hardware.
A quick review of the resources in an FPGA
Xilinx FPGA designs contain the following core components: Configurable Logic Blocks (CLBs), Programmable Routing Blocks (PRBs), I/O Blocks (IOBs) and Digital Signal Processors (DSPs). Within CLBs we have 4 sub-components: Flip-flops (FFs), Loop-up-tables (LUTs), multiplexers (MUXs) and SRAM.
When accounting for resources consumed, we focus particularly on the following which are further defined below:
- DSP: DSPs have been optimized to implement various common digital signal processing functions with maximum performance and minimum logic resource utilization. They have functions to provide multipliers, adders, substractors, accumulators, coefficient register storage or a summation unit, amongst others.
- FF: they are the smallest storage resource on the FPGA and each FF within a CLB is a binary register used to save logic states between clock cycles on an FPGA circuit.
- LUT: stores a predefined list of outputs for every combination of inputs. LUTs provide a fast way to retrieve the output of a logic operation because possible results are stored and then referenced, rather than calculated.
- URAM: UltraRAM is a large, lightweight memory block intended to allow the replacement of off-board memories enabling better overall performance.
simple_adder1
: a quick look into the flow
simple_adder
is pretty straightforward:
1 2 3 4 5 |
|
We can build this example packaged as a ROS package (though it doesn't interact with the computational graph) as follows:
$ colcon acceleration select kv260 # select the KV260 firmware
$ colcon build --merge-install --build-base=build-kv260 --install-base=install-kv260 --mixin kv260 --packages-select simple_adder
The simple_adder
package uses the vitis_hls_generate_tcl
macro on its CMakeLists.txt. This macro commands the build system (ament
) that when the package is built it should generate a Tcl script for simple_adder
. This Tcl script will allow architects with HLS experience to use the traditional HLS interface to further optimize and investigate the kernel through C simulation, synthesis, RTL simulation, etc.
Here's a peek to the macro syntax used:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
The Xilinx Tcl traditional path
When using the vitis_hls_generate_tcl
macro above, a script is automatically generated under ~/krs_ws/build-kv60/simple_adder/project_simpleadder1.tcl
:
open_project -reset project_simpleadder1
add_files /home/xilinx/ros2_ws/src/xilinx/xilinx_examples/simple_adder/src/adder1.cpp
add_files -tb /home/xilinx/ros2_ws/src/xilinx/xilinx_examples/simple_adder/src/testbench.cpp -cflags "-isystem /home/xilinx/ros2_ws/src/xilinx/xilinx_examples/simple_adder/include"
set_top simple_adder
# solution_4ns
open_solution solution_4ns
set_part {xczu9eg-ffvb1156-2-e}
create_clock -period 4
csim_design -ldflags "-lOpenCL" -profile
csynth_design
# solution_10ns
open_solution solution_10ns
set_part {xczu9eg-ffvb1156-2-e}
create_clock -period 10
csim_design -ldflags "-lOpenCL" -profile
csynth_design
exit
vitis_hls -f <file-name>
allowing to perform C simulation and synthesis (in this particular case).
$ vitis_hls -f project_simpleadder1.tcl
****** Vitis HLS - High-Level Synthesis from C, C++ and OpenCL v2020.2.2 (64-bit)
**** SW Build 3118627 on Tue Feb 9 05:13:49 MST 2021
**** IP Build 3115676 on Tue Feb 9 10:48:11 MST 2021
** Copyright 1986-2021 Xilinx, Inc. All Rights Reserved.
source /tools/Xilinx/Vitis_HLS/2020.2/scripts/vitis_hls/hls.tcl -notrace
INFO: [HLS 200-10] Running '/tools/Xilinx/Vitis_HLS/2020.2/bin/unwrapped/lnx64.o/vitis_hls'
INFO: [HLS 200-10] For user 'xilinx' on host 'xilinx' (Linux_x86_64 version 5.10.37-rt39-tsn-measurements) on Sat Jul 10 07:39:11 CEST 2021
INFO: [HLS 200-10] On os Ubuntu 20.04.2 LTS
INFO: [HLS 200-10] In directory '/home/xilinx/ros2_ws/build-zcu102/simple_adder'
Sourcing Tcl script 'project_simpleadder1.tcl'
INFO: [HLS 200-1510] Running: open_project -reset project_simpleadder1
INFO: [HLS 200-10] Opening and resetting project '/home/xilinx/ros2_ws/build-zcu102/simple_adder/project_simpleadder1'.
WARNING: [HLS 200-40] No /home/xilinx/ros2_ws/build-zcu102/simple_adder/project_simpleadder1/solution_4ns/solution_4ns.aps file found.
WARNING: [HLS 200-40] No /home/xilinx/ros2_ws/build-zcu102/simple_adder/project_simpleadder1/solution_10ns/solution_10ns.aps file found.
INFO: [HLS 200-1510] Running: add_files /home/xilinx/ros2_ws/src/xilinx/xilinx_examples/simple_adder/src/adder1.cpp
INFO: [HLS 200-10] Adding design file '/home/xilinx/ros2_ws/src/xilinx/xilinx_examples/simple_adder/src/adder1.cpp' to the project
INFO: [HLS 200-1510] Running: add_files -tb /home/xilinx/ros2_ws/src/xilinx/xilinx_examples/simple_adder/src/testbench.cpp -cflags -isystem /home/xilinx/ros2_ws/src/xilinx/xilinx_examples/simple_adder/include
INFO: [HLS 200-10] Adding test bench file '/home/xilinx/ros2_ws/src/xilinx/xilinx_examples/simple_adder/src/testbench.cpp' to the project
INFO: [HLS 200-1510] Running: set_top simple_adder
INFO: [HLS 200-1510] Running: open_solution solution_4ns
INFO: [HLS 200-10] Creating and opening solution '/home/xilinx/ros2_ws/build-zcu102/simple_adder/project_simpleadder1/solution_4ns'.
INFO: [HLS 200-1505] Using default flow_target 'vivado'
Resolution: For help on HLS 200-1505 see www.xilinx.com/cgi-bin/docs/rdoc?v=2020.2;t=hls+guidance;d=200-1505.html
INFO: [HLS 200-1510] Running: set_part xczu9eg-ffvb1156-2-e
INFO: [HLS 200-10] Setting target device to 'xczu9eg-ffvb1156-2-e'
INFO: [HLS 200-1510] Running: create_clock -period 4
INFO: [SYN 201-201] Setting up clock 'default' with a period of 4ns.
INFO: [HLS 200-1510] Running: csim_design -ldflags -lOpenCL -profile
INFO: [SIM 211-2] *************** CSIM start ***************
INFO: [SIM 211-4] CSIM will launch CLANG as the compiler.
Compiling ../../../../../../src/xilinx/xilinx_examples/simple_adder/src/testbench.cpp in debug mode
Compiling ../../../../../../src/xilinx/xilinx_examples/simple_adder/src/adder1.cpp in debug mode
Generating csim.exe
Expected result: 100, Got Result: 100
Expected result: 103, Got Result: 103
Expected result: 106, Got Result: 106
Expected result: 109, Got Result: 109
Expected result: 112, Got Result: 112
Expected result: 115, Got Result: 115
Expected result: 118, Got Result: 118
Expected result: 121, Got Result: 121
Expected result: 124, Got Result: 124
Expected result: 127, Got Result: 127
Generating dot files
INFO: [SIM 211-1] CSim done with 0 errors.
INFO: [SIM 211-3] *************** CSIM finish ***************
INFO: [HLS 200-111] Finished Command csim_design CPU user time: 0.65 seconds. CPU system time: 0.31 seconds. Elapsed time: 0.8 seconds; current allocated memory: 195.056 MB.
INFO: [HLS 200-1510] Running: csynth_design
INFO: [HLS 200-111] Finished File checks and directory preparation: CPU user time: 0 seconds. CPU system time: 0 seconds. Elapsed time: 0 seconds; current allocated memory: 195.260 MB.
INFO: [HLS 200-10] Analyzing design file '/home/xilinx/ros2_ws/src/xilinx/xilinx_examples/simple_adder/src/adder1.cpp' ...
INFO: [HLS 200-111] Finished Source Code Analysis and Preprocessing: CPU user time: 0.13 seconds. CPU system time: 0.09 seconds. Elapsed time: 0.23 seconds; current allocated memory: 195.911 MB.
INFO: [HLS 200-777] Using interface defaults for 'Vivado' flow target.
INFO: [HLS 200-111] Finished Compiling Optimization and Transform: CPU user time: 2.84 seconds. CPU system time: 0.26 seconds. Elapsed time: 3.23 seconds; current allocated memory: 196.203 MB.
INFO: [HLS 200-111] Finished Checking Pragmas: CPU user time: 0 seconds. CPU system time: 0 seconds. Elapsed time: 0 seconds; current allocated memory: 196.220 MB.
INFO: [HLS 200-10] Starting code transformations ...
INFO: [HLS 200-111] Finished Standard Transforms: CPU user time: 0.01 seconds. CPU system time: 0 seconds. Elapsed time: 0.01 seconds; current allocated memory: 197.187 MB.
INFO: [HLS 200-10] Checking synthesizability ...
INFO: [HLS 200-111] Finished Checking Synthesizability: CPU user time: 0.01 seconds. CPU system time: 0 seconds. Elapsed time: 0.01 seconds; current allocated memory: 196.621 MB.
INFO: [HLS 200-111] Finished Loop, function and other optimizations: CPU user time: 0.03 seconds. CPU system time: 0.01 seconds. Elapsed time: 0.04 seconds; current allocated memory: 216.648 MB.
INFO: [HLS 200-111] Finished Architecture Synthesis: CPU user time: 0.02 seconds. CPU system time: 0 seconds. Elapsed time: 0.02 seconds; current allocated memory: 208.313 MB.
INFO: [HLS 200-10] Starting hardware synthesis ...
INFO: [HLS 200-10] Synthesizing 'simple_adder' ...
INFO: [HLS 200-10] ----------------------------------------------------------------
INFO: [HLS 200-42] -- Implementing module 'simple_adder'
INFO: [HLS 200-10] ----------------------------------------------------------------
INFO: [SCHED 204-11] Starting scheduling ...
INFO: [SCHED 204-11] Finished scheduling.
INFO: [HLS 200-111] Finished Scheduling: CPU user time: 0.01 seconds. CPU system time: 0 seconds. Elapsed time: 0.02 seconds; current allocated memory: 208.520 MB.
INFO: [BIND 205-100] Starting micro-architecture generation ...
INFO: [BIND 205-101] Performing variable lifetime analysis.
INFO: [BIND 205-101] Exploring resource sharing.
INFO: [BIND 205-101] Binding ...
INFO: [BIND 205-100] Finished micro-architecture generation.
INFO: [HLS 200-111] Finished Binding: CPU user time: 0.01 seconds. CPU system time: 0 seconds. Elapsed time: 0.01 seconds; current allocated memory: 208.601 MB.
INFO: [HLS 200-10] ----------------------------------------------------------------
INFO: [HLS 200-10] -- Generating RTL for module 'simple_adder'
INFO: [HLS 200-10] ----------------------------------------------------------------
INFO: [RTGEN 206-500] Setting interface mode on port 'simple_adder/a' to 'ap_none'.
INFO: [RTGEN 206-500] Setting interface mode on port 'simple_adder/b' to 'ap_none'.
INFO: [RTGEN 206-500] Setting interface mode on function 'simple_adder' to 'ap_ctrl_hs'.
INFO: [RTGEN 206-100] Finished creating RTL model for 'simple_adder'.
INFO: [HLS 200-111] Finished Creating RTL model: CPU user time: 0.01 seconds. CPU system time: 0.01 seconds. Elapsed time: 0.01 seconds; current allocated memory: 208.723 MB.
INFO: [HLS 200-111] Finished Generating all RTL models: CPU user time: 0.8 seconds. CPU system time: 0.01 seconds. Elapsed time: 0.82 seconds; current allocated memory: 214.826 MB.
INFO: [VHDL 208-304] Generating VHDL RTL for simple_adder.
INFO: [VLOG 209-307] Generating Verilog RTL for simple_adder.
INFO: [HLS 200-789] **** Estimated Fmax: 984.25 MHz
INFO: [HLS 200-111] Finished Command csynth_design CPU user time: 3.9 seconds. CPU system time: 0.38 seconds. Elapsed time: 4.43 seconds; current allocated memory: 215.042 MB.
INFO: [HLS 200-1510] Running: open_solution solution_10ns
INFO: [HLS 200-10] Creating and opening solution '/home/xilinx/ros2_ws/build-zcu102/simple_adder/project_simpleadder1/solution_10ns'.
INFO: [HLS 200-1505] Using default flow_target 'vivado'
Resolution: For help on HLS 200-1505 see www.xilinx.com/cgi-bin/docs/rdoc?v=2020.2;t=hls+guidance;d=200-1505.html
INFO: [HLS 200-1510] Running: set_part xczu9eg-ffvb1156-2-e
INFO: [HLS 200-1510] Running: create_clock -period 10
INFO: [SYN 201-201] Setting up clock 'default' with a period of 10ns.
INFO: [HLS 200-1510] Running: csim_design -ldflags -lOpenCL -profile
INFO: [SIM 211-2] *************** CSIM start ***************
INFO: [SIM 211-4] CSIM will launch CLANG as the compiler.
Compiling ../../../../../../src/xilinx/xilinx_examples/simple_adder/src/testbench.cpp in debug mode
Compiling ../../../../../../src/xilinx/xilinx_examples/simple_adder/src/adder1.cpp in debug mode
Generating csim.exe
Expected result: 100, Got Result: 100
Expected result: 103, Got Result: 103
Expected result: 106, Got Result: 106
Expected result: 109, Got Result: 109
Expected result: 112, Got Result: 112
Expected result: 115, Got Result: 115
Expected result: 118, Got Result: 118
Expected result: 121, Got Result: 121
Expected result: 124, Got Result: 124
Expected result: 127, Got Result: 127
Generating dot files
INFO: [SIM 211-1] CSim done with 0 errors.
INFO: [SIM 211-3] *************** CSIM finish ***************
INFO: [HLS 200-111] Finished Command csim_design CPU user time: 0.45 seconds. CPU system time: 0.25 seconds. Elapsed time: 0.71 seconds; current allocated memory: 204.178 MB.
INFO: [HLS 200-1510] Running: csynth_design
INFO: [HLS 200-111] Finished File checks and directory preparation: CPU user time: 0.01 seconds. CPU system time: 0 seconds. Elapsed time: 0.01 seconds; current allocated memory: 204.280 MB.
INFO: [HLS 200-10] Analyzing design file '/home/xilinx/ros2_ws/src/xilinx/xilinx_examples/simple_adder/src/adder1.cpp' ...
INFO: [HLS 200-111] Finished Source Code Analysis and Preprocessing: CPU user time: 0.12 seconds. CPU system time: 0.1 seconds. Elapsed time: 0.23 seconds; current allocated memory: 204.290 MB.
INFO: [HLS 200-777] Using interface defaults for 'Vivado' flow target.
INFO: [HLS 200-111] Finished Compiling Optimization and Transform: CPU user time: 2.96 seconds. CPU system time: 0.28 seconds. Elapsed time: 3.41 seconds; current allocated memory: 204.363 MB.
INFO: [HLS 200-111] Finished Checking Pragmas: CPU user time: 0 seconds. CPU system time: 0 seconds. Elapsed time: 0 seconds; current allocated memory: 204.364 MB.
INFO: [HLS 200-10] Starting code transformations ...
INFO: [HLS 200-111] Finished Standard Transforms: CPU user time: 0 seconds. CPU system time: 0 seconds. Elapsed time: 0 seconds; current allocated memory: 205.081 MB.
INFO: [HLS 200-10] Checking synthesizability ...
INFO: [HLS 200-111] Finished Checking Synthesizability: CPU user time: 0.01 seconds. CPU system time: 0 seconds. Elapsed time: 0.01 seconds; current allocated memory: 204.483 MB.
INFO: [HLS 200-111] Finished Loop, function and other optimizations: CPU user time: 0.04 seconds. CPU system time: 0.01 seconds. Elapsed time: 0.04 seconds; current allocated memory: 224.451 MB.
INFO: [HLS 200-111] Finished Architecture Synthesis: CPU user time: 0.01 seconds. CPU system time: 0 seconds. Elapsed time: 0.02 seconds; current allocated memory: 216.047 MB.
INFO: [HLS 200-10] Starting hardware synthesis ...
INFO: [HLS 200-10] Synthesizing 'simple_adder' ...
INFO: [HLS 200-10] ----------------------------------------------------------------
INFO: [HLS 200-42] -- Implementing module 'simple_adder'
INFO: [HLS 200-10] ----------------------------------------------------------------
INFO: [SCHED 204-11] Starting scheduling ...
INFO: [SCHED 204-11] Finished scheduling.
INFO: [HLS 200-111] Finished Scheduling: CPU user time: 0.01 seconds. CPU system time: 0 seconds. Elapsed time: 0.02 seconds; current allocated memory: 216.082 MB.
INFO: [BIND 205-100] Starting micro-architecture generation ...
INFO: [BIND 205-101] Performing variable lifetime analysis.
INFO: [BIND 205-101] Exploring resource sharing.
INFO: [BIND 205-101] Binding ...
INFO: [BIND 205-100] Finished micro-architecture generation.
INFO: [HLS 200-111] Finished Binding: CPU user time: 0.01 seconds. CPU system time: 0 seconds. Elapsed time: 0.01 seconds; current allocated memory: 216.140 MB.
INFO: [HLS 200-10] ----------------------------------------------------------------
INFO: [HLS 200-10] -- Generating RTL for module 'simple_adder'
INFO: [HLS 200-10] ----------------------------------------------------------------
INFO: [RTGEN 206-500] Setting interface mode on port 'simple_adder/a' to 'ap_none'.
INFO: [RTGEN 206-500] Setting interface mode on port 'simple_adder/b' to 'ap_none'.
INFO: [RTGEN 206-500] Setting interface mode on function 'simple_adder' to 'ap_ctrl_hs'.
INFO: [RTGEN 206-100] Finished creating RTL model for 'simple_add<er'.
INFO: [HLS 200-111] Finished Creating RTL model: CPU user time: 0.01 seconds. CPU system time: 0 seconds. Elapsed time: 0.01 seconds; current allocated memory: 216.195 MB.
INFO: [HLS 200-111] Finished Generating all RTL models: CPU user time: 0.75 seconds. CPU system time: 0.02 seconds. Elapsed time: 0.77 seconds; current allocated memory: 216.821 MB.
INFO: [VHDL 208-304] Generating VHDL RTL for simple_adder.
INFO: [VLOG 209-307] Generating Verilog RTL for simple_adder.
INFO: [HLS 200-789] **** Estimated Fmax: 984.25 MHz
INFO: [HLS 200-111] Finished Command csynth_design CPU user time: 3.96 seconds. CPU system time: 0.41 seconds. Elapsed time: 4.57 seconds; current allocated memory: 216.911 MB.
INFO: [HLS 200-112] Total CPU user time: 11.55 seconds. Total CPU system time: 1.84 seconds. Total elapsed time: 12.47 seconds; peak allocated memory: 224.451 MB.
INFO: [Common 17-206] Exiting vitis_hls at Sat Jul 10 07:39:24 2021...
With KRS, we can avoid using Tcl and use instead the ROS 2 extensions to colcon
to easily perform C simulation, synthesis, implementation and more. Before running things, ROS 2 tools will dump the following status:
$ colcon acceleration hls simple_adder
Project: project_simpleadder2
Path: /home/xilinx/krs_ws/build-kv260/simple_adder/project_simpleadder2
- Solution: solution_4ns
- C Simulation: Not Run
- C Synthesis: Not Run
- C/RTL Co-simulation: Not Run
- Export:
- IP Catalog: Not Run
- System Generator: Not Run
- Export Evaluation: Not Run
- Solution: solution_10ns
- C Simulation: Not Run
- C Synthesis: Not Run
- C/RTL Co-simulation: Not Run
- Export:
- IP Catalog: Not Run
- System Generator: Not Run
- Export Evaluation: Not Run
Project: project_simpleadder1
Path: /home/xilinx/krs_ws/build-kv260/simple_adder/project_simpleadder1
- Solution: solution_4ns
- C Simulation: Not Run
- C Synthesis: Not Run
- C/RTL Co-simulation: Not Run
- Export:
- IP Catalog: Not Run
- System Generator: Not Run
- Export Evaluation: Not Run
Let's run it and get some results:
$ colcon acceleration hls simple_adder --run
Found Tcl script "project_simpleadder2.tcl" for package: simple_adder
Executing /home/xilinx/krs_ws/build-kv260/simple_adder/project_simpleadder2.tcl
Found Tcl script "project_simpleadder1.tcl" for package: simple_adder
Executing /home/xilinx/krs_ws/build-kv260/simple_adder/project_simpleadder1.tcl
Project: project_simpleadder2
Path: /home/xilinx/krs_ws/build-kv260/simple_adder/project_simpleadder2
- Solution: solution_4ns
- C Simulation: Pass
- C Synthesis: Run
- C/RTL Co-simulation: Not Run
- Export:
- IP Catalog: Not Run
- System Generator: Not Run
- Export Evaluation: Not Run
- Solution: solution_10ns
- C Simulation: Pass
- C Synthesis: Run
- C/RTL Co-simulation: Not Run
- Export:
- IP Catalog: Not Run
- System Generator: Not Run
- Export Evaluation: Not Run
Project: project_simpleadder1
Path: /home/xilinx/krs_ws/build-kv260/simple_adder/project_simpleadder1
- Solution: solution_4ns
- C Simulation: Pass
- C Synthesis: Run
- C/RTL Co-simulation: Not Run
- Export:
- IP Catalog: Not Run
- System Generator: Not Run
- Export Evaluation: Not Run
If we want to inspect the results from the CLI, we can add the --synthesis-report
flag:
$ colcon acceleration hls simple_adder --synthesis-report
...
Project: project_simpleadder1
Path: /home/xilinx/krs_ws/build-kv260/simple_adder/project_simpleadder1
- Solution: solution_4ns
- C Simulation: Pass
- C Synthesis: Run
- C/RTL Co-simulation: Not Run
- Export:
- IP Catalog: Not Run
- System Generator: Not Run
- Export Evaluation: Not Run
- Synthesis report: /home/xilinx/krs_ws/build-kv260/simple_adder/project_simpleadder1/solution_4ns/syn/report/simple_adder_csynth.rpt
================================================================
== Vitis HLS Report for 'simple_adder'
================================================================
* Date: Sun Aug 22 15:58:31 2021
* Version: 2020.2.2 (Build 3118627 on Tue Feb 9 05:13:49 MST 2021)
* Project: project_simpleadder1
* Solution: solution_4ns (Vitis Kernel Flow Target)
* Product family: zynquplus
* Target device: xck26-sfvc784-2LV-c
================================================================
== Performance Estimates
================================================================
+ Timing:
* Summary:
+--------+---------+----------+------------+
| Clock | Target | Estimated| Uncertainty|
+--------+---------+----------+------------+
|ap_clk | 4.00 ns| 2.016 ns| 1.08 ns|
+--------+---------+----------+------------+
+ Latency:
* Summary:
+---------+---------+----------+----------+-----+-----+---------+
| Latency (cycles) | Latency (absolute) | Interval | Pipeline|
| min | max | min | max | min | max | Type |
+---------+---------+----------+----------+-----+-----+---------+
| 0| 0| 0 ns| 0 ns| 1| 1| none|
+---------+---------+----------+----------+-----+-----+---------+
+ Detail:
* Instance:
N/A
* Loop:
N/A
================================================================
== Utilization Estimates
================================================================
* Summary:
+-----------------+---------+------+--------+--------+-----+
| Name | BRAM_18K| DSP | FF | LUT | URAM|
+-----------------+---------+------+--------+--------+-----+
|DSP | -| -| -| -| -|
|Expression | -| -| 0| 41| -|
|FIFO | -| -| -| -| -|
|Instance | 0| -| 144| 232| -|
|Memory | -| -| -| -| -|
|Multiplexer | -| -| -| 18| -|
|Register | -| -| 37| -| -|
+-----------------+---------+------+--------+--------+-----+
|Total | 0| 0| 181| 291| 0|
+-----------------+---------+------+--------+--------+-----+
|Available | 288| 1248| 234240| 117120| 64|
+-----------------+---------+------+--------+--------+-----+
|Utilization (%) | 0| 0| ~0| ~0| 0|
+-----------------+---------+------+--------+--------+-----+
...
Results show how the simple_adder
function can be implemented with only a few LUTs and using only one single cycle (0 is counted as the first cycle). The FPGA can be programmed to run with a clock at 2.016 ns
(estimated). This means that by using solely 291 LUTs and 181 FFs of the FPGA to build specialized circuitry, we can get deterministic responses when launching the simple_adder
function with a maximum response period of (2.016 ns
(estimated) + 1.08 ns
(uncertainty)). In other words, 3.09600
ns.
Let's compare this with the results we may get if we were to run this (only) on the PS system witout relying on the FPGA. The Zynq UltraScale+ MPSoC targeted uses Quad-core Arm Cortex-A53 which has a CPU frequency of up to 1.5 GHz. Since the clock of the processor can theoretically run at 1.5 GHz, this means that one cycle has a period of approximately 0.666 ns
. If the CPU were to be able to fit the whole function into one cycle, this would is indeed better than the 3.09600 ns
we estimated before when using the FPGA, however, things aren't that easy. Neither Von-Neumann-based CPU architectures can fit all operations into one cycle nor adaptive SoCs like the Zynq UltraScale+ MPSoC can leverage hardware acceleration without considering the interfacing with the FPGA. The following considerations should be taken into account:
-
CPUs control-driven machine model is based on a token of control, which indicates when a statement should be executed. This gives CPUs full control to implement easily complex data and control structures however, this also comes at the cost of being less efficient since every operation needs to push data in-and-out of ALUs (each operation needs to be managed in this control flow mechanism). Ultimately this leads to multiple cycles for even the simplest operations like what's illustrated in
simple_adder
above. -
Besides the additional cycles required for the sole computation, the PS deals with tons of complex aspects that may very easily interrupt the computation, produce a switch of context and get back to the computation of
simple_adder
afterwards. Even in a somewhat ideal scenario, with a soft/firm real-time operating system running on the PS, the kernel can incur on delays of several tenths of microseconds. -
FPGAs offer a deterministic response which can be specially exploited when relying onits resources, e.g. while driving I/O directly. In adaptive SoCs, interfacing the Processing System (PS, the CPU), with the Programmable Logic (PL, the FPGA) has a time/cycle cost which should be considered. If the output of the function/kernel is to return to the PS, one should account for the complexity of such function/kernel. In very simple examples like the
simple_adder
above, this cost of interfacing PS-PL is generally much bigger than the optimizations one could get and the determinism is essentially degraded due to the involvement of the CPU.
Using the Vitis HLS GUI
The project files generated by ROS 2 CLI tools can also be opened with vitis_hls
GUI by pointing to the new project folder created. Within the Vitis HLS GUI, the various reports generated can be inspected graphically:
(click on the images to see them big)
The data that we just inspected through Vitis HLS GUI is available in reports which can be parsed and exposed in a CLI interface. KRS does exactly this. KRS provides a series of CLI verbs and subverbs that allow to fetch this information directly from the CLI allowing ROS developers to create their own development flows.
Let's now complicate a bit more the simple_adder
function and see how faster clocks aren't alwasy better. Specially, we show how FPGAs can be optimized to fit operations in less cycles delivering lower latencies.
simple_adder2
: optimizing FPGA synthesis for lower latency responses
The source code of simple_adder2
will now be the following:
simple_adder source code
1 2 3 4 5 |
|
The CMakeLists.txt file uses now a different testbench and kernel source code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Note that the macro will generate one solution per each CLOCK
(in ns) argument provided.
Let's compare the Schedule Viewer of the 4 ns
and 10 ns
clock solutions. These were generated with a different firmware (zcu102
). Similar ones can be also obtained with the KV260 board. See Hello Xilinx example if you need to recap on how to switch between multiple firmware options ;).
(Click on each image to see it big)
| Image | Comments |
|---|---|
Targeting 4 ns clock. Note the whole operation takes 4 cycles. |
|
Targeting 10 ns clock. Note the whole operation takes 2 cycles. |
Futher inspecting the solutions with colcon
CLI extensions:
$ colcon krs hls simple_adder --synthesis-report
Project: project_simpleadder2
Path: /home/xilinx/krs_ws/build-kv260/simple_adder/project_simpleadder2
- Solution: solution_4ns
- C Simulation: Pass
- C Synthesis: Run
- C/RTL Co-simulation: Not Run
- Export:
- IP Catalog: Not Run
- System Generator: Not Run
- Export Evaluation: Not Run
- Synthesis report: /home/xilinx/krs_ws/build-kv260/simple_adder/project_simpleadder2/solution_4ns/syn/report/simple_adder_csynth.rpt
================================================================
== Vitis HLS Report for 'simple_adder'
================================================================
* Date: Sun Aug 22 15:58:17 2021
* Version: 2020.2.2 (Build 3118627 on Tue Feb 9 05:13:49 MST 2021)
* Project: project_simpleadder2
* Solution: solution_4ns (Vitis Kernel Flow Target)
* Product family: zynquplus
* Target device: xck26-sfvc784-2LV-c
================================================================
== Performance Estimates
================================================================
+ Timing:
* Summary:
+--------+---------+----------+------------+
| Clock | Target | Estimated| Uncertainty|
+--------+---------+----------+------------+
|ap_clk | 4.00 ns| 2.365 ns| 1.08 ns|
+--------+---------+----------+------------+
+ Latency:
* Summary:
+---------+---------+-----------+-----------+-----+-----+---------+
| Latency (cycles) | Latency (absolute) | Interval | Pipeline|
| min | max | min | max | min | max | Type |
+---------+---------+-----------+-----------+-----+-----+---------+
| 5| 5| 20.000 ns| 20.000 ns| 6| 6| none|
+---------+---------+-----------+-----------+-----+-----+---------+
+ Detail:
* Instance:
N/A
* Loop:
N/A
================================================================
== Utilization Estimates
================================================================
* Summary:
+-----------------+---------+------+--------+--------+-----+
| Name | BRAM_18K| DSP | FF | LUT | URAM|
+-----------------+---------+------+--------+--------+-----+
|DSP | -| -| -| -| -|
|Expression | -| -| 0| 41| -|
|FIFO | -| -| -| -| -|
|Instance | 0| 0| 639| 379| -|
|Memory | -| -| -| -| -|
|Multiplexer | -| -| -| 46| -|
|Register | -| -| 106| -| -|
+-----------------+---------+------+--------+--------+-----+
|Total | 0| 0| 745| 466| 0|
+-----------------+---------+------+--------+--------+-----+
|Available | 288| 1248| 234240| 117120| 64|
+-----------------+---------+------+--------+--------+-----+
|Utilization (%) | 0| 0| ~0| ~0| 0|
+-----------------+---------+------+--------+--------+-----+
...
- Solution: solution_10ns
- C Simulation: Pass
- C Synthesis: Run
- C/RTL Co-simulation: Not Run
- Export:
- IP Catalog: Not Run
- System Generator: Not Run
- Export Evaluation: Not Run
- Synthesis report: /home/xilinx/krs_ws/build-kv260/simple_adder/project_simpleadder2/solution_10ns/syn/report/simple_adder_csynth.rpt
================================================================
== Vitis HLS Report for 'simple_adder'
================================================================
* Date: Sun Aug 22 15:58:23 2021
* Version: 2020.2.2 (Build 3118627 on Tue Feb 9 05:13:49 MST 2021)
* Project: project_simpleadder2
* Solution: solution_10ns (Vitis Kernel Flow Target)
* Product family: zynquplus
* Target device: xck26-sfvc784-2LV-c
================================================================
== Performance Estimates
================================================================
+ Timing:
* Summary:
+--------+----------+----------+------------+
| Clock | Target | Estimated| Uncertainty|
+--------+----------+----------+------------+
|ap_clk | 10.00 ns| 5.436 ns| 2.70 ns|
+--------+----------+----------+------------+
+ Latency:
* Summary:
+---------+---------+-----------+-----------+-----+-----+---------+
| Latency (cycles) | Latency (absolute) | Interval | Pipeline|
| min | max | min | max | min | max | Type |
+---------+---------+-----------+-----------+-----+-----+---------+
| 1| 1| 10.000 ns| 10.000 ns| 2| 2| none|
+---------+---------+-----------+-----------+-----+-----+---------+
+ Detail:
* Instance:
N/A
* Loop:
N/A
================================================================
== Utilization Estimates
================================================================
* Summary:
+-----------------+---------+------+--------+--------+-----+
| Name | BRAM_18K| DSP | FF | LUT | URAM|
+-----------------+---------+------+--------+--------+-----+
|DSP | -| -| -| -| -|
|Expression | -| -| 0| 41| -|
|FIFO | -| -| -| -| -|
|Instance | 0| 0| 144| 292| -|
|Memory | -| -| -| -| -|
|Multiplexer | -| -| -| 32| -|
|Register | -| -| 70| -| -|
+-----------------+---------+------+--------+--------+-----+
|Total | 0| 0| 214| 365| 0|
+-----------------+---------+------+--------+--------+-----+
|Available | 288| 1248| 234240| 117120| 64|
+-----------------+---------+------+--------+--------+-----+
|Utilization (%) | 0| 0| ~0| ~0| 0|
+-----------------+---------+------+--------+--------+-----+
...
We observe how using a target 10 ns
clock (which is slower than 4 ns
) leads to a) the use of less LUT and FF resources and b) a lower latency (due to a smaller number of cycles required). It's pretty interesting to note that getting a higher frequency in the clock does not necesarily mean we'll obtain a lower period for the function. This happens very clearly in this case.
colcon
CLI tooling also allows to obtain a quick summary of all the solutions to evaluate time and use of resources:
$ colcon acceleration hls simple_adder --summary
# /home/xilinx/krs_ws/build-kv260/simple_adder/project_simpleadder2.tcl
Solution# tar.clk est.clk latency_max BRAM_18K DSP FF LUT
solution_10ns 10.00 5.436 10.000 0 (0%) 0 (0%) 214 (~0%) 365 (~0%)
solution_4ns 4.00 2.365 20.000 0 (0%) 0 (0%) 745 (~0%) 466 (~0%)
# /home/xilinx/krs_ws/build-kv260/simple_adder/project_simpleadder1.tcl
Solution# tar.clk est.clk latency_max BRAM_18K DSP FF LUT
solution_4ns 4.00 2.016 0 0 (0%) 0 (0%) 181 (~0%) 291 (~0%)


Your de-identified data is combined with lots of other data. All that data will be used and reused for new research. Watch the video below to learn about what happens to your data, and read more about it here (opens in a new tab).
What happens to your data
Your de-identified data is combined with lots of other data. All that data will be used and reused for new research. Watch the video below to learn about what happens to your data, and read more about it here (opens in a new tab).


0.13.5 Release : I Missed My Lunch
The PiTiVi team is proud to announce the fifth release in the 0.13 PiTiVi series.
Due to its dependency on GStreamer, The PiTiVi team strongly recommends users have all official latest gstreamer libraries and plugins installed for the best user experience.
Features of this release
- periodic backup of the current project file
- easy crossfading transitions of overlapping clips
- better icons for link and group operations
- new add keyframe button
- fixed support for the missing plugins installer
- improved support for pictures
- various performance improvements (less conversions, faster linking)
Requirements
- gstreamer >= 0.10.28
- gst-python >= 0.10.19
- gnonlin >= 0.10.16
- pygtk >= 2.14.0
- Python >= 2.5
- zope.interface (http://www.zope.org/Products/ZopeInterface)
- setuptools (http://peak.telecommunity.com/DevCenter/setuptools)
- pygoocanvas (http://live.gnome.org/GooCanvas)
- (optional) dbus and HAL for capture support
Known Issues
- If using gst-plugins-good < 0.10.25 scaling will not add black borders. You will need to set the proper width and height in the project settings
- Some files might not respond when seeking in them the first time
- Keyframe percentage labels are sometimes shown at the wrong position
- See also Performance problems in 0.13.4.

Information and Feedback
- Information for users and developers can be found on the PiTiVi website : http://www.pitivi.org/
- Comments and feedback are welcome.
- Mailing-list<EMAIL_ADDRESS>- PiTiVi bug-tracker : http://bugzilla.gnome.org/browse.cgi?product=pitivi
Bugs Fixed
The results of the search are


{% extends 'layout-bsa.html' %}
{% block pageTitle %}
Which of these are included in your rent? - LIS training - NHSBSA
{% endblock %}
{% block outerContent %}
{% endblock %}
{% block content %}
Before you start
Which of these are included in your rent?


Solve your daily life problems in 1 minute.
Interested in a free chapter? Get it now
“OMG! I cannot believe that I have got a brand new landing page after getting Omega. It was super easy to edit and publish.”
Jonathan Taylor
Chapters we’ve covered
Create custom landing pages with Omega that converts more visitors than any website.
1
Create custom landing pages with Omega that converts more visitors than any website. With lots of unique blocks, you can easily build a page without coding.
With lots of unique blocks, you can easily build a page without coding. Build your next landing page quickly.
With lots of unique blocks, you can easily build a page without coding. Build your next landing page quickly.
With lots of unique blocks, you can easily build a page without coding. Build your next landing page quickly.
Create custom landing pages with Omega that converts more visitors than any website.
Get a free chapter of this book
Create custom landing pages with Omega that converts more visitors than any website.
Get a free chapterPeople are already reading this
book and improving!
Satisfaction rate comes from our
awesome customers.
Average customer ratings we have
got from Amazon users.
Create custom landing pages with Omega that converts
more visitors than any website.
“You made it so simple. My new
site is so much faster and easier
to work with than my old site. I
just choose the page, make the
change and click save.”
From Amazon.com
“Simply the best. Better than all
the rest. I’d recommend this
product to beginners and
advanced users.”
From Amazon.com
Must have book for students,
who want to be Product
Designer, UX Designer, or
Interaction Designer.
From Amazon.com
Joseph Williams
Hey! My name is Joseph Williams and I'm a product designer based in Berlin. Most
recently I led the design of multiple products at WeWork and prior to that I worked
with startups building their products and design culture.
Previous products I built for the design community are used by tens of thousands of
designers working at companies like Google, Airbnb, Netflix and Boeing. Products I
built or designed are featured in Wired, TechCrunch, Forbes, Quartz, Smashing
Magazine, Awwwards and more.
Reach me on Twitter or Email.


The stunning sequel to the #1 New York Times bestseller Dear Martin. Incarcerated teen Quan writes letters to Justyce about his experiences in the American juvenile justice system. Perfect for fans...
By Kesnel Samuel on Jan 09, 2021
The stunning sequel to the #1 New York Times bestseller Dear Martin. Incarcerated teen Quan writes letters to Justyce about his experiences in the American juvenile justice system. Perfect for fans...
By Kesnel Samuel on Feb 13, 2021
The stunning sequel to the #1 New York Times bestseller Dear Martin. Incarcerated teen Quan writes letters to Justyce about his experiences in the American juvenile justice system. Perfect for fans...
By Kesnel Samuel on March 31, 2021
The stunning sequel to the #1 New York Times bestseller Dear Martin. Incarcerated teen Quan writes letters to Justyce about his experiences in the American juvenile justice system. Perfect for fans...
By Kesnel Samuel on Jun 01, 2021


Various Code I've written and contributed to.
github.com/tbaschak/bofhexcuses | tbaschak.github.io/bofhexcuses
HTML5 "excuses" project I forked from colepeters/designerexcuses and gave a BOFH twist.
github.com/tbaschak/check_watchdogs15 | tbaschak.github.io/check_watchdogs15
Nagios plugin I wrote to monitor temperature, humidity, and dewpoint via SNMP from the IT Watchdogs 15/15P.
github.com/tbaschak/check_uptime_snmp
Nagios plugin I modified to monitor system uptime via SNMP.
6paster is a private pastebin clone with TTL values to limit post life. Contributed documentation re: setup with nginx and posting from a here document.
github.com/tbaschak/php-ldap-changepw | tbaschak.github.io/php-ldap-changepw
Old code I wrote for an employer years ago to change a user's LDAP password. Use only as a base for learning, this code is not written with heavy security in mind.


AxesHelper.
An axis object to visualize the 1, 2 or 3 axes. I use AxesHelper in my three.js projects.
Content
- Quick start.
- Use the THREE.OrbitControls to rotate the camera.
- Use Raycaster for mouse picking (working out what objects in the 3d space the mouse is over).
- Choose a point at which the camera is looking.
- Graphical user interface for changing settings.
- Example of your web page.
Quick start
- Create a folder on your localhost named as [folderName].
- Download three.js repository into your "[folderName]\three.js\dev" folder.
- Download commonNodeJS repository into your "[folderName]\commonNodeJS\master" folder.
- Add your web page into [folderName]. Example:
<!DOCTYPE html>

<title>AxesHelper</title>
<link type="text/css" rel="stylesheet" href="https://threejs.org/examples/main.css">

<link type="text/css" rel="stylesheet" href="commonNodeJS/master/css/main.css">

three.js
- AxesHelper.
By anhr

<canvas id="canvas"></canvas>

NOTE. Please include three.THREE = THREE; line into your project before use my library. See example above.
The easiest way to use AxesHelper in your code is import AxesHelper from AxesHelper.js file in your JavaScript module. Example.
import AxesHelper from './commonNodeJS/master/AxesHelper/AxesHelper.js';
Now you can use AxesHelper in your javascript code.
The simplest AxesHelper has at least one axis.
new AxesHelper( scene, options );
Now we want to customize AxesHelper.
Name of the X is 'time'. Number of X scale marks is 5.
Minimum Y is 0.
See options.scales of the AxesHelper for details.
Please edit options for it.
const options = new Options({
scales: {
text: {
//Please specify the textHeight if you want the changing of the text height is available in gui.
//Default textHeight is 0.04
textHeight: 0.04,
//fov: camera.fov,
//Precision of the scale marks is 3 digit.
//Please specify the precision if you want the changing of the precision is available in gui.
//Default precision is 4.
precision: 3,
},
x: {
name: 'time',
marks: 5
},
y: {
min: 0,
},
z: {}
}
});
Use the THREE.OrbitControls to rotate the camera.
Add line after creating of the renderer in your code.
options.createOrbitControls( camera, renderer, scene );
Use Raycaster for mouse picking (working out what objects in the 3d space the mouse is over).
Please create an 3D object, for example points.
- Use THREE.Points.
const arrayFuncs = [
new THREE.Vector3( 0.5, 0.5 ,0.5 ),
new THREE.Vector3( -0.5, -0.5 ,-0.5 )
]
const points = new THREE.Points( new THREE.BufferGeometry().setFromPoints( arrayFuncs ),
new THREE.PointsMaterial( {
color: 0xffffff,
size: 5,//0.05,
sizeAttenuation: false,
alphaTest: 0.5,
} ) );
scene.add( points );
Add event listeners and add points to particles after creating of renderer.
options.eventListeners = new Options.raycaster.EventListeners( camera, renderer, { options: options, scene: scene } );
options.eventListeners.addParticle( points );
For testing please move cursor over point. Cursor will be changing to 'pointer'.
You can see a dot lines from point to axes if you click over point.
You can customize the raycaster events. For example you can display an alert message if user has click over point.
points.userData.raycaster = {
onMouseDown: function ( intersection ) {
alert( 'You have clicked over point.' );
Options.raycaster.onMouseDown( intersection, options );
}
}
See Raycaster#EventListeners for more details.
- Easier way for displaying points is using of MyPoints.
First, import MyPoints.
import MyPoints from './commonNodeJS/master/myPoints/myPoints.js';
Now you can use MyPoints in your javascript code.
MyPoints( [
[],//first point. Zero position. White color.
[ -0.5, 0.5, 0.5 ],//second point. White color.
], scene, { options: options } );
Please call MyPoints after creating of renderer and options.eventListeners if you want to use the pointsOptions.shaderMaterial = false key.
MyPoints( [
[],//first point. Zero position. White color.
[ -0.5, 0.5, 0.5 ],//second point. White color.
], scene, {
options: options,
pointsOptions: { shaderMaterial: false, },
} );
Choose a point at which the camera is looking.
First, import Player.
import Player from './commonNodeJS/master/player/player.js';
See Player API for details.
- Point of THREE.Points is camers target.
Please, add the cameraTarget key into arrayFuncs array and use Player.getPoints for get of the points array for creation of the THREE.Points.
const arrayFuncs = [
new THREE.Vector3( 0.5, 0.5 ,0.5 ),//First point
{
vector: new THREE.Vector3( -0.5, -0.5 ,-0.5 ),
cameraTarget: { camera: camera, },
}//Second point
]
const points = new THREE.Points( new THREE.BufferGeometry().setFromPoints(
Player.getPoints( arrayFuncs, { group: scene, } ),
Player.getItemSize( arrayFuncs ) ),
new THREE.PointsMaterial( {
color: 0xffffff,
size: 5,//0.05,
sizeAttenuation: false,
alphaTest: 0.5,
} ) );
Define points.userData.player and call Player.selectPlayScene(...).
points.userData.player = { arrayFuncs: arrayFuncs, }
Player.selectPlayScene( scene, { options: options } );
ATTENTION!!! Call Player.selectPlayScene( scene, { options: options } ); after creation of the OrbitControls instance in the options.createOrbitControls( camera, renderer, scene ); line.
Now you can see the second point ( position is -0.5, -0.5 ,-0.5 ) in the center of the canvas. In other words, camera look at the second point.
- Point of MyPoints is camera target.
Please remove cameraTarget key from second point of arrayFuncs
const arrayFuncs = [
new THREE.Vector3( 0.5, 0.5 ,0.5 ),//First point
{
vector: new THREE.Vector3( -0.5, -0.5 ,-0.5 ),
//cameraTarget: { camera: camera, },
}//Second point
]
and add cameraTarget to second point of MyPoints
MyPoints( [
[],//first point. Zero position. White color.
{
vector: new THREE.Vector3( -0.5, 0.5, 0.5 ),
cameraTarget: { camera: camera, },
}//second point. White color.
], scene, { options: options } );
Please create MyPoints before Player.selectPlayScene( scene, { options: options } ); line if you want to use the pointsOptions.shaderMaterial = false key.
MyPoints( [
[],//first point. Zero position. White color.
{
vector: new THREE.Vector3( -0.5, 0.5, 0.5 ),
cameraTarget: { camera: camera, },
}//second point. White color.
], scene, {
options: options,
pointsOptions: { shaderMaterial: false, },
} );
Now you can see the second point ( position is -0.5, 0.5, 0.5 ) of MyPoints in the center of the canvas. In other words, camera look at the second point.
Graphical user interface for changing settings.
AxesHelper settings.
Import dat.gui.
import { dat } from './commonNodeJS/master/dat/dat.module.js';
three.dat = dat;
Add AxesHelperGui into dat.gui for manual change settings of the AxesHelper.
Import AxesHelperGui.
import AxesHelperGui from './commonNodeJS/master/AxesHelper/AxesHelperGui.js';
Create AxesHelperGui instance after creating of AxesHelper instance.
AxesHelperGui( options );
Now you can see the "Axes Helper" folder in the dat.gui.
Select a point from the mesh.
Add guiSelectPoint into dat.gui for select a point from the mesh.
Move a group of meshes.
Sometimes you need to move a group of meshes for better visualization. Use MoveGroupGui for it.
Import MoveGroupGui.
import MoveGroupGui from './commonNodeJS/master/MoveGroupGui.js';
Create the MoveGroupGui instance.
new MoveGroupGui( scene, options );
Now you can see the 'Move Group' folder in the dat.gui. You can move, scale and rotate the scene. Unfortunately, you also move the axes. For resolving of the issue, create groupMove and move all your meshes from scene to groupMove.
const groupMove = new THREE.Group();
scene.add( groupMove );
Move groupMove instead of the scene. Replace scene to groupMove in the new MoveGroupGui.
new MoveGroupGui( groupMove, options );
Remove points from scene and add it into groupMove.
//scene.add( points );
groupMove.add( points );
Remove MyPoints from scene and add it into groupMove.
MyPoints( [
[],//first point. Zero position. White color.
{
vector: new THREE.Vector3( -0.5, 0.5, 0.5 ),
cameraTarget: { camera: camera, },
}//second point. White color.
], groupMove, { options: options } );
Example of your web page.
The following code is the result of this tutorial.
<!DOCTYPE html>

<title>AxesHelper</title>
<link type="text/css" rel="stylesheet" href="https://threejs.org/examples/main.css">

<link type="text/css" rel="stylesheet" href="commonNodeJS/master/css/main.css">

three.js
- AxesHelper.
By anhr

<canvas id="canvas"></canvas>

Enjoy my code :)


| Class | Description |
|---|---|
| BooleanSetting |
Boolean Setting
|
| ConfigEntries |
A list of available configuration values.
|
| ConfigEntry |
A configuration value type and the correspodning configuration.
|
| ConfigMap |
A map of configurations for an Installed App.
|
| ConfigurationData |
A request for a pages flow to drive app installation.
|
| ConfigurationResponseData |
Expected response for a Configuration lifecycle execution.
|
| ConfirmationData |
A request to send a confirmation link to a SmartApp for ownership validation.
|
| DecimalSetting |
DECIMAL Setting
|
| DeviceCommandsEvent |
An event that contains commands for devices that were created by this app.
|
| DeviceCommandsEventCommand |
DeviceCommandsEventCommand
|
| DeviceConfig |
A device configuration.
|
| DeviceEvent |
An event on a device that matched a subscription for this app.
|
| DeviceSetting |
Device Setting
|
| EmailSetting |
Email Setting
|
| EnumSetting |
Enum Setting
|
| Event |
The event information, only populated if the execution type is EVENT.
|
| EventData |
The data payload to an execution request with an AppLifecycle of EVENT.
|
| EventResponseData |
Empty object response for an Event lifecycle execution.
|
| ExecutionRequest |
The root model for all executions.
|
| ExecutionResponse |
Expected response structure for an SmartApp execution.
|
| GroupedOption |
GroupedOption
|
| ImageSetting |
Image Setting
|
| ImagesSetting |
Images Setting
|
| InitializeSetting |
The initial setting to be returned when starting a new configuration install.
|
| InstallData |
The data payload to an execution request with an AppLifecycle of INSTALL.
|
| InstalledApp |
The information associated with this installed app.
|
| InstallResponseData |
Empty object response for an Install lifecycle execution.
|
| LinkSetting |
URL link Setting
|
| ModeConfig |
A mode configuration.
|
| ModeEvent |
ModeEvent
|
| ModeSetting |
Mode Setting
|
| NumberSetting |
Number Setting
|
| OAuthCallbackData |
Provides intergration with the result of a third party oauth attempt.
|
| OAuthCallbackResponseData |
Empty object response for an OAuth Callback lifecycle execution.
|
| OAuthSetting |
OAuth Setting
|
| Option |
Option
|
| Page |
Page
|
| PageSetting |
Jump to page Setting
|
| ParagraphSetting |
Paragraph Setting
|
| PasswordSetting |
Password Setting
|
| Permissions |
A list of permissions associated with this execution.
|
| PhoneSetting |
Phone Setting
|
| PingData |
A request to ping a SmartApp to ensure connectivity.
|
| PingResponseData |
Expected response for a Ping lifecycle execution.
|
| SceneSetting |
Scene Setting
|
| Section |
Section
|
| SectionSetting |
SectionSetting
|
| Setting |
Setting
|
| StringConfig |
A simple string configuration.
|
| TextSetting |
Text Setting
|
| TimerEvent |
An event that is caused by a schedule for this app being fired.
|
| TimeSetting |
Time Setting
|
| UninstallData |
The data payload to an execution request with an AppLifecycle of UNINSTALL.
|
| UninstallResponseData |
Empty object response for an Uninstall lifecycle execution.
|
| UpdateData |
The data payload to an execution request with an AppLifecycle of UPDATE.
|
| UpdateResponseData |
Empty object response for an Update lifecycle execution.
|
| VideoSetting |
Video Setting
|
| Enum | Description |
|---|---|
| AppLifecycle |
Every invocation of a SmartApp is associated to a specific lifecycle event.
|
| ConfigEntry.ValueTypeEnum |
The value type.
|
| ConfigurationPhase |
Denotes the current installation phase.
|
| DeviceSetting.PermissionsEnum |
Gets or Sets permissions
|
| EventType |
The type of event passed to the app being executed.
|
| SettingType |
Denotes the type of setting.
|
| StyleType |
Style of the setting.
|
| TimerType |
The type of TIMER_EVENT.
|


COSBench
See:
Description
Description
COSBench (Cloud Object Storage Benchmark) is a benchmark tool that we are developing in Intel with the intention of facilitating both system evaluation and performance optimization.
So far the tool is available under NDA, and we are working on the process to open source it. It has been shared among over 10 entities including both inside and outside Intel.
Distributed Test Architecture
COSBench is with distributed test architecture, in deployment, it contains a few components: controller, driver (a.k.a load generator) and web console. One normal workflow is as following:
- user submits one defined workload (in xml file) through web console to controller,
- controller parses the workload configuration file, and schedules portions of the workload (called mission) to different drivers.
- driver parses its mission and generate loads by following instructions in mission.
- controller regularly collects run-time statistics from drivers and aggregates them.
- web console periodically queries results from controller and shows run-time results.
Modular Framework
COSBench is developed with Java and OSGI-based, which provides good cross platform compatibility and highly modular framework. A few modules (a.k.a. OSGI bundles) are included in COSBench project, below diagram depicts the relationship between them.
Features
COSBench is highly extensible and scalable, with mainly the following features:
We now support Openstack Swift (with either Swauth or Keystone), and amplidata amplistor v2.3, v2.5 and v3.1 system. More adaptors will be added in the future!
|
||||||||||
| PREV NEXT | FRAMES NO FRAMES |


{{ partial "header.html" . }}
Strava athletes upload millions of activities every day
To use the Strava API, you need to comply with the Strava API Agreement and the Brand Guidelines. Mandatory logos, linking and attribution rules can also be found in the guidelines.
Agreement Guidelines


Basic default calendar
Selected Date
Starting week day
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Calendar with custom start date
Calendar with custom events


Skupper examples
Introductory examples
Hello World
A simple multi-service HTTP application that can be deployed across multiple Kubernetes clusters using Skupper. This is our most elemental HTTP example.
Communicating over TCP between two clusters
Our most basic TCP example. It demonstrates TCP communication tunneled through a Skupper network from a private to a public namespace and back again.
HTTP examples
Load balancing HTTP requests across clusters
See how to deploy a set of HTTP server processes across multiple clusters and observe anycast application routing over a Virtual Application Network.
Deploying the Istio Bookinfo example across clusters
See how you can use Skupper to distribute the microservices of the Istio Bookinfo application to multiple public and private clouds.
TCP examples
Accessing a PostgreSQL database in the private cloud
Learn how to share a PostgreSQL database across multiple Kubernetes clusters that are located in different public and private cloud providers.
Deploying a MongoDB replica set across clusters
Learn how to share a MongoDB database across multiple Kubernetes clusters that are located in different public and private cloud providers.


Vera Simon
Our Team Leader, she is in charge on making sure that all the sections in the projects run in perfect condition.
Lambda School alumni, Computer Science background.
DevDesk Queue is a simple platform to get that extra hand while you are coding.
Our Team Leader, she is in charge on making sure that all the sections in the projects run in perfect condition.
Lambda School alumni, Computer Science background.
Our Frontend Engineer, he makes music and reads in his spare time. He is responsible of the frontend features & UI Components, which interact with the backend.
He is currently at Lambda School studying to be a Software Engineer.
Our Web Designer, in her spare time you can find her camping and hiking.
She is currently at Lambda School studying to be a Web Developer.
Our Backend Engineer, he is a musician and is currently at Lambda School studying to be a Software Engineer.
He is responsible for all data Migrations and Seeds set up for mock data.


--- layout: post title: FCGI replacement in the making for Rails categories: [] author: admin published: true date: 2005-09-19 07:20:05.000000000 +01:00 ---
Zed A. Shaw is working on a SCGI implementation in pure Ruby that’ll hopefully make for a more pleasant experience than FCGI once ready. He just announced the v0.3 of the SCGI Rails Runner and I’d encourage everyone to go have a look. It may not yet be ready to dethrone FCGI, but with enough exposure, it’ll hopefully soon be a viable alternative.


Certificate Authority public key The Department of Computer Science has its own Certificate Authority for use with secure connections. This will be used to authenticate the certificates used to secure https connections (such as webmail) as well as secure connections with POP and IMAP. Instructions for downloading and installing the Certificate Authority can be found here.
Account issues What is my quota limit?512Mb is the default quota limit.
How can I tell how much disk space I am using?You can use the `quota -v` command to report your disk utilization and your quota allocation.
My class requires more space than I have available. How can I get my quota increased?Talk to your Professor about your quota needs. They will request a quota increase from the System Administrators
Okay, I am in my account, and it is over quota. What do I do?You can run findhog to see what the 20 largest files in your home directory are. Alternatively, findhog x will find the largest x files in your home directory
There is also a script called rm-junk that goes through your home directory and looks for caches and core files and asks you if you want to remove them. Just type "y" at the prompt and it will delete them for you.
You can get a copy of the default dot files (.bash_profile, .cshrc, .login, etc.) from /usr/local/pub/X/
Can I change my shell?Currently you can not change your own shell, but if you want your default shell changed to bash you can contact the System Administrators (70-3590) and they can change it for you.
How do I change my password?You can change your password with the command cspasswd. This is available on any DCS linux machine. A reference document about good password practice is found in the HOWTOs section of this Web site.
My unix password does not work on the Windows machines. What do I do?Your passwords are out of sync. You will need to see the System Administrators in room 70-3590 to get your passwords re-synced
When I run the cspasswd command it complains that it can not change my NT password. What gives?Your passwords are out of sync. You will need to see the System Administrators in room 70-3590 to get your passwords re-synced
Help! I deleted some important files in my account! How do I get them back?If the files existed overnight, they can be backed up from that point in time. Send mail to<EMAIL_ADDRESS>with the file name(s), the last time it was modified, and where the files existed in your directory.
I have a project that will take several hours of compute time, but I don't want to sit around and wait for it -- what can I do?The best way to do this is to no-hup the process (see the nohup man page) so it continues to run after you log out, and nice the process (see the nice man page) up to 20.
Can I connect to the CS machines remotely?You can use ssh to connect to any of the linux machines in the lab. Available tools for remote connection to the lab machines. See the HOWTOs section for instructions on using these tools.
Yes you can. Please see the series of HOWTOs for various client operating systems.
How do I copy files from my own machine to my CS account?You can use a USB flash drive.
You can use various tools to securely connect to the CS lab machines. See the HOWTOs section for instructions on using these tools.
ftp.cs.rit.edu is available for anonymous downloads only.
Software and ConfigurationFirefox won't start.
First make sure you're not already logged into another CS computer. You can only run Firefox on a single machine at a time.
If that's not the issue, then you will need to manually remove the lock file for the browser. When Firefox or Chromium crash, they will leave these files in your account which will keep you from opening them on any CS computer. The files you need to remove are:
Firefox
~/.mozilla/firefox/????????.default/.parentlock
~/.mozilla/firefox/????????.default/lock
where ???????? are random numbers and letters unique to your account (i.e. wed4pa82)
The Department of Computer Science provides mail for students taking CS courses. Many faculty and advisor messages will be sent to your CS account, and it i s assumed you are reading it.
Your mail address is<EMAIL_ADDRESS>We provide webmail access, secure POP3, and secure IMAP.
Some basic configuration information:
There is info on mail client connections in the HOWTOs section for this site.
Can I forward my email to another system?To be able to forward your email to another account, you need the .forward file in your home directory. The .forward file should ONLY have the email address to which you are forwarding. And the .forward file should have the permission 600 otherwise the mail server will just ignore it.
Is mail filtered for spam and viruses?Yes. Messages that contain viruses are quarantined. All other messages are ranked based on spam probability and an X-Spam-Status is added to your message headers. We will not filter it out for you.
Can I do any mail filtering?Procmail is provided for mail filtering. In combination with Spam Assassin it makes an effective spam trap. A good reference to doing this properly can be found in the HOWTOs section
Window Managers What is the default window manager on the CS systems?The default window manager is Unity - it is a branch of Gnome managed by Ubuntu
What other window managers are available?There is a series of HowTos for using window managers in the HOWTOs section for this site.
RegulationsWhat is contained in the Computer Science Department Code of Conduct?
Here are the security requirements for devices connecting to RIT's network.


|
|
def | __init__ (self, device_id, supervisor) |
| |
|
def | on_power_change (self, source_device_id, target_device_id, time, new_power) |
| |
|
def | on_capacity_change (self, source_device_id, target_device_id, time, value) |
| |
|
def | on_price_change (self, source_device_id, target_device_id, time, new_price) |
| |
|
def | on_time_change (self, new_time) |
| |
|
def | process_events (self) |
| |
|
def | set_allocated (self, allocate) |
| |
|
def | send_request (self, request) |
| |
The documentation for this class was generated from the following file:


Error
config.php
already exists. If you would like to set up this app for another GitHub instance, please configure it manually following the documentation, or rename the existing config.php
and then merge it with the new one.
config.php
already exists. If you would like to set up this app for another GitHub instance, please configure it manually following the documentation, or rename the existing config.php
and then merge it with the new one.


Nipissing
Nippissing is a small liberal arts university located near Lake Huron and in the heart of nature.
Nippissing is known for its small student body of just over 5000, and small ratio of students to faculty.
Nippissing offers over 25 different programs and is home to 7 different varsity sports teams including soccer,
basketball and volleyball. Nippising was founded in 1992 and has a great relationship with the community of North Bay.
- Top Programs
- Art and sciences
- Environmental and Physical Geography
- Teaching
- Location
- Map
- Located in North Bay
- On the border of Lake Nipissing
- 3 hours away from Toronto
- Number of Students:
- 5,679
- Average Tuition:
- Tuition varies on the program
- Domestic tuition CAD 12,500- CAD 15,000
- International tuition CAD 23,190.00
- Entry Requirements:
- Completion of Ontario Secondary School Diploma (OSSD)
- Minimum of six 4U/4M courses including ENG4U
- Top 6 must be at 70% or higher
- International rating:
- 2189
- Canadian rating:
- 63
- Average class size:
- 29
Nipissing University
100 College Dr
PO Box 5002
North Bay ON P1B 8L7
Tel:<PHONE_NUMBER>
Fax:<PHONE_NUMBER>
www.nipissingu.ca


Thank you for updating your profile to College & Retirement Solutions. We'll contact you with any questions regarding information you've provided. Should you have any questions, please call us at<PHONE_NUMBER>.
In order to service your account, we need a few more details from you. Please fill out the form below.


Different shades of Nandi statue at abhisheka
This was the 14th edition of festivities
by Special Correspondent MYSURUHundreds of people witnessed the annual abhisheka for the Nandi statue at Chamundi Hill on Sunday.
Organised by the members of the Bettada Balaga Charitable Trust, this was the 14th edition of the event and brought the granite statue alive in different hues.
As priests chanted sacred hymns and offered special prayers, various ingredients, including milk, curds, sugarcane juice etc., mixed with vermilion, turmeric and water was poured from a special platform constructed for the purpose.
The 350-year-old statue turned white as it was bathed in milk and then turned yellow and red, as the abhisheka continued and water with coloured ingredients cascaded from head to toe.
A battery of 10 priests presided over the proceedings and conducted the special rituals followed by mangalarthi.
The statue was restored by the State Archaeological Department last year and the accumulated grime was removed.
Members of the Bettada Balaga Trust, senior seers of Adi Chunchanagiri Mutt, Hosa Mutt were among those present.


module ActiveRecord::Persistence
Active Record Persistence¶ ↑
Public Instance Methods
Returns an instance of the specified klass
with the attributes
of the current record. This is mostly useful in relation to single-table
inheritance structures where you want a subclass to appear as the
superclass. This can be used along with record identification in Action
Pack to allow, say, Client < Company
to do something like
render partial: @client.becomes(Company)
to render that
instance using the companies/company partial instead of clients/client.
Note: The new instance will share a link to the same attributes as the original class. So any change to the attributes in either instance will affect the other.
# File lib/active_record/persistence.rb, line 198 def becomes(klass) became = klass.new became.instance_variable_set("@attributes", @attributes) changed_attributes = @changed_attributes if defined?(@changed_attributes) became.instance_variable_set("@changed_attributes", changed_attributes || {}) became.instance_variable_set("@new_record", new_record?) became.instance_variable_set("@destroyed", destroyed?) became.instance_variable_set("@errors", errors) became end
Wrapper around becomes
that also changes the instance's
sti column value. This is especially useful if you want to persist the
changed class in your database.
Note: The old instance's sti column value will be changed too, as both objects share the same set of attributes.
# File lib/active_record/persistence.rb, line 215 def becomes!(klass) became = becomes(klass) sti_type = nil if !klass.descends_from_active_record? sti_type = klass.sti_name end became.public_send("#{klass.inheritance_column}=", sti_type) became end
Initializes attribute
to zero if nil
and
subtracts the value passed as by
(default is 1). The decrement
is performed directly on the underlying attribute, no setter is invoked.
Only makes sense for number-based attributes. Returns self
.
# File lib/active_record/persistence.rb, line 328 def decrement(attribute, by = 1) self[attribute] ||= 0 self[attribute] -= by self end
Wrapper around decrement
that saves the record. This method
differs from its non-bang version in that it passes through the attribute
setter. Saving is not subjected to validation checks. Returns
true
if the record could be saved.
# File lib/active_record/persistence.rb, line 338 def decrement!(attribute, by = 1) decrement(attribute, by).update_attribute(attribute, self[attribute]) end
Deletes the record in the database and freezes this instance to reflect that no changes should be made (since they can't be persisted). Returns the frozen instance.
The row is simply removed with an SQL DELETE
statement on the
record's primary key, and no callbacks are executed.
To enforce the object's before_destroy
and
after_destroy
callbacks or any :dependent
association options, use #destroy
.
# File lib/active_record/persistence.rb, line 155 def delete self.class.delete(id) if persisted? @destroyed = true freeze end
Deletes the record in the database and freezes this instance to reflect that no changes should be made (since they can't be persisted).
There's a series of callbacks associated with destroy
. If
the before_destroy
callback return false
the
action is cancelled and destroy
returns false
.
See ActiveRecord::Callbacks for further
details.
# File lib/active_record/persistence.rb, line 168 def destroy raise ReadOnlyRecord, "#{self.class} is marked as readonly" if readonly? destroy_associations self.class.connection.add_transaction_record(self) destroy_row if persisted? @destroyed = true freeze end
Deletes the record in the database and freezes this instance to reflect that no changes should be made (since they can't be persisted).
There's a series of callbacks associated with destroy!
. If
the before_destroy
callback return false
the
action is cancelled and destroy!
raises ActiveRecord::RecordNotDestroyed. See ActiveRecord::Callbacks for further details.
# File lib/active_record/persistence.rb, line 184 def destroy! destroy || raise(RecordNotDestroyed.new("Failed to destroy the record", self)) end
Returns true if this object has been destroyed, otherwise returns false.
# File lib/active_record/persistence.rb, line 91 def destroyed? sync_with_transaction_state @destroyed end
Initializes attribute
to zero if nil
and adds the
value passed as by
(default is 1). The increment is performed
directly on the underlying attribute, no setter is invoked. Only makes
sense for number-based attributes. Returns self
.
# File lib/active_record/persistence.rb, line 311 def increment(attribute, by = 1) self[attribute] ||= 0 self[attribute] += by self end
Wrapper around increment
that saves the record. This method
differs from its non-bang version in that it passes through the attribute
setter. Saving is not subjected to validation checks. Returns
true
if the record could be saved.
# File lib/active_record/persistence.rb, line 321 def increment!(attribute, by = 1) increment(attribute, by).update_attribute(attribute, self[attribute]) end
Returns true if this object hasn't been saved yet – that is, a record for the object doesn't exist in the database yet; otherwise, returns false.
# File lib/active_record/persistence.rb, line 85 def new_record? sync_with_transaction_state @new_record end
Returns true if the record is persisted, i.e. it's not a new record and it was not destroyed, otherwise returns false.
# File lib/active_record/persistence.rb, line 98 def persisted? !(new_record? || destroyed?) end
Reloads the record from the database.
This method finds record by its primary key (which could be assigned manually) and modifies the receiver in-place:
account = Account.new # => #<Account id: nil, email: nil> account.id = 1 account.reload # Account Load (1.2ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT 1 [["id", 1]] # => #<Account id: 1, email<EMAIL_ADDRESS>Attributes are reloaded from the database, and caches busted, in particular the associations cache and the QueryCache.
If the record no longer exists in the database
ActiveRecord::RecordNotFound
is raised. Otherwise, in addition
to the in-place modification the method returns self
for
convenience.
The optional :lock
flag option allows you to lock the reloaded
record:
reload(lock: true) # reload with pessimistic locking
Reloading is commonly used in test suites to test something is actually written to the database, or when some action modifies the corresponding row in the database but not the object in memory:
assert account.deposit!(25) assert_equal 25, account.credit # check it is updated in memory assert_equal 25, account.reload.credit # check it is also persisted
Another common use case is optimistic locking handling:
def with_optimistic_retry begin yield rescue ActiveRecord::StaleObjectError begin # Reload lock_version in particular. reload rescue ActiveRecord::RecordNotFound # If the record is gone there is nothing to do. else retry end end end
# File lib/active_record/persistence.rb, line 407 def reload(options = nil) clear_aggregation_cache clear_association_cache self.class.connection.clear_query_cache fresh_object = if options && options[:lock] self.class.unscoped { self.class.lock(options[:lock]).find(id) } else self.class.unscoped { self.class.find(id) } end @attributes = fresh_object.instance_variable_get('@attributes') @new_record = false self end
Saves the model.
If the model is new a record gets created in the database, otherwise the existing record gets updated.
By default, save always run validations. If any of them fail the action is
cancelled and save
returns false
. However, if you
supply validate: false, validations are bypassed altogether. See ActiveRecord::Validations for more information.
There's a series of callbacks associated with save
. If any
of the before_*
callbacks return false
the action
is cancelled and save
returns false
. See ActiveRecord::Callbacks for further details.
Attributes marked as readonly are silently ignored if the record is being updated.
# File lib/active_record/persistence.rb, line 119 def save(*) create_or_update rescue ActiveRecord::RecordInvalid false end
Saves the model.
If the model is new a record gets created in the database, otherwise the existing record gets updated.
With save!
validations always run. If any of them fail ActiveRecord::RecordInvalid gets raised. See
ActiveRecord::Validations for more
information.
There's a series of callbacks associated with save!
. If
any of the before_*
callbacks return false
the
action is cancelled and save!
raises ActiveRecord::RecordNotSaved. See ActiveRecord::Callbacks for further details.
Attributes marked as readonly are silently ignored if the record is being updated.
# File lib/active_record/persistence.rb, line 141 def save!(*) create_or_update || raise(RecordNotSaved.new("Failed to save the record", self)) end
Assigns to attribute
the boolean opposite of
attribute?
. So if the predicate returns true
the
attribute will become false
. This method toggles directly the
underlying value without calling any setter. Returns self
.
# File lib/active_record/persistence.rb, line 346 def toggle(attribute) self[attribute] = !send("#{attribute}?") self end
Wrapper around toggle
that saves the record. This method
differs from its non-bang version in that it passes through the attribute
setter. Saving is not subjected to validation checks. Returns
true
if the record could be saved.
# File lib/active_record/persistence.rb, line 355 def toggle!(attribute) toggle(attribute).update_attribute(attribute, self[attribute]) end
Saves the record with the updated_at/on attributes set to the current time.
Please note that no validation is performed and only the
after_touch
, after_commit
and
after_rollback
callbacks are executed.
If attribute names are passed, they are updated along with updated_at/on attributes.
product.touch # updates updated_at/on product.touch(:designed_at) # updates the designed_at attribute and updated_at/on product.touch(:started_at, :ended_at) # updates started_at, ended_at and updated_at/on attributes
If used along with belongs_to
then touch
will
invoke touch
method on associated object.
class Brake < ActiveRecord::Base belongs_to :car, touch: true end class Car < ActiveRecord::Base belongs_to :corporation, touch: true end # triggers @brake.car.touch and @brake.car.corporation.touch @brake.touch
Note that touch
must be used on a persisted object, or else an
ActiveRecordError will be thrown. For
example:
ball = Ball.new ball.touch(:updated_at) # => raises ActiveRecordError
# File lib/active_record/persistence.rb, line 455 def touch(*names) raise ActiveRecordError, "cannot touch on a new record object" unless persisted? attributes = timestamp_attributes_for_update_in_model attributes.concat(names) unless attributes.empty? current_time = current_time_from_proper_timezone changes = {} attributes.each do |column| column = column.to_s changes[column] = write_attribute(column, current_time) end changes[self.class.locking_column] = increment_lock if locking_enabled? clear_attribute_changes(changes.keys) primary_key = self.class.primary_key self.class.unscoped.where(primary_key => self[primary_key]).update_all(changes) == 1 else true end end
Updates the attributes of the model from the passed-in hash and saves the record, all wrapped in a transaction. If the object is invalid, the saving will fail and false will be returned.
# File lib/active_record/persistence.rb, line 247 def update(attributes) # The following transaction covers any possible database side-effects of the # attributes assignment. For example, setting the IDs of a child collection. with_transaction_returning_status do assign_attributes(attributes) save end end
Updates its receiver just like update
but calls
save!
instead of save
, so an exception is raised
if the record is invalid.
# File lib/active_record/persistence.rb, line 260 def update!(attributes) # The following transaction covers any possible database side-effects of the # attributes assignment. For example, setting the IDs of a child collection. with_transaction_returning_status do assign_attributes(attributes) save! end end
Updates a single attribute and saves the record. This is especially useful for boolean flags on existing records. Also note that
-
Validation is skipped.
-
Callbacks are invoked.
-
updated_at/updated_on column is updated if that column is available.
-
Updates all the attributes that are dirty in this object.
This method raises an ActiveRecord::ActiveRecordError
if the
attribute is marked as readonly.
See also update_column
.
# File lib/active_record/persistence.rb, line 237 def update_attribute(name, value) name = name.to_s verify_readonly_attribute(name) send("#{name}=", value) save(validate: false) end
Equivalent to update_columns(name => value)
.
# File lib/active_record/persistence.rb, line 272 def update_column(name, value) update_columns(name => value) end
Updates the attributes directly in the database issuing an UPDATE SQL statement and sets them in the receiver:
user.update_columns(last_request_at: Time.current)
This is the fastest way to update attributes because it goes straight to the database, but take into account that in consequence the regular update procedures are totally bypassed. In particular:
-
Validations are skipped.
-
Callbacks are skipped.
-
updated_at
/updated_on
are not updated.
This method raises an ActiveRecord::ActiveRecordError
when
called on new objects, or when at least one of the attributes is marked as
readonly.
# File lib/active_record/persistence.rb, line 291 def update_columns(attributes) raise ActiveRecordError, "cannot update a new record" if new_record? raise ActiveRecordError, "cannot update a destroyed record" if destroyed? attributes.each_key do |key| verify_readonly_attribute(key.to_s) end updated_count = self.class.unscoped.where(self.class.primary_key => id).update_all(attributes) attributes.each do |k, v| raw_write_attribute(k, v) end updated_count == 1 end
Private Instance Methods
Creates a record with values matching those of the instance attributes and returns its id.
# File lib/active_record/persistence.rb, line 521 def _create_record(attribute_names = self.attribute_names) attributes_values = arel_attributes_with_values_for_create(attribute_names) new_id = self.class.unscoped.insert attributes_values self.id ||= new_id if self.class.primary_key @new_record = false id end
Updates the associated record with values matching those of the instance attributes. Returns the number of affected rows.
# File lib/active_record/persistence.rb, line 510 def _update_record(attribute_names = self.attribute_names) attributes_values = arel_attributes_with_values_for_update(attribute_names) if attributes_values.empty? 0 else self.class.unscoped._update_record attributes_values, id, id_was end end
# File lib/active_record/persistence.rb, line 502 def create_or_update raise ReadOnlyRecord, "#{self.class} is marked as readonly" if readonly? result = new_record? ? _create_record : _update_record result != false end
A hook to be overridden by association modules.
# File lib/active_record/persistence.rb, line 483 def destroy_associations end
# File lib/active_record/persistence.rb, line 486 def destroy_row relation_for_destroy.delete_all end
# File lib/active_record/persistence.rb, line 490 def relation_for_destroy pk = self.class.primary_key column = self.class.columns_hash[pk] substitute = self.class.connection.substitute_at(column) relation = self.class.unscoped.where( self.class.arel_table[pk].eq(substitute)) relation.bind_values = [[column, id]] relation end
# File lib/active_record/persistence.rb, line 531 def verify_readonly_attribute(name) raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attributes.include?(name) end


In boost to climate policy, EU makes first move to end fossil fuel funding
BRUSSELS: A preliminary text agreed by EU member states calls on the European Investment Bank to stop funding fossil fuel projects, in what would be a breakthrough in the bloc's climate policy and a blow to the coal, gas and oil industries.
The document, seen by Reuters, was agreed on Tuesday by mid-ranking representatives of the EU's 28 national governments, but still needs the green light from more senior diplomats.
The text for the first time calls on the European Investment Bank (EIB), a multilateral development bank (MDB) and the bloc's top lender, to bring to an end its multi-billion-euro funding of fossil fuel projects in a bid to reduce carbon emissions.
The EU "encourages the MDBs to adopt responsible investment policies and to phase out financing of fossil fuel projects, in particular those using solid fossil fuels, taking into account the sustainable development and energy needs of partner countries," the document said.
EIB figures show the bank funded almost €2 billion (US$2.2 billion) of fossil fuel projects last year and €13.4 billion worth since 2013.
The text will be discussed at a meeting of the EU's top diplomats later on Wednesday. Two EU officials said negotiations were still under way and the text could be changed and softened.
EU countries have long been divided over this matter. Some support the move while others, like Germany, Italy, Poland and Latvia, want the EIB to keep funding some types of gas projects to help them move away from coal or nuclear power, or for energy security reasons.
EU finance ministers are set to adopt the text at a meeting on Friday, a week before the EIB board is due to discuss its energy funding policy.
The EIB board, which is composed of the same EU finance ministers who will have to endorse the document on Friday, failed to find an agreement to end fossil fuel funding last October, as countries remained divided.


Other options include autoplay, number of items to scroll, animation speed when scrolling right and left, initial number of visible items, and more!