1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

moved VILLASfpga specific code to separate repo

This commit is contained in:
Steffen Vogel 2017-11-21 21:51:07 +01:00
parent e0959b562f
commit 5fb48d607e
98 changed files with 4023 additions and 4620 deletions

22
etc/amqp.conf Normal file
View file

@ -0,0 +1,22 @@
{
"nodes" : {
"node1" : {
"type" : "amqp",
"format" : "json",
"uri" : "amqp://broker",
"exchange" : "mytestexchange",
"routing_key" : "abc",
"ssl" : {
"verify_hostname" : true,
"verify_peer" : true,
"ca_cert" : "/path/to/ca.crt",
"client_cert" : "/path/to/client.crt",
"client_key" : "/path/to/client.key"
}
}
}
}

View file

@ -1,73 +0,0 @@
/** Example configuration file for VILLASnode.
*
* The syntax of this file is similar to JSON.
* A detailed description of the format can be found here:
* http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
# Some global settings are used by multiple configuration files
# and therefore defined in separate files
@include "global.conf"
@include "plugins.conf"
fpgas = {
vc707 = {
/* Card identification */
id = "10ee:7022";
slot = "01:00.0";
intc = 0x5000;
reset = 0x2000;
do_reset = true;
ips = {
switch_0 = {
vlnv = "xilinx.com:ip:axis_interconnect:2.1"
baseaddr = 0x0000;
numports = 3;
paths = (
{ in = "dma_0", out = "rtds_0" },
{ in = "rtds_0", out = "dma_0" }
)
},
rtds_0 = {
vlnv = "acs.eonerc.rwth-aachen.de:user:rtds_axis:1.0"
baseaddr = 0x3000;
port = 0;
},
dma_0 = {
vlnv = "xilinx.com:ip:axi_dma:7.1";
baseaddr = 0x1000;
port = 2;
irq = 0
}
}
}
}
nodes = {
rtds = {
datamover = "dma_0";
use_irqs = false;
}
}

View file

@ -1,168 +0,0 @@
/** Example configuration file for VILLASfpga / VILLASnode.
*
* The syntax of this file is similar to JSON.
* A detailed description of the format can be found here:
* http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
# Some global settings are used by multiple configuration files
# and therefore defined in separate files
@include "global.conf"
@include "plugins.conf"
############ Dictionary of FPGAs ############
fpgas = {
vc707 = {
id = "10ee:7022"; # Card identification
slot = "01:00.0"; # Usually only id or slot is required
do_reset = true; # Perform a full reset of the FPGA board
# Requires a IP core named 'axi_reset_0'
############ List of IP cores on FPGA ############
#
# Every IP core can have the following settings:
# baseaddr Baseaddress as accessible from BAR0 memory region
# irq Interrupt index of MSI interrupt controller
# port Port index of AXI4-Stream interconnect
ips = {
### Utility IPs
axi_pcie_intc_0 = {
vlnv = "acs.eonerc.rwth-aachen.de:user:axi_pcie_intc:1.0";
baseaddr = 0xb000;
},
switch_0 = {
vlnv = "xilinx.com:ip:axis_interconnect:2.1"
baseaddr = 0x5000;
num_ports = 10;
paths = (
// { in = "fifo_mm_s_0", out = "fifo_mm_s_0" }, # Loopback fifo_mm_s_0
// { in = "dma_0", out = "dma_0" }, # Loopback dma_0
// { in = "dma_1", out = "dma_1" } # Loopback dma_1
// { in = "rtds_axis_0", out = "fifo_mm_s_0", reverse = true } # Linux <-> RTDS
// { in = "rtds_axis_0", out = "dma_0", reverse = true } # Linux (dma_0) <-> RTDS
{ in = "rtds_axis_0", out = "dma_1", reverse = true } # Linux (dma_1) <-> RTDS
// { in = "rtds_axis_0", out = "fifo_mm_s_0", reverse = true } # Linux (fifo_mm_s_0) <-> RTDS
// { in = "dma_0", out = "hls_dft_0", reverse = true } # DFT <-> Linux
// { in = "rtds_axis_0", out = "hls_dft_0", reverse = true }, # DFT <-> RTDS
)
},
axi_reset_0 = {
vlnv = "xilinx.com:ip:axi_gpio:2.0";
baseaddr = 0x7000;
},
timer_0 = {
vlnv = "xilinx.com:ip:axi_timer:2.0";
baseaddr = 0x4000;
irq = 0;
},
### Data mover IPs
dma_0 = {
vlnv = "xilinx.com:ip:axi_dma:7.1";
baseaddr = 0x3000;
port = 1;
irq = 3; /* 3 - 4 */
},
dma_1 = {
vlnv = "xilinx.com:ip:axi_dma:7.1";
baseaddr = 0x2000;
port = 6;
irq = 3; /* 3 - 4 */
},
fifo_mm_s_0 = {
vlnv = "xilinx.com:ip:axi_fifo_mm_s:4.1";
baseaddr = 0x6000;
baseaddr_axi4 = 0xC000;
port = 2;
irq = 2;
},
### Interface IPs
rtds_axis_0 = {
vlnv = "acs.eonerc.rwth-aachen.de:user:rtds_axis:1.0";
baseaddr = 0x8000;
port = 0;
irq = 5; /* 5 -7 */
},
### Model IPs
hls_dft_0 = {
vlnv = "acs.eonerc.rwth-aachen.de:hls:hls_dft:1.0";
baseaddr = 0x9000;
port = 5;
irq = 1;
period = 400; /* in samples: 20ms / 50uS = 400*/
harmonics = [ 0, 1, 3, 5, 7 ]
decimation = 0; /* 0 = disabled */
//harmonics = [ 0, 1, 2, 5, 22 ]
},
axis_data_fifo_0 = {
vlnv = "xilinx.com:ip:axis_data_fifo:1.1";
port = 3;
},
axis_data_fifo_1 = {
vlnv = "xilinx.com:ip:axis_data_fifo:1.1";
port = 6;
},
}
}
}
############ Dictionary of nodes ############
nodes = {
dma_0 = {
type = "fpga"; # Datamovers to VILLASfpga
datamover = "dma_0"; # Name of IP core in fpga.ips
use_irqs = false; # Use polling or MSI interrupts?
},
dma_1 = {
type = "fpga";
datamover = "dma_1";
use_irqs = false;
},
fifo_0 = {
type = "fpga";
datamover = "fifo_mm_s_0";
use_irqs = false;
},
simple_circuit = {
type = "cbuilder";
model = "simple_circuit",
timestep = 25e-6; # in seconds
parameters = [
1.0, # R2 = 1 Ohm
0.001 # C2 = 1000 uF
];
}
}
############ List of paths ############
paths = (
{ in = "dma_1", out = "simple_circuit", reverse = true }
)

18
etc/influxdb.conf Normal file
View file

@ -0,0 +1,18 @@
hugepages = 100
logging = {
level = 10
}
nodes = {
influxdb_node = {
type = "influxdb",
samplelen = 3,
server = "relaxed_colden:8089",
key = "villas",
fields = [
"a", "b", "c"
]
}
}

View file

@ -0,0 +1,200 @@
# configuration file for the setup for integration testing: inl-csu-usc-nrel
# Test with acs-rtds (nrel), acs-opal1 (csu), acs-opal2 (usc)
#
# host: inl-villas
# inl devices: inl-rtds73, inl-rtds74, inl-rtds83
# remote nodes: csu-villas, usc-villas, nrel-rtds
#
############ nodes ############
stats = 5.0;
nodes = {
# ss1-ss4 (inl-csu)
inl-rtds84 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12084";
remote = "141.221.118.84:12084";
},
#ss4 (in demo schematic)
csu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12004";
remote = "129.82.106.227:12004";
#remote = "10.10.15.1:12004"; # test with acs-opal
},
results-ss4 = {
type = "file",
out = {
uri = "rtsuperlab/IntegrationTesting/ss1ss4_inl-csu_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
flush = false,
mode = "w+"
}
},
# ss1-ss5 (inl-nrel)
inl-rtds74 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12074";
remote = "141.221.118.74:12074";
},
#ss5 (in demo schematic)
nrel-rtds = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12001"; #TODO: this should be changed to 12005, ask nrel
remote = "192.174.56.96:12001";
},
results-ss5 = {
type = "file",
out = {
uri = "rtsuperlab/IntegrationTesting/ss1ss5_inl-nrel_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
flush = false,
mode = "w+"
}
},
# ss1-ss7 (inl-usc)
inl-rtds83 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12083";
remote = "141.221.118.83:12083";
},
#ss7 (in demo schematic)
#we have to use two nodes and different ports for usc (some weird behavior of VPN/Firewall)
inl-to-usc-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12007";
remote = "129.252.22.104:13007"; #TODO: the idea is to use ports > 13000 for inl-web, take care to avoid conflict
},
usc-to-inl-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12077";
remote = "129.252.22.104:13077";
},
results-ss7 = {
type = "file",
out = {
uri = "rtsuperlab/IntegrationTesting/ss1ss7_inl-usc_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
flush = false,
mode = "w+"
}
}
};
############ paths ############
#we introduce a path for each direction as later we need it for writing to a file
paths = (
# ss1-ss4 (inl-csu) co-simulation interface
{
in = "inl-rtds84",
out = ["csu-villas", "results-ss4"],
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "csu-villas",
out = "inl-rtds84",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss5 (inl-nrel) co-simulation interface
{
in = "inl-rtds74",
out = ["nrel-rtds", "results-ss5"]
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "nrel-rtds",
out = "inl-rtds74",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss7 (inl-usc) co-simulation interface
{
in = "inl-rtds83",
out = ["inl-to-usc-villas", "results-ss7"],
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "usc-to-inl-villas",
out = "inl-rtds83",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,255 @@
# configuration file for the setup for integration testing: inl-csu-usc-nrel
# Test with acs-rtds (nrel), acs-opal1 (csu), acs-opal2 (usc)
#
# host: inl-villas
# inl devices: inl-rtds73, inl-rtds74, inl-rtds83
# remote nodes: csu-villas, usc-villas, nrel-rtds
#
############ nodes ############
stats = 5.0;
nodes = {
# ss1-ss2 (inl-rwth)
inl-rtds73 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12073";
remote = "141.221.118.73:12073";
},
#ss2 (in demo schematic)
rwth-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12002";
remote = "10.10.15.1:12002";
},
results-ss2 = {
type = "file",
out = {
uri = "rtsuperlab/IntegrationTesting/IntegrationTesting_0825/ss1ss2_inl-csu_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
flush = false,
mode = "w+"
}
},
# ss1-ss4 (inl-csu)
inl-rtds84 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12084";
remote = "141.221.118.84:12084";
},
#ss4 (in demo schematic)
csu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12004";
remote = "129.82.106.227:12004";
#remote = "10.10.15.1:12004"; # test with acs-opal
},
results-ss4 = {
type = "file",
out = {
uri = "rtsuperlab/IntegrationTesting/IntegrationTesting_0825/ss1ss4_inl-csu_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
flush = false,
mode = "w+"
}
},
# ss1-ss5 (inl-nrel)
inl-rtds74 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12074";
remote = "141.221.118.74:12074";
},
#ss5 (in demo schematic)
nrel-rtds = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12001"; #TODO: this should be changed to 12005, ask nrel
remote = "192.174.56.96:12001";
},
results-ss5 = {
type = "file",
out = {
uri = "rtsuperlab/IntegrationTesting/IntegrationTesting_0825/ss1ss5_inl-nrel_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
flush = false,
mode = "w+"
}
},
# ss1-ss7 (inl-usc)
inl-rtds83 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12083";
remote = "141.221.118.83:12083";
},
#ss7 (in demo schematic)
#we have to use two nodes and different ports for usc (some weird behavior of VPN/Firewall)
inl-to-usc-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12007";
remote = "129.252.22.104:13007"; #TODO: the idea is to use ports > 13000 for inl-web, take care to avoid conflict
},
usc-to-inl-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12077";
remote = "129.252.22.104:13077";
},
results-ss7 = {
type = "file",
out = {
uri = "rtsuperlab/IntegrationTesting/IntegrationTesting_0825/ss1ss7_inl-usc_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
flush = false,
mode = "w+"
}
}
};
############ paths ############
#we introduce a path for each direction as later we need it for writing to a file
paths = (
# ss1-ss2 (inl-rwth) co-simulation interface
{
in = "inl-rtds73",
out = ["rwth-villas", "results-ss2"],
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "rwth-villas",
out = "inl-rtds73",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss4 (inl-csu) co-simulation interface
{
in = "inl-rtds84",
out = ["csu-villas", "results-ss4"],
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "csu-villas",
out = "inl-rtds84",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss5 (inl-nrel) co-simulation interface
{
in = "inl-rtds74",
out = ["nrel-rtds", "results-ss5"]
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "nrel-rtds",
out = "inl-rtds74",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss7 (inl-usc) co-simulation interface
{
in = "inl-rtds83",
out = ["inl-to-usc-villas", "results-ss7"],
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "usc-to-inl-villas",
out = "inl-rtds83",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,255 @@
# configuration file for the setup for integration testing: inl-csu-usc-nrel
# Test with acs-rtds (nrel), acs-opal1 (csu), acs-opal2 (usc)
#
# host: inl-villas
# inl devices: inl-rtds73, inl-rtds74, inl-rtds83
# remote nodes: csu-villas, usc-villas, nrel-rtds
#
############ nodes ############
stats = 5.0;
nodes = {
# ss1-ss2 (inl-rwth)
inl-rtds73 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12073";
remote = "141.221.118.73:12073";
},
#ss2 (in demo schematic)
rwth-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12002";
remote = "10.10.15.1:12002";
},
results-ss2 = {
type = "file",
out = {
uri = "rtsuperlab/IntegrationTesting/IntegrationTesting_0830/ss1ss2_inl-csu_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
flush = false,
mode = "w+"
}
},
# ss1-ss4 (inl-csu)
inl-rtds84 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12084";
remote = "141.221.118.84:12084";
},
#ss4 (in demo schematic)
csu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12004";
remote = "129.82.106.227:12004";
#remote = "10.10.15.1:12004"; # test with acs-opal
},
results-ss4 = {
type = "file",
out = {
uri = "rtsuperlab/IntegrationTesting/IntegrationTesting_0830/ss1ss4_inl-csu_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
flush = false,
mode = "w+"
}
},
# ss1-ss5 (inl-nrel)
inl-rtds83 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12083";
remote = "141.221.118.83:12083";
},
#ss5 (in demo schematic)
nrel-rtds = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12005"; #TODO: this should be changed to 12005, ask nrel
remote = "192.174.56.96:12005";
},
results-ss5 = {
type = "file",
out = {
uri = "rtsuperlab/IntegrationTesting/IntegrationTesting_0830/ss1ss5_inl-nrel_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
flush = false,
mode = "w+"
}
},
# ss1-ss7 (inl-usc)
inl-rtds74 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12074";
remote = "141.221.118.74:12074";
},
#ss7 (in demo schematic)
#we have to use two nodes and different ports for usc (some weird behavior of VPN/Firewall)
inl-to-usc-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12007";
remote = "129.252.22.104:13007"; #TODO: the idea is to use ports > 13000 for inl-web, take care to avoid conflict
},
usc-to-inl-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12077";
remote = "129.252.22.104:13077";
},
results-ss7 = {
type = "file",
out = {
uri = "rtsuperlab/IntegrationTesting/IntegrationTesting_0830/ss1ss7_inl-usc_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
flush = false,
mode = "w+"
}
}
};
############ paths ############
#we introduce a path for each direction as later we need it for writing to a file
paths = (
# ss1-ss2 (inl-rwth) co-simulation interface
{
in = "inl-rtds73",
out = ["rwth-villas", "results-ss2"],
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "rwth-villas",
out = "inl-rtds73",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss4 (inl-csu) co-simulation interface
{
in = "inl-rtds84",
out = ["csu-villas", "results-ss4"],
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "csu-villas",
out = "inl-rtds84",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss5 (inl-nrel) co-simulation interface
{
in = "inl-rtds83",
out = ["nrel-rtds", "results-ss5"]
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "nrel-rtds",
out = "inl-rtds83",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss7 (inl-usc) co-simulation interface
{
in = "inl-rtds74",
out = ["inl-to-usc-villas", "results-ss7"],
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "usc-to-inl-villas",
out = "inl-rtds74",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,171 @@
# configuration file for the setup for integration testing: inl-csu-usc-nrel
# Test with acs-rtds (nrel), acs-opal1 (csu), acs-opal2 (usc)
#
# host: inl-villas
# inl devices: inl-rtds73, inl-rtds74, inl-rtds83
# remote nodes: csu-villas, usc-villas, nrel-rtds
#
############ nodes ############
stats = 5.0;
nodes = {
# ss1-ss4 (inl-csu)
inl-rtds84 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12084";
remote = "141.221.118.84:12084";
},
#ss4 (in demo schematic)
csu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12004";
remote = "129.82.106.227:12004";
#remote = "10.10.15.1:12004"; # test with acs-opal
},
# ss1-ss5 (inl-nrel)
inl-rtds74 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12074";
remote = "141.221.118.74:12074";
},
#ss5 (in demo schematic)
nrel-rtds = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12001"; #TODO: this should be changed to 12005, ask nrel
remote = "192.174.56.96:12001";
},
# ss1-ss7 (inl-usc)
inl-rtds83 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12083";
remote = "141.221.118.83:12083";
},
#ss7 (in demo schematic)
#we have to use two nodes and different ports for usc (some weird behavior of VPN/Firewall)
inl-to-usc-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12007";
remote = "129.252.22.104:13007"; #TODO: the idea is to use ports > 13000 for inl-web, take care to avoid conflict
},
usc-to-inl-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12077";
remote = "129.252.22.104:13077";
}
};
############ paths ############
#we introduce a path for each direction as later we need it for writing to a file
paths = (
# ss1-ss4 (inl-csu) co-simulation interface
{
in = "inl-rtds84",
out = "csu-villas",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "csu-villas",
out = "inl-rtds84",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss5 (inl-nrel) co-simulation interface
{
in = "inl-rtds74",
out = "nrel-rtds",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "nrel-rtds",
out = "inl-rtds74",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss7 (inl-usc) co-simulation interface
{
in = "inl-rtds83",
out = "inl-to-usc-villas",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "usc-to-inl-villas",
out = "inl-rtds83",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,215 @@
# configuration file for the setup for integration testing: inl-csu-usc-nrel
# Test with acs-rtds (nrel), acs-opal1 (csu), acs-opal2 (usc)
#
# host: inl-villas
# inl devices: inl-rtds73, inl-rtds74, inl-rtds83
# remote nodes: csu-villas, usc-villas, nrel-rtds
#
############ nodes ############
stats = 5.0;
nodes = {
# ss1-ss2 (inl-rwth)
inl-rtds73 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12073";
remote = "141.221.118.73:12073";
},
#ss2 (in demo schematic)
rwth-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12002";
remote = "10.10.15.1:12002";
},
# ss1-ss4 (inl-csu)
inl-rtds84 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12084";
remote = "141.221.118.84:12084";
},
#ss4 (in demo schematic)
csu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12004";
remote = "129.82.106.227:12004";
#remote = "10.10.15.1:12004"; # test with acs-opal
},
# ss1-ss5 (inl-nrel)
inl-rtds74 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12074";
remote = "141.221.118.74:12074";
},
#ss5 (in demo schematic)
nrel-rtds = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12001"; #TODO: this should be changed to 12005, ask nrel
remote = "192.174.56.96:12001";
},
# ss1-ss7 (inl-usc)
inl-rtds83 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12083";
remote = "141.221.118.83:12083";
},
#ss7 (in demo schematic)
#we have to use two nodes and different ports for usc (some weird behavior of VPN/Firewall)
inl-to-usc-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12007";
remote = "129.252.22.104:13007"; #TODO: the idea is to use ports > 13000 for inl-web, take care to avoid conflict
},
usc-to-inl-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12077";
remote = "129.252.22.104:13077";
}
};
############ paths ############
#we introduce a path for each direction as later we need it for writing to a file
paths = (
# ss1-ss2 (inl-rwth) co-simulation interface
{
in = "inl-rtds73",
out = "rwth-villas",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "rwth-villas",
out = "inl-rtds73",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss4 (inl-csu) co-simulation interface
{
in = "inl-rtds84",
out = "csu-villas",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "csu-villas",
out = "inl-rtds84",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss5 (inl-nrel) co-simulation interface
{
in = "inl-rtds74",
out = "nrel-rtds",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "nrel-rtds",
out = "inl-rtds74",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss7 (inl-usc) co-simulation interface
{
in = "inl-rtds83",
out = "inl-to-usc-villas",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "usc-to-inl-villas",
out = "inl-rtds83",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,215 @@
# configuration file for the setup for integration testing: inl-csu-usc-nrel
# Test with acs-rtds (nrel), acs-opal1 (csu), acs-opal2 (usc)
#
# host: inl-villas
# inl devices: inl-rtds73, inl-rtds74, inl-rtds83
# remote nodes: csu-villas, usc-villas, nrel-rtds
#
############ nodes ############
stats = 5.0;
nodes = {
# ss1-ss2 (inl-rwth)
inl-rtds73 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12073";
remote = "141.221.118.73:12073";
},
#ss2 (in demo schematic)
rwth-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12002";
remote = "10.10.15.1:12002";
},
# ss1-ss4 (inl-csu)
inl-rtds84 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12084";
remote = "141.221.118.84:12084";
},
#ss4 (in demo schematic)
csu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12004";
remote = "129.82.106.227:12004";
#remote = "10.10.15.1:12004"; # test with acs-opal
},
# ss1-ss5 (inl-nrel)
inl-rtds83 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12083";
remote = "141.221.118.83:12083";
},
#ss5 (in demo schematic)
nrel-rtds = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12005"; #TODO: this should be changed to 12005, ask nrel
remote = "192.174.56.96:12005";
},
# ss1-ss7 (inl-usc)
inl-rtds74 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12074";
remote = "141.221.118.74:12074";
},
#ss7 (in demo schematic)
#we have to use two nodes and different ports for usc (some weird behavior of VPN/Firewall)
inl-to-usc-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12007";
remote = "129.252.22.104:13007"; #TODO: the idea is to use ports > 13000 for inl-web, take care to avoid conflict
},
usc-to-inl-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12077";
remote = "129.252.22.104:13077";
}
};
############ paths ############
#we introduce a path for each direction as later we need it for writing to a file
paths = (
# ss1-ss2 (inl-rwth) co-simulation interface
{
in = "inl-rtds73",
out = "rwth-villas",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "rwth-villas",
out = "inl-rtds73",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss4 (inl-csu) co-simulation interface
{
in = "inl-rtds84",
out = "csu-villas",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "csu-villas",
out = "inl-rtds84",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss5 (inl-nrel) co-simulation interface
{
in = "inl-rtds83",
out = "nrel-rtds",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "nrel-rtds",
out = "inl-rtds83",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss7 (inl-usc) co-simulation interface
{
in = "inl-rtds74",
out = "inl-to-usc-villas",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "usc-to-inl-villas",
out = "inl-rtds74",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,171 @@
# configuration file for the setup for integration testing: inl-csu-usc-nrel
# Test with acs-rtds (nrel), acs-opal1 (csu), acs-opal2 (usc)
#
# host: inl-villas
# inl devices: inl-rtds73, inl-rtds74, inl-rtds83
# remote nodes: csu-villas, usc-villas, nrel-rtds
#
############ nodes ############
stats = 5.0;
nodes = {
# ss1-ss4 (inl-csu)
inl-rtds73 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12073";
remote = "141.221.118.73:12073";
},
#ss4 (in demo schematic)
csu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12004";
remote = "129.82.106.227:12004";
#remote = "10.10.15.1:12004"; # test with acs-opal
},
# ss1-ss5 (inl-nrel)
inl-rtds74 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12074";
remote = "141.221.118.74:12074";
},
#ss5 (in demo schematic)
nrel-rtds = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12001"; #TODO: this should be changed to 12005, ask nrel
remote = "192.174.56.96:12001";
},
# ss1-ss7 (inl-usc)
inl-rtds83 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12083";
remote = "141.221.118.83:12083";
},
#ss7 (in demo schematic)
#we have to use two nodes and different ports for usc (some weird behavior of VPN/Firewall)
inl-to-usc-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12007";
remote = "129.252.22.104:13007"; #TODO: the idea is to use ports > 13000 for inl-web, take care to avoid conflict
},
usc-to-inl-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12077";
remote = "129.252.22.104:13077";
}
};
############ paths ############
#we introduce a path for each direction as later we need it for writing to a file
paths = (
# ss1-ss4 (inl-csu) co-simulation interface
{
in = "inl-rtds73",
out = "csu-villas",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "csu-villas",
out = "inl-rtds73",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss5 (inl-nrel) co-simulation interface
{
in = "inl-rtds74",
out = "nrel-rtds",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "nrel-rtds",
out = "inl-rtds74",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss7 (inl-usc) co-simulation interface
{
in = "inl-rtds83",
out = "inl-to-usc-villas",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "usc-to-inl-villas",
out = "inl-rtds83",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,171 @@
# configuration file for the setup for integration testing: inl-csu-usc-nrel
# Test with acs-rtds (nrel), acs-opal1 (csu), acs-opal2 (usc)
#
# host: inl-villas
# inl devices: inl-rtds73, inl-rtds74, inl-rtds83
# remote nodes: csu-villas, usc-villas, nrel-rtds
#
############ nodes ############
stats = 5.0;
nodes = {
# ss1-ss4 (inl-csu)
inl-rtds73 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12073";
remote = "141.221.118.73:12073";
},
#ss4 (in demo schematic)
csu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12004";
remote = "129.82.106.227:12004";
#remote = "10.10.15.1:12004"; # test with acs-opal
},
# ss1-ss5 (inl-nrel)
inl-rtds74 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12074";
remote = "141.221.118.74:12074";
},
#ss5 (in demo schematic)
nrel-rtds = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12001"; #TODO: this should be changed to 12005, ask nrel
remote = "192.174.56.96:12001";
},
# ss1-ss7 (inl-usc)
inl-rtds83 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12083";
remote = "141.221.118.83:12083";
},
#ss7 (in demo schematic)
#we have to use two nodes and different ports for usc (some weird behavior of VPN/Firewall)
inl-to-usc-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12007";
remote = "129.252.22.104:13007"; #TODO: the idea is to use ports > 13000 for inl-web, take care to avoid conflict
},
usc-to-inl-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12077";
remote = "129.252.22.104:13077";
}
};
############ paths ############
#we introduce a path for each direction as later we need it for writing to a file
paths = (
# ss1-ss4 (inl-csu) co-simulation interface
{
in = "inl-rtds73",
out = "csu-villas",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "csu-villas",
out = "inl-rtds73",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss5 (inl-nrel) co-simulation interface
{
in = "inl-rtds74",
out = "nrel-rtds",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "nrel-rtds",
out = "inl-rtds74",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss7 (inl-usc) co-simulation interface
{
in = "inl-rtds83",
out = "inl-to-usc-villas",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "usc-to-inl-villas",
out = "inl-rtds83",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,200 @@
# configuration file for the setup for integration testing: inl-csu-usc-nrel
# Test with acs-rtds (nrel), acs-opal1 (csu), acs-opal2 (usc)
#
# host: inl-villas
# inl devices: inl-rtds73, inl-rtds74, inl-rtds83
# remote nodes: csu-villas, usc-villas, nrel-rtds
#
############ nodes ############
stats = 5.0;
nodes = {
# ss1-ss4 (inl-csu)
inl-rtds73 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12073";
remote = "141.221.118.73:12073";
},
#ss4 (in demo schematic)
csu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12004";
remote = "129.82.106.227:12004";
#remote = "10.10.15.1:12004"; # test with acs-opal
},
results-ss4 = {
type = "file",
out = {
uri = "rtsuperlab/IntegrationTesting/ss1ss4_inl-csu_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
flush = false,
mode = "w+"
}
},
# ss1-ss5 (inl-nrel)
inl-rtds74 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12074";
remote = "141.221.118.74:12074";
},
#ss5 (in demo schematic)
nrel-rtds = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12001"; #TODO: this should be changed to 12005, ask nrel
remote = "192.174.56.96:12001";
},
results-ss5 = {
type = "file",
out = {
uri = "rtsuperlab/IntegrationTesting/ss1ss5_inl-nrel_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
flush = false,
mode = "w+"
}
},
# ss1-ss7 (inl-usc)
inl-rtds83 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12083";
remote = "141.221.118.83:12083";
},
#ss7 (in demo schematic)
#we have to use two nodes and different ports for usc (some weird behavior of VPN/Firewall)
inl-to-usc-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12007";
remote = "129.252.22.104:13007"; #TODO: the idea is to use ports > 13000 for inl-web, take care to avoid conflict
},
usc-to-inl-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12077";
remote = "129.252.22.104:13077";
},
results-ss7 = {
type = "file",
out = {
uri = "rtsuperlab/IntegrationTesting/ss1ss7_inl-usc_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
flush = false,
mode = "w+"
}
}
};
############ paths ############
#we introduce a path for each direction as later we need it for writing to a file
paths = (
# ss1-ss4 (inl-csu) co-simulation interface
{
in = "inl-rtds73",
out = ["csu-villas", "results-ss4"],
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "csu-villas",
out = "inl-rtds73",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss5 (inl-nrel) co-simulation interface
{
in = "inl-rtds74",
out = ["nrel-rtds", "results-ss5"]
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "nrel-rtds",
out = "inl-rtds74",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
# ss1-ss7 (inl-usc) co-simulation interface
{
in = "inl-rtds83",
out = ["inl-to-usc-villas", "results-ss7"],
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "usc-to-inl-villas",
out = "inl-rtds83",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,70 @@
# configuration file for the setup for integration testing: inl-csu-usc-nrel
# Test with acs-rtds (nrel), acs-opal1 (csu), acs-opal2 (usc)
#
# host: inl-villas
# inl devices: inl-rtds73, inl-rtds74, inl-rtds83
# remote nodes: csu-villas, usc-villas, nrel-rtds
#
############ nodes ############
stats = 5.0;
nodes = {
# ss1-ss5 (inl-nrel)
inl-rtds74 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12074";
remote = "141.221.118.74:12074";
},
#ss5 (in demo schematic)
nrel-rtds = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12001"; #TODO: this should be changed to 12005, ask nrel
remote = "192.174.56.96:12001";
}
};
############ paths ############
#we introduce a path for each direction as later we need it for writing to a file
paths = (
# ss1-ss5 (inl-nrel) co-simulation interface
{
in = "inl-rtds74",
out = "nrel-rtds",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "nrel-rtds",
out = "inl-rtds74",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,70 @@
# configuration file for the setup for integration testing: inl-csu-usc-nrel
# Test with acs-rtds (nrel), acs-opal1 (csu), acs-opal2 (usc)
#
# host: inl-villas
# inl devices: inl-rtds73, inl-rtds74, inl-rtds83
# remote nodes: csu-villas, usc-villas, nrel-rtds
#
############ nodes ############
stats = 5.0;
nodes = {
# ss1-ss5 (inl-nrel)
inl-rtds74 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12074";
remote = "141.221.118.74:12074";
},
#ss5 (in demo schematic)
nrel-rtds = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12005"; #TODO: this should be changed to 12005, ask nrel
remote = "192.174.56.96:12005";
}
};
############ paths ############
#we introduce a path for each direction as later we need it for writing to a file
paths = (
# ss1-ss5 (inl-nrel) co-simulation interface
{
in = "inl-rtds74",
out = "nrel-rtds",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "nrel-rtds",
out = "inl-rtds74",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,63 @@
# configuration file for co-simulation setup acs-inl: inl-rtds - inl-villas -- acs-villas - acs-rtds
#
# host: inl-villas
# inl devices: inl-rtds11
# remote nodes: acs-villas
#
############ nodes ############
stats = 1.0;
nodes = {
inl-rtds74 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12074";
remote = "141.221.118.74:12074";
}
#ss2(in demo schematic)
acs-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12002";
remote = "10.10.15.1:12002";
}
};
############ paths ############
paths = (
{
in = "inl-rtds74",
out = "acs-villas",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "acs-villas",
out = "inl-rtds74",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,73 @@
# configuration file for co-simulation setup acs-inl: inl-rtds - inl-villas -- acs-villas - acs-rtds
#
# host: inl-villas
# inl devices: inl-rtds11
# remote nodes: acs-villas
#
############ nodes ############
stats = 0.1;
nodes = {
inl-rtds11 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12011";
remote = "141.221.118.74:12011";
}
#ss2(in demo schematic)
acs-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12002";
remote = "10.10.15.1:12002";
},
results = {
type = "file",
out = {
uri = "rtsuperlab/cosim_generic/acs-inl/test_rcrd/ssA_cosim_inl-acs_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
#flush = false,
mode = "w+"
}
}
};
############ paths ############
paths = (
{
in = "inl-rtds11",
out = ["acs-villas", "results"],
hooks = (
{
type = "stats",
warmup = 3000,
format = "json"
}
)
},
{
in = "acs-villas",
out = "inl-rtds11",
hooks = (
{
type = "stats",
warmup = 3000,
format = "json"
}
)
}
);

View file

@ -0,0 +1,73 @@
# configuration file for co-simulation setup acs-inl: inl-rtds - inl-villas -- acs-villas - acs-rtds
#
# host: inl-villas
# inl devices: inl-rtds11
# remote nodes: acs-villas
#
############ nodes ############
stats = 0.1;
nodes = {
inl-rtds11 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12011";
remote = "141.221.118.74:12011";
}
#ss2(in demo schematic)
acs-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12002";
remote = "10.10.15.1:12002";
},
results = {
type = "file",
out = {
uri = "tmp/rtsuperlab/acs-inl/test_rcrd/ssA_cosim_inl-acs_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
#flush = false,
mode = "w+"
}
}
};
############ paths ############
paths = (
{
in = "inl-rtds11",
out = ["acs-villas", "results"],
hooks = (
{
type = "stats",
warmup = 3000,
format = "json"
}
)
},
{
in = "acs-villas",
out = "inl-rtds11",
hooks = (
{
type = "stats",
warmup = 3000,
format = "json"
}
)
}
);

View file

@ -0,0 +1,56 @@
# configuration file
# host: inl-villas
# inl devices: inl-rtds83
# remote nodes: csu-villas
# Test: rtds - VILLASnode - VILLASnode - opal
#
#
############ nodes ############
stats = 1.0;
http = {enabled = false}
nodes = {
inl-rtds83 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12083";
remote = "141.221.118.83:12083";
},
#ss4 (in demo schematic)
csu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12004";
remote = "129.82.106.227:12004";
}
};
paths = (
{
in = "inl-rtds83",
out = "csu-villas"
hooks = (
{
type = "stats",
warmup = 3000
#format = "json"
}
)
},
{
in = "csu-villas",
out = "inl-rtds83",
hooks = (
{
type = "stats",
warmup = 3000
#format = "json"
}
)
}
);

View file

@ -0,0 +1,68 @@
# configuration file
# host: inl-villas
# inl devices: inl-rtds11
# remote nodes: csu-villas
# Test: rtds - VILLASnode - VILLASnode - opal
#
#
############ nodes ############
stats = 1.0;
http = {enabled = false}
nodes = {
inl-rtds83 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12083";
remote = "141.221.118.83:12083";
},
#ss4 (in demo schematic)
csu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12004";
remote = "129.82.106.227:12004";
},
results = {
type = "file",
out = {
uri = "rtsuperlab/cosim_wscc_ssX/csu-inl/test1/ss1_cosim_inl-csu_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
flush = false,
mode = "w+"
}
}
};
paths = (
{
in = "inl-rtds83",
out = ["csu-villas", "results"]
hooks = (
{
type = "stats",
warmup = 3000
#format = "json"
}
)
},
{
in = "csu-villas",
out = "inl-rtds83",
hooks = (
{
type = "stats",
warmup = 3000
#format = "json"
}
)
}
);

View file

@ -0,0 +1,59 @@
# configuration file for co-simulation setup fsu-inl: inl-rtds - inl-villas -- fsu-villas - fsu-rtds
#
# host: fsu-villas
# inl devices: fsu-rtds11
# remote nodes: fsu-villas
############ nodes ############
stats = 0.1;
nodes = {
inl-rtds11 = {
#Card 3, Port 1
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12011";
remote = "141.221.118.74:12011";
}
#ss8 (in demo schematic)
fsu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12008";
remote = "10.146.64.3:12008";
}
};
paths = (
{
in = "inl-rtds11",
out = "fsu-villas",
hooks = (
{
type = "stats",
warmup = 3000,
format = "json"
}
)
},
{
in = "fsu-villas",
out = "inl-rtds11",
hooks = (
{
type = "stats",
warmup = 3000,
format = "json"
}
)
}
);

View file

@ -0,0 +1,68 @@
# configuration file for co-simulation setup fsu-inl: inl-rtds - inl-villas -- fsu-villas - fsu-rtds
#
# host: fsu-villas
# inl devices: fsu-rtds11
# remote nodes: fsu-villas
############ nodes ############
stats = 0.1;
nodes = {
inl-rtds11 = {
#Card 3, Port 1
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12011";
remote = "141.221.118.74:12011";
}
#ss8 (in demo schematic)
fsu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12008";
remote = "10.146.64.3:12008";
},
results = {
type = "file",
out = {
uri = "rtsuperlab/cosim_generic/fsu-inl/test2/ssA_cosim_inl-fsu_%Y%m%d_%H-%M-%S.csv", # start the file name with ssN (id of subsystem that DRTS in your labsimulates)
flush = false,
mode = "w+"
}
}
};
paths = (
{
in = "inl-rtds11",
out = ["fsu-villas", "results"],
hooks = (
{
type = "stats",
warmup = 3000,
format = "json"
}
)
},
{
in = "fsu-villas",
out = "inl-rtds11",
hooks = (
{
type = "stats",
warmup = 3000,
format = "json"
}
)
}
);

View file

@ -0,0 +1,64 @@
# configuration file for co-simulation setup acs-inl: inl-rtds - inl-villas -- acs-villas - acs-rtds
#
# host: inl-villas
# inl devices: inl-rtds11
# remote nodes: nrel-rtds
#
############ nodes ############
stats = 1.0;
nodes = {
inl-rtds74 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12011";
remote = "141.221.118.74:12011";
},
#ss?(in demo schematic)
nrel-rtds = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12001";
remote = "192.174.56.96:12001";
}
};
############ paths ############
paths = (
{
in = "inl-rtds74",
out = "nrel-rtds",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "nrel-rtds",
out = "inl-rtds74",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,68 @@
# configuration file
# host: inl-villas
# remote nodes:usc-villas
#
#
############ nodes ############
http = {enabled = false};
stats = 1.0;
nodes = {
inl-rtds83 = {
#Card 3, Port 1
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12083";
remote = "141.221.118.83:12083";
},
#ss7 (in demo schematic)
inl-to-usc-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12007";
remote = "129.252.22.104:13007";
},
usc-to-inl-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12077";
remote = "129.252.22.104:13077";
}
};
paths = (
{
in = "usc-to-inl-villas",
out = "inl-rtds83",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "inl-rtds83",
out = "inl-to-usc-villas",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,65 @@
# configuration file for the setup for integration testing: inl-csu-usc-nrel
# Test with acs-rtds (nrel), acs-opal1 (csu), acs-opal2 (usc)
#
# host: inl-villas
# inl devices: inl-rtds73, inl-rtds74, inl-rtds83
# remote nodes: csu-villas, usc-villas, nrel-rtds
#
############ nodes ############
stats = 1.0;
nodes = {
inl-rtds73 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12073";
remote = "141.221.118.74:12073";
},
inl-opal = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12099";
remote = "141.221.118.109:12099"
}
};
############ paths ############
paths = (
#inl-csu co-simulation interface
{
in = "inl-rtds73",
out = "inl-opal",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "inl-opal",
out = "inl-rtds73",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,61 @@
# configuration file
# host: inl-villas
# inl devices: inl-rtds11, inl-rtds21
# remote nodes: acs-villas, polito_villas, csu-villas
#
#
############ nodes ############
stats = 0.1;
nodes = {
inl-rtds12 = {
#SKT 1.17
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12011";
remote = "141.221.118.73:12011";
},
#ss3 (in demo schematic)
polito-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12003";
remote = "130.192.95.241:12003";
}
};
paths = (
{
in = "inl-rtds12",
out = "polito-villas",
#reverse = true,
hooks = (
{
type = "stats",
warmup = 3000,
verbose = true,
format = "json"
}
)
},
{
in = "polito-villas",
out = "inl-rtds12",
#reverse = true,
hooks = (
{
type = "stats",
warmup = 3000,
verbose = true,
format = "json"
}
)
}
);

View file

@ -0,0 +1,60 @@
# configuration file
# host: inl-villas
# inl devices: inl-rtds11, inl-rtds21
# remote nodes: acs-villas, polito_villas, csu-villas
#
#
############ nodes ############
stats = 0.1;
nodes = {
inl-rtds11 = {
#SKT 1.18
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12011";
remote = "141.221.118.74:12011";
},
#ss3 (in demo schematic)
polito-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12003";
remote = "130.192.95.241:12003";
}
};
paths = (
{
in = "inl-rtds11",
out = "polito-villas",
#reverse = true,
hooks = (
{
type = "stats",
warmup = 3000,
verbose = true,
format = "json"
}
)
},
{
in = "polito-villas",
out = "inl-rtds11",
#reverse = true,
hooks = (
{
type = "stats",
warmup = 3000,
verbose = true,
format = "json"
}
)
}
);

View file

@ -0,0 +1,38 @@
# configuration file
# host: inl-villas
# inl devices: inl-rtds11, inl-rtds21
# remote nodes: acs-villas, polito_villas, csu-villas
#
#
############ nodes ############
stats = 0.1;
nodes = {
inl-rtds12 = {
#SKT 1.17
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12011";
remote = "141.221.118.73:12011";
}
};
paths = (
{
in = "inl-rtds12",
out = "inl-rtds12",
#reverse = true,
hooks = (
{
type = "stats",
warmup = 3000,
verbose = true,
format = "json"
}
)
}
);

View file

@ -0,0 +1,36 @@
# configuration file
# host: inl-villas
# inl devices: inl-rtds11, inl-rtds21
# remote nodes: acs-villas, polito_villas, csu-villas
#
#
############ nodes ############
stats = 0.1;
nodes = {
inl-rtds11 = {
#SKT 1.18
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12011";
remote = "141.221.118.74:12011";
}
};
paths = (
{
in = "inl-rtds11",
out = "inl-rtds11",
hooks = (
{
type = "stats",
warmup = 3000,
verbose = true,
format = "json"
}
)
}
);

View file

@ -0,0 +1,48 @@
# configuration file
#
# host: inl-villas
#
############ nodes ############
stats = 1.0;
nodes = {
inl-rtds73 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12073";
remote = "141.221.118.73:12073";
},
inl-web = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12022";
remote = "141.221.118.94:12022";
}
};
############ paths ############
paths = (
{
in = "inl-rtds73",
out = "inl-web",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,70 @@
# configuration file for co-simulation setup acs-inl: inl-rtds - inl-villas -- acs-villas - acs-rtds
#
# host: inl-villas
# inl devices: inl-rtds11
# remote nodes: acs-villas
#
############ nodes ############
stats = 1.0;
nodes = {
inl-rtds11 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12011";
remote = "141.221.118.74:12011";
},
inl-web = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12022";
remote = "141.221.118.94:12022";
},
#ss2(in demo schematic)
acs-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12002";
remote = "10.10.15.1:12002";
}
};
############ paths ############
paths = (
{
in = "inl-rtds11",
out = ["acs-villas","inl-web"],
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "acs-villas",
out = "inl-rtds11",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,61 @@
# configuration file
# host: inl-villas
# remote nodes:inl-opal
#
#
############ nodes ############
http = {enabled = false}
stats = 1.0;
nodes = {
inl-opal = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12109";
remote = "141.221.118.109:12109";
},
inl-picard160 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12160";
remote = "141.221.118.160:5000";
}
};
paths = (
{
in = "inl-opal",
out = "inl-picard160",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
},
{
in = "inl-picard160",
out = "inl-opal",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,40 @@
# configuration file
# host: inl-villas
# remote nodes:inl-opal
#
#
############ nodes ############
http = {enabled = false}
stats = 1.0;
nodes = {
inl-opal = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12109";
remote = "141.221.118.109:12109";
}
};
paths = (
{
in = "inl-opal",
out = "inl-opal",
hooks = (
{
type = "stats",
warmup = 3000,
#format = "json"
}
)
}
);

View file

@ -0,0 +1,52 @@
# configuration file
# host: inl-villas
# remote nodes:usc-villas
#
#
############ nodes ############
http = {enabled = false}
nodes = {
inl-rtds11 = {
#Card 3, Port 1
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:11000";
remote = "141.221.118.160:5000";
},
#ss7 (in demo schematic)
inl-to-usc-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12007";
remote = "129.252.22.104:13007";
},
usc-to-inl-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12077";
remote = "129.252.22.104:13077";
}
};
paths = (
{
in = "usc-to-inl-villas",
out = "inl-rtds11"
},
{
in = "inl-rtds11",
out = "inl-to-usc-villas"
}
);

View file

@ -0,0 +1,33 @@
# configuration file
# host: inl-villas
# remote nodes:csu-villas
#
#
############ nodes ############
nodes = {
#ss4 (in demo schematic)
csu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12004";
remote = "129.82.106.227:12004";
}
};
paths = (
{
in = "csu-villas",
out = "csu-villas"
#hooks = (
# {
# type = "print";
# }
#)
}
);

View file

@ -0,0 +1,34 @@
# configuration file
# host: inl-villas
# remote nodes:fsu-villas
#
#
############ nodes ############
nodes = {
#ss8 (in demo schematic)
fsu-villas = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12008";
remote = "10.146.64.3:12008";
}
};
paths = (
{
in = "fsu-villas",
out = "fsu-villas"
#hooks = (
# {
# type = "print";
# }
#)
}
);

View file

@ -0,0 +1,40 @@
# configuration file
# host: inl-villas
# remote nodes: acs-villas, polito_villas, csu-villas
#
#
############ nodes ############
nodes = {
#ss2(in demo schematic)
acs-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12002";
remote = "10.10.15.1:12002";
},
#ss3 (in demo schematic)
polito-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12003";
remote = "130.192.95.241:12003";
}
};
paths = (
{
in = "polito-villas",
out = "polito-villas",
hooks = (
{
type = "print";
}
)
}
);

View file

@ -0,0 +1,23 @@
# configuration file
# host: inl-villas
# loopback to GTNET-SKT
#
############ nodes ############
nodes = {
inl-rtds11 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12001";
remote = "141.221.118.73:12001";
}
};
paths = (
{
in = "inl-rtds11",
out = "inl-rtds11"
}
);

View file

@ -0,0 +1,40 @@
# configuration file
# host: inl-villas
# remote nodes:usc-villas
#
#
############ nodes ############
nodes = {
#ss2(in demo schematic)
acs-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12002";
remote = "10.10.15.1:12002";
},
#ss7 (in demo schematic)
usc-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12007";
remote = "129.252.22.104:13007";
}
};
paths = (
{
in = "usc-villas",
out = "usc-villas",
hooks = (
{
type = "print";
}
)
}
);

View file

@ -0,0 +1,37 @@
# configuration file
# host: inl-villas
# remote nodes:usc-villas
#
#
############ nodes ############
http = {enabled = false}
nodes = {
#ss7 (in demo schematic)
usc-villas1 = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12007";
remote = "129.252.22.104:13007";
},
usc-villas2 = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12077";
remote = "129.252.22.104:13077";
}
};
paths = (
{
in = "usc-villas2",
out = "usc-villas1"
}
);

View file

@ -0,0 +1,42 @@
# configuration file
# host: inl-villas
# remote nodes: acs-villas, polito_villas, usc-villas, fsu-villas
#
#
############ nodes ############
nodes = {
#ss2(in demo schematic)
acs-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12002";
remote = "10.10.15.1:12002";
},
#ss3 (in demo schematic)
polito-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12003";
remote = "130.192.95.241:12003";
},
#ss7 (in demo schematic)
usc-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12007";
remote = "129.252.22.104:12007";
}
#ss8 (in demo schematic)
fsu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12008";
remote = "10.146.64.3:12008";
}
}

View file

@ -0,0 +1,37 @@
# configuration file
# host: inl-villas
# remote nodes:usc-villas
#
#
############ nodes ############
http = {enabled = false}
nodes = {
#ss7 (in demo schematic)
inl-to-usc-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12007";
remote = "129.252.22.104:13007";
},
usc-to-inl-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12077";
remote = "129.252.22.104:13077";
}
};
paths = (
{
in = "usc-to-inl-villas",
out = "inl-to-usc-villas"
}
);

View file

@ -0,0 +1,67 @@
# configuration file
# host: inl-villas
# inl devices: inl-rtds11, inl-rtds21
# remote nodes: acs-villas, polito_villas, csu-villas
#
#
############ nodes ############
stats = 0.1;
nodes = {
inl-rtds11 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12008";
remote = "141.221.118.73:12008";
},
inl-rtds21 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12009";
remote = "141.221.118.83:12009";
},
#ss2(in demo schematic)
acs-villas = {
type = "socket";
layer = "udp";
#header = "gtnet-skt";
local = "141.221.118.93:12002";
remote = "10.10.15.1:12002";
}
};
paths = (
{
in = "inl-rtds21",
out = "acs-villas",
#reverse = true,
hooks = (
{
type = "stats",
warmup = 3000,
verbose = true,
format = "json"
}
)
},
{
in = "acs-villas",
out = "inl-rtds21",
#reverse = true,
hooks = (
{
type = "stats",
warmup = 3000,
verbose = true,
format = "json"
}
)
}
);

View file

@ -0,0 +1,56 @@
# configuration file
# host: inl-villas
# inl devices: inl-rtds11
# remote nodes: csu-villas
# Test: rtds - VILLASnode - VILLASnode - opal
#
#
############ nodes ############
stats = 1.0;
nodes = {
inl-rtds11 = {
#Card 3, Port 1
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12011";
remote = "141.221.118.74:12011";
},
#ss4 (in demo schematic)
csu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12004";
remote = "129.82.106.227:12004";
}
};
paths = (
{
in = "inl-rtds11",
out = "csu-villas"
hooks = (
{
type = "stats",
warmup = 3000
#format = "json"
}
)
},
{
in = "csu-villas",
out = "inl-rtds11",
hooks = (
{
type = "stats",
warmup = 3000
#format = "json"
}
)
}
);

View file

@ -0,0 +1,58 @@
# configuration file
# host: inl-villas
# inl devices: inl-rtds11, inl-rtds21
# remote nodes: fsu-villas
# Test: rtds - VILLASnode - VILLASnode - rtds
#
#
############ nodes ############
stats = 0.1;
nodes = {
inl-rtds11 = {
#Card 3, Port 1
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12001";
remote = "141.221.118.74:12001";
},
inl-rtds21 = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12002";
remote = "141.221.118.83:12002";
},
#ss8 (in demo schematic)
fsu-villas = {
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12008";
remote = "10.146.64.3:12008";
}
};
paths = (
{
in = "inl-rtds11",
out = "fsu-villas",
reverse = true,
hooks = (
{
type = "stats",
warmup = 3000,
format = "json"
}
# {
# type="print";
# }
)
}
);

View file

@ -0,0 +1,52 @@
# configuration file
# host: inl-villas
# remote nodes:usc-villas
#
#
############ nodes ############
http = {enabled = false}
nodes = {
inl-rtds11 = {
#Card 3, Port 1
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12011";
remote = "141.221.118.74:12011";
},
#ss7 (in demo schematic)
inl-to-usc-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12007";
remote = "129.252.22.104:13007";
},
usc-to-inl-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12077";
remote = "129.252.22.104:13077";
}
};
paths = (
{
in = "usc-to-inl-villas",
out = "inl-rtds11"
},
{
in = "inl-rtds11",
out = "inl-to-usc-villas"
}
);

View file

@ -0,0 +1,45 @@
# configuration file
# host: inl-villas
# inl devices: inl-rtds11
# remote nodes: csu-villas
# Test: rtds - VILLASnode - VILLASnode - opal
#
#
############ nodes ############
stats = 0.1;
nodes = {
inl-rtds11 = {
#Card 3, Port 1
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12001";
remote = "141.221.118.74:12001";
},
#ss4 (in demo schematic)
csu-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12004";
remote = "129.82.106.227:12004";
}
};
paths = (
{
in = "inl-rtds11",
out = "csu-villas",
reverse = true,
hooks = (
{
type = "stats",
warmup = 3000,
format = "json"
}
)
}
);

View file

@ -0,0 +1,37 @@
# configuration file
# host: inl-villas
# remote nodes: acs-villas, polito_villas, csu-villas
#
#
############ nodes ############
nodes = {
#ss3 (in demo schematic)
polito-villas = {
type = "socket";
layer = "udp";
local = "141.221.118.93:12003";
remote = "130.192.95.241:12003";
},
inl-rtds11 = {
#Card 3, Port 1
type = "socket";
layer = "udp";
header = "gtnet-skt";
local = "141.221.118.93:12011";
remote = "141.221.118.74:12011";
}
};
paths = (
{
in = "polito-villas",
out = "inl-rtds11"
}
);

37
etc/loopback2.conf Normal file
View file

@ -0,0 +1,37 @@
stats = 1
nodes = {
socket_node1 = {
type = "socket",
local = "*:12000",
remote = "127.0.0.1:12000"
},
socket_node2 = {
type = "socket",
local = "*:12001",
remote = "127.0.0.1:12001"
}
socket_node2a = {
type = "socket",
local = "*:12003",
remote = "127.0.0.1:12001"
}
}
paths = (
{
in = [
"socket_node1.data[0-3]",
"socket_node2.data[0-3]"
]
hooks = (
{
type = "print"
}
)
}
)

20
etc/multiple_dest.conf Normal file
View file

@ -0,0 +1,20 @@
nodes = {
node_a = {
type = "signal"
signal = "sine"
}
results-ss2 = {
type = "file",
uri = "asdasrtsuperlab/ss1ss2_inl-csu_%Y%m%d_%H-%M-%S.csv",
flush = false,
mode = "w+"
}
}
paths = (
{
in = "node_a"
out = [ "results-ss2" ]
}
)

View file

@ -0,0 +1,13 @@
log = {
level = 15
}
http = {
port = 8081
}
nodes = {
node1 = {
type = "loopback";
}
}

View file

@ -0,0 +1,11 @@
{
"nodes" : {
"node1" : {
"type" : "websocket",
"destinations" : [
"ws://localhost/node1"
]
}
}
}

52
etc/sampled_values.conf Normal file
View file

@ -0,0 +1,52 @@
{
"logging" : {
"level" : 1
},
"nodes" : {
"node1" : {
"type" : "iec61850-9-2",
"interface" : "lo",
"dst_address" : "01:0c:cd:01:00:01",
"publish" : {
"fields" : [
"float32",
"float64",
"int8",
"int32"
],
"svid" : "test1234",
"datset" : "test",
"smpmod" : "samples_per_second",
"confrev" : 55
},
"subscribe" : {
"fields" : [
"float32",
"float64",
"int8",
"int32"
]
}
},
"node2" : {
"type" : "iec61850-9-2",
"interface" : "lo",
"publish" : {
"svid" : "testSV",
"datset" : "abc",
"fields" : [ "float32", "float64", "int8", "int32" ]
},
"subscribe" : {
"fields" : [ "float32", "float64", "int8", "int32" ]
}
}
}
}

14
etc/unix_domain.conf Normal file
View file

@ -0,0 +1,14 @@
nodes = {
unix_domain_node = {
type = "socket",
layer = "udp",
# layer = "unix",
format = "protobuf",
local = "*:12000";
remote = "127.0.0.1:12001"
# local = "/var/run/villas-node.server.sock",
# remote = "/var/run/villas-node.client.sock",
}
}

108
etc/websocket-demo2.conf Normal file
View file

@ -0,0 +1,108 @@
/** Example configuration file for VILLASnode.
*
* The syntax of this file is similar to JSON.
* A detailed description of the format can be found here:
* http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
stats = 1;
logging = {
level = 1
}
nodes = {
sig = {
type = "signal",
vectorize = 1,
signal = "mixed",
values = 5,
rate = 40,
amplitude = 2000000,
hooks = (
{ type = "stats" }
)
},
sig2 = {
type = "signal",
vectorize = 1,
signal = "mixed",
values = 5,
rate = 40,
hooks = (
{ type = "stats" }
)
},
stats = {
type = "stats",
node = "sig",
rate = 40
},
ws_stats = {
type = "websocket"
vectorize = 40,
},
ws_sig = {
type = "websocket",
vectorize = 40,
description = "Demo Channel",
series = (
{ label = "Random walk", unit = "V", yaxis = 2 },
{ label = "Sine", unit = "A" },
{ label = "Square", unit = "Var"},
{ label = "Triangle", unit = "°C" },
{ label = "Ramp", unit = "°C" }
),
hooks = (
{ type = "stats" }
)
},
ws_sig2 = {
type = "websocket",
vectorize = 40,
description = "Demo Channel",
series = (
{ label = "Random walk", unit = "V", yaxis = 2 },
{ label = "Sine", unit = "A" },
{ label = "Square", unit = "Var"},
{ label = "Triangle", unit = "°C" },
{ label = "Ramp", unit = "°C" }
),
hooks = (
{ type = "stats" }
)
},
};
############ List of paths ############
paths = (
{ in = "sig", out = "ws_sig" },
{ in = "sig2", out = "ws_sig2" },
{ in = "stats", out = "ws_stats" }
);

View file

@ -1,95 +0,0 @@
/** FPGA card
*
* This class represents a FPGA device.
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
/** @addtogroup fpga VILLASfpga
* @{
*/
#pragma once
#include <jansson.h>
#include "common.h"
#include "kernel/pci.h"
#include "kernel/vfio.h"
/* Forward declarations */
struct fpga_ip;
struct vfio_container;
struct fpga_card {
char *name; /**< The name of the FPGA card */
enum state state; /**< The state of this FPGA card. */
struct pci *pci;
struct pci_device filter; /**< Filter for PCI device. */
struct vfio_container *vfio_container;
struct vfio_device vfio_device; /**< VFIO device handle. */
int do_reset; /**< Reset VILLASfpga during startup? */
int affinity; /**< Affinity for MSI interrupts */
struct list ips; /**< List of IP components on FPGA. */
char *map; /**< PCI BAR0 mapping for register access */
size_t maplen;
size_t dmalen;
/* Some IP cores are special and referenced here */
struct fpga_ip *intc;
struct fpga_ip *reset;
struct fpga_ip *sw;
};
/** Initialize FPGA card and its IP components. */
int fpga_card_init(struct fpga_card *c, struct pci *pci, struct vfio_container *vc);
/** Parse configuration of FPGA card including IP cores from config. */
int fpga_card_parse(struct fpga_card *c, json_t *cfg, const char *name);
int fpga_card_parse_list(struct list *l, json_t *cfg);
/** Check if the FPGA card configuration is plausible. */
int fpga_card_check(struct fpga_card *c);
/** Start FPGA card. */
int fpga_card_start(struct fpga_card *c);
/** Stop FPGA card. */
int fpga_card_stop(struct fpga_card *c);
/** Destroy FPGA card. */
int fpga_card_destroy(struct fpga_card *c);
/** Dump details of FPGA card to stdout. */
void fpga_card_dump(struct fpga_card *c);
/** Reset the FPGA to a known state */
int fpga_card_reset(struct fpga_card *c);
/** @} */

View file

@ -1,119 +0,0 @@
/** Interlectual Property component.
*
* This class represents a module within the FPGA.
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
/** @addtogroup fpga VILLASfpga
* @{
*/
#pragma once
#include <stdint.h>
#include "common.h"
#include "fpga/vlnv.h"
#include "fpga/ips/dma.h"
#include "fpga/ips/switch.h"
#include "fpga/ips/fifo.h"
#include "fpga/ips/rtds_axis.h"
#include "fpga/ips/timer.h"
#include "fpga/ips/model.h"
#include "fpga/ips/dft.h"
#include "fpga/ips/intc.h"
enum fpga_ip_types {
FPGA_IP_TYPE_DM_DMA, /**< A datamover IP exchanges streaming data between the FPGA and the CPU. */
FPGA_IP_TYPE_DM_FIFO, /**< A datamover IP exchanges streaming data between the FPGA and the CPU. */
FPGA_IP_TYPE_MODEL, /**< A model IP simulates a system on the FPGA. */
FPGA_IP_TYPE_MATH, /**< A math IP performs some kind of mathematical operation on the streaming data */
FPGA_IP_TYPE_MISC, /**< Other IP components like timer, counters, interrupt conctrollers or routing. */
FPGA_IP_TYPE_INTERFACE /**< A interface IP connects the FPGA to another system or controller. */
} type;
struct fpga_ip_type {
struct fpga_vlnv vlnv;
enum fpga_ip_types type;
int (*init)(struct fpga_ip *c);
int (*parse)(struct fpga_ip *c, json_t *cfg);
int (*check)(struct fpga_ip *c);
int (*start)(struct fpga_ip *c);
int (*stop)(struct fpga_ip *c);
int (*destroy)(struct fpga_ip *c);
int (*reset)(struct fpga_ip *c);
void (*dump)(struct fpga_ip *c);
size_t size; /**< Amount of memory which should be reserved for struct fpga_ip::_vd */
};
struct fpga_ip {
char *name; /**< Name of the FPGA IP component. */
struct fpga_vlnv vlnv; /**< The Vendor, Library, Name, Version tag of the FPGA IP component. */
enum state state; /**< The current state of the FPGA IP component. */
struct fpga_ip_type *_vt; /**< Vtable containing FPGA IP type function pointers. */
void *_vd; /**< Virtual data (used by struct fpga_ip::_vt functions) */
uintptr_t baseaddr; /**< The baseadress of this FPGA IP component */
uintptr_t baseaddr_axi4; /**< Used by AXI4 FIFO DM */
int port; /**< The port of the AXI4-Stream switch to which this FPGA IP component is connected. */
int irq; /**< The interrupt number of the FPGA IP component. */
struct fpga_card *card; /**< The FPGA to which this IP instance belongs to. */
};
/** Initialize IP core. */
int fpga_ip_init(struct fpga_ip *c, struct fpga_ip_type *vt);
/** Parse IP core configuration from configuration file */
int fpga_ip_parse(struct fpga_ip *c, json_t *cfg, const char *name);
/** Check configuration of IP core. */
int fpga_ip_check(struct fpga_ip *c);
/** Start IP core. */
int fpga_ip_start(struct fpga_ip *c);
/** Stop IP core. */
int fpga_ip_stop(struct fpga_ip *c);
/** Release dynamic memory allocated by this IP core. */
int fpga_ip_destroy(struct fpga_ip *c);
/** Dump details about this IP core to stdout. */
void fpga_ip_dump(struct fpga_ip *c);
/** Reset IP component to its initial state. */
int fpga_ip_reset(struct fpga_ip *c);
/** Find a registered FPGA IP core type with the given VLNV identifier. */
struct fpga_ip_type * fpga_ip_type_lookup(const char *vstr);
/** @} */

View file

@ -1,36 +0,0 @@
/** Moving window / Recursive DFT implementation based on HLS
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
/** @addtogroup fpga VILLASfpga
* @{
*/
#pragma once
#include <xilinx/xhls_dft.h>
/* Forward declaration */
struct ip;
struct dft {
XHls_dft inst;
int period; /* in samples */
int num_harmonics;
float *fharmonics;
int decimation;
};
int dft_parse(struct fpga_ip *c, json_t *cfg);
int dft_start(struct fpga_ip *c);
int dft_stop(struct fpga_ip *c);
int dft_destroy(struct fpga_ip *c);
/** @} */

View file

@ -1,72 +0,0 @@
/** DMA related helper functions.
*
* These functions present a simpler interface to Xilinx' DMA driver (XAxiDma_*).
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
/** @addtogroup fpga VILLASfpga
* @{
*/
#pragma once
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <xilinx/xaxidma.h>
/* Forward declarations */
struct fpga_ip;
#define FPGA_DMA_BASEADDR 0x00000000
#define FPGA_DMA_BOUNDARY 0x1000
#define FPGA_DMA_BD_OFFSET 0xC0000000
#define FPGA_DMA_BD_SIZE (32 << 20) // 32 MB
#define XAXIDMA_SR_SGINCL_MASK 0x00000008
struct dma_mem {
char *base_virt;
char *base_phys;
size_t len;
};
struct dma {
XAxiDma inst;
struct dma_mem bd;
};
struct ip;
int dma_mem_split(struct dma_mem *o, struct dma_mem *a, struct dma_mem *b);
int dma_alloc(struct fpga_ip *c, struct dma_mem *mem, size_t len, int flags);
int dma_free(struct fpga_ip *c, struct dma_mem *mem);
int dma_write(struct fpga_ip *c, char *buf, size_t len);
int dma_read(struct fpga_ip *c, char *buf, size_t len);
int dma_read_complete(struct fpga_ip *c, char **buf, size_t *len);
int dma_write_complete(struct fpga_ip *c, char **buf, size_t *len);
int dma_sg_write(struct fpga_ip *c, char *buf, size_t len);
int dma_sg_read(struct fpga_ip *c, char *buf, size_t len);
int dma_sg_write_complete(struct fpga_ip *c, char **buf, size_t *len);
int dma_sg_read_complete(struct fpga_ip *c, char **buf, size_t *len);
int dma_simple_read(struct fpga_ip *c, char *buf, size_t len);
int dma_simple_write(struct fpga_ip *c, char *buf, size_t len);
int dma_simple_read_complete(struct fpga_ip *c, char **buf, size_t *len);
int dma_simple_write_complete(struct fpga_ip *c, char **buf, size_t *len);
int dma_ping_pong(struct fpga_ip *c, char *src, char *dst, size_t len);
int dma_start(struct fpga_ip *c);
/** @} */

View file

@ -1,36 +0,0 @@
/** FIFO related helper functions
*
* These functions present a simpler interface to Xilinx' FIFO driver (XLlFifo_*)
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
/** @addtogroup fpga VILLASfpga
* @{
*/
#pragma once
#include <sys/types.h>
#include <xilinx/xstatus.h>
#include <xilinx/xllfifo.h>
struct fifo {
XLlFifo inst;
uint32_t baseaddr_axi4;
};
/* Forward declarations */
struct ip;
int fifo_start(struct fpga_ip *c);
ssize_t fifo_write(struct fpga_ip *c, char *buf, size_t len);
ssize_t fifo_read(struct fpga_ip *c, char *buf, size_t len);
/** @} */

View file

@ -1,39 +0,0 @@
/** AXI-PCIe Interrupt controller
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
/** @addtogroup fpga VILLASfpga
* @{
*/
#pragma once
#include <xilinx/xintc.h>
enum intc_flags {
INTC_ENABLED = (1 << 0),
INTC_POLLING = (1 << 1)
};
struct intc {
int num_irqs; /**< Number of available MSI vectors */
int efds[32]; /**< Event FDs */
int nos[32]; /**< Interrupt numbers from /proc/interrupts */
int flags[32]; /**< Mask of intc_flags */
};
int intc_init(struct fpga_ip *c);
int intc_destroy(struct fpga_ip *c);
int intc_enable(struct fpga_ip *c, uint32_t mask, int poll);
int intc_disable(struct fpga_ip *c, uint32_t mask);
uint64_t intc_wait(struct fpga_ip *c, int irq);
/** @} */

View file

@ -1,131 +0,0 @@
/** Interface to Xilinx System Generator Models via PCIe
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
*********************************************************************************/
/** @addtogroup fpga VILLASfpga
* @{
*/
#pragma once
#include <stdlib.h>
#include <stdint.h>
#include "list.h"
#define XSG_MAPLEN 0x1000
#define XSG_MAGIC 0xDEADBABE
/* Forward declaration */
struct ip;
enum model_type {
MODEL_TYPE_HLS,
MODEL_TYPE_XSG
};
enum model_xsg_block_type {
XSG_BLOCK_GATEWAY_IN = 0x1000,
XSG_BLOCK_GATEWAY_OUT = 0x1001,
XSG_BLOCK_INFO = 0x2000
};
enum model_parameter_type {
MODEL_PARAMETER_TYPE_UFIX,
MODEL_PARAMETER_TYPE_FIX,
MODEL_PARAMETER_TYPE_FLOAT,
MODEL_PARAMETER_TYPE_BOOLEAN
};
enum model_parameter_direction {
MODEL_PARAMETER_IN,
MODEL_PARAMETER_OUT,
MODEL_PARAMETER_INOUT
};
union model_parameter_value {
uint32_t ufix;
int32_t fix;
float flt;
bool bol;
};
struct xsg_model {
uint32_t *map;
ssize_t maplen;
};
struct hls_model {
};
struct model {
enum model_type type; /**< Either HLS or XSG model */
struct list parameters; /**< List of model parameters. */
struct list infos; /**< A list of key / value pairs with model details */
union {
struct xsg_model xsg; /**< XSG specific model data */
struct hls_model hls; /**< HLS specific model data */
};
};
struct model_info {
char *field;
char *value;
};
struct model_parameter {
char *name; /**< Name of the parameter */
enum model_parameter_direction direction; /**< Read / Write / Read-write? */
enum model_parameter_type type; /**< Data type. Integers are represented by MODEL_GW_TYPE_(U)FIX with model_gw::binpt == 0 */
int binpt; /**< Binary point for type == MODEL_GW_TYPE_(U)FIX */
uintptr_t offset; /**< Register offset to model::baseaddress */
union model_parameter_value default_value;
struct fpga_ip *ip; /**< A pointer to the model structure to which this parameters belongs to. */
};
/** Initialize a model */
int model_init(struct fpga_ip *c);
/** Parse model */
int model_parse(struct fpga_ip *c, json_t *cfg);
/** Destroy a model */
int model_destroy(struct fpga_ip *c);
/** Print detailed information about the model to the screen. */
void model_dump(struct fpga_ip *c);
/** Add a new parameter to the model */
void model_parameter_add(struct fpga_ip *c, const char *name, enum model_parameter_direction dir, enum model_parameter_type type);
/** Remove an existing parameter by its name */
int model_parameter_remove(struct fpga_ip *c, const char *name);
/** Read a model parameter.
*
* Note: the data type of the register is taken into account.
* All datatypes are converted to double.
*/
int model_parameter_read(struct model_parameter *p, double *v);
/** Update a model parameter.
*
* Note: the data type of the register is taken into account.
* The double argument will be converted to the respective data type of the
* GatewayIn/Out block.
*/
int model_parameter_write(struct model_parameter *p, double v);
int model_parameter_update(struct model_parameter *p, struct model_parameter *u);
/** @} */

View file

@ -1,46 +0,0 @@
/** Driver for AXI Stream wrapper around RTDS_InterfaceModule (rtds_axis )
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
/** @addtogroup fpga VILLASfpga
* @{
*/
#pragma once
/* Forward declarations */
struct ip;
#define RTDS_HZ 100000000 // 100 MHz
#define RTDS_AXIS_MAX_TX 64 /**< The amount of values which is supported by the vfpga card */
#define RTDS_AXIS_MAX_RX 64 /**< The amount of values which is supported by the vfpga card */
/* Register offsets */
#define RTDS_AXIS_SR_OFFSET 0x00 /**< Status Register (read-only). See RTDS_AXIS_SR_* constant. */
#define RTDS_AXIS_CR_OFFSET 0x04 /**< Control Register (read/write) */
#define RTDS_AXIS_TSCNT_LOW_OFFSET 0x08 /**< Lower 32 bits of timestep counter (read-only). */
#define RTDS_AXIS_TSCNT_HIGH_OFFSET 0x0C /**< Higher 32 bits of timestep counter (read-only). */
#define RTDS_AXIS_TS_PERIOD_OFFSET 0x10 /**< Period in clock cycles of previous timestep (read-only). */
#define RTDS_AXIS_COALESC_OFFSET 0x14 /**< IRQ Coalescing register (read/write). */
#define RTDS_AXIS_VERSION_OFFSET 0x18 /**< 16 bit version field passed back to the rack for version reporting (visible from “status” command, read/write). */
#define RTDS_AXIS_MRATE 0x1C /**< Multi-rate register */
/* Status register bits */
#define RTDS_AXIS_SR_CARDDETECTED (1 << 0)/**< 1 when RTDS software has detected and configured card. */
#define RTDS_AXIS_SR_LINKUP (1 << 1)/**< 1 when RTDS communication link has been negotiated. */
#define RTDS_AXIS_SR_TX_FULL (1 << 2)/**< Tx buffer is full, writes that happen when UserTxFull=1 will be dropped (Throttling / buffering is performed by hardware). */
#define RTDS_AXIS_SR_TX_INPROGRESS (1 << 3)/**< Indicates when data is being put on link. */
#define RTDS_AXIS_SR_CASE_RUNNING (1 << 4)/**< There is currently a simulation running. */
/* Control register bits */
#define RTDS_AXIS_CR_DISABLE_LINK 0 /**< Disable SFP TX when set */
void rtds_axis_dump(struct fpga_ip *c);
double rtds_axis_dt(struct fpga_ip *c);
/** @} */

View file

@ -1,51 +0,0 @@
/** AXI Stream interconnect related helper functions
*
* These functions present a simpler interface to Xilinx' AXI Stream switch driver (XAxis_Switch_*)
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
/** @addtogroup fpga VILLASfpga
* @{
*/
#pragma once
#include <jansson.h>
#include <xilinx/xaxis_switch.h>
#include "list.h"
/* Forward declarations */
struct ip;
struct sw_path {
const char *in;
const char *out;
};
struct sw {
XAxis_Switch inst;
int num_ports;
struct list paths;
};
struct ip;
int switch_start(struct fpga_ip *c);
/** Initialize paths which have been parsed by switch_parse() */
int switch_init_paths(struct fpga_ip *c);
int switch_destroy(struct fpga_ip *c);
int switch_parse(struct fpga_ip *c, json_t *cfg);
int switch_connect(struct fpga_ip *c, struct fpga_ip *mi, struct fpga_ip *si);
int switch_disconnect(struct fpga_ip *c, struct fpga_ip *mi, struct fpga_ip *si);
/** @} */

View file

@ -1,27 +0,0 @@
/** Timer related helper functions
*
* These functions present a simpler interface to Xilinx' Timer Counter driver (XTmrCtr_*)
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
/** @addtogroup fpga VILLASfpga
* @{
*/
#pragma once
#include <xilinx/xtmrctr.h>
/* Forward declarations */
struct fpga_ip;
struct timer {
XTmrCtr inst;
};
int timer_start(struct fpga_ip *c);
/** @} */

View file

@ -1,53 +0,0 @@
/** Vendor, Library, Name, Version (VLNV) tag.
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
/** @addtogroup fpga VILLASfpga
* @{
*/
#ifndef _FPGA_VLNV_H_
#define _FPGA_VLNV_H_
/* Forward declarations */
struct list;
struct fpga_vlnv {
char *vendor;
char *library;
char *name;
char *version;
};
/** Return the first IP block in list \p l which matches the VLNV */
struct fpga_ip * fpga_vlnv_lookup(struct list *l, struct fpga_vlnv *v);
/** Check if IP block \p c matched VLNV. */
int fpga_vlnv_cmp(struct fpga_vlnv *a, struct fpga_vlnv *b);
/** Tokenizes VLNV \p vlnv and stores it into \p c */
int fpga_vlnv_parse(struct fpga_vlnv *c, const char *vlnv);
/** Release memory allocated by fpga_vlnv_parse(). */
int fpga_vlnv_destroy(struct fpga_vlnv *v);
#endif /** _FPGA_VLNV_H_ @} */

View file

@ -24,7 +24,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
/** @addtogroup fpga Kernel @{ */
/** @addtogroup kernel Kernel @{ */
#pragma once

View file

@ -21,7 +21,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
/** @addtogroup fpga Kernel @{ */
/** @addtogroup kernel Kernel @{ */
#pragma once

View file

@ -21,7 +21,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
/** @addtogroup fpga Kernel @{ */
/** @addtogroup kernel Kernel @{ */
#pragma once

View file

@ -1,62 +0,0 @@
/** Linux PCI helpers
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
/** @addtogroup fpga Kernel @{ */
#pragma once
#include "list.h"
#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
#define PCI_FUNC(devfn) ((devfn) & 0x07)
struct pci_device {
struct {
int vendor;
int device;
int class;
} id;
struct {
int domain;
int bus;
int device;
int function;
} slot; /**< Bus, Device, Function (BDF) */
};
struct pci {
struct list devices; /**< List of available PCI devices in the system (struct pci_device) */
};
/** Initialize Linux PCI handle.
*
* This search for all available PCI devices under /sys/bus/pci
*
* @retval 0 Success. Everything went well.
* @retval <0 Error. Something went wrong.
*/
int pci_init(struct pci *p);
/** Destroy handle. */
int pci_destroy(struct pci *p);
int pci_device_parse_slot(struct pci_device *f, const char *str, const char **error);
int pci_device_parse_id(struct pci_device *f, const char *str, const char **error);
int pci_device_compare(const struct pci_device *d, const struct pci_device *f);
struct pci_device * pci_lookup_device(struct pci *p, struct pci_device *filter);
/** Bind a new LKM to the PCI device */
int pci_attach_driver(struct pci_device *d, const char *driver);
/** Return the IOMMU group of this PCI device or -1 if the device is not in a group. */
int pci_get_iommu_group(struct pci_device *d);
/** @} */

View file

@ -22,7 +22,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
/** @addtogroup fpga Kernel @{ */
/** @addtogroup kernel Kernel @{ */
#pragma once

View file

@ -26,7 +26,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
/** @addtogroup fpga Kernel @{ */
/** @addtogroup kernel Kernel @{ */
#pragma once

View file

@ -1,112 +0,0 @@
/** Virtual Function IO wrapper around kernel API
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
*********************************************************************************/
/** @addtogroup fpga Kernel @{ */
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <sys/mman.h>
#include <linux/vfio.h>
#include <linux/pci_regs.h>
#include "list.h"
#define VFIO_DEV(x) "/dev/vfio/" x
/* Forward declarations */
struct pci_device;
struct vfio_group {
int fd; /**< VFIO group file descriptor */
int index; /**< Index of the IOMMU group as listed under /sys/kernel/iommu_groups/ */
struct vfio_group_status status; /**< Status of group */
struct list devices;
struct vfio_container *container; /**< The VFIO container to which this group is belonging */
};
struct vfio_device {
char *name; /**< Name of the device as listed under /sys/kernel/iommu_groups/[vfio_group::index]/devices/ */
int fd; /**< VFIO device file descriptor */
struct vfio_device_info info;
struct vfio_irq_info *irqs;
struct vfio_region_info *regions;
void **mappings;
struct pci_device *pci_device; /**< libpci handle of the device */
struct vfio_group *group; /**< The VFIO group this device belongs to */
};
struct vfio_container {
int fd;
int version;
int extensions;
uint64_t iova_next; /**< Next free IOVA address */
struct list groups;
};
/** Initialize a new VFIO container. */
int vfio_init(struct vfio_container *c);
/** Initialize a VFIO group and attach it to an existing VFIO container. */
int vfio_group_attach(struct vfio_group *g, struct vfio_container *c, int index);
/** Initialize a VFIO device, lookup the VFIO group it belongs to, create the group if not already existing. */
int vfio_device_attach(struct vfio_device *d, struct vfio_container *c, const char *name, int index);
/** Initialie a VFIO-PCI device (uses vfio_device_attach() internally) */
int vfio_pci_attach(struct vfio_device *d, struct vfio_container *c, struct pci_device *pdev);
/** Hot resets a VFIO-PCI device */
int vfio_pci_reset(struct vfio_device *d);
int vfio_pci_msi_init(struct vfio_device *d, int efds[32]);
int vfio_pci_msi_deinit(struct vfio_device *d, int efds[32]);
int vfio_pci_msi_find(struct vfio_device *d, int nos[32]);
/** Enable memory accesses and bus mastering for PCI device */
int vfio_pci_enable(struct vfio_device *d);
/** Reset a VFIO device */
int vfio_device_reset(struct vfio_device *d);
/** Release memory and close container */
int vfio_destroy(struct vfio_container *c);
/** Release memory of group */
int vfio_group_destroy(struct vfio_group *g);
/** Release memory of device */
int vfio_device_destroy(struct vfio_device *g);
/** Print a dump of all attached groups and their devices including regions and IRQs */
void vfio_dump(struct vfio_container *c);
/** Map a device memory region to the application address space (e.g. PCI BARs) */
void * vfio_map_region(struct vfio_device *d, int idx);
/** Map VM to an IOVA, which is accessible by devices in the container */
int vfio_map_dma(struct vfio_container *c, uint64_t virt, uint64_t phys, size_t len);
/** Unmap DMA memory */
int vfio_unmap_dma(struct vfio_container *c, uint64_t virt, uint64_t phys, size_t len);
/** munmap() a region which has been mapped by vfio_map_region() */
int vfio_unmap_region(struct vfio_device *d, int idx);
/** @} */

View file

@ -1,24 +0,0 @@
# Makefile.
#
# @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
# @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
# @license GNU General Public License (version 3)
#
# VILLASnode
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
LIB_SRCS += $(wildcard lib/fpga/*.c)
LIB_SRCS += $(wildcard lib/fpga/ips/*.c)

View file

@ -1,313 +0,0 @@
/** FPGA card.
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <unistd.h>
#include "config.h"
#include "log.h"
#include "log_config.h"
#include "list.h"
#include "utils.h"
#include "kernel/pci.h"
#include "kernel/vfio.h"
#include "fpga/ip.h"
#include "fpga/card.h"
int fpga_card_init(struct fpga_card *c, struct pci *pci, struct vfio_container *vc)
{
assert(c->state = STATE_DESTROYED);
c->vfio_container = vc;
c->pci = pci;
list_init(&c->ips);
/* Default values */
c->filter.id.vendor = FPGA_PCI_VID_XILINX;
c->filter.id.device = FPGA_PCI_PID_VFPGA;
c->affinity = 0;
c->do_reset = 0;
c->state = STATE_INITIALIZED;
return 0;
}
int fpga_card_parse(struct fpga_card *c, json_t *cfg, const char *name)
{
int ret;
json_t *json_ips;
json_t *json_slot = NULL;
json_t *json_id = NULL;
json_error_t err;
c->name = strdup(name);
ret = json_unpack_ex(cfg, &err, 0, "{ s?: i, s?: b, s?: o, s?: o, s: o }",
"affinity", &c->affinity,
"do_reset", &c->do_reset,
"slot", &json_slot,
"id", &json_id,
"ips", &json_ips
);
if (ret)
jerror(&err, "Failed to parse FPGA vard configuration");
if (json_slot) {
const char *err, *slot;
slot = json_string_value(json_slot);
if (slot) {
ret = pci_device_parse_slot(&c->filter, slot, &err);
if (ret)
error("Failed to parse PCI slot: %s", err);
}
else
error("PCI slot must be a string");
}
if (json_id) {
const char *err, *id;
id = json_string_value(json_id);
if (id) {
ret = pci_device_parse_id(&c->filter, (char*) id, &err);
if (ret)
error("Failed to parse PCI id: %s", err);
}
else
error("PCI ID must be a string");
}
if (!json_is_object(json_ips))
error("FPGA card IPs section must be an object");
const char *name_ip;
json_t *json_ip;
json_object_foreach(json_ips, name_ip, json_ip) {
const char *vlnv;
struct fpga_ip_type *vt;
struct fpga_ip *ip = (struct fpga_ip *) alloc(sizeof(struct fpga_ip));
ip->card = c;
ret = json_unpack_ex(json_ip, &err, 0, "{ s: s }", "vlnv", &vlnv);
if (ret)
error("Failed to parse FPGA IP '%s' of card '%s'", name_ip, name);
vt = fpga_ip_type_lookup(vlnv);
if (!vt)
error("FPGA IP core VLNV identifier '%s' is invalid", vlnv);
ret = fpga_ip_init(ip, vt);
if (ret)
error("Failed to initalize FPGA IP core");
ret = fpga_ip_parse(ip, json_ip, name_ip);
if (ret)
error("Failed to parse FPGA IP core");
list_push(&c->ips, ip);
}
c->state = STATE_PARSED;
return 0;
}
int fpga_card_parse_list(struct list *cards, json_t *cfg)
{
int ret;
if (!json_is_object(cfg))
error("FPGA card configuration section must be a JSON object");
const char *name;
json_t *json_fpga;
json_object_foreach(cfg, name, json_fpga) {
struct fpga_card *c = (struct fpga_card *) alloc(sizeof(struct fpga_card));
ret = fpga_card_parse(c, json_fpga, name);
if (ret)
error("Failed to parse FPGA card configuration");
list_push(cards, c);
}
return 0;
}
int fpga_card_start(struct fpga_card *c)
{
int ret;
struct pci_device *pdev;
assert(c->state == STATE_CHECKED);
/* Search for FPGA card */
pdev = pci_lookup_device(c->pci, &c->filter);
if (!pdev)
error("Failed to find PCI device");
/* Attach PCIe card to VFIO container */
ret = vfio_pci_attach(&c->vfio_device, c->vfio_container, pdev);
if (ret)
error("Failed to attach VFIO device");
/* Map PCIe BAR */
c->map = vfio_map_region(&c->vfio_device, VFIO_PCI_BAR0_REGION_INDEX);
if (c->map == MAP_FAILED)
serror("Failed to mmap() BAR0");
/* Enable memory access and PCI bus mastering for DMA */
ret = vfio_pci_enable(&c->vfio_device);
if (ret)
serror("Failed to enable PCI device");
/* Reset system? */
if (c->do_reset) {
/* Reset / detect PCI device */
ret = vfio_pci_reset(&c->vfio_device);
if (ret)
serror("Failed to reset PCI device");
ret = fpga_card_reset(c);
if (ret)
error("Failed to reset FGPA card");
}
/* Initialize IP cores */
for (size_t j = 0; j < list_length(&c->ips); j++) {
struct fpga_ip *i = (struct fpga_ip *) list_at(&c->ips, j);
ret = fpga_ip_start(i);
if (ret)
error("Failed to initalize FPGA IP core: %s (%u)", i->name, ret);
}
c->state = STATE_STARTED;
return 0;
}
int fpga_card_stop(struct fpga_card *c)
{
int ret;
assert(c->state == STATE_STOPPED);
for (size_t j = 0; j < list_length(&c->ips); j++) {
struct fpga_ip *i = (struct fpga_ip *) list_at(&c->ips, j);
ret = fpga_ip_stop(i);
if (ret)
error("Failed to stop FPGA IP core: %s (%u)", i->name, ret);
}
c->state = STATE_STOPPED;
return 0;
}
void fpga_card_dump(struct fpga_card *c)
{
info("VILLASfpga card:");
{ INDENT
info("Slot: %04x:%02x:%02x.%d", c->vfio_device.pci_device->slot.domain, c->vfio_device.pci_device->slot.bus, c->vfio_device.pci_device->slot.device, c->vfio_device.pci_device->slot.function);
info("Vendor ID: %04x", c->vfio_device.pci_device->id.vendor);
info("Device ID: %04x", c->vfio_device.pci_device->id.device);
info("Class ID: %04x", c->vfio_device.pci_device->id.class);
info("BAR0 mapped at %p", c->map);
info("IP blocks:");
for (size_t j = 0; j < list_length(&c->ips); j++) { INDENT
struct fpga_ip *i = (struct fpga_ip *) list_at(&c->ips, j);
fpga_ip_dump(i);
}
}
vfio_dump(c->vfio_device.group->container);
}
int fpga_card_check(struct fpga_card *c)
{
/* Check FPGA configuration */
c->reset = fpga_vlnv_lookup(&c->ips, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_gpio", NULL });
if (!c->reset)
error("FPGA is missing a reset controller");
c->intc = fpga_vlnv_lookup(&c->ips, &(struct fpga_vlnv) { "acs.eonerc.rwth-aachen.de", "user", "axi_pcie_intc", NULL });
if (!c->intc)
error("FPGA is missing a interrupt controller");
c->sw = fpga_vlnv_lookup(&c->ips, &(struct fpga_vlnv) { "xilinx.com", "ip", "axis_interconnect", NULL });
if (!c->sw)
warn("FPGA is missing an AXI4-Stream switch");
return 0;
}
int fpga_card_destroy(struct fpga_card *c)
{
list_destroy(&c->ips, (dtor_cb_t) fpga_ip_destroy, true);
return 0;
}
int fpga_card_reset(struct fpga_card *c)
{
int ret;
char state[4096];
/* Save current state of PCI configuration space */
ret = pread(c->vfio_device.fd, state, sizeof(state), (off_t) VFIO_PCI_CONFIG_REGION_INDEX << 40);
if (ret != sizeof(state))
return -1;
uint32_t *rst_reg = (uint32_t *) (c->map + c->reset->baseaddr);
debug(3, "FPGA: reset");
rst_reg[0] = 1;
usleep(100000);
/* Restore previous state of PCI configuration space */
ret = pwrite(c->vfio_device.fd, state, sizeof(state), (off_t) VFIO_PCI_CONFIG_REGION_INDEX << 40);
if (ret != sizeof(state))
return -1;
/* After reset the value should be zero again */
if (rst_reg[0])
return -2;
c->state = STATE_INITIALIZED;
return 0;
}

View file

@ -1,167 +0,0 @@
/** FPGA IP component.
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include "log_config.h"
#include "log.h"
#include "plugin.h"
int fpga_ip_init(struct fpga_ip *c, struct fpga_ip_type *vt)
{
int ret;
assert(c->state == STATE_DESTROYED);
c->_vt = vt;
c->_vd = alloc(vt->size);
ret = c->_vt->init ? c->_vt->init(c) : 0;
if (ret)
return ret;
c->state = STATE_INITIALIZED;
debug(8, "IP Core %s initalized (%u)", c->name, ret);
return ret;
}
int fpga_ip_parse(struct fpga_ip *c, json_t *cfg, const char *name)
{
int ret, baseaddr = -1;
assert(c->state != STATE_STARTED && c->state != STATE_DESTROYED);
c->name = strdup(name);
c->baseaddr = -1;
c->irq = -1;
c->port = -1;
json_error_t err;
ret = json_unpack_ex(cfg, &err, 0, "{ s?: i, s?: i, s?: i }",
"baseaddr", &baseaddr,
"irq", &c->irq,
"port", &c->port
);
if (ret)
jerror(&err, "Failed to parse configuration for FPGA IP '%s'", name);
c->baseaddr = baseaddr;
/* Type sepecific settings */
ret = c->_vt && c->_vt->parse ? c->_vt->parse(c, cfg) : 0;
if (ret)
error("Failed to parse settings for IP core '%s'", name);
c->state = STATE_PARSED;
return 0;
}
int fpga_ip_start(struct fpga_ip *c)
{
int ret;
assert(c->state == STATE_CHECKED);
ret = c->_vt->start ? c->_vt->start(c) : 0;
if (ret)
return ret;
c->state = STATE_STARTED;
return 0;
}
int fpga_ip_stop(struct fpga_ip *c)
{
int ret;
assert(c->state == STATE_STARTED);
ret = c->_vt->stop ? c->_vt->stop(c) : 0;
if (ret)
return ret;
c->state = STATE_STOPPED;
return 0;
}
int fpga_ip_destroy(struct fpga_ip *c)
{
int ret;
assert(c->state != STATE_DESTROYED);
fpga_vlnv_destroy(&c->vlnv);
ret = c->_vt->destroy ? c->_vt->destroy(c) : 0;
if (ret)
return ret;
c->state = STATE_DESTROYED;
free(c->_vd);
return 0;
}
int fpga_ip_reset(struct fpga_ip *c)
{
debug(3, "Reset IP core: %s", c->name);
return c->_vt->reset ? c->_vt->reset(c) : 0;
}
void fpga_ip_dump(struct fpga_ip *c)
{
assert(c->state != STATE_DESTROYED);
info("IP %s: vlnv=%s:%s:%s:%s baseaddr=%#jx, irq=%d, port=%d",
c->name, c->vlnv.vendor, c->vlnv.library, c->vlnv.name, c->vlnv.version,
c->baseaddr, c->irq, c->port);
if (c->_vt->dump)
c->_vt->dump(c);
}
struct fpga_ip_type * fpga_ip_type_lookup(const char *vstr)
{
int ret;
struct fpga_vlnv vlnv;
ret = fpga_vlnv_parse(&vlnv, vstr);
if (ret)
return NULL;
/* Try to find matching IP type */
for (size_t i = 0; i < list_length(&plugins); i++) {
struct plugin *p = (struct plugin *) list_at(&plugins, i);
if (p->type == PLUGIN_TYPE_FPGA_IP && !fpga_vlnv_cmp(&vlnv, &p->ip.vlnv))
return &p->ip;
}
return NULL;
}

View file

@ -1,25 +0,0 @@
# Makefile.
#
# @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
# @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
# @license GNU General Public License (version 3)
#
# VILLASnode
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
LIB_SRCS += $(wildcard lib/fpga/*.c)
include lib/fpga/ips/Makefile.inc

View file

@ -1,125 +0,0 @@
/** Moving window / Recursive DFT implementation based on HLS
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
#include "log.h"
#include "log_config.h"
#include "plugin.h"
#include "fpga/ip.h"
#include "fpga/card.h"
#include "fpga/ips/dft.h"
int dft_parse(struct fpga_ip *c, json_t *cfg)
{
struct dft *dft = (struct dft *) c->_vd;
int ret;
json_t *json_harms;
json_error_t err;
ret = json_unpack_ex(cfg, &err, 0, "{ s: i, s: i, s: o }",
"period", &dft->period,
"decimation", &dft->decimation,
"harmonics", &json_harms
);
if (ret)
jerror(&err, "Failed to parse configuration of FPGA IP '%s'", c->name);
if (!json_is_array(json_harms))
error("DFT IP core requires 'harmonics' to be an array of integers!");
dft->num_harmonics = json_array_size(json_harms);
if (dft->num_harmonics <= 0)
error("DFT IP core requires 'harmonics' to contain at least 1 value!");
dft->fharmonics = alloc(sizeof(float) * dft->num_harmonics);
size_t index;
json_t *json_harm;
json_array_foreach(json_harms, index, json_harm) {
if (!json_is_real(json_harm))
error("DFT IP core requires all 'harmonics' values to be of floating point type");
dft->fharmonics[index] = (float) json_number_value(json_harm) / dft->period;
}
return 0;
}
int dft_start(struct fpga_ip *c)
{
int ret;
struct fpga_card *f = c->card;
struct dft *dft = (struct dft *) c->_vd;
XHls_dft *xdft = &dft->inst;
XHls_dft_Config xdft_cfg = {
.Ctrl_BaseAddress = (uintptr_t) f->map + c->baseaddr
};
ret = XHls_dft_CfgInitialize(xdft, &xdft_cfg);
if (ret != XST_SUCCESS)
return ret;
int max_harmonics = XHls_dft_Get_fharmonics_TotalBytes(xdft) / sizeof(dft->fharmonics[0]);
if (dft->num_harmonics > max_harmonics)
error("DFT IP core supports a maximum of %u harmonics", max_harmonics);
XHls_dft_Set_num_harmonics_V(xdft, dft->num_harmonics);
XHls_dft_Set_decimation_V(xdft, dft->decimation);
memcpy((void *) (uintptr_t) XHls_dft_Get_fharmonics_BaseAddress(xdft), dft->fharmonics, dft->num_harmonics * sizeof(dft->fharmonics[0]));
XHls_dft_EnableAutoRestart(xdft);
XHls_dft_Start(xdft);
return 0;
}
int dft_stop(struct fpga_ip *c)
{
struct dft *dft = (struct dft *) c->_vd;
XHls_dft *xdft = &dft->inst;
XHls_dft_DisableAutoRestart(xdft);
return 0;
}
int dft_destroy(struct fpga_ip *c)
{
struct dft *dft = (struct dft *) c->_vd;
if (dft->fharmonics) {
free(dft->fharmonics);
dft->fharmonics = NULL;
}
return 0;
}
static struct plugin p = {
.name = "Discrete Fourier Transform",
.description = "Perfom Discrete Fourier Transforms with variable number of harmonics on the FPGA",
.type = PLUGIN_TYPE_FPGA_IP,
.ip = {
.vlnv = { "acs.eonerc.rwth-aachen.de", "hls", "hls_dft", NULL },
.type = FPGA_IP_TYPE_MATH,
.start = dft_start,
.stop = dft_stop,
.destroy = dft_destroy,
.parse = dft_parse,
.size = sizeof(struct dft)
}
};
REGISTER_PLUGIN(&p)

View file

@ -1,641 +0,0 @@
/** DMA related helper functions
*
* These functions present a simpler interface to Xilinx' DMA driver (XAxiDma_*)
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/mman.h>
#include "log.h"
#include "plugin.h"
#include "utils.h"
#include "fpga/ip.h"
#include "fpga/card.h"
#include "fpga/ips/dma.h"
int dma_mem_split(struct dma_mem *o, struct dma_mem *a, struct dma_mem *b)
{
int split = o->len / 2;
a->base_virt = o->base_virt;
a->base_phys = o->base_phys;
b->base_virt = a->base_virt + split;
b->base_phys = a->base_phys + split;
a->len = split;
b->len = o->len - split;
return 0;
}
int dma_alloc(struct fpga_ip *c, struct dma_mem *mem, size_t len, int flags)
{
int ret;
struct fpga_card *f = c->card;
/* Align to next bigger page size chunk */
if (len & 0xFFF) {
len += 0x1000;
len &= ~0xFFF;
}
mem->len = len;
mem->base_phys = (void *) -1; /* find free */
mem->base_virt = mmap(0, mem->len, PROT_READ | PROT_WRITE, flags | MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, 0, 0);
if (mem->base_virt == MAP_FAILED)
return -1;
ret = vfio_map_dma(f->vfio_device.group->container, (uint64_t) mem->base_virt, (uint64_t) mem->base_phys, mem->len);
if (ret)
return -2;
return 0;
}
int dma_free(struct fpga_ip *c, struct dma_mem *mem)
{
int ret;
ret = vfio_unmap_dma(c->card->vfio_device.group->container, (uint64_t) mem->base_virt, (uint64_t) mem->base_phys, mem->len);
if (ret)
return ret;
ret = munmap(mem->base_virt, mem->len);
if (ret)
return ret;
return 0;
}
int dma_ping_pong(struct fpga_ip *c, char *src, char *dst, size_t len)
{
int ret;
ret = dma_read(c, dst, len);
if (ret)
return ret;
ret = dma_write(c, src, len);
if (ret)
return ret;
ret = dma_write_complete(c, NULL, NULL);
if (ret)
return ret;
ret = dma_read_complete(c, NULL, NULL);
if (ret)
return ret;
return 0;
}
int dma_write(struct fpga_ip *c, char *buf, size_t len)
{
struct dma *dma = (struct dma *) c->_vd;
XAxiDma *xdma = &dma->inst;
debug(25, "DMA write: dmac=%s buf=%p len=%#zx", c->name, buf, len);
return xdma->HasSg
? dma_sg_write(c, buf, len)
: dma_simple_write(c, buf, len);
}
int dma_read(struct fpga_ip *c, char *buf, size_t len)
{
struct dma *dma = (struct dma *) c->_vd;
XAxiDma *xdma = &dma->inst;
debug(25, "DMA read: dmac=%s buf=%p len=%#zx", c->name, buf, len);
return xdma->HasSg
? dma_sg_read(c, buf, len)
: dma_simple_read(c, buf, len);
}
int dma_read_complete(struct fpga_ip *c, char **buf, size_t *len)
{
struct dma *dma = (struct dma *) c->_vd;
XAxiDma *xdma = &dma->inst;
debug(25, "DMA read complete: dmac=%s", c->name);
return xdma->HasSg
? dma_sg_read_complete(c, buf, len)
: dma_simple_read_complete(c, buf, len);
}
int dma_write_complete(struct fpga_ip *c, char **buf, size_t *len)
{
struct dma *dma = (struct dma *) c->_vd;
XAxiDma *xdma = &dma->inst;
debug(25, "DMA write complete: dmac=%s", c->name);
return xdma->HasSg
? dma_sg_write_complete(c, buf, len)
: dma_simple_write_complete(c, buf, len);
}
int dma_sg_write(struct fpga_ip *c, char *buf, size_t len)
{
int ret, bdcnt;
struct dma *dma = (struct dma *) c->_vd;
XAxiDma *xdma = &dma->inst;
XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma);
XAxiDma_Bd *bds, *bd;
uint32_t remaining, bdlen, bdbuf, cr;
/* Checks */
if (!xdma->HasSg)
return -1;
if (len < 1)
return -2;
if (!xdma->HasMm2S)
return -3;
if (!ring->HasDRE) {
uint32_t mask = xdma->MicroDmaMode ? XAXIDMA_MICROMODE_MIN_BUF_ALIGN : ring->DataWidth - 1;
if ((uintptr_t) buf & mask)
return -4;
}
bdcnt = CEIL(len, FPGA_DMA_BOUNDARY);
ret = XAxiDma_BdRingAlloc(ring, bdcnt, &bds);
if (ret != XST_SUCCESS)
return -5;
remaining = len;
bdbuf = (uintptr_t) buf;
bd = bds;
for (int i = 0; i < bdcnt; i++) {
bdlen = MIN(remaining, FPGA_DMA_BOUNDARY);
ret = XAxiDma_BdSetBufAddr(bd, bdbuf);
if (ret != XST_SUCCESS)
goto out;
ret = XAxiDma_BdSetLength(bd, bdlen, ring->MaxTransferLen);
if (ret != XST_SUCCESS)
goto out;
/* Set SOF / EOF / ID */
cr = 0;
if (i == 0)
cr |= XAXIDMA_BD_CTRL_TXSOF_MASK;
if (i == bdcnt - 1)
cr |= XAXIDMA_BD_CTRL_TXEOF_MASK;
XAxiDma_BdSetCtrl(bd, cr);
XAxiDma_BdSetId(bd, (uintptr_t) buf);
remaining -= bdlen;
bdbuf += bdlen;
bd = (XAxiDma_Bd *) XAxiDma_BdRingNext(ring, bd);
}
/* Give the BD to DMA to kick off the transmission. */
ret = XAxiDma_BdRingToHw(ring, bdcnt, bds);
if (ret != XST_SUCCESS)
return -8;
return 0;
out:
ret = XAxiDma_BdRingUnAlloc(ring, bdcnt, bds);
if (ret != XST_SUCCESS)
return -6;
return -5;
}
int dma_sg_read(struct fpga_ip *c, char *buf, size_t len)
{
int ret, bdcnt;
struct dma *dma = (struct dma *) c->_vd;
XAxiDma *xdma = &dma->inst;
XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma);
XAxiDma_Bd *bds, *bd;
uint32_t remaining, bdlen, bdbuf;
/* Checks */
if (!xdma->HasSg)
return -1;
if (len < 1)
return -2;
if (!xdma->HasS2Mm)
return -3;
if (!ring->HasDRE) {
uint32_t mask = xdma->MicroDmaMode ? XAXIDMA_MICROMODE_MIN_BUF_ALIGN : ring->DataWidth - 1;
if ((uintptr_t) buf & mask)
return -4;
}
bdcnt = CEIL(len, FPGA_DMA_BOUNDARY);
ret = XAxiDma_BdRingAlloc(ring, bdcnt, &bds);
if (ret != XST_SUCCESS)
return -5;
bdbuf = (uintptr_t) buf;
remaining = len;
bd = bds;
for (int i = 0; i < bdcnt; i++) {
bdlen = MIN(remaining, FPGA_DMA_BOUNDARY);
ret = XAxiDma_BdSetLength(bd, bdlen, ring->MaxTransferLen);
if (ret != XST_SUCCESS)
goto out;
ret = XAxiDma_BdSetBufAddr(bd, bdbuf);
if (ret != XST_SUCCESS)
goto out;
/* Receive BDs do not need to set anything for the control
* The hardware will set the SOF/EOF bits per stream ret */
XAxiDma_BdSetCtrl(bd, 0);
XAxiDma_BdSetId(bd, (uintptr_t) buf);
remaining -= bdlen;
bdbuf += bdlen;
bd = (XAxiDma_Bd *) XAxiDma_BdRingNext(ring, bd);
}
ret = XAxiDma_BdRingToHw(ring, bdcnt, bds);
if (ret != XST_SUCCESS)
return -8;
return 0;
out:
ret = XAxiDma_BdRingUnAlloc(ring, bdcnt, bds);
if (ret != XST_SUCCESS)
return -6;
return -5;
}
int dma_sg_write_complete(struct fpga_ip *c, char **buf, size_t *len)
{
struct dma *dma = (struct dma *) c->_vd;
XAxiDma *xdma = &dma->inst;
XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma);
XAxiDma_Bd *bds;
int processed, ret;
/* Wait until the one BD TX transaction is done */
while (!(XAxiDma_IntrGetIrq(xdma, XAXIDMA_DMA_TO_DEVICE) & XAXIDMA_IRQ_IOC_MASK))
intc_wait(c->card->intc, c->irq);
XAxiDma_IntrAckIrq(xdma, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DMA_TO_DEVICE);
processed = XAxiDma_BdRingFromHw(ring, XAXIDMA_ALL_BDS, &bds);
if (len != NULL)
*len = XAxiDma_BdGetActualLength(bds, XAXIDMA_MAX_TRANSFER_LEN);
if (buf != NULL)
*buf = (char *) (uintptr_t) XAxiDma_BdGetId(bds);
/* Free all processed TX BDs for future transmission */
ret = XAxiDma_BdRingFree(ring, processed, bds);
if (ret != XST_SUCCESS)
return -1;
return 0;
}
int dma_sg_read_complete(struct fpga_ip *c, char **buf, size_t *len)
{
struct dma *dma = (struct dma *) c->_vd;
XAxiDma *xdma = &dma->inst;
XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma);
XAxiDma_Bd *bds, *bd;
int ret, bdcnt;
uint32_t recvlen, sr;
uintptr_t recvbuf = 0;
if (!xdma->HasSg)
return -1;
while (!(XAxiDma_IntrGetIrq(xdma, XAXIDMA_DEVICE_TO_DMA) & XAXIDMA_IRQ_IOC_MASK))
intc_wait(c->card->intc, c->irq + 1);
XAxiDma_IntrAckIrq(xdma, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DEVICE_TO_DMA);
bdcnt = XAxiDma_BdRingFromHw(ring, XAXIDMA_ALL_BDS, &bds);
recvlen = 0;
bd = bds;
for (int i = 0; i < bdcnt; i++) {
recvlen += XAxiDma_BdGetActualLength(bd, ring->MaxTransferLen);
sr = XAxiDma_BdGetSts(bd);
if (sr & XAXIDMA_BD_STS_RXSOF_MASK)
if (i != 0)
warn("sof not first");
if (sr & XAXIDMA_BD_STS_RXEOF_MASK)
if (i != bdcnt - 1)
warn("eof not last");
recvbuf = XAxiDma_BdGetId(bd);
bd = (XAxiDma_Bd *) XAxiDma_BdRingNext(ring, bd);
}
if (len != NULL)
*len = recvlen;
if (buf != NULL)
*buf = (char *) recvbuf;
/* Free all processed RX BDs for future transmission */
ret = XAxiDma_BdRingFree(ring, bdcnt, bds);
if (ret != XST_SUCCESS)
return -3;
return 0;
}
int dma_simple_read(struct fpga_ip *c, char *buf, size_t len)
{
struct dma *dma = (struct dma *) c->_vd;
XAxiDma *xdma = &dma->inst;
XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma);
/* Checks */
if (xdma->HasSg)
return -1;
if ((len < 1) || (len > FPGA_DMA_BOUNDARY))
return -2;
if (!xdma->HasS2Mm)
return -3;
if (!ring->HasDRE) {
uint32_t mask = xdma->MicroDmaMode ? XAXIDMA_MICROMODE_MIN_BUF_ALIGN : ring->DataWidth - 1;
if ((uintptr_t) buf & mask)
return -4;
}
if(!(XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_SR_OFFSET) & XAXIDMA_HALTED_MASK)) {
if (XAxiDma_Busy(xdma, XAXIDMA_DEVICE_TO_DMA))
return -5;
}
XAxiDma_WriteReg(ring->ChanBase, XAXIDMA_DESTADDR_OFFSET, LOWER_32_BITS((uintptr_t) buf));
if (xdma->AddrWidth > 32)
XAxiDma_WriteReg(ring->ChanBase, XAXIDMA_DESTADDR_MSB_OFFSET, UPPER_32_BITS((uintptr_t) buf));
XAxiDma_WriteReg(ring->ChanBase, XAXIDMA_CR_OFFSET, XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_CR_OFFSET) | XAXIDMA_CR_RUNSTOP_MASK);
XAxiDma_WriteReg(ring->ChanBase, XAXIDMA_BUFFLEN_OFFSET, len);
return XST_SUCCESS;
}
int dma_simple_write(struct fpga_ip *c, char *buf, size_t len)
{
struct dma *dma = (struct dma *) c->_vd;
XAxiDma *xdma = &dma->inst;
XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma);
/* Checks */
if (xdma->HasSg)
return -1;
if ((len < 1) || (len > FPGA_DMA_BOUNDARY))
return -2;
if (!xdma->HasMm2S)
return -3;
if (!ring->HasDRE) {
uint32_t mask = xdma->MicroDmaMode ? XAXIDMA_MICROMODE_MIN_BUF_ALIGN : ring->DataWidth - 1;
if ((uintptr_t) buf & mask)
return -4;
}
/* If the engine is doing transfer, cannot submit */
if(!(XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_SR_OFFSET) & XAXIDMA_HALTED_MASK)) {
if (XAxiDma_Busy(xdma, XAXIDMA_DMA_TO_DEVICE))
return -5;
}
XAxiDma_WriteReg(ring->ChanBase, XAXIDMA_SRCADDR_OFFSET, LOWER_32_BITS((uintptr_t) buf));
if (xdma->AddrWidth > 32)
XAxiDma_WriteReg(ring->ChanBase, XAXIDMA_SRCADDR_MSB_OFFSET, UPPER_32_BITS((uintptr_t) buf));
XAxiDma_WriteReg(ring->ChanBase, XAXIDMA_CR_OFFSET, XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_CR_OFFSET) | XAXIDMA_CR_RUNSTOP_MASK);
XAxiDma_WriteReg(ring->ChanBase, XAXIDMA_BUFFLEN_OFFSET, len);
return XST_SUCCESS;
}
int dma_simple_read_complete(struct fpga_ip *c, char **buf, size_t *len)
{
struct dma *dma = (struct dma *) c->_vd;
XAxiDma *xdma = &dma->inst;
XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma);
while (!(XAxiDma_IntrGetIrq(xdma, XAXIDMA_DEVICE_TO_DMA) & XAXIDMA_IRQ_IOC_MASK))
intc_wait(c->card->intc, c->irq + 1);
XAxiDma_IntrAckIrq(xdma, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DEVICE_TO_DMA);
if (len)
*len = XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_BUFFLEN_OFFSET);
if (buf) {
*buf = (char *) (uintptr_t) XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_DESTADDR_OFFSET);
if (xdma->AddrWidth > 32)
*buf += XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_DESTADDR_MSB_OFFSET);
}
return 0;
}
int dma_simple_write_complete(struct fpga_ip *c, char **buf, size_t *len)
{
struct dma *dma = (struct dma *) c->_vd;
XAxiDma *xdma = &dma->inst;
XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma);
while (!(XAxiDma_IntrGetIrq(xdma, XAXIDMA_DMA_TO_DEVICE) & XAXIDMA_IRQ_IOC_MASK))
intc_wait(c->card->intc, c->irq);
XAxiDma_IntrAckIrq(xdma, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DMA_TO_DEVICE);
if (len)
*len = XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_BUFFLEN_OFFSET);
if (buf) {
*buf = (char *) (uintptr_t) XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_SRCADDR_OFFSET);
if (xdma->AddrWidth > 32)
*buf += XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_SRCADDR_MSB_OFFSET);
}
return 0;
}
static int dma_setup_ring(XAxiDma_BdRing *ring, struct dma_mem *bdbuf)
{
int delay = 0;
int coalesce = 1;
int ret, cnt;
XAxiDma_Bd clearbd;
/* Disable all RX interrupts before RxBD space setup */
XAxiDma_BdRingIntDisable(ring, XAXIDMA_IRQ_ALL_MASK);
/* Set delay and coalescing */
XAxiDma_BdRingSetCoalesce(ring, coalesce, delay);
/* Setup Rx BD space */
cnt = XAxiDma_BdRingCntCalc(XAXIDMA_BD_MINIMUM_ALIGNMENT, bdbuf->len);
ret = XAxiDma_BdRingCreate(ring, (uintptr_t) bdbuf->base_phys, (uintptr_t) bdbuf->base_virt, XAXIDMA_BD_MINIMUM_ALIGNMENT, cnt);
if (ret != XST_SUCCESS)
return -1;
XAxiDma_BdClear(&clearbd);
ret = XAxiDma_BdRingClone(ring, &clearbd);
if (ret != XST_SUCCESS)
return -2;
/* Start the channel */
ret = XAxiDma_BdRingStart(ring);
if (ret != XST_SUCCESS)
return -3;
return XST_SUCCESS;
}
static int dma_init_rings(XAxiDma *xdma, struct dma_mem *bd)
{
int ret;
struct dma_mem bd_rx, bd_tx;
ret = dma_mem_split(bd, &bd_rx, &bd_tx);
if (ret)
return -1;
ret = dma_setup_ring(XAxiDma_GetRxRing(xdma), &bd_rx);
if (ret != XST_SUCCESS)
return -2;
ret = dma_setup_ring(XAxiDma_GetTxRing(xdma), &bd_tx);
if (ret != XST_SUCCESS)
return -3;
return 0;
}
int dma_start(struct fpga_ip *c)
{
int ret, sg;
struct dma *dma = (struct dma *) c->_vd;
XAxiDma *xdma = &dma->inst;
/* Guess DMA type */
sg = (XAxiDma_In32((uintptr_t) c->card->map + c->baseaddr + XAXIDMA_TX_OFFSET+ XAXIDMA_SR_OFFSET) &
XAxiDma_In32((uintptr_t) c->card->map + c->baseaddr + XAXIDMA_RX_OFFSET+ XAXIDMA_SR_OFFSET) & XAXIDMA_SR_SGINCL_MASK) ? 1 : 0;
XAxiDma_Config xdma_cfg = {
.BaseAddr = (uintptr_t) c->card->map + c->baseaddr,
.HasStsCntrlStrm = 0,
.HasMm2S = 1,
.HasMm2SDRE = 1,
.Mm2SDataWidth = 128,
.HasS2Mm = 1,
.HasS2MmDRE = 1, /* Data Realignment Engine */
.HasSg = sg,
.S2MmDataWidth = 128,
.Mm2sNumChannels = 1,
.S2MmNumChannels = 1,
.Mm2SBurstSize = 64,
.S2MmBurstSize = 64,
.MicroDmaMode = 0,
.AddrWidth = 32
};
ret = XAxiDma_CfgInitialize(xdma, &xdma_cfg);
if (ret != XST_SUCCESS)
return -1;
/* Perform selftest */
ret = XAxiDma_Selftest(xdma);
if (ret != XST_SUCCESS)
return -2;
/* Map buffer descriptors */
if (xdma->HasSg) {
ret = dma_alloc(c, &dma->bd, FPGA_DMA_BD_SIZE, 0);
if (ret)
return -3;
ret = dma_init_rings(xdma, &dma->bd);
if (ret)
return -4;
}
/* Enable completion interrupts for both channels */
XAxiDma_IntrEnable(xdma, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DMA_TO_DEVICE);
XAxiDma_IntrEnable(xdma, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DEVICE_TO_DMA);
return 0;
}
int dma_reset(struct fpga_ip *c)
{
struct dma *dma = (struct dma *) c->_vd;
XAxiDma_Reset(&dma->inst);
return 0;
}
static struct plugin p = {
.name = "Xilinx's AXI4 Direct Memory Access Controller",
.description = "Transfer data streams between VILLASnode and VILLASfpga",
.type = PLUGIN_TYPE_FPGA_IP,
.ip = {
.vlnv = { "xilinx.com", "ip", "axi_dma", NULL },
.type = FPGA_IP_TYPE_DM_DMA,
.init = dma_start,
.reset = dma_reset,
.size = sizeof(struct dma)
}
};
REGISTER_PLUGIN(&p)

View file

@ -1,137 +0,0 @@
/** FIFO related helper functions
*
* These functions present a simpler interface to Xilinx' FIFO driver (XLlFifo_*)
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
#include <unistd.h>
#include "utils.h"
#include "plugin.h"
#include "fpga/ip.h"
#include "fpga/card.h"
#include "fpga/ips/fifo.h"
#include "fpga/ips/intc.h"
int fifo_start(struct fpga_ip *c)
{
int ret;
struct fpga_card *f = c->card;
struct fifo *fifo = (struct fifo *) c->_vd;
XLlFifo *xfifo = &fifo->inst;
XLlFifo_Config fifo_cfg = {
.BaseAddress = (uintptr_t) f->map + c->baseaddr,
.Axi4BaseAddress = (uintptr_t) c->card->map + fifo->baseaddr_axi4,
.Datainterface = (fifo->baseaddr_axi4 != -1) ? 1 : 0 /* use AXI4 for Data, AXI4-Lite for control */
};
ret = XLlFifo_CfgInitialize(xfifo, &fifo_cfg, (uintptr_t) c->card->map + c->baseaddr);
if (ret != XST_SUCCESS)
return -1;
XLlFifo_IntEnable(xfifo, XLLF_INT_RC_MASK); /* Receive complete IRQ */
return 0;
}
int fifo_stop(struct fpga_ip *c)
{
struct fifo *fifo = (struct fifo *) c->_vd;
XLlFifo *xfifo = &fifo->inst;
XLlFifo_IntDisable(xfifo, XLLF_INT_RC_MASK); /* Receive complete IRQ */
return 0;
}
ssize_t fifo_write(struct fpga_ip *c, char *buf, size_t len)
{
struct fifo *fifo = (struct fifo *) c->_vd;
XLlFifo *xllfifo = &fifo->inst;
uint32_t tdfv;
tdfv = XLlFifo_TxVacancy(xllfifo);
if (tdfv < len)
return -1;
XLlFifo_Write(xllfifo, buf, len);
XLlFifo_TxSetLen(xllfifo, len);
return len;
}
ssize_t fifo_read(struct fpga_ip *c, char *buf, size_t len)
{
struct fifo *fifo = (struct fifo *) c->_vd;
XLlFifo *xllfifo = &fifo->inst;
size_t nextlen = 0;
uint32_t rxlen;
while (!XLlFifo_IsRxDone(xllfifo))
intc_wait(c->card->intc, c->irq);
XLlFifo_IntClear(xllfifo, XLLF_INT_RC_MASK);
/* Get length of next frame */
rxlen = XLlFifo_RxGetLen(xllfifo);
nextlen = MIN(rxlen, len);
/* Read from FIFO */
XLlFifo_Read(xllfifo, buf, nextlen);
return nextlen;
}
int fifo_parse(struct fpga_ip *c, json_t *cfg)
{
struct fifo *fifo = (struct fifo *) c->_vd;
int baseaddr_axi4 = -1, ret;
json_error_t err;
fifo->baseaddr_axi4 = -1;
ret = json_unpack_ex(cfg, &err, 0, "{ s?: i }", "baseaddr_axi4", &baseaddr_axi4);
if (ret)
jerror(&err, "Failed to parse configuration of FPGA IP '%s'", c->name);
fifo->baseaddr_axi4 = baseaddr_axi4;
return 0;
}
int fifo_reset(struct fpga_ip *c)
{
struct fifo *fifo = (struct fifo *) c->_vd;
XLlFifo_Reset(&fifo->inst);
return 0;
}
static struct plugin p = {
.name = "Xilinx's AXI4 FIFO data mover",
.description = "",
.type = PLUGIN_TYPE_FPGA_IP,
.ip = {
.vlnv = { "xilinx.com", "ip", "axi_fifo_mm_s", NULL },
.type = FPGA_IP_TYPE_DM_FIFO,
.start = fifo_start,
.stop = fifo_stop,
.parse = fifo_parse,
.reset = fifo_reset,
.size = sizeof(struct fifo)
}
};
REGISTER_PLUGIN(&p)

View file

@ -1,166 +0,0 @@
/** AXI-PCIe Interrupt controller
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
#include <unistd.h>
#include "config.h"
#include "log.h"
#include "plugin.h"
#include "nodes/fpga.h"
#include "kernel/vfio.h"
#include "kernel/kernel.h"
#include "fpga/ip.h"
#include "fpga/card.h"
#include "fpga/ips/intc.h"
int intc_start(struct fpga_ip *c)
{
int ret;
struct fpga_card *f = c->card;
struct intc *intc = (struct intc *) c->_vd;
uintptr_t base = (uintptr_t) f->map + c->baseaddr;
if (c != f->intc)
error("There can be only one interrupt controller per FPGA");
intc->num_irqs = vfio_pci_msi_init(&f->vfio_device, intc->efds);
if (intc->num_irqs < 0)
return -1;
ret = vfio_pci_msi_find(&f->vfio_device, intc->nos);
if (ret)
return -2;
/* For each IRQ */
for (int i = 0; i < intc->num_irqs; i++) {
/* Pin to core */
ret = kernel_irq_setaffinity(intc->nos[i], f->affinity, NULL);
if (ret)
serror("Failed to change affinity of VFIO-MSI interrupt");
/* Setup vector */
XIntc_Out32(base + XIN_IVAR_OFFSET + i * 4, i);
}
XIntc_Out32(base + XIN_IMR_OFFSET, 0); /* Use manual acknowlegement for all IRQs */
XIntc_Out32(base + XIN_IAR_OFFSET, 0xFFFFFFFF); /* Acknowlege all pending IRQs manually */
XIntc_Out32(base + XIN_IMR_OFFSET, 0xFFFFFFFF); /* Use fast acknowlegement for all IRQs */
XIntc_Out32(base + XIN_IER_OFFSET, 0x00000000); /* Disable all IRQs by default */
XIntc_Out32(base + XIN_MER_OFFSET, XIN_INT_HARDWARE_ENABLE_MASK | XIN_INT_MASTER_ENABLE_MASK);
debug(4, "FPGA: enabled interrupts");
return 0;
}
int intc_destroy(struct fpga_ip *c)
{
struct fpga_card *f = c->card;
struct intc *intc = (struct intc *) c->_vd;
vfio_pci_msi_deinit(&f->vfio_device, intc->efds);
return 0;
}
int intc_enable(struct fpga_ip *c, uint32_t mask, int flags)
{
struct fpga_card *f = c->card;
struct intc *intc = (struct intc *) c->_vd;
uint32_t ier, imr;
uintptr_t base = (uintptr_t) f->map + c->baseaddr;
/* Current state of INTC */
ier = XIntc_In32(base + XIN_IER_OFFSET);
imr = XIntc_In32(base + XIN_IMR_OFFSET);
/* Clear pending IRQs */
XIntc_Out32(base + XIN_IAR_OFFSET, mask);
for (int i = 0; i < intc->num_irqs; i++) {
if (mask & (1 << i))
intc->flags[i] = flags;
}
if (flags & INTC_POLLING) {
XIntc_Out32(base + XIN_IMR_OFFSET, imr & ~mask);
XIntc_Out32(base + XIN_IER_OFFSET, ier & ~mask);
}
else {
XIntc_Out32(base + XIN_IER_OFFSET, ier | mask);
XIntc_Out32(base + XIN_IMR_OFFSET, imr | mask);
}
debug(3, "New ier = %#x", XIntc_In32(base + XIN_IER_OFFSET));
debug(3, "New imr = %#x", XIntc_In32(base + XIN_IMR_OFFSET));
debug(3, "New isr = %#x", XIntc_In32(base + XIN_ISR_OFFSET));
debug(8, "FPGA: Interupt enabled: mask=%#x flags=%#x", mask, flags);
return 0;
}
int intc_disable(struct fpga_ip *c, uint32_t mask)
{
struct fpga_card *f = c->card;
uintptr_t base = (uintptr_t) f->map + c->baseaddr;
uint32_t ier = XIntc_In32(base + XIN_IER_OFFSET);
XIntc_Out32(base + XIN_IER_OFFSET, ier & ~mask);
return 0;
}
uint64_t intc_wait(struct fpga_ip *c, int irq)
{
struct fpga_card *f = c->card;
struct intc *intc = (struct intc *) c->_vd;
uintptr_t base = (uintptr_t) f->map + c->baseaddr;
if (intc->flags[irq] & INTC_POLLING) {
uint32_t isr, mask = 1 << irq;
do {
isr = XIntc_In32(base + XIN_ISR_OFFSET);
pthread_testcancel();
} while ((isr & mask) != mask);
XIntc_Out32(base + XIN_IAR_OFFSET, mask);
return 1;
}
else {
uint64_t cnt;
ssize_t ret = read(intc->efds[irq], &cnt, sizeof(cnt));
if (ret != sizeof(cnt))
return 0;
return cnt;
}
}
static struct plugin p = {
.name = "Xilinx's programmable interrupt controller",
.description = "",
.type = PLUGIN_TYPE_FPGA_IP,
.ip = {
.vlnv = { "acs.eonerc.rwth-aachen.de", "user", "axi_pcie_intc", NULL },
.type = FPGA_IP_TYPE_MISC,
.start = intc_start,
.destroy = intc_destroy,
.size = sizeof(struct intc)
}
};
REGISTER_PLUGIN(&p)

View file

@ -1,411 +0,0 @@
/** Interface to Xilinx System Generator Models via PCIe
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
*********************************************************************************/
#include <stdint.h>
#include <time.h>
#include <string.h>
#include <math.h>
#include "utils.h"
#include "log.h"
#include "log_config.h"
#include "plugin.h"
#include "fpga/ip.h"
#include "fpga/card.h"
#include "fpga/ips/model.h"
static int model_parameter_destroy(struct model_parameter *p)
{
free(p->name);
return 0;
}
static int model_info_destroy(struct model_info *i)
{
free(i->field);
free(i->value);
return 0;
}
static uint32_t model_xsg_map_checksum(uint32_t *map, size_t len)
{
uint32_t chks = 0;
for (int i = 2; i < len-1; i++)
chks += map[i];
return chks; /* moduluo 2^32 because of overflow */
}
static int model_xsg_map_parse(uint32_t *map, size_t len, struct list *parameters, struct list *infos)
{
#define copy_string(off) strndup((char *) (data + (off)), (length - (off)) * 4);
int j;
struct model_info *i;
/* Check magic */
if (map[0] != XSG_MAGIC)
error("Invalid magic: %#x", map[0]);
for (j = 2; j < len-1;) {
uint16_t type = map[j] & 0xFFFF;
uint16_t length = map[j] >> 16;
uint32_t *data = &map[j+1];
switch (type) {
case XSG_BLOCK_GATEWAY_IN:
case XSG_BLOCK_GATEWAY_OUT:
if (length < 4)
break; /* block is to small to describe a gateway */
struct model_parameter *e, *p = (struct model_parameter *) alloc(sizeof(struct model_parameter));
p->name = copy_string(3);
p->default_value.flt = *((float *) &data[1]);
p->offset = data[2];
p->direction = type & 0x1;
p->type = (data[0] >> 0) & 0xFF;
p->binpt = (data[0] >> 8) & 0xFF;
e = list_lookup(parameters, p->name);
if (e)
model_parameter_update(e, p);
else
list_push(parameters, p);
break;
case XSG_BLOCK_INFO:
i = alloc(sizeof(struct model_info));
i->field = copy_string(0);
i->value = copy_string((int) ceil((double) (strlen(i->field) + 1) / 4))
list_push(infos, i);
break;
default:
warn("Unknown block type: %#06x", type);
}
j += length + 1;
}
return 0;
#undef copy_string
}
static uint32_t model_xsg_map_read_word(uint32_t offset, void *baseaddr)
{
volatile uint32_t *addr = baseaddr + 0x00;
volatile uint32_t *data = baseaddr + 0x04;
*addr = offset; /* Update addr reg */
return *data; /* Read data reg */
}
static int model_xsg_map_read(uint32_t *map, size_t len, void *baseaddr)
{
size_t maplen;
uint32_t magic;
/* Check magic */
magic = model_xsg_map_read_word(0, baseaddr);
if (magic != XSG_MAGIC)
return -1;
maplen = model_xsg_map_read_word(1, baseaddr);
if (maplen < 3)
return -2;
/* Read Data */
int i;
for (i = 0; i < MIN(maplen, len); i++)
map[i] = model_xsg_map_read_word(i, baseaddr);
return i;
}
int model_parse(struct fpga_ip *c, json_t *cfg)
{
struct model *m = (struct model *) c->_vd;
int ret;
json_t *json_params;
json_error_t err;
if (strcmp(c->vlnv.library, "hls") == 0)
m->type = MODEL_TYPE_HLS;
else if (strcmp(c->vlnv.library, "sysgen") == 0)
m->type = MODEL_TYPE_XSG;
else
error("Unsupported model type: %s", c->vlnv.library);
ret = json_unpack_ex(cfg, &err, 0, "{ s?: o }", "parameters", &json_params);
if (ret)
jerror(&err, "Failed to parse configuration of FPGA IP '%s'", c->name);
if (json_params) {
if (!json_is_object(json_params))
error("Setting 'parameters' must be a JSON object");
const char *name;
json_t *value;
json_object_foreach(json_params, name, value) {
if (!json_is_real(value))
error("Parameters of FPGA IP '%s' must be of type floating point", c->name);
struct model_parameter *p = (struct model_parameter *) alloc(sizeof(struct model_parameter));
p->name = strdup(name);
p->default_value.flt = json_real_value(value);
list_push(&m->parameters, p);
}
}
return 0;
}
static int model_init_from_xsg_map(struct model *m, void *baseaddr)
{
int ret, chks;
if (baseaddr == (void *) -1)
return -1;
m->xsg.map = alloc(XSG_MAPLEN);
m->xsg.maplen = model_xsg_map_read(m->xsg.map, XSG_MAPLEN, baseaddr);
if (m->xsg.maplen < 0)
return -1;
debug(5, "XSG: memory map length = %#zx", m->xsg.maplen);
chks = m->xsg.map[m->xsg.maplen - 1];
if (chks != model_xsg_map_checksum(m->xsg.map, m->xsg.maplen))
return -2;
ret = model_xsg_map_parse(m->xsg.map, m->xsg.maplen, &m->parameters, &m->infos);
if (ret)
return -3;
debug(5, "XSG: Parsed %zu parameters and %zu model infos", list_length(&m->parameters), list_length(&m->infos));
return 0;
}
int model_init(struct fpga_ip *c)
{
int ret;
struct model *m = (struct model *) c->_vd;
list_init(&m->parameters);
list_init(&m->infos);
if (!fpga_vlnv_cmp(&c->vlnv, &(struct fpga_vlnv) { NULL, "sysgen", NULL, NULL }))
ret = model_init_from_xsg_map(m, c->card->map + c->baseaddr);
else
ret = 0;
/* Set default values for parameters */
for (size_t i = 0; i < list_length(&m->parameters); i++) {
struct model_parameter *p = (struct model_parameter *) list_at(&m->parameters, i);
p->ip = c;
if (p->direction == MODEL_PARAMETER_IN) {
model_parameter_write(p, p->default_value.flt);
info("Set parameter '%s' updated to default value: %f", p->name, p->default_value.flt);
}
}
if (ret)
error("Failed to init XSG model: %d", ret);
return 0;
}
int model_destroy(struct fpga_ip *c)
{
struct model *m = (struct model *) c->_vd;
list_destroy(&m->parameters, (dtor_cb_t) model_parameter_destroy, true);
list_destroy(&m->infos, (dtor_cb_t) model_info_destroy, true);
if (m->xsg.map != NULL)
free(m->xsg.map);
return 0;
}
void model_dump(struct fpga_ip *c)
{
struct model *m = (struct model *) c->_vd;
const char *param_type[] = { "UFix", "Fix", "Float", "Boolean" };
const char *parameter_dirs[] = { "In", "Out", "In/Out" };
{ INDENT
info("Parameters:");
for (size_t i = 0; i < list_length(&m->parameters); i++) { INDENT
struct model_parameter *p = (struct model_parameter *) list_at(&m->parameters, i);
if (p->direction == MODEL_PARAMETER_IN)
info("%#jx: %s (%s) = %.3f %s %u",
p->offset,
p->name,
parameter_dirs[p->direction],
p->default_value.flt,
param_type[p->type],
p->binpt
);
else if (p->direction == MODEL_PARAMETER_OUT)
info("%#jx: %s (%s)",
p->offset,
p->name,
parameter_dirs[p->direction]
);
}
info("Infos:");
for (size_t j = 0; j < list_length(&m->infos); j++) { INDENT
struct model_info *i = (struct model_info *) list_at(&m->infos, j);
info("%s: %s", i->field, i->value);
}
}
}
int model_parameter_read(struct model_parameter *p, double *v)
{
struct fpga_ip *c = p->ip;
union model_parameter_value *ptr = (union model_parameter_value *) (c->card->map + c->baseaddr + p->offset);
switch (p->type) {
case MODEL_PARAMETER_TYPE_UFIX:
*v = (double) ptr->ufix / (1 << p->binpt);
break;
case MODEL_PARAMETER_TYPE_FIX:
*v = (double) ptr->fix / (1 << p->binpt);
break;
case MODEL_PARAMETER_TYPE_FLOAT:
*v = (double) ptr->flt;
break;
case MODEL_PARAMETER_TYPE_BOOLEAN:
*v = (double) ptr->ufix ? 1 : 0;
}
return 0;
}
int model_parameter_write(struct model_parameter *p, double v)
{
struct fpga_ip *c = p->ip;
union model_parameter_value *ptr = (union model_parameter_value *) (c->card->map + c->baseaddr + p->offset);
switch (p->type) {
case MODEL_PARAMETER_TYPE_UFIX:
ptr->ufix = (uint32_t) (v * (1 << p->binpt));
break;
case MODEL_PARAMETER_TYPE_FIX:
ptr->fix = (int32_t) (v * (1 << p->binpt));
break;
case MODEL_PARAMETER_TYPE_FLOAT:
ptr->flt = (float) v;
break;
case MODEL_PARAMETER_TYPE_BOOLEAN:
ptr->bol = (bool) v;
break;
}
return 0;
}
void model_parameter_add(struct fpga_ip *c, const char *name, enum model_parameter_direction dir, enum model_parameter_type type)
{
struct model *m = (struct model *) c->_vd;
struct model_parameter *p = (struct model_parameter *) alloc(sizeof(struct model_parameter));
p->name = strdup(name);
p->type = type;
p->direction = dir;
list_push(&m->parameters, p);
}
int model_parameter_remove(struct fpga_ip *c, const char *name)
{
struct model *m = (struct model *) c->_vd;
struct model_parameter *p;
p = list_lookup(&m->parameters, name);
if (!p)
return -1;
list_remove(&m->parameters, p);
return 0;
}
int model_parameter_update(struct model_parameter *p, struct model_parameter *u)
{
if (strcmp(p->name, u->name) != 0)
return -1;
p->direction = u->direction;
p->type = u->type;
p->binpt = u->binpt;
p->offset = u->offset;
return 0;
}
static struct plugin p_hls = {
.name = "Xilinx High Level Synthesis (HLS) model",
.description = "",
.type = PLUGIN_TYPE_FPGA_IP,
.ip = {
.vlnv = { NULL, "hls", NULL, NULL },
.type = FPGA_IP_TYPE_MODEL,
.init = model_init,
.destroy = model_destroy,
.dump = model_dump,
.parse = model_parse
}
};
REGISTER_PLUGIN(&p_hls)
static struct plugin p_sysgen = {
.name = "Xilinx System Generator for DSP (XSG) model",
.description = "",
.type = PLUGIN_TYPE_FPGA_IP,
.ip = {
.vlnv = { NULL, "sysgen", NULL, NULL },
.type = FPGA_IP_TYPE_MODEL,
.init = model_init,
.destroy = model_destroy,
.dump = model_dump,
.parse = model_parse,
.size = sizeof(struct model)
}
};
REGISTER_PLUGIN(&p_sysgen)

View file

@ -1,64 +0,0 @@
/** Driver for AXI Stream wrapper around RTDS_InterfaceModule (rtds_axis )
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
#include <stdint.h>
#include "log.h"
#include "utils.h"
#include "plugin.h"
#include "fpga/ip.h"
#include "fpga/card.h"
#include "fpga/ips/rtds_axis.h"
void rtds_axis_dump(struct fpga_ip *c)
{
/* Check RTDS_Axis registers */
uint32_t *regs = (uint32_t *) (c->card->map + c->baseaddr);
uint32_t sr = regs[RTDS_AXIS_SR_OFFSET/4];
info("RTDS AXI Stream interface details");
{ INDENT
info("RTDS status: %#08x", sr);
{ INDENT
info("Card detected: %s", sr & RTDS_AXIS_SR_CARDDETECTED ? CLR_GRN("yes") : CLR_RED("no"));
info("Link up: %s", sr & RTDS_AXIS_SR_LINKUP ? CLR_GRN("yes") : CLR_RED("no"));
info("TX queue full: %s", sr & RTDS_AXIS_SR_TX_FULL ? CLR_RED("yes") : CLR_GRN("no"));
info("TX in progress: %s", sr & RTDS_AXIS_SR_TX_INPROGRESS ? CLR_YEL("yes") : "no");
info("Case running: %s", sr & RTDS_AXIS_SR_CASE_RUNNING ? CLR_GRN("yes") : CLR_RED("no"));
}
info("RTDS control: %#08x", regs[RTDS_AXIS_CR_OFFSET/4]);
info("RTDS IRQ coalesc: %u", regs[RTDS_AXIS_COALESC_OFFSET/4]);
info("RTDS IRQ version: %#06x", regs[RTDS_AXIS_VERSION_OFFSET/4]);
info("RTDS IRQ multi-rate: %u", regs[RTDS_AXIS_MRATE/4]);
info("RTDS timestep counter: %lu", (uint64_t) regs[RTDS_AXIS_TSCNT_LOW_OFFSET/4] | (uint64_t) regs[RTDS_AXIS_TSCNT_HIGH_OFFSET/4] << 32);
info("RTDS timestep period: %.3f uS", rtds_axis_dt(c) * 1e6);
}
}
double rtds_axis_dt(struct fpga_ip *c)
{
uint32_t *regs = (uint32_t *) (c->card->map + c->baseaddr);
uint16_t dt = regs[RTDS_AXIS_TS_PERIOD_OFFSET/4];
return (dt == 0xFFFF) ? -1.0 : (double) dt / RTDS_HZ;
}
static struct plugin p = {
.name = "RTDS's AXI4-Stream - GTFPGA interface",
.description = "",
.type = PLUGIN_TYPE_FPGA_IP,
.ip = {
.vlnv = { "acs.eonerc.rwth-aachen.de", "user", "rtds_axis", NULL },
.type = FPGA_IP_TYPE_INTERFACE,
.dump = rtds_axis_dump,
.size = 0
}
};
REGISTER_PLUGIN(&p)

View file

@ -1,205 +0,0 @@
/** AXI Stream interconnect related helper functions
*
* These functions present a simpler interface to Xilinx' AXI Stream switch driver (XAxis_Switch_*)
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
#include "list.h"
#include "log.h"
#include "log_config.h"
#include "plugin.h"
#include "fpga/ip.h"
#include "fpga/card.h"
#include "fpga/ips/switch.h"
int switch_start(struct fpga_ip *c)
{
int ret;
struct fpga_card *f = c->card;
struct sw *sw = (struct sw *) c->_vd;
XAxis_Switch *xsw = &sw->inst;
if (c != f->sw)
error("There can be only one AXI4-Stream interconnect per FPGA");
/* Setup AXI-stream switch */
XAxis_Switch_Config sw_cfg = {
.BaseAddress = (uintptr_t) f->map + c->baseaddr,
.MaxNumMI = sw->num_ports,
.MaxNumSI = sw->num_ports
};
ret = XAxisScr_CfgInitialize(xsw, &sw_cfg, (uintptr_t) c->card->map + c->baseaddr);
if (ret != XST_SUCCESS)
return -1;
/* Disable all masters */
XAxisScr_RegUpdateDisable(xsw);
XAxisScr_MiPortDisableAll(xsw);
XAxisScr_RegUpdateEnable(xsw);
switch_init_paths(c);
return 0;
}
int switch_init_paths(struct fpga_ip *c)
{
int ret;
struct sw *sw = (struct sw *) c->_vd;
XAxis_Switch *xsw = &sw->inst;
XAxisScr_RegUpdateDisable(xsw);
XAxisScr_MiPortDisableAll(xsw);
for (size_t i = 0; i < list_length(&sw->paths); i++) {
struct sw_path *p = (struct sw_path *) list_at(&sw->paths, i);
struct fpga_ip *mi, *si;
mi = list_lookup(&c->card->ips, p->out);
si = list_lookup(&c->card->ips, p->in);
if (!mi || !si || mi->port == -1 || si->port == -1)
error("Invalid path configuration for FPGA");
ret = switch_connect(c, mi, si);
if (ret)
error("Failed to configure switch");
}
XAxisScr_RegUpdateEnable(xsw);
return 0;
}
int switch_destroy(struct fpga_ip *c)
{
struct sw *sw = (struct sw *) c->_vd;
list_destroy(&sw->paths, NULL, true);
return 0;
}
int switch_parse(struct fpga_ip *c, json_t *cfg)
{
struct sw *sw = (struct sw *) c->_vd;
int ret;
size_t index;
json_error_t err;
json_t *json_path, *json_paths = NULL;
list_init(&sw->paths);
ret = json_unpack_ex(cfg, &err, 0, "{ s: i, s?: o }",
"num_ports", &sw->num_ports,
"paths", &json_paths
);
if (ret)
jerror(&err, "Failed to parse configuration of FPGA IP '%s'", c->name);
if (!json_paths)
return 0; /* no switch config available */
if (!json_is_array(json_paths))
error("Setting 'paths' of FPGA IP '%s' should be an array of JSON objects", c->name);
json_array_foreach(json_paths, index, json_path) {
struct sw_path *p = (struct sw_path *) alloc(sizeof(struct sw_path));
int reverse = 0;
ret = json_unpack_ex(json_path, &err, 0, "{ s?: b, s: s, s: s }",
"reverse", &reverse,
"in", &p->in,
"out", &p->out
);
if (ret)
jerror(&err, "Failed to parse path %zu of FPGA IP '%s'", index, c->name);
list_push(&sw->paths, p);
if (reverse) {
struct sw_path *r = memdup(p, sizeof(struct sw_path));
r->in = p->out;
r->out = p->in;
list_push(&sw->paths, r);
}
}
return 0;
}
int switch_connect(struct fpga_ip *c, struct fpga_ip *mi, struct fpga_ip *si)
{
struct sw *sw = (struct sw *) c->_vd;
XAxis_Switch *xsw = &sw->inst;
uint32_t mux, port;
/* Check if theres already something connected */
for (int i = 0; i < sw->num_ports; i++) {
mux = XAxisScr_ReadReg(xsw->Config.BaseAddress, XAXIS_SCR_MI_MUX_START_OFFSET + i * 4);
if (!(mux & XAXIS_SCR_MI_X_DISABLE_MASK)) {
port = mux & ~XAXIS_SCR_MI_X_DISABLE_MASK;
if (port == si->port) {
warn("Switch: Slave port %s (%u) has been connected already to port %u. Disconnecting...", si->name, si->port, i);
XAxisScr_RegUpdateDisable(xsw);
XAxisScr_MiPortDisable(xsw, i);
XAxisScr_RegUpdateEnable(xsw);
}
}
}
/* Reconfigure switch */
XAxisScr_RegUpdateDisable(xsw);
XAxisScr_MiPortEnable(xsw, mi->port, si->port);
XAxisScr_RegUpdateEnable(xsw);
/* Reset IPs */
/*ip_reset(mi);
ip_reset(si);*/
debug(8, "FPGA: Switch connected %s (%u) to %s (%u)", mi->name, mi->port, si->name, si->port);
return 0;
}
int switch_disconnect(struct fpga_ip *c, struct fpga_ip *mi, struct fpga_ip *si)
{
struct sw *sw = (struct sw *) c->_vd;
XAxis_Switch *xsw = &sw->inst;
if (!XAxisScr_IsMiPortEnabled(xsw, mi->port, si->port))
return -1;
XAxisScr_MiPortDisable(xsw, mi->port);
return 0;
}
static struct plugin p = {
.name = "Xilinx's AXI4-Stream switch",
.description = "",
.type = PLUGIN_TYPE_FPGA_IP,
.ip = {
.vlnv = { "xilinx.com", "ip", "axis_interconnect", NULL },
.type = FPGA_IP_TYPE_MISC,
.start = switch_start,
.destroy = switch_destroy,
.parse = switch_parse,
.size = sizeof(struct sw)
}
};
REGISTER_PLUGIN(&p)

View file

@ -1,46 +0,0 @@
/** Timer related helper functions
*
* These functions present a simpler interface to Xilinx' Timer Counter driver (XTmrCtr_*)
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
#include "config.h"
#include "plugin.h"
#include "fpga/ip.h"
#include "fpga/card.h"
#include "fpga/ips/timer.h"
int timer_start(struct fpga_ip *c)
{
struct fpga_card *f = c->card;
struct timer *tmr = (struct timer *) c->_vd;
XTmrCtr *xtmr = &tmr->inst;
XTmrCtr_Config xtmr_cfg = {
.BaseAddress = (uintptr_t) f->map + c->baseaddr,
.SysClockFreqHz = FPGA_AXI_HZ
};
XTmrCtr_CfgInitialize(xtmr, &xtmr_cfg, (uintptr_t) f->map + c->baseaddr);
XTmrCtr_InitHw(xtmr);
return 0;
}
static struct plugin p = {
.name = "Xilinx's programmable timer / counter",
.description = "",
.type = PLUGIN_TYPE_FPGA_IP,
.ip = {
.vlnv = { "xilinx.com", "ip", "axi_timer", NULL },
.type = FPGA_IP_TYPE_MISC,
.start = timer_start,
.size = sizeof(struct timer)
}
};
REGISTER_PLUGIN(&p)

View file

@ -1,64 +0,0 @@
/** Vendor, Library, Name, Version (VLNV) tag
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "fpga/vlnv.h"
#include "fpga/ip.h"
struct fpga_ip * fpga_vlnv_lookup(struct list *l, struct fpga_vlnv *v)
{
return (struct fpga_ip *) list_search(l, (cmp_cb_t) fpga_vlnv_cmp, v);
}
int fpga_vlnv_cmp(struct fpga_vlnv *a, struct fpga_vlnv *b)
{
return ((!a->vendor || !b->vendor || !strcmp(a->vendor, b->vendor )) &&
(!a->library || !b->library || !strcmp(a->library, b->library)) &&
(!a->name || !b->name || !strcmp(a->name, b->name )) &&
(!a->version || !b->version || !strcmp(a->version, b->version))) ? 0 : 1;
}
int fpga_vlnv_parse(struct fpga_vlnv *c, const char *vlnv)
{
char *tmp = strdup(vlnv);
c->vendor = strdup(strtok(tmp, ":"));
c->library = strdup(strtok(NULL, ":"));
c->name = strdup(strtok(NULL, ":"));
c->version = strdup(strtok(NULL, ":"));
free(tmp);
return 0;
}
int fpga_vlnv_destroy(struct fpga_vlnv *v)
{
free(v->vendor);
free(v->library);
free(v->name);
free(v->version);
return 0;
}

View file

@ -38,7 +38,7 @@ WITH_SHMEM ?= 1
WITH_STATS ?= 1
WITH_INFLUXDB ?= 1
WITH_AMQP ?= 1
WITH_IEC61850 ?= 1
WITH_IEC61850 ?= 0
# Enabled loopback node-type
ifeq ($(WITH_LOOPBACK),1)
@ -97,15 +97,12 @@ ifneq ($(or $(wildcard /usr/include/libiec61850/*), $(wildcard /usr/local/includ
endif
endif
# Enable VILLASfpga support when libxil is available
# Enable VILLASfpga support when libvillas-fpga is available
ifeq ($(WITH_FPGA),1)
ifeq ($(shell $(PKGCONFIG) libxil; echo $$?),0)
LIB_SRCS += $(addprefix lib/nodes/, fpga.c) \
$(addprefix lib/kernel/, pci.c vfio.c) \
ifeq ($(shell $(PKGCONFIG) libvillas-fpga; echo $$?),0)
LIB_SRCS += lib/nodes/fpga.c
include lib/fpga/Makefile.inc
LIB_PKGS += libxil
LIB_PKGS += libvillas-fpga
LIB_CFLAGS += -DWITH_FPGA
endif
endif

View file

@ -81,7 +81,6 @@ RUN dnf -y install \
libwebsockets-devel \
zeromq-devel \
nanomsg-devel \
libxil-devel \
protobuf-c-devel \
libiec61850-devel

View file

@ -81,7 +81,6 @@ RUN yum -y install \
libnl3-devel \
zeromq-devel \
nanomsg-devel \
libxil-devel \
protobuf-c-devel \
libiec61850-devel

View file

@ -86,10 +86,6 @@ RUN apt-get update && apt-get install -y \
COPY thirdparty/criterion /tmp/criterion
RUN mkdir -p /tmp/criterion/build && cd /tmp/criterion/build && cmake .. && make install && rm -rf /tmp/*
# Build & Install libxil
COPY thirdparty/libxil /tmp/libxil
RUN mkdir -p /tmp/libxil/build && cd /tmp/libxil/build && cmake .. && make install && rm -rf /tmp/*
# Build & Install libwebsockets
COPY thirdparty/libwebsockets /tmp/libwebsockets
RUN mkdir -p /tmp/libwebsockets/build && cd /tmp/libwebsockets/build && cmake -DLWS_IPV6=1 -DLWS_WITH_STATIC=0 -DLWS_WITHOUT_TESTAPPS=1 -DLWS_WITH_HTTP2=1 .. && make install && rm -rf /tmp/*

View file

@ -39,28 +39,10 @@ ifeq ($(WITH_WEBSOCKET),1)
endif
endif
# Enable VILLASfpga support when libxil is available
ifeq ($(shell $(PKGCONFIG) libxil; echo $$?),0)
LIB_SRCS += $(addprefix lib/nodes/, fpga.c)
LIB_SRCS += $(addprefix lib/kernel/, pci.c vfio.c)
LIB_SRCS += $(wildcard lib/fpga/*.c)
TARGETS += $(BUILDDIR)/villas-fpga
PKGS += libxil
# Add support for LAPACK / BLAS benchmarks / solvers
ifeq ($(shell $(PKGCONFIG) blas lapack; echo $$?),0)
PKGS += blas lapack
BENCH_OBJS += fpga-bench-overruns.o
endif
endif
src: $(TARGETS)
$(TARGETS): $(BUILDDIR)/villas-%: $(BUILDDIR)/src/%.o
# Some additional prereqs for individual binaries
$(BUILDDIR)/villas-fpga: $(addprefix $(BUILDDIR)/src/,fpga-bench.o $(BENCH_OBJS))
# Compile executable objects
$(BUILDDIR)/src/%.o: src/%.c | $$(dir $$@)
$(CC) $(SRC_CFLAGS) -c $< -o $@

View file

@ -1,150 +0,0 @@
/** Benchmarks for VILLASfpga: LAPACK & BLAS
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
#include <stdio.h>
#include <sys/utsname.h>
#include <fpga/card.h>
#include <fpga/ip.h>
#include <fpga/ips/switch.h>
#include <fpga/ips/intc.h>
#include <utils.h>
#include <villas/log.h>
/* Some hard-coded configuration for the FPGA benchmarks */
#define BENCH_WARMUP 100
/* Declared in fpga-bench.c */
extern int intc_flags;
extern struct utsname uts;
/* LAPACK & BLAS Fortran prototypes */
extern int dgemm_(char *transa, char *transb, int *m, int *n, int *k, double *alpha, double *a, int *lda, double *b, int *ldb, double *beta, double *c, int *ldc);
extern int dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv, int *info);
extern int dgetri_(int *n, double *a, int *lda, int *ipiv, double *work, int *lwork, int *info);
static int lapack_generate_workload(int N, double *C)
{
double *A = alloc(N * N * sizeof(double));
srand(time(NULL));
for (int i = 0; i < N * N; i++)
A[i] = 100 * (double) rand() / RAND_MAX + 1;
char transA = 'T';
char transB = 'N';
double alpha = 1;
double beta = 1;
/* C = A' * A, to get an invertible matrix */
dgemm_(&transA, &transB, &N, &N, &N, &alpha, A, &N, A, &N, &beta, C, &N);
free(A);
return 0;
}
static int lapack_workload(int N, double *A)
{
int info = 0;
int lworkspace = N;
int ipiv[N];
double workspace[N];
dgetrf_(&N, &N, A, &N, ipiv, &info);
if (info > 0)
error("Failed to pivot matrix");
dgetri_(&N, A, &N, ipiv, workspace, &lworkspace, &info);
if (info > 0)
error("Failed to LU factorized matrix");
return 0;
}
int fpga_benchmark_overruns(struct fpga_card *c)
{
struct fpga_ip *rtds, *dm;
dm = list_lookup(&c->ips, "dma_1");
rtds = list_lookup(&c->ips, "rtds_axis_0");
if (!rtds || !c->intc)
return -1;
int ret;
float period = 50e-6;
int runs = 1.0 / period;
int overruns;
info("runs = %u", runs);
switch_connect(c->sw, dm, rtds);
switch_connect(c->sw, rtds, dm);
intc_enable(c->intc, (1 << (dm->irq + 1 )), intc_flags);
/* Dump results */
char fn[256];
snprintf(fn, sizeof(fn), "results/overruns_lu_rtds_axis_%s_%s.dat", intc_flags & INTC_POLLING ? "polling" : "irq", uts.release);
FILE *g = fopen(fn, "w");
fprintf(g, "# period = %f\n", period);
fprintf(g, "# runs = %u\n", runs);
struct dma_mem mem;
ret = dma_alloc(dm, &mem, 0x1000, 0);
if (ret)
error("Failed to allocate DMA memory");
uint32_t *data_rx = (uint32_t *) mem.base_virt;
uint32_t *data_tx = (uint32_t *) mem.base_virt + 0x200;
uint64_t total, start, stop;
for (int p = 3; p < 45; p++) {
double *A = alloc(p*p*sizeof(double));
lapack_generate_workload(p, A);
overruns = 0;
total = 0;
for (int i = 0; i < 2000; i++) {
dma_read(dm, mem.base_phys, 0x200);
dma_read_complete(dm, NULL, NULL);
}
for (int i = 0; i < runs + BENCH_WARMUP; i++) {
dma_read(dm, mem.base_phys, 0x200);
start = rdtsc();
lapack_workload(p, A);
stop = rdtsc();
dma_read_complete(dm, NULL, NULL);
/* Send data to rtds */
data_tx[0] = i;
dma_write(dm, mem.base_phys + 0x200, 64 * sizeof(data_tx[0]));
if (i < BENCH_WARMUP)
continue;
if (i - data_rx[0] > 2)
overruns++;
total += stop - start;
}
free(A);
info("iter = %u clks = %ju overruns = %u", p, total / runs, overruns);
fprintf(g, "%u %ju %u\n", p, total / runs, overruns);
if (overruns >= runs)
break;
}
fclose(g);
return 0;
}

View file

@ -1,333 +0,0 @@
/** Benchmarks for VILLASfpga
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <sys/utsname.h>
#include <villas/utils.h>
#include <villas/log.h>
#include <villas/timing.h>
#include <villas/fpga/ip.h>
#include <villas/fpga/card.h>
#include <villas/fpga/ips/intc.h>
#include <villas/fpga/ips/timer.h>
#include "config.h"
/* Some hard-coded configuration for the FPGA benchmarks */
#define BENCH_DM 3
// 1 FIFO
// 2 DMA SG
// 3 DMA Simple
#define BENCH_RUNS 3000000
#define BENCH_WARMUP 100
#define BENCH_DM_EXP_MIN 0
#define BENCH_DM_EXP_MAX 20
int fpga_benchmark_datamover(struct fpga_card *c);
int fpga_benchmark_jitter(struct fpga_card *c);
int fpga_benchmark_memcpy(struct fpga_card *c);
int fpga_benchmark_latency(struct fpga_card *c);
#if defined(WITH_BLAS) && defined(WITH_LAPACK)
int fpga_benchmark_overruns(struct fpga_card *c);
#endif
int intc_flags = 0;
struct utsname uts;
int fpga_benchmarks(int argc, char *argv[], struct fpga_card *c)
{
int ret;
struct bench {
const char *name;
int (*func)(struct fpga_card *c);
} benchmarks[] = {
{ "datamover", fpga_benchmark_datamover },
{ "jitter", fpga_benchmark_jitter },
{ "memcpy", fpga_benchmark_memcpy },
#if defined(WITH_BLAS) && defined(WITH_LAPACK)
{ "overruns", fpga_benchmark_overruns },
#endif
{ "latency", fpga_benchmark_latency }
};
if (argc < 2)
error("Usage: fpga benchmark (bench)");
struct bench *bench = NULL;
for (int i = 0; i < ARRAY_LEN(benchmarks); i++) {
if (strcmp(benchmarks[i].name, argv[1]) == 0) {
bench = &benchmarks[i];
break;
}
}
if (bench == NULL)
error("There is no benchmark named: %s", argv[1]);
ret = uname(&uts);
if (ret)
return -1;
again: ret = bench->func(c);
if (ret)
error("Benchmark %s failed", bench->name);
/* Rerun test with polling */
if (intc_flags == 0) {
intc_flags |= INTC_POLLING;
getchar();
goto again;
}
return -1;
}
int fpga_benchmark_jitter(struct fpga_card *c)
{
int ret;
struct fpga_ip *ip = list_lookup(&c->ips, "timer_0");
if (!ip || !c->intc)
return -1;
struct timer *tmr = (struct timer *) ip->_vd;
XTmrCtr *xtmr = &tmr->inst;
ret = intc_enable(c->intc, (1 << ip->irq), intc_flags);
if (ret)
error("Failed to enable interrupt");
float period = 50e-6;
int runs = 300.0 / period;
int *hist = alloc(8 << 20);
XTmrCtr_SetOptions(xtmr, 0, XTC_INT_MODE_OPTION | XTC_EXT_COMPARE_OPTION | XTC_DOWN_COUNT_OPTION | XTC_AUTO_RELOAD_OPTION);
XTmrCtr_SetResetValue(xtmr, 0, period * FPGA_AXI_HZ);
XTmrCtr_Start(xtmr, 0);
uint64_t end, start = rdtsc();
for (int i = 0; i < runs; i++) {
uint64_t cnt = intc_wait(c->intc, ip->irq);
if (cnt != 1)
warn("fail");
/* Ackowledge IRQ */
XTmrCtr_WriteReg((uintptr_t) c->map + ip->baseaddr, 0, XTC_TCSR_OFFSET, XTmrCtr_ReadReg((uintptr_t) c->map + ip->baseaddr, 0, XTC_TCSR_OFFSET));
end = rdtsc();
hist[i] = end - start;
start = end;
}
XTmrCtr_Stop(xtmr, 0);
char fn[256];
snprintf(fn, sizeof(fn), "results/jitter_%s_%s.dat", intc_flags & INTC_POLLING ? "polling" : "irq", uts.release);
FILE *g = fopen(fn, "w");
for (int i = 0; i < runs; i++)
fprintf(g, "%u\n", hist[i]);
fclose(g);
free(hist);
ret = intc_disable(c->intc, (1 << ip->irq));
if (ret)
error("Failed to disable interrupt");
return 0;
}
int fpga_benchmark_latency(struct fpga_card *c)
{
int ret;
uint64_t start, end;
if (!c->intc)
return -1;
int runs = 1000000;
int hist[runs];
ret = intc_enable(c->intc, 0x100, intc_flags);
if (ret)
error("Failed to enable interrupts");
for (int i = 0; i < runs; i++) {
start = rdtsc();
XIntc_Out32((uintptr_t) c->map + c->intc->baseaddr + XIN_ISR_OFFSET, 0x100);
intc_wait(c->intc, 8);
end = rdtsc();
hist[i] = end - start;
}
char fn[256];
snprintf(fn, sizeof(fn), "results/latency_%s_%s.dat", intc_flags & INTC_POLLING ? "polling" : "irq", uts.release);
FILE *g = fopen(fn, "w");
for (int i = 0; i < runs; i++)
fprintf(g, "%u\n", hist[i]);
fclose(g);
ret = intc_disable(c->intc, 0x100);
if (ret)
error("Failed to disable interrupt");
return 0;
}
int fpga_benchmark_datamover(struct fpga_card *c)
{
int ret;
struct fpga_ip *dm;
struct dma_mem mem, src, dst;
#if BENCH_DM == 1
char *dm_name = "fifo_mm_s_0";
#elif BENCH_DM == 2
char *dm_name = "dma_0";
#elif BENCH_DM == 3
char *dm_name = "dma_1";
#endif
dm = list_lookup(&c->ips, dm_name);
if (!dm)
error("Unknown datamover");
ret = switch_connect(c->sw, dm, dm);
if (ret)
error("Failed to configure switch");
ret = intc_enable(c->intc, (1 << dm->irq) | (1 << (dm->irq + 1)), intc_flags);
if (ret)
error("Failed to enable interrupt");
/* Allocate DMA memory */
ret = dma_alloc(dm, &mem, 2 * (1 << BENCH_DM_EXP_MAX), 0);
if (ret)
error("Failed to allocate DMA memory");
ret = dma_mem_split(&mem, &src, &dst);
if (ret)
return -1;
/* Open file for results */
char fn[256];
snprintf(fn, sizeof(fn), "results/datamover_%s_%s_%s.dat", dm_name, intc_flags & INTC_POLLING ? "polling" : "irq", uts.release);
FILE *g = fopen(fn, "w");
for (int exp = BENCH_DM_EXP_MIN; exp <= BENCH_DM_EXP_MAX; exp++) {
uint64_t start, stop, total = 0, len = 1 << exp;
#if BENCH_DM == 1
if (exp > 11)
break; /* FIFO and Simple DMA are limited to 4kb */
#elif BENCH_DM == 3
if (exp >= 12)
break; /* FIFO and Simple DMA are limited to 4kb */
#endif
read_random(src.base_virt, len);
memset(dst.base_virt, 0, len);
info("Start DM bench: len=%#jx", len);
uint64_t runs = BENCH_RUNS >> exp;
for (int i = 0; i < runs + BENCH_WARMUP; i++) {
start = rdtsc();
#if BENCH_DM == 1
ssize_t ret;
ret = fifo_write(dm, src.base_virt, len);
if (ret < 0)
error("Failed write to FIFO with len = %zu", len);
ret = fifo_read(dm, dst.base_virt, dst.len);
if (ret < 0)
error("Failed read from FIFO with len = %zu", len);
#else
ret = dma_ping_pong(dm, src.base_phys, dst.base_phys, len);
if (ret)
error("DMA ping pong failed");
#endif
stop = rdtsc();
if (memcmp(src.base_virt, dst.base_virt, len))
warn("Compare failed");
if (i > BENCH_WARMUP)
total += stop - start;
}
info("exp %u avg %lu", exp, total / runs);
fprintf(g, "%lu %lu\n", len, total / runs);
}
fclose(g);
ret = switch_disconnect(c->sw, dm, dm);
if (ret)
error("Failed to configure switch");
ret = dma_free(dm, &mem);
if (ret)
error("Failed to release DMA memory");
ret = intc_disable(c->intc, (1 << dm->irq) | (1 << (dm->irq + 1)));
if (ret)
error("Failed to enable interrupt");
return 0;
}
int fpga_benchmark_memcpy(struct fpga_card *c)
{
char *map = c->map + 0x200000;
uint32_t *mapi = (uint32_t *) map;
char fn[256];
snprintf(fn, sizeof(fn), "results/bar0_%s_%s.dat", intc_flags & INTC_POLLING ? "polling" : "irq", uts.release);
FILE *g = fopen(fn, "w");
fprintf(g, "# bytes cycles\n");
uint32_t dummy = 0;
for (int exp = BENCH_DM_EXP_MIN; exp <= BENCH_DM_EXP_MAX; exp++) {
uint64_t len = 1 << exp;
uint64_t start, end, total = 0;
uint64_t runs = (BENCH_RUNS << 2) >> exp;
for (int i = 0; i < runs + BENCH_WARMUP; i++) {
start = rdtsc();
for (int j = 0; j < len / 4; j++)
// mapi[j] = j; // write
dummy += mapi[j]; // read
end = rdtsc();
if (i > BENCH_WARMUP)
total += end - start;
}
info("exp = %u\truns = %ju\ttotal = %ju\tavg = %ju\tavgw = %ju", exp, runs, total, total / runs, total / (runs * len));
fprintf(g, "%zu %lu %ju\n", len, total / runs, runs);
}
fclose(g);
return 0;
}

View file

@ -1,105 +0,0 @@
/** VILLASfpga utility for tests and benchmarks
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
**********************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <villas/log.h>
#include <villas/super_node.h>
#include <villas/timing.h>
#include <villas/utils.h>
#include <villas/memory.h>
#include <villas/nodes/fpga.h>
#include <villas/kernel/rt.h>
#include <villas/kernel/pci.h>
#include <villas/kernel/kernel.h>
#include <villas/fpga/card.h>
/* Declarations */
int fpga_benchmarks(int argc, char *argv[], struct fpga_card *c);
void usage()
{
printf("Usage: villas-fpga [OPTIONS] CONFIG CARD\n\n");
printf(" CONFIG path to a configuration file\n");
printf(" CARD name of the FPGA card\n");
printf(" OPTIONS is one or more of the following options:\n");
printf(" -d set log level\n");
printf(" -h show this help\n");
printf(" -V show the version of the tool\n");
printf("\n");
print_copyright();
}
int main(int argc, char *argv[])
{
int ret;
struct super_node sn;
struct fpga_card *card;
/* Parse arguments */
char c, *endptr;
while ((c = getopt(argc, argv, "Vd:h")) != -1) {
switch (c) {
case 'V':
print_version();
exit(EXIT_SUCCESS);
case 'd':
sn.log.level = strtoul(optarg, &endptr, 10);
goto check;
case 'h':
case '?':
default:
usage();
exit(EXIT_SUCCESS);
}
check: if (optarg == endptr)
error("Failed to parse parse option argument '-%c %s'", c, optarg);
}
if (argc != optind + 2) {
usage();
exit(EXIT_FAILURE);
}
char *configfile = argv[optind];
super_node_init(&sn);
super_node_parse_uri(&sn, configfile);
log_init(&sn.log, sn.log.level, sn.log.facilities);
rt_init(sn.priority, sn.affinity);
memory_init(sn.hugepages);
/* Initialize VILLASfpga card */
ret = fpga_init(&sn);
if (ret)
error("Failed to initialize FPGA card");
card = fpga_lookup_card(argv[2]);
if (!card)
error("FPGA card '%s' does not exist", argv[2]);
fpga_card_dump(card);
/* Run benchmarks */
fpga_benchmarks(argc-optind-1, argv+optind+1, card);
/* Shutdown */
ret = fpga_deinit();
if (ret)
error("Failed to de-initialize FPGA card");
super_node_destroy(&sn);
return 0;
}

View file

@ -1,404 +0,0 @@
/** Test procedures for VILLASfpga
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
*********************************************************************************/
#ifdef WITH_FPGA
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <math.h>
#include <criterion/criterion.h>
#include <criterion/options.h>
#include <xilinx/xtmrctr.h>
#include <villas/super_node.h>
#include <villas/utils.h>
#include <villas/nodes/fpga.h>
#include <villas/fpga/ip.h>
#include <villas/fpga/card.h>
#include <villas/fpga/vlnv.h>
#include <villas/fpga/ips/intc.h>
#include <villas/fpga/ips/timer.h>
#define TEST_CONFIG "/villas/etc/fpga.conf"
#define TEST_LEN 0x1000
#define CPU_HZ 3392389000
#define FPGA_AXI_HZ 125000000
static struct list cards;
static struct fpga_card *card;
static struct super_node sn = { .state = STATE_DESTROYED };
static struct pci pci;
static struct vfio_container vc;
static void init()
{
int ret;
ret = super_node_init(&sn);
cr_assert_eq(ret, 0, "Failed to initialize Supernode");
ret = super_node_parse_uri(&sn, TEST_CONFIG);
cr_assert_eq(ret, 0, "Failed to parse configuration");
ret = super_node_check(&sn);
cr_assert_eq(ret, 0, "Failed to check configuration");
ret = pci_init(&pci);
cr_assert_eq(ret, 0, "Failed to initialize PCI sub-system");
ret = vfio_init(&vc);
cr_assert_eq(ret, 0, "Failed to initiliaze VFIO sub-system");
/* Parse FPGA configuration */
list_init(&cards);
ret = fpga_card_parse_list(&cards, sn.cfg);
cr_assert_eq(ret, 0, "Failed to parse FPGA config");
card = list_lookup(&cards, "vc707");
cr_assert(card, "FPGA card not found");
if (criterion_options.logging_threshold < CRITERION_IMPORTANT)
fpga_card_dump(card);
}
static void fini()
{
int ret;
ret = fpga_card_destroy(card);
cr_assert_eq(ret, 0, "Failed to de-initilize FPGA");
super_node_destroy(&sn);
}
TestSuite(fpga,
.init = init,
.fini = fini,
.description = "VILLASfpga",
.disabled = true);
Test(fpga, intc, .description = "Interrupt Controller")
{
int ret;
uint32_t isr;
cr_assert(card->intc);
ret = intc_enable(card->intc, 0xFF00, 0);
cr_assert_eq(ret, 0, "Failed to enable interrupt");
/* Fake IRQs in software by writing to ISR */
XIntc_Out32((uintptr_t) card->map + card->intc->baseaddr + XIN_ISR_OFFSET, 0xFF00);
/* Wait for 8 SW triggered IRQs */
for (int i = 0; i < 8; i++)
intc_wait(card->intc, i+8);
/* Check ISR if all SW IRQs have been deliverd */
isr = XIntc_In32((uintptr_t) card->map + card->intc->baseaddr + XIN_ISR_OFFSET);
ret = intc_disable(card->intc, 0xFF00);
cr_assert_eq(ret, 0, "Failed to disable interrupt");
cr_assert_eq(isr & 0xFF00, 0); /* ISR should get cleared by MSI_Grant_signal */
}
Test(fpga, xsg, .description = "XSG: multiply_add")
{
int ret;
double factor, err = 0;
struct fpga_ip *ip, *dma;
struct model_parameter *p;
struct dma_mem mem;
ip = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { NULL, "sysgen", "xsg_multiply", NULL });
cr_assert(ip);
dma = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_dma", NULL });
cr_assert(dma);
struct model *model = (struct model *) ip->_vd;
p = list_lookup(&model->parameters, "factor");
if (!p)
error("Missing parameter 'factor' for model '%s'", ip->name);
ret = model_parameter_read(p, &factor);
cr_assert_eq(ret, 0, "Failed to read parameter 'factor' from model '%s'", ip->name);
info("Model param: factor = %f", factor);
ret = switch_connect(card->sw, dma, ip);
cr_assert_eq(ret, 0, "Failed to configure switch");
ret = switch_connect(card->sw, ip, dma);
cr_assert_eq(ret, 0, "Failed to configure switch");
ret = dma_alloc(dma, &mem, 0x1000, 0);
cr_assert_eq(ret, 0, "Failed to allocate DMA memory");
float *src = (float *) mem.base_virt;
float *dst = (float *) mem.base_virt + 0x800;
for (int i = 0; i < 6; i++)
src[i] = 1.1 * (i+1);
ret = dma_ping_pong(dma, (char *) src, (char *) dst, 6 * sizeof(float));
cr_assert_eq(ret, 0, "Failed to to ping pong DMA transfer: %d", ret);
for (int i = 0; i < 6; i++)
err += fabs(factor * src[i] - dst[i]);
info("Error after FPGA operation: err = %f", err);
ret = switch_disconnect(card->sw, dma, ip);
cr_assert_eq(ret, 0, "Failed to configure switch");
ret = switch_disconnect(card->sw, ip, dma);
cr_assert_eq(ret, 0, "Failed to configure switch");
ret = dma_free(dma, &mem);
cr_assert_eq(ret, 0, "Failed to release DMA memory");
cr_assert(err < 1e-3);
}
Test(fpga, hls_dft, .description = "HLS: hls_dft")
{
int ret;
struct fpga_ip *hls, *rtds;
rtds = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { "acs.eonerc.rwth-aachen.de", "user", "rtds_axis", NULL });
hls = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { NULL, "hls", "hls_dft", NULL });
/* Check if required IP is available on FPGA */
cr_assert(hls && rtds);
ret = intc_enable(card->intc, (1 << rtds->irq), 0);
cr_assert_eq(ret, 0, "Failed to enable interrupt");
ret = switch_connect(card->sw, rtds, hls);
cr_assert_eq(ret, 0, "Failed to configure switch");
ret = switch_connect(card->sw, hls, rtds);
cr_assert_eq(ret, 0, "Failed to configure switch");
while(1) {
/* Dump RTDS AXI Stream state */
rtds_axis_dump(rtds);
sleep(1);
}
#if 0
int len = 2000;
int NSAMPLES = 400;
float src[len], dst[len];
for (int i = 0; i < len; i++) {
src[i] = 4 + 5.0 * sin(2.0 * M_PI * 1 * i / NSAMPLES) +
2.0 * sin(2.0 * M_PI * 2 * i / NSAMPLES) +
1.0 * sin(2.0 * M_PI * 5 * i / NSAMPLES) +
0.5 * sin(2.0 * M_PI * 9 * i / NSAMPLES) +
0.2 * sin(2.0 * M_PI * 15 * i / NSAMPLES);
fifo_write()
}
#endif
ret = switch_disconnect(card->sw, rtds, hls);
cr_assert_eq(ret, 0, "Failed to configure switch");
ret = switch_disconnect(card->sw, hls, rtds);
cr_assert_eq(ret, 0, "Failed to configure switch");
}
Test(fpga, fifo, .description = "FIFO")
{
int ret;
ssize_t len;
char src[255], dst[255];
struct fpga_ip *fifo;
fifo = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_fifo_mm_s", NULL });
cr_assert(fifo);
ret = intc_enable(card->intc, (1 << fifo->irq), 0);
cr_assert_eq(ret, 0, "Failed to enable interrupt");
ret = switch_connect(card->sw, fifo, fifo);
cr_assert_eq(ret, 0, "Failed to configure switch");
/* Get some random data to compare */
memset(dst, 0, sizeof(dst));
len = read_random((char *) src, sizeof(src));
if (len != sizeof(src))
error("Failed to get random data");
len = fifo_write(fifo, (char *) src, sizeof(src));
if (len != sizeof(src))
error("Failed to send to FIFO");
len = fifo_read(fifo, (char *) dst, sizeof(dst));
if (len != sizeof(dst))
error("Failed to read from FIFO");
ret = intc_disable(card->intc, (1 << fifo->irq));
cr_assert_eq(ret, 0, "Failed to disable interrupt");
ret = switch_disconnect(card->sw, fifo, fifo);
cr_assert_eq(ret, 0, "Failed to configure switch");
/* Compare data */
cr_assert_eq(memcmp(src, dst, sizeof(src)), 0);
}
Test(fpga, dma, .description = "DMA")
{
int ret = -1;
struct dma_mem mem, src, dst;
for (size_t i = 0; i < list_length(&card->ips); i++) { INDENT
struct fpga_ip *dm = (struct fpga_ip *) list_at(&card->ips, i);
if (fpga_vlnv_cmp(&dm->vlnv, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_dma", NULL }))
continue; /* skip non DMA IP cores */
struct dma *dma = (struct dma *) dm->_vd;
/* Simple DMA can only transfer up to 4 kb due to
* PCIe page size burst limitation */
ssize_t len2, len = dma->inst.HasSg ? 64 << 20 : 1 << 2;
ret = dma_alloc(dm, &mem, 2 * len, 0);
cr_assert_eq(ret, 0);
ret = dma_mem_split(&mem, &src, &dst);
cr_assert_eq(ret, 0);
/* Get new random data */
len2 = read_random(src.base_virt, len);
if (len2 != len)
serror("Failed to get random data");
int irq_mm2s = dm->irq;
int irq_s2mm = dm->irq + 1;
ret = intc_enable(card->intc, (1 << irq_mm2s) | (1 << irq_s2mm), 0);
cr_assert_eq(ret, 0, "Failed to enable interrupt");
ret = switch_connect(card->sw, dm, dm);
cr_assert_eq(ret, 0, "Failed to configure switch");
/* Start transfer */
ret = dma_ping_pong(dm, src.base_phys, dst.base_phys, dst.len);
cr_assert_eq(ret, 0, "DMA ping pong failed");
ret = memcmp(src.base_virt, dst.base_virt, src.len);
info("DMA %s (%s): %s", dm->name, dma->inst.HasSg ? "scatter-gather" : "simple", ret ? CLR_RED("failed") : CLR_GRN("passed"));
ret = switch_disconnect(card->sw, dm, dm);
cr_assert_eq(ret, 0, "Failed to configure switch");
ret = intc_disable(card->intc, (1 << irq_mm2s) | (1 << irq_s2mm));
cr_assert_eq(ret, 0, "Failed to disable interrupt");
ret = dma_free(dm, &mem);
cr_assert_eq(ret, 0, "Failed to release DMA memory");
}
cr_assert_eq(ret, 0);
}
Test(fpga, timer, .description = "Timer Counter")
{
int ret;
struct fpga_ip *ip;
struct timer *tmr;
ip = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_timer", NULL });
cr_assert(ip);
tmr = (struct timer *) ip->_vd;
XTmrCtr *xtmr = &tmr->inst;
ret = intc_enable(card->intc, (1 << ip->irq), 0);
cr_assert_eq(ret, 0, "Failed to enable interrupt");
XTmrCtr_SetOptions(xtmr, 0, XTC_EXT_COMPARE_OPTION | XTC_DOWN_COUNT_OPTION);
XTmrCtr_SetResetValue(xtmr, 0, FPGA_AXI_HZ / 125);
XTmrCtr_Start(xtmr, 0);
uint64_t counter = intc_wait(card->intc, ip->irq);
info("Got IRQ: counter = %ju", counter);
if (counter == 1)
return;
else
warn("Counter was not 1");
intc_disable(card->intc, (1 << ip->irq));
cr_assert_eq(ret, 0, "Failed to disable interrupt");
return;
}
Test(fpga, rtds_rtt, .description = "RTDS: tight rtt")
{
int ret;
struct fpga_ip *ip, *rtds;
struct dma_mem buf;
size_t recvlen;
/* Get IP cores */
rtds = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { "acs.eonerc.rwth-aachen.de", "user", "rtds_axis", NULL });
cr_assert(rtds);
ip = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_dma", NULL });
cr_assert(ip);
ret = switch_connect(card->sw, rtds, ip);
cr_assert_eq(ret, 0, "Failed to configure switch");
ret = switch_connect(card->sw, ip, rtds);
cr_assert_eq(ret, 0, "Failed to configure switch");
ret = dma_alloc(ip, &buf, 0x100, 0);
cr_assert_eq(ret, 0, "Failed to allocate DMA memory");
while (1) {
ret = dma_read(ip, buf.base_phys, buf.len);
cr_assert_eq(ret, 0, "Failed to start DMA read: %d", ret);
ret = dma_read_complete(ip, NULL, &recvlen);
cr_assert_eq(ret, 0, "Failed to complete DMA read: %d", ret);
ret = dma_write(ip, buf.base_phys, recvlen);
cr_assert_eq(ret, 0, "Failed to start DMA write: %d", ret);
ret = dma_write_complete(ip, NULL, NULL);
cr_assert_eq(ret, 0, "Failed to complete DMA write: %d", ret);
}
ret = switch_disconnect(card->sw, rtds, ip);
cr_assert_eq(ret, 0, "Failed to configure switch");
ret = switch_disconnect(card->sw, ip, rtds);
cr_assert_eq(ret, 0, "Failed to configure switch");
ret = dma_free(ip, &buf);
cr_assert_eq(ret, 0, "Failed to release DMA memory");
}
#endif /* WITH_FPGA */

View file

@ -84,7 +84,7 @@ SKIPPED=0
TIMEDOUT=0
# Preamble
echo -e "Starting integration tests for VILLASnode/fpga:\n"
echo -e "Starting integration tests for VILLASnode:\n"
for TEST in ${TESTS}; do
TESTNAME=$(basename -s .sh ${TEST})

View file

@ -1,47 +0,0 @@
#!/bin/bash
#
# Detach and rebind a PCI device to a PCI kernel driver
#
# @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
# @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
# @license GNU General Public License (version 3)
#
# VILLASnode
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
##################################################################################
if [ "$#" -ne 2 ]; then
echo "usage: $0 BUS:DEV:FNC DRIVER"
exit 1
fi
BDF=$1
DRIVER=$2
VENDOR=$(cut -b3- /sys/bus/pci/devices/${BDF}/vendor)
DEVICE=$(cut -b3- /sys/bus/pci/devices/${BDF}/device)
SYSFS_DEVICE=/sys/bus/pci/devices/${BDF}
SYSFS_DRIVER=/sys/bus/pci/drivers/${DRIVER}
echo "Device: $VENDOR $DEVICE $BDF"
if [ -L "${SYSFS_DEVICE}/driver" ] && [ -d "${SYSFS_DEVICE}/driver" ]; then
echo ${BDF} > ${SYSFS_DEVICE}/driver/unbind
fi
echo "${VENDOR} ${DEVICE}" > ${SYSFS_DRIVER}/new_id
echo "${BDF}" > ${SYSFS_DRIVER}/bind
echo "${VENDOR} ${DEVICE}" > ${SYSFS_DRIVER}/remove_id

View file

@ -1,35 +0,0 @@
#!/bin/bash
#
# Reset PCI devices like FPGAs after a reflash
#
# @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
# @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
# @license GNU General Public License (version 3)
#
# VILLASnode
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
##################################################################################
if [ "$#" -ne 1 ]; then
echo "usage: $0 BUS:DEV:FNC"
exit 1
fi
BDF=$1
echo "1" > /sys/bus/pci/devices/$BDF/remove
echo "1" > /sys/bus/pci/rescan
echo "1" > /sys/bus/pci/devices/$BDF/enable