Commit 0f59185c authored by Dimitris Lampridis's avatar Dimitris Lampridis

Merge branch 'proposed_master'

parents dbd72902 f277c6a6
......@@ -4,9 +4,6 @@
[submodule "dependencies/fine-delay"]
path = dependencies/fmc-delay-1ns-8cha
url = https://ohwr.org/project/fmc-delay-1ns-8cha.git
[submodule "dependencies/fmc-tdc"]
path = dependencies/fmc-tdc-1ns-5cha-gw
url = https://ohwr.org/project/fmc-tdc-1ns-5cha-gw.git
[submodule "dependencies/vme64x-core"]
path = dependencies/vme64x-core
url = https://ohwr.org/project/vme64x-core.git
......@@ -19,9 +16,6 @@
[submodule "dependencies/urv-core"]
path = dependencies/urv-core
url = https://ohwr.org/project/urv-core.git
[submodule "dependencies/fmc-adc-100m14b4cha-gw"]
path = dependencies/fmc-adc-100m14b4cha-gw
url = https://ohwr.org/project/fmc-adc-100m14b4cha-gw.git
[submodule "dependencies/ddr3-sp6-core"]
path = dependencies/ddr3-sp6-core
url = https://ohwr.org/project/ddr3-sp6-core.git
......@@ -34,3 +28,11 @@
[submodule "dependencies/svec"]
path = dependencies/svec
url = https://ohwr.org/project/svec.git
[submodule "dependencies/fmc-tdc"]
path = dependencies/fmc-tdc
url = https://ohwr.org/project/fmc-tdc.git
branch = develop
[submodule "dependencies/fmc-adc-100m14b4cha"]
path = dependencies/fmc-adc-100m14b4cha
url = https://ohwr.org/project/fmc-adc-100m14b4cha.git
branch = master
......@@ -5,6 +5,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- udev rules for proper node initialisation
### Changed
- Better python packaging, including wrtd-tool
### Fixed
- Building of drivers in newer (post 4.19) Linux kernels
## [1.0.1] - 2021-02-10
### Fixed
......
Subproject commit b06636f542b2a69ca461db1faee767814ac27714
Subproject commit dabad887078b575d7d4eff8ab570e29c299853ef
Subproject commit dae483e3ca0ee971861ef7a5455a2dd7b3c610a0
Subproject commit 2bdeecbd4f349f3e72c42373de84432286ae3306
Subproject commit 099aebecd2b6237dd49dfee6f67cb3c072b7bd96
Subproject commit e66d3b45345e1c518697ad5574f80cb825527465
Subproject commit 284373b7ea1db559dd323634dd34a8dba1811c12
Subproject commit 7d76d2b6503cd3f129fd4bc3797b6abfefb752c5
Subproject commit e52fec7c961efbc3f66419fc8eb2d16accef0e2a
Subproject commit 483c3fc7306cec24a5e770dd548820c8cc3147f7
Subproject commit cf6b2894a6c0d3e0b755f73f1310a58074770eda
Subproject commit 5c8b5729b24364698839f3ff1762f9944a4b4bf8
Subproject commit 3dcac4483417a159f0b9495adab0c15b7b45692b
Subproject commit 3884a65545907de3a0d41d549a4be9e6cccb4916
......@@ -59,7 +59,7 @@ master_doc = 'index'
# General information about the project.
project = u'White Rabbit Trigger Distribution'
copyright = u'2019, CERN, documentation released under CC-BY-SA-4.0'
author = u'Dimitris Lampridis <dimitris.lampridis@cern.ch'
author = u'Dimitris Lampridis <dimitris.lampridis@cern.ch>'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
......@@ -75,7 +75,7 @@ release = u'1.0'
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
......
......@@ -232,7 +232,7 @@ functions. These include:
+ :cpp:func:`wr_link_up`
+ :cpp:func:`wr_time_ready`
+ :cpp:func:`wr_enable_lock`
+ :cpp:func:`wr_time_locked`
+ :cpp:func:`wr_aux_locked`
+ :cpp:func:`wr_sync_timeout`
* :ref:`fw_api_event_in`
......@@ -264,7 +264,7 @@ done.
.. doxygenfunction:: wr_link_up
.. doxygenfunction:: wr_time_ready
.. doxygenfunction:: wr_enable_lock
.. doxygenfunction:: wr_time_locked
.. doxygenfunction:: wr_aux_locked
.. doxygenfunction:: wr_sync_timeout
Event I/O
......
......@@ -14,6 +14,8 @@ Installation
procedures have been finalised and tested, the contents of the wiki page will be merged
here.
.. _permissions:
Permissions
===========
......
......@@ -98,7 +98,7 @@ design WRTD to be as close to LXI as possible. In particular:
.. hint:: Do not worry if you do not understand some of the terminology yet. It will be explained in
:numref:`basic_concepts`.
In the future, and with `White Rabbit being standardised within the next release of IEEE-1588
In the future, and with `White Rabbit standardised within IEEE-1588-2019
<https://www.ohwr.org/project/wr-std/wikis/home>`_, it is foreseen to try to merge WRTD with
IVI/LXI. A possible way to do this would be to add a new IVI specification, similar to IVI-3.15,
describing the API to control WRTD-enabled devices. This API would be an extension, allowing any
......
......@@ -15,9 +15,14 @@ Currently these include:
WRTD.
#. :ref:`svec_ref_tdc_fd`: A pulse-in/pulse-out WRTD Node in VME format, for generic trigger
distribution applications.
#. :ref:`svec_ref_tdc_x2`: A pulse-in WRTD Node in VME format.
#. :ref:`svec_ref_fd_x2`: A pulse-out WRTD Node in VME format.
.. toctree::
:hidden:
ref_spec_fmc_adc
ref_svec_tdc_fd
ref_svec_tdc_x2
ref_svec_fd_x2
ref_svec_adc_x2
.. Copyright (c) 2019 CERN (home.cern)
SPDX-License-Identifier: CC-BY-SA-4.0
.. _svec_ref_adc_x2:
SVEC-based ADC x 2
==================
This is a WRTD :ref:`node` based on the `Simple VME FMC Carrier (SVEC)
<https://www.ohwr.org/project/svec/wikis/home>`_ and the `FMC ADC 100M 14b 4cha (FMC-ADC)
<https://www.ohwr.org/project/fmc-adc-100m14b4cha/wikis/home>`_.
This :ref:`node` provides the possibility to generate WRTD :ref:`Messages <message>` based on
trigger events of the FMC-ADC, as well as to trigger the FMC-ADC from incoming WRTD :ref:`Messages
<message>`.
The node has 10 :ref:`Local Input Channels <local_channel>`. Channels 1 to 4
are mapped to the internal trigger of adc #1, channel 5 to the external trigger
input of adc #1, channels 6 to 9 to the intern triggers of adc #2 and
channel 10 to the external trigger input of adc #2.
.. Copyright (c) 2019 CERN (home.cern)
SPDX-License-Identifier: CC-BY-SA-4.0
.. _svec_ref_fd_x2:
SVEC-based FD x 2
=================
This is a WRTD :ref:`node` based on the `Simple VME FMC Carrier (SVEC)
<https://www.ohwr.org/project/svec/wikis/home>`_ and the `FMC Fine Delay generator
(FMC-FD) <https://www.ohwr.org/project/fmc-delay-1ns-8cha/wikis/home>`_.
The basic principle of this :ref:`node` is simple: the :ref:`node`
also receives WRTD :ref:`Messages <message>` which are then used to
generate pulses at a predefined moment on one of the FMC-FD outputs.
Architecture and performances are similar to :ref:`svec_ref_tdc_fd`.
The node has 10 :ref:`Local Output Channels <local_channel>`, they are
mapped to the five inputs of each FMC-FD.
......@@ -25,7 +25,7 @@ SVEC-based TDC+FD
+----------------------------------------+------------+------------+
| Average input to Message latency | 20μs | N.A. |
+----------------------------------------+------------+------------+
| Average Message to output latency | N.A. | 40μs |
| Average Message to output latency | N.A. | 20μs |
+----------------------------------------+------------+------------+
| Can receive Messages over WR | NO | YES |
+----------------------------------------+------------+------------+
......@@ -34,8 +34,8 @@ SVEC-based TDC+FD
This is a WRTD :ref:`node` based on the `Simple VME FMC Carrier (SVEC)
<https://www.ohwr.org/project/svec/wikis/home>`_, the `FMC Time to Digital Converter (FMC-TDC)
<https://www.ohwr.org/project/fmc-tdc-1ns-5cha-hw/wikis/home>`_ and the `FMC Fine Delay generator
(FMC-FD) <https://www.ohwr.org/project/fmc-delay-1ns-8cha/wikis/home>`_.
<https://www.ohwr.org/project/fmc-tdc/wikis/home>`_ and the `FMC Fine Delay generator (FMC-FD)
<https://www.ohwr.org/project/fmc-delay-1ns-8cha/wikis/home>`_.
.. important:: The FMC-TDC should always be attached to "FMC Slot 1" of the SVEC, and the FMC-FD
should always be attached to "FMC Slot 2". It is not necessary though to have both
......
.. Copyright (c) 2019 CERN (home.cern)
SPDX-License-Identifier: CC-BY-SA-4.0
.. _svec_ref_tdc_x2:
SVEC-based TDC x 2
==================
This is a WRTD :ref:`node` based on the `Simple VME FMC Carrier (SVEC)
<https://www.ohwr.org/project/svec/wikis/home>`_ and the `FMC Time to Digital Converter (FMC-TDC)
<https://www.ohwr.org/project/fmc-tdc/wikis/home>`_.
The basic principle of this :ref:`node` is simple: it takes in
external pulses on its FMC-TDC inputs, timestamps them using WR time
and converts them to WRTD :ref:`Messages <message>`, to be sent over
the WR network.
Architecture and performances are similar to :ref:`svec_ref_tdc_fd`.
The node has 10 :ref:`Local Input Channels <local_channel>`, they are mapped
to the five inputs of each FMC-TDC.
docutils==0.14
Sphinx==1.8.5
sphinx_rtd_theme
breathe==4.11.0
recommonmark==0.5.0
decorator==4.4.0
docutils==0.17.1
Sphinx==5.1.1
sphinx_rtd_theme==1.0.0
breathe==4.34.0
recommonmark==0.7.1
decorator==5.1.1
......@@ -92,6 +92,40 @@ Functions
examples. However, in a real application, users should always check the status code of every call
to a WRTD function, like in :numref:`lst-get_error`.
.. hint::
If you want to be sure that the buffer that you pass to :cpp:func:`wrtd_get_error`
is large enough, without having to resort to querying like in :numref:`lst-get_error`, you can
always allocate a buffer of :c:macro:`WRTD_ERR_MSG_BUF_SIZE`. WRTD guarantees that all error
messages shall not exceed this size.
.. doxygendefine:: WRTD_ERR_MSG_BUF_SIZE
.. code-block:: c
:caption: Retrieving the error message with a pre-defined buffer size
#include <libwrtd.h>
int main(void) {
wrtd_dev *wrtd;
wrtd_status status;
char err_msg[WRTD_ERR_MSG_BUF_SIZE];
status = wrtd_init(1, false, NULL, &wrtd);
status = wrtd_get_attr_bool(wrtd, WRTD_GLOBAL_REP_CAP_ID,
WRTD_ATTR_EVENT_LOG_EMPTY);
if (status != WRTD_SUCCESS) {
/* retrieve the error code and message */
wrtd_get_error(wrtd, &err_code, WRTD_ERR_MSG_BUF_SIZE, err_msg)
printf("ERROR: %d, %s\n", err_code, err_msg);
return status;
}
wrtd_close(wrtd);
return 0;
}
.. _api_init:
Initialisation API
......@@ -257,7 +291,7 @@ Functions
/* get the delay configured for "rule1" */
status = wrtd_get_attr_tstamp(wrtd, "rule1",
WRTD_ATTR_RULE_DELAY, &ts");
WRTD_ATTR_RULE_DELAY, &ts);
wrtd_close(wrtd);
}
......@@ -295,6 +329,7 @@ The Event Logging API provides functions for accessing the :ref:`event_log`.
int main(void) {
wrtd_dev *wrtd;
wrtd_status status;
char *log_msg;
int buf_size;
......@@ -332,6 +367,7 @@ The Event Logging API provides functions for accessing the :ref:`event_log`.
int main(void) {
wrtd_dev *wrtd;
wrtd_status status;
char log_msg[WRTD_LOG_ENTRY_SIZE];
status = wrtd_init(1, false, NULL, &wrtd);
......@@ -368,6 +404,7 @@ Configuration of an Alarm happens by setting the relevant :ref:`Attributes <attr
int i, count;
char rep_cap_id[16];
wrtd_dev *wrtd;
wrtd_status status;
status = wrtd_init(1, false, NULL, &wrtd);
......@@ -427,6 +464,7 @@ Configuration of a Rule happens by setting the relevant :ref:`Attributes <attrib
int i, count;
char rep_cap_id[16];
wrtd_dev *wrtd;
wrtd_status status;
status = wrtd_init(1, false, NULL, &wrtd);
......@@ -487,7 +525,7 @@ Configuration of a Rule happens by setting the relevant :ref:`Attributes <attrib
/* Enable rule */
status = wrtd_set_attr_bool(wrtd, "rule1",
WRTD_ATTR_RULE_ENABLED, True);
WRTD_ATTR_RULE_ENABLED, true);
wrtd_close(wrtd);
......@@ -516,6 +554,7 @@ relevant :ref:`Attributes <attribute>` via the :ref:`api_attr`.
int i, count, major, minor;
char rep_cap_id[16];
wrtd_dev *wrtd;
wrtd_status status;
status = wrtd_init(1, false, NULL, &wrtd);
......
......@@ -42,7 +42,7 @@ In order to retrieve the ID of the :ref:`node`, the :py:class:`PyWrtd` class pro
methods :py:meth:`PyWrtd.PyWrtd.get_node_count` and :py:meth:`PyWrtd.PyWrtd.get_node_id` that can be
used before you instantiate the :py:class:`PyWrtd` object.
If the ID is wrong or if the user does not have the correct :ref:`permissions <permissions>` to
If the ID is wrong or if the user does not have the correct :ref:`permissions` to
access it, WRTD will return :cpp:enumerator:`WRTD_ERROR_RESOURCE_UNKNOWN`.
.. code-block:: python
......
......@@ -6,13 +6,11 @@
Tools
=====
.. module:: PyWrtd
WRTD provides a comand-line, Python based tool (:ref:`wrtd_tool`) for accessing a :ref:`node`.
.. hint::
Please make sure that you run the tool wih the proper :ref:`permissions <permissions>`.
Please make sure that you run the tool wih the proper :ref:`permissions`.
For details on how to install the tool (and their dependencies), please refer to
:numref:`installation`.
......@@ -65,6 +63,7 @@ A list of the available commands can be retrieved by passing the ``-h`` option t
disable-alarm Disable an Alarm
disable-all-alarms Disable all Alarms
alarm-info Display information about an Alarm
cli Command line interface
Each command has its own built-in help system as well, which can be invoked by selecting a command
and passing the ``-h`` option after the command:
......
......@@ -120,7 +120,7 @@ INST "cmp0_fmc_adc_mezzanine/*/cmp_ext_trig_sync/sync0" RLOC_ORIGIN = X68Y
#----------------------------------------
INST "cmp0_fmc_adc_mezzanine/cmp_fmc_spi/*/Wrapped_SPI/shift/s_out" IOB = FALSE;
INST "cmp0_fmc_adc_mezzanine/cmp_fmc_spi/*/Wrapped_SPI/clgen/clk_out" IOB = FALSE;
INST "cmp0_fmc_adc_mezzanine/cmp_fmc_onewire/*/Wrapped_1wire/owr_oen_1" IOB = FALSE;
INST "cmp0_fmc_adc_mezzanine/cmp_fmc_onewire/i_readout/*" IOB = FALSE;
#----------------------------------------
# Clocks
......
board = "svec"
target = "xilinx"
action = "synthesis"
syn_device = "xc6slx150t"
syn_grade = "-3"
syn_package = "fgg900"
syn_top = "wrtd_ref_svec_adc_x2"
syn_project = "wrtd_ref_svec_adc_x2.xise"
syn_tool = "ise"
# Allow the user to override fetchto using:
# hdlmake -p "fetchto='xxx'"
if locals().get('fetchto', None) is None:
fetchto = "../../../dependencies"
files = [
"buildinfo_pkg.vhd",
# fetchto + "/fmc-tdc/hdl/syn/svec/svec-tdc0.ucf",
# fetchto + "/fmc-tdc/hdl/syn/svec/svec-tdc1.ucf",
"wrtd_ref_svec_adc_x2.ucf",
]
modules = {
"local" : [
"../../top/wrtd_ref_svec_adc_x2",
],
}
#syn_pre_project_cmd = "make -C ../../../software/firmware"
# Do not fail during hdlmake fetch
try:
exec(open(fetchto + "/general-cores/tools/gen_buildinfo.py").read())
except:
pass
syn_post_project_cmd = "$(TCL_INTERPRETER) syn_extra_steps.tcl $(PROJECT_FILE)"
svec_base_ucf = ['wr', 'ddr4', 'ddr5', 'led', 'gpio']
ctrls = ["bank4_64b_32b", "bank5_64b_32b"]
# get project file from 1st command-line argument
set project_file [lindex $argv 0]
if {![file exists $project_file]} {
report ERROR "Missing file $project_file, exiting."
exit -1
}
xilinx::project open $project_file
# Some of these are not respected by ISE when passed through hdlmake,
# so we add them all ourselves after creating the project
#
# Not respected by ISE when passed through hdlmake:
# 1. Pack I/O Registers/Latches into IOBs
# 2. Register Duplication Map
xilinx::project set "Enable Multi-Threading" "2" -process "Map"
xilinx::project set "Enable Multi-Threading" "4" -process "Place & Route"
xilinx::project set "Pack I/O Registers into IOBs" "Yes"
xilinx::project set "Pack I/O Registers/Latches into IOBs" "For Inputs and Outputs"
xilinx::project set "Register Balancing" "Yes"
xilinx::project set "Register Duplication Map" "On"
#xilinx::project set "Placer Extra Effort Map" "Normal"
#xilinx::project set "Extra Effort (Highest PAR level only)" "Normal"
xilinx::project save
xilinx::project close
# SPDX-FileCopyrightText: 2020 CERN (home.cern)
#
# SPDX-License-Identifier: CC0-1.0
#===============================================================================
# IO Constraints
#===============================================================================
#----------------------------------------
# FMC slots
#----------------------------------------
# FMC0
NET "adc_ext_trigger_n_i[0]" LOC = "A15";
NET "adc_ext_trigger_p_i[0]" LOC = "B15";
NET "adc_dco_n_i[0]" LOC = "A16";
NET "adc_dco_p_i[0]" LOC = "C16";
NET "adc_fr_n_i[0]" LOC = "G21";
NET "adc_fr_p_i[0]" LOC = "H21";
NET "adc_outa_n_i[0]" LOC = "E17";
NET "adc_outa_p_i[0]" LOC = "F17";
NET "adc_outb_n_i[0]" LOC = "G16";
NET "adc_outb_p_i[0]" LOC = "H16";
NET "adc_outa_n_i[1]" LOC = "E19";
NET "adc_outa_p_i[1]" LOC = "F19";
NET "adc_outb_n_i[1]" LOC = "F18";
NET "adc_outb_p_i[1]" LOC = "G18";
NET "adc_outa_n_i[2]" LOC = "K21";
NET "adc_outa_p_i[2]" LOC = "L21";
NET "adc_outb_n_i[2]" LOC = "L20";
NET "adc_outb_p_i[2]" LOC = "M20";
NET "adc_outa_n_i[3]" LOC = "F22";
NET "adc_outa_p_i[3]" LOC = "G22";
NET "adc_outb_n_i[3]" LOC = "L19";
NET "adc_outb_p_i[3]" LOC = "M19";
NET "adc_spi_din_i[0]" LOC = "F11";
NET "adc_spi_dout_o[0]" LOC = "K11";
NET "adc_spi_sck_o[0]" LOC = "L11";
NET "adc_spi_cs_adc_n_o[0]" LOC = "J13";
NET "adc_spi_cs_dac1_n_o[0]" LOC = "H11";
NET "adc_spi_cs_dac2_n_o[0]" LOC = "G11";
NET "adc_spi_cs_dac3_n_o[0]" LOC = "J12";
NET "adc_spi_cs_dac4_n_o[0]" LOC = "H12";
NET "adc_gpio_dac_clr_n_o[0]" LOC = "H13";
NET "adc_gpio_led_acq_o[0]" LOC = "K12";
NET "adc_gpio_led_trig_o[0]" LOC = "L12";
NET "adc_gpio_ssr_ch1_o[0]" LOC = "L14";
NET "adc_gpio_ssr_ch1_o[1]" LOC = "K14";
NET "adc_gpio_ssr_ch1_o[2]" LOC = "L13";
NET "adc_gpio_ssr_ch1_o[3]" LOC = "E11";
NET "adc_gpio_ssr_ch1_o[4]" LOC = "G10";
NET "adc_gpio_ssr_ch1_o[5]" LOC = "F10";
NET "adc_gpio_ssr_ch1_o[6]" LOC = "F9";
NET "adc_gpio_ssr_ch2_o[0]" LOC = "F15";
NET "adc_gpio_ssr_ch2_o[1]" LOC = "F14";
NET "adc_gpio_ssr_ch2_o[2]" LOC = "F13";
NET "adc_gpio_ssr_ch2_o[3]" LOC = "E13";
NET "adc_gpio_ssr_ch2_o[4]" LOC = "G12";
NET "adc_gpio_ssr_ch2_o[5]" LOC = "M13";
NET "adc_gpio_ssr_ch2_o[6]" LOC = "F12";
NET "adc_gpio_ssr_ch3_o[0]" LOC = "F23";
NET "adc_gpio_ssr_ch3_o[1]" LOC = "E23";
NET "adc_gpio_ssr_ch3_o[2]" LOC = "F21";
NET "adc_gpio_ssr_ch3_o[3]" LOC = "E21";
NET "adc_gpio_ssr_ch3_o[4]" LOC = "G20";
NET "adc_gpio_ssr_ch3_o[5]" LOC = "F20";
NET "adc_gpio_ssr_ch3_o[6]" LOC = "E15";
NET "adc_gpio_ssr_ch4_o[0]" LOC = "J22";
NET "adc_gpio_ssr_ch4_o[1]" LOC = "H22";
NET "adc_gpio_ssr_ch4_o[2]" LOC = "E25";
NET "adc_gpio_ssr_ch4_o[3]" LOC = "D25";
NET "adc_gpio_ssr_ch4_o[4]" LOC = "D24";
NET "adc_gpio_ssr_ch4_o[5]" LOC = "B25";
NET "adc_gpio_ssr_ch4_o[6]" LOC = "C24";
NET "adc_gpio_si570_oe_o[0]" LOC = "A25";
NET "adc_si570_scl_b[0]" LOC = "H14";
NET "adc_si570_sda_b[0]" LOC = "J14";
NET "adc_one_wire_b[0]" LOC = "E9";
# FMC1
NET "adc_ext_trigger_n_i[1]" LOC = "AD16";
NET "adc_ext_trigger_p_i[1]" LOC = "AC16";
NET "adc_dco_n_i[1]" LOC = "AK17";
NET "adc_dco_p_i[1]" LOC = "AJ17";
NET "adc_fr_n_i[1]" LOC = "AH8";
NET "adc_fr_p_i[1]" LOC = "AG8";
NET "adc_outa_n_i[4]" LOC = "AA15";
NET "adc_outa_p_i[4]" LOC = "Y15";
NET "adc_outb_n_i[4]" LOC = "AA17";
NET "adc_outb_p_i[4]" LOC = "Y17";
NET "adc_outa_n_i[5]" LOC = "AC14";
NET "adc_outa_p_i[5]" LOC = "AB14";
NET "adc_outb_n_i[5]" LOC = "AD15";
NET "adc_outb_p_i[5]" LOC = "AC15";
NET "adc_outa_n_i[6]" LOC = "AA14";
NET "adc_outa_p_i[6]" LOC = "Y14";
NET "adc_outb_n_i[6]" LOC = "Y13";
NET "adc_outb_p_i[6]" LOC = "W14";
NET "adc_outa_n_i[7]" LOC = "AE12";
NET "adc_outa_p_i[7]" LOC = "AD12";
NET "adc_outb_n_i[7]" LOC = "AF11";
NET "adc_outb_p_i[7]" LOC = "AE11";
NET "adc_spi_din_i[1]" LOC = "AB17";
NET "adc_spi_dout_o[1]" LOC = "AA21";
NET "adc_spi_sck_o[1]" LOC = "Y21";
NET "adc_spi_cs_adc_n_o[1]" LOC = "W20";
NET "adc_spi_cs_dac1_n_o[1]" LOC = "W19";
NET "adc_spi_cs_dac2_n_o[1]" LOC = "Y19";
NET "adc_spi_cs_dac3_n_o[1]" LOC = "AA19";
NET "adc_spi_cs_dac4_n_o[1]" LOC = "AB19";
NET "adc_gpio_dac_clr_n_o[1]" LOC = "Y20";
NET "adc_gpio_led_acq_o[1]" LOC = "AC22";
NET "adc_gpio_led_trig_o[1]" LOC = "AA22";
NET "adc_gpio_ssr_ch1_o[7]" LOC = "AC19";
NET "adc_gpio_ssr_ch1_o[8]" LOC = "AD19";
NET "adc_gpio_ssr_ch1_o[9]" LOC = "AC20";
NET "adc_gpio_ssr_ch1_o[10]" LOC = "AD17";
NET "adc_gpio_ssr_ch1_o[11]" LOC = "AB21";
NET "adc_gpio_ssr_ch1_o[12]" LOC = "AC21";
NET "adc_gpio_ssr_ch1_o[13]" LOC = "AC24";
NET "adc_gpio_ssr_ch2_o[7]" LOC = "AE19";
NET "adc_gpio_ssr_ch2_o[8]" LOC = "AF23";
NET "adc_gpio_ssr_ch2_o[9]" LOC = "AE24";
NET "adc_gpio_ssr_ch2_o[10]" LOC = "AF24";
NET "adc_gpio_ssr_ch2_o[11]" LOC = "AD22";
NET "adc_gpio_ssr_ch2_o[12]" LOC = "AB20";
NET "adc_gpio_ssr_ch2_o[13]" LOC = "AE22";
NET "adc_gpio_ssr_ch3_o[7]" LOC = "AB12";
NET "adc_gpio_ssr_ch3_o[8]" LOC = "AC12";
NET "adc_gpio_ssr_ch3_o[9]" LOC = "AE15";
NET "adc_gpio_ssr_ch3_o[10]" LOC = "AF15";
NET "adc_gpio_ssr_ch3_o[11]" LOC = "Y16";
NET "adc_gpio_ssr_ch3_o[12]" LOC = "AB16";
NET "adc_gpio_ssr_ch3_o[13]" LOC = "AF19";
NET "adc_gpio_ssr_ch4_o[7]" LOC = "AC11";
NET "adc_gpio_ssr_ch4_o[8]" LOC = "AD11";
NET "adc_gpio_ssr_ch4_o[9]" LOC = "AE13";
NET "adc_gpio_ssr_ch4_o[10]" LOC = "AF13";
NET "adc_gpio_ssr_ch4_o[11]" LOC = "AJ15";
NET "adc_gpio_ssr_ch4_o[12]" LOC = "AD10";
NET "adc_gpio_ssr_ch4_o[13]" LOC = "AK15";
NET "adc_gpio_si570_oe_o[1]" LOC = "AE10";
NET "adc_si570_scl_b[1]" LOC = "AF21";
NET "adc_si570_sda_b[1]" LOC = "AE21";
NET "adc_one_wire_b[1]" LOC = "AD24";
# IO standards
NET "adc_ext_trigger_?_i[*]" IOSTANDARD = "LVDS_25";
NET "adc_dco_?_i[*]" IOSTANDARD = "LVDS_25";
NET "adc_fr_?_i[*]" IOSTANDARD = "LVDS_25";
NET "adc_out?_?_i[*]" IOSTANDARD = "LVDS_25";
NET "adc_spi_din_i[*]" IOSTANDARD = "LVCMOS25";
NET "adc_spi_dout_o[*]" IOSTANDARD = "LVCMOS25";
NET "adc_spi_sck_o[*]" IOSTANDARD = "LVCMOS25";
NET "adc_spi_cs_adc_n_o[*]" IOSTANDARD = "LVCMOS25";
NET "adc_spi_cs_dac?_n_o[*]" IOSTANDARD = "LVCMOS25";
NET "adc_gpio_dac_clr_n_o[*]" IOSTANDARD = "LVCMOS25";
NET "adc_gpio_led_acq_o[*]" IOSTANDARD = "LVCMOS25";
NET "adc_gpio_led_trig_o[*]" IOSTANDARD = "LVCMOS25";
NET "adc_gpio_ssr_ch?_o[*]" IOSTANDARD = "LVCMOS25";
NET "adc_gpio_si570_oe_o[*]" IOSTANDARD = "LVCMOS25";
NET "adc_si570_scl_b[*]" IOSTANDARD = "LVCMOS25";
NET "adc_si570_sda_b[*]" IOSTANDARD = "LVCMOS25";
NET "adc_one_wire_b[*]" IOSTANDARD = "LVCMOS25";
#===============================================================================
# Timing constraints and exceptions
#===============================================================================
# Tightly constrain the location and max delay from the external trigger input
# to its synchroniser. This is needed to have consistent alignment between trigger
# and data across implementations. Note that due to RLOC constraints in the
# gc_sync_ffs, the synchroniser cannot be placed on the single FF of the IOB.
NET "gen_fmc_mezzanine[?].*/*/cmp_ext_trig_sync/gc_sync_ffs_in" MAXDELAY = 2.0 ns;
INST "gen_fmc_mezzanine[0].*/*/cmp_ext_trig_sync/sync0" RLOC_ORIGIN = X66Y189;
INST "gen_fmc_mezzanine[1].*/*/cmp_ext_trig_sync/sync0" RLOC_ORIGIN = X69Y2;
#----------------------------------------
# IOB exceptions
#----------------------------------------
INST "gen_fmc_mezzanine[*].*/cmp_fmc_spi/*/Wrapped_SPI/shift/s_out" IOB = FALSE;
INST "gen_fmc_mezzanine[*].*/cmp_fmc_spi/*/Wrapped_SPI/clgen/clk_out" IOB = FALSE;
INST "gen_fmc_mezzanine[*].*/cmp_fmc_i2c/U_Wrapped_I2C/*" IOB = FALSE;
INST "gen_fmc_mezzanine[*].*/cmp_fmc_onewire/*" IOB = FALSE;
#----------------------------------------
# Clocks
#----------------------------------------
NET "adc_dco_p_i[0]" TNM_NET = adc0_dco;
NET "adc_dco_n_i[0]" TNM_NET = adc0_dco;
TIMESPEC TS_adc0_dco = PERIOD "adc0_dco" 2.5 ns HIGH 50%;
NET "adc_dco_p_i[1]" TNM_NET = adc1_dco;
NET "adc_dco_n_i[1]" TNM_NET = adc1_dco;
TIMESPEC TS_adc1_dco = PERIOD "adc1_dco" 2.5 ns HIGH 50%;
#----------------------------------------
# Cross-clock domain sync
#----------------------------------------
NET "gen_fmc_mezzanine[0].*/cmp_fmc_adc_100Ms_core/fs_clk" TNM_NET = fs0_clk;
NET "gen_fmc_mezzanine[1].*/cmp_fmc_adc_100Ms_core/fs_clk" TNM_NET = fs1_clk;
TIMEGRP "adc0_sync_ffs" = "sync_ffs" EXCEPT "fs0_clk";
TIMEGRP "adc1_sync_ffs" = "sync_ffs" EXCEPT "fs1_clk";
#TIMESPEC TS_adc0_sync_ffs = FROM fs0_clk TO "adc0_sync_ffs" TIG;
#TIMESPEC TS_adc1_sync_ffs = FROM fs1_clk TO "adc1_sync_ffs" TIG;
TIMEGRP "adc0_sync_reg" = "sync_reg" EXCEPT "fs0_clk";
TIMEGRP "adc1_sync_reg" = "sync_reg" EXCEPT "fs1_clk";
TIMESPEC TS_adc0_sync_reg = FROM fs0_clk TO "adc0_sync_reg" 8ns DATAPATHONLY;
TIMESPEC TS_adc1_sync_reg = FROM fs1_clk TO "adc1_sync_reg" 8ns DATAPATHONLY;
# No sync words used in FMC-ADC
#TIMESPEC TS_adc0_sync_word = FROM sync_word TO fs0_clk 30ns DATAPATHONLY;
#TIMESPEC TS_adc1_sync_word = FROM sync_word TO fs1_clk 30ns DATAPATHONLY;
board = "svec"
target = "xilinx"
action = "synthesis"
syn_device = "xc6slx150t"
syn_grade = "-3"
syn_package = "fgg900"
syn_top = "wrtd_ref_svec_fd_x2"
syn_project = "wrtd_ref_svec_fd_x2.xise"
syn_tool = "ise"
# Allow the user to override fetchto using:
# hdlmake -p "fetchto='xxx'"
if locals().get('fetchto', None) is None:
fetchto = "../../../dependencies"
files = [
"wrtd_ref_svec_fd_x2.ucf",
"buildinfo_pkg.vhd",
fetchto + "/fmc-delay-1ns-8cha/hdl/syn/svec/svec-fd0.ucf",
fetchto + "/fmc-delay-1ns-8cha/hdl/syn/svec/svec-fd1.ucf",
]
modules = {
"local" : [
"../../top/wrtd_ref_svec_fd_x2",
],
}
#syn_pre_project_cmd = "make -C ../../../software/firmware"
# Do not fail during hdlmake fetch
try:
exec(open(fetchto + "/general-cores/tools/gen_buildinfo.py").read())
except:
pass
syn_post_project_cmd = "$(TCL_INTERPRETER) syn_extra_steps.tcl $(PROJECT_FILE)"
svec_base_ucf = ['wr', 'led', 'gpio']
ctrls = ["bank4_64b_32b", "bank5_64b_32b"]
# get project file from 1st command-line argument
set project_file [lindex $argv 0]
if {![file exists $project_file]} {
report ERROR "Missing file $project_file, exiting."
exit -1
}
xilinx::project open $project_file
# Some of these are not respected by ISE when passed through hdlmake,
# so we add them all ourselves after creating the project
#
# Not respected by ISE when passed through hdlmake:
# 1. Pack I/O Registers/Latches into IOBs
# 2. Register Duplication Map
xilinx::project set "Enable Multi-Threading" "2" -process "Map"
xilinx::project set "Enable Multi-Threading" "4" -process "Place & Route"
xilinx::project set "Pack I/O Registers into IOBs" "Yes"
xilinx::project set "Pack I/O Registers/Latches into IOBs" "For Inputs and Outputs"
xilinx::project set "Register Balancing" "Yes"
xilinx::project set "Register Duplication Map" "On"
#xilinx::project set "Placer Extra Effort Map" "Normal"
#xilinx::project set "Extra Effort (Highest PAR level only)" "Normal"
xilinx::project save
xilinx::project close
#===============================================================================
# Timing constraints and exceptions
#===============================================================================
NET "fp_gpio3_b" TNM_NET = fp_gpio3;
TIMESPEC TS_fp_gpio3 = PERIOD "fp_gpio3" 100 ns HIGH 50%;
NET "fmc0_fd_clk_ref_n_i" TNM_NET = fmc0_fd_clk_ref_n_i;
TIMESPEC TS_fmc0_fd_clk_ref_n_i = PERIOD "fmc0_fd_clk_ref_n_i" 8 ns HIGH 50%;
NET "fmc1_fd_clk_ref_n_i" TNM_NET = fmc1_fd_clk_ref_n_i;
TIMESPEC TS_fmc1_fd_clk_ref_n_i = PERIOD "fmc1_fd_clk_ref_n_i" 8 ns HIGH 50%;
#----------------------------------------
# Cross-clock domain sync
#----------------------------------------
# IMPORTANT: timing constraints are also coming from SVEC base UCF files
# Declaration of domains
NET "dcm0_clk_ref_0" TNM_NET = fd0_clk;
NET "dcm1_clk_ref_0" TNM_NET = fd1_clk;
# Exceptions for crossings via gc_sync_ffs
#TIMEGRP "fdl_sync_ffs" = "sync_ffs" EXCEPT "fdl_clk";
#TIMEGRP "tdc_sync_ffs" = "sync_ffs" EXCEPT "tdc_clk";
#TIMESPEC TS_fdl_sync_ffs = FROM fdl_clk TO "fdl_sync_ffs" TIG;
#TIMESPEC TS_tdc_sync_ffs = FROM tdc_clk TO "tdc_sync_ffs" TIG;
# Exceptions for crossings via gc_sync_register
#TIMEGRP "fdl_sync_reg" = "sync_reg" EXCEPT "fdl_clk";
#TIMEGRP "tdc_sync_reg" = "sync_reg" EXCEPT "tdc_clk";
#TIMESPEC TS_fdl_sync_reg = FROM fdl_clk TO "fdl_sync_reg" 8ns DATAPATHONLY;
#TIMESPEC TS_tdc_sync_reg = FROM tdc_clk TO "tdc_sync_reg" 8ns DATAPATHONLY;
board = "svec"
target = "xilinx"
action = "synthesis"
syn_device = "xc6slx150t"
syn_grade = "-3"
syn_package = "fgg900"
syn_top = "wrtd_ref_svec_tdc_x2"
syn_project = "wrtd_ref_svec_tdc_x2.xise"
syn_tool = "ise"
# Allow the user to override fetchto using:
# hdlmake -p "fetchto='xxx'"
if locals().get('fetchto', None) is None:
fetchto = "../../../dependencies"
files = [
"buildinfo_pkg.vhd",
fetchto + "/fmc-tdc/hdl/syn/svec/svec-tdc0.ucf",
fetchto + "/fmc-tdc/hdl/syn/svec/svec-tdc1.ucf",
"wrtd_ref_svec_tdc_x2.ucf",
]
modules = {
"local" : [
"../../top/wrtd_ref_svec_tdc_x2",
],
}
syn_pre_project_cmd = "make -C ../../../software/firmware"
# Do not fail during hdlmake fetch
try:
exec(open(fetchto + "/general-cores/tools/gen_buildinfo.py").read())
except:
pass
syn_post_project_cmd = "$(TCL_INTERPRETER) syn_extra_steps.tcl $(PROJECT_FILE)"
svec_base_ucf = ['wr', 'led', 'gpio']
ctrls = ["bank4_64b_32b", "bank5_64b_32b"]
# get project file from 1st command-line argument
set project_file [lindex $argv 0]
if {![file exists $project_file]} {
report ERROR "Missing file $project_file, exiting."
exit -1
}
xilinx::project open $project_file
# Some of these are not respected by ISE when passed through hdlmake,
# so we add them all ourselves after creating the project
#
# Not respected by ISE when passed through hdlmake:
# 1. Pack I/O Registers/Latches into IOBs
# 2. Register Duplication Map
xilinx::project set "Enable Multi-Threading" "2" -process "Map"
xilinx::project set "Enable Multi-Threading" "4" -process "Place & Route"
xilinx::project set "Pack I/O Registers into IOBs" "Yes"
xilinx::project set "Pack I/O Registers/Latches into IOBs" "For Inputs and Outputs"
xilinx::project set "Register Balancing" "Yes"
xilinx::project set "Register Duplication Map" "On"
#xilinx::project set "Placer Extra Effort Map" "Normal"
#xilinx::project set "Extra Effort (Highest PAR level only)" "Normal"
xilinx::project save
xilinx::project close
#===============================================================================
# Timing constraints and exceptions
#===============================================================================
NET "fp_gpio3_b" TNM_NET = fp_gpio3;
TIMESPEC TS_fp_gpio3 = PERIOD "fp_gpio3" 100 ns HIGH 50%;
NET "fmc0_tdc_clk_125m_n_i" TNM_NET = fmc0_tdc_clk_125m_n_i;
TIMESPEC TS_fmc0_tdc_clk_125m_n_i = PERIOD "fmc0_tdc_clk_125m_n_i" 8 ns HIGH 50%;
NET "fmc1_tdc_clk_125m_n_i" TNM_NET = fmc1_tdc_clk_125m_n_i;
TIMESPEC TS_fmc1_tdc_clk_125m_n_i = PERIOD "fmc1_tdc_clk_125m_n_i" 8 ns HIGH 50%;
#----------------------------------------
# Cross-clock domain sync
#----------------------------------------
# IMPORTANT: timing constraints are also coming from SVEC base UCF files
# Declaration of domains
NET "tdc0_clk_125m" TNM_NET = tdc0_clk;
NET "tdc1_clk_125m" TNM_NET = tdc1_clk;
# Exceptions for crossings via gc_sync_ffs
TIMEGRP "tdc0_sync_ffs" = "sync_ffs" EXCEPT "tdc0_clk";
#TIMESPEC TS_tdc_sync_ffs = FROM tdc_clk TO "tdc_sync_ffs" TIG;
# Exceptions for crossings via gc_sync_register
#TIMEGRP "tdc_sync_reg" = "sync_reg" EXCEPT "tdc_clk";
#TIMESPEC TS_tdc_sync_reg = FROM tdc_clk TO "tdc_sync_reg" 8ns DATAPATHONLY;
......@@ -18,7 +18,7 @@ include_dirs = [
fetchto + "/gn4124-core/hdl/sim/gn4124_bfm",
fetchto + "/general-cores/sim",
fetchto + "/mock-turtle/hdl/testbench/include",
fetchto + "/fmc-adc-100m14b4cha-gw/hdl/testbench/include",
fetchto + "/fmc-adc-100m14b4cha/hdl/testbench/include",
]
files = [
......
......@@ -241,7 +241,7 @@ module dut_env
always@(negedge clk_400m_adc)
begin
#625ps;
if(adc_div == 1) begin
if(adc_div == 3) begin
adc0_fr <= ~adc0_fr;
adc_div <= 0;
end
......
......@@ -27,12 +27,21 @@
`include "gn4124_bfm.svh"
`include "wrtd_driver.svh"
`include "fmc_adc_mezzanine_mmap.v"
`include "fmc_adc_100Ms_csr.v"
`include "fmc_adc_100Ms_channel_regs.v"
`include "fmc_adc_eic_regs.v"
`define DMA_BASE 'h00c0
`define VIC_BASE 'h0100
`define ADC_CSR_BASE 'h5000
`define ADC_EIC_BASE 'h5500
`define ADC_OFFSET 'h4000
`define ADC_CSR_BASE `ADC_OFFSET + `ADDR_FMC_ADC_MEZZANINE_MMAP_FMC_ADC_100M_CSR
`define ADC_EIC_BASE `ADC_OFFSET + `ADDR_FMC_ADC_MEZZANINE_MMAP_FMC_ADC_EIC
`define ADC_CH1_BASE `ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_FMC_ADC_CH1
`define ADC_CH2_BASE `ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_FMC_ADC_CH2
`define ADC_CH3_BASE `ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_FMC_ADC_CH3
`define ADC_CH4_BASE `ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_FMC_ADC_CH4
module main;
......@@ -69,6 +78,7 @@ module main;
begin
accA = hostA.get_accessor();
accA.set_default_xfer_size(4);
devA = new (accA, MT_BASE, MtIrqMonitorA, "DUT:A");
devA.init();
devA.add_rule ( "rule0" );
......@@ -83,17 +93,17 @@ module main;
accA.write(`VIC_BASE + 'h0, 'h1);
// Config DUTA to trigger on external trigger and get 64 samples
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_PRE_SAMPLES, 'h00);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_POST_SAMPLES, 'h40);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_SHOTS, 'h01);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH1_CALIB, 'h8000);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH2_CALIB, 'h8000);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH3_CALIB, 'h8000);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH4_CALIB, 'h8000);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH1_SAT, 'h7fff);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH2_SAT, 'h7fff);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH3_SAT, 'h7fff);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH4_SAT, 'h7fff);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_PRE_SAMPLES, 'h0000);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_POST_SAMPLES, 'h0040);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_SHOTS, 'h0001);
accA.write(`ADC_CH1_BASE + `ADDR_FMC_ADC_100MS_CHANNEL_REGS_CALIB, 'h8000);
accA.write(`ADC_CH2_BASE + `ADDR_FMC_ADC_100MS_CHANNEL_REGS_CALIB, 'h8000);
accA.write(`ADC_CH3_BASE + `ADDR_FMC_ADC_100MS_CHANNEL_REGS_CALIB, 'h8000);
accA.write(`ADC_CH4_BASE + `ADDR_FMC_ADC_100MS_CHANNEL_REGS_CALIB, 'h8000);
accA.write(`ADC_CH1_BASE + `ADDR_FMC_ADC_100MS_CHANNEL_REGS_SAT, 'h7fff);
accA.write(`ADC_CH2_BASE + `ADDR_FMC_ADC_100MS_CHANNEL_REGS_SAT, 'h7fff);
accA.write(`ADC_CH3_BASE + `ADDR_FMC_ADC_100MS_CHANNEL_REGS_SAT, 'h7fff);
accA.write(`ADC_CH4_BASE + `ADDR_FMC_ADC_100MS_CHANNEL_REGS_SAT, 'h7fff);
val = (1'b1 << `FMC_ADC_100MS_CSR_TRIG_EN_EXT_OFFSET);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_TRIG_EN, val);
......@@ -123,17 +133,17 @@ module main;
accB.write(`VIC_BASE + 'h0, 'h1);
// Config DUTB to trigger on WRTD and get 64 samples
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_PRE_SAMPLES, 'h00);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_POST_SAMPLES, 'h40);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_SHOTS, 'h01);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH1_CALIB, 'h8000);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH2_CALIB, 'h8000);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH3_CALIB, 'h8000);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH4_CALIB, 'h8000);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH1_SAT, 'h7fff);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH2_SAT, 'h7fff);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH3_SAT, 'h7fff);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH4_SAT, 'h7fff);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_PRE_SAMPLES, 'h0000);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_POST_SAMPLES, 'h0040);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_SHOTS, 'h0001);
accB.write(`ADC_CH1_BASE + `ADDR_FMC_ADC_100MS_CHANNEL_REGS_CALIB, 'h8000);
accB.write(`ADC_CH2_BASE + `ADDR_FMC_ADC_100MS_CHANNEL_REGS_CALIB, 'h8000);
accB.write(`ADC_CH3_BASE + `ADDR_FMC_ADC_100MS_CHANNEL_REGS_CALIB, 'h8000);
accB.write(`ADC_CH4_BASE + `ADDR_FMC_ADC_100MS_CHANNEL_REGS_CALIB, 'h8000);
accB.write(`ADC_CH1_BASE + `ADDR_FMC_ADC_100MS_CHANNEL_REGS_SAT, 'h7fff);
accB.write(`ADC_CH2_BASE + `ADDR_FMC_ADC_100MS_CHANNEL_REGS_SAT, 'h7fff);
accB.write(`ADC_CH3_BASE + `ADDR_FMC_ADC_100MS_CHANNEL_REGS_SAT, 'h7fff);
accB.write(`ADC_CH4_BASE + `ADDR_FMC_ADC_100MS_CHANNEL_REGS_SAT, 'h7fff);
expected = 'h39;
accB.read(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_STA, val);
......
......@@ -13,6 +13,6 @@ modules = {
"https://ohwr.org/project/ddr3-sp6-core.git",
"https://ohwr.org/project/gn4124-core.git",
"https://ohwr.org/project/spec.git",
"https://ohwr.org/project/fmc-adc-100m14b4cha-gw.git",
"https://ohwr.org/project/fmc-adc-100m14b4cha.git",
],
}
......@@ -290,10 +290,6 @@ architecture arch of wrtd_ref_spec150t_adc is
signal cnx_slave_out : t_wishbone_slave_out_array(c_NUM_WB_SLAVES-1 downto 0);
signal cnx_slave_in : t_wishbone_slave_in_array(c_NUM_WB_SLAVES-1 downto 0);
-- GN4124 core DMA port to DDR wishbone bus
signal gn_wb_ddr_in : t_wishbone_master_in;
signal gn_wb_ddr_out : t_wishbone_master_out;
-- MT endpoints
signal rmq_endpoint_out : t_mt_rmq_endpoint_iface_out;
signal rmq_endpoint_in : t_mt_rmq_endpoint_iface_in;
......@@ -677,9 +673,6 @@ begin -- architecture arch
mezz_one_wire_b => fmc0_adc_one_wire_b,
sys_scl_b => fmc0_scl_b,
sys_sda_b => fmc0_sda_b,
wr_tm_link_up_i => tm_link_up,
wr_tm_time_valid_i => tm_time_valid_sync,
wr_tm_tai_i => tm_tai,
......
files = [
"wrtd_ref_svec_adc_x2.vhd",
"wrtd_adc_x2_host_map.vhd",
"wrtd_adc_x2_fmc_map.vhd",
]
fetchto = "../../../dependencies"
modules = {
"git" : [
"https://ohwr.org/project/svec.git",
"https://ohwr.org/project/general-cores.git",
"https://ohwr.org/project/wr-cores.git",
"https://ohwr.org/project/vme64x-core.git",
"https://ohwr.org/project/urv-core.git",
"https://ohwr.org/project/mock-turtle.git",
"https://ohwr.org/project/fmc-adc-100m14b4cha.git",
"https://ohwr.org/project/ddr3-sp6-core.git",
],
}
# SPDX-FileCopyrightText: 2020 CERN (home.cern)
#
# SPDX-License-Identifier: CC-BY-SA-4.0 OR CERN-OHL-W-2.0+ OR GPL-2.0-or-later
memory-map:
name: wrtd_adc_x2_fmc_map
bus: wb-32-be
description: WRTD ADC x2 dedicated peripheral map
size: 0x4000
x-hdl:
busgroup: True
pipeline: wr,rd
children:
- submap:
name: adc0_trigin
address: 0x0000
size: 0x1000
description: FMC ADC0 trigin
interface: wb-32-be
x-hdl:
busgroup: True
- submap:
name: adc0_trigout
address: 0x1000
size: 0x1000
description: FMC ADC0 trigout
interface: wb-32-be
x-hdl:
busgroup: True
- submap:
name: adc1_trigin
address: 0x2000
size: 0x1000
description: FMC ADC1 trigin
interface: wb-32-be
x-hdl:
busgroup: True
- submap:
name: adc1_trigout
address: 0x3000
size: 0x1000
description: FMC ADC1 trigout
interface: wb-32-be
x-hdl:
busgroup: True
-- Do not edit. Generated on Thu Feb 25 09:17:02 2021 by tgingold
-- With Cheby 1.4.dev0 and these options:
-- --gen-hdl=wrtd_adc_x2_fmc_map.vhd -i wrtd_adc_x2_fmc_map.cheby
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
entity wrtd_adc_x2_fmc_map is
port (
rst_n_i : in std_logic;
clk_i : in std_logic;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out;
-- FMC ADC0 trigin
adc0_trigin_i : in t_wishbone_master_in;
adc0_trigin_o : out t_wishbone_master_out;
-- FMC ADC0 trigout
adc0_trigout_i : in t_wishbone_master_in;
adc0_trigout_o : out t_wishbone_master_out;
-- FMC ADC1 trigin
adc1_trigin_i : in t_wishbone_master_in;
adc1_trigin_o : out t_wishbone_master_out;
-- FMC ADC1 trigout
adc1_trigout_i : in t_wishbone_master_in;
adc1_trigout_o : out t_wishbone_master_out
);
end wrtd_adc_x2_fmc_map;
architecture syn of wrtd_adc_x2_fmc_map is
signal adr_int : std_logic_vector(13 downto 2);
signal rd_req_int : std_logic;
signal wr_req_int : std_logic;
signal rd_ack_int : std_logic;
signal wr_ack_int : std_logic;
signal wb_en : std_logic;
signal ack_int : std_logic;
signal wb_rip : std_logic;
signal wb_wip : std_logic;
signal adc0_trigin_re : std_logic;
signal adc0_trigin_we : std_logic;
signal adc0_trigin_wt : std_logic;
signal adc0_trigin_rt : std_logic;
signal adc0_trigin_tr : std_logic;
signal adc0_trigin_wack : std_logic;
signal adc0_trigin_rack : std_logic;
signal adc0_trigout_re : std_logic;
signal adc0_trigout_we : std_logic;
signal adc0_trigout_wt : std_logic;
signal adc0_trigout_rt : std_logic;
signal adc0_trigout_tr : std_logic;
signal adc0_trigout_wack : std_logic;
signal adc0_trigout_rack : std_logic;
signal adc1_trigin_re : std_logic;
signal adc1_trigin_we : std_logic;
signal adc1_trigin_wt : std_logic;
signal adc1_trigin_rt : std_logic;
signal adc1_trigin_tr : std_logic;
signal adc1_trigin_wack : std_logic;
signal adc1_trigin_rack : std_logic;
signal adc1_trigout_re : std_logic;
signal adc1_trigout_we : std_logic;
signal adc1_trigout_wt : std_logic;
signal adc1_trigout_rt : std_logic;
signal adc1_trigout_tr : std_logic;
signal adc1_trigout_wack : std_logic;
signal adc1_trigout_rack : std_logic;
signal rd_req_d0 : std_logic;
signal rd_adr_d0 : std_logic_vector(13 downto 2);
signal rd_ack_d0 : std_logic;
signal rd_dat_d0 : std_logic_vector(31 downto 0);
signal wr_req_d0 : std_logic;
signal wr_dat_d0 : std_logic_vector(31 downto 0);
signal wr_sel_d0 : std_logic_vector(3 downto 0);
signal wr_ack_d0 : std_logic;
begin
-- WB decode signals
adr_int <= wb_i.adr(13 downto 2);
wb_en <= wb_i.cyc and wb_i.stb;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_rip <= '0';
else
wb_rip <= (wb_rip or (wb_en and not wb_i.we)) and not rd_ack_int;
end if;
end if;
end process;
rd_req_int <= (wb_en and not wb_i.we) and not wb_rip;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_wip <= '0';
else
wb_wip <= (wb_wip or (wb_en and wb_i.we)) and not wr_ack_int;
end if;
end if;
end process;
wr_req_int <= (wb_en and wb_i.we) and not wb_wip;
ack_int <= rd_ack_int or wr_ack_int;
wb_o.ack <= ack_int;
wb_o.stall <= not ack_int and wb_en;
wb_o.rty <= '0';
wb_o.err <= '0';
-- pipelining for rd-in+rd-out+wr-in+wr-out
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
rd_req_d0 <= '0';
rd_ack_int <= '0';
wr_req_d0 <= '0';
wr_ack_int <= '0';
else
rd_req_d0 <= rd_req_int;
rd_adr_d0 <= adr_int;
rd_ack_int <= rd_ack_d0;
wb_o.dat <= rd_dat_d0;
wr_req_d0 <= wr_req_int;
wr_dat_d0 <= wb_i.dat;
wr_sel_d0 <= wb_i.sel;
wr_ack_int <= wr_ack_d0;
end if;
end if;
end process;
-- Interface adc0_trigin
adc0_trigin_tr <= adc0_trigin_wt or adc0_trigin_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
adc0_trigin_rt <= '0';
adc0_trigin_wt <= '0';
else
adc0_trigin_rt <= (adc0_trigin_rt or adc0_trigin_re) and not adc0_trigin_rack;
adc0_trigin_wt <= (adc0_trigin_wt or adc0_trigin_we) and not adc0_trigin_wack;
end if;
end if;
end process;
adc0_trigin_o.cyc <= adc0_trigin_tr;
adc0_trigin_o.stb <= adc0_trigin_tr;
adc0_trigin_wack <= adc0_trigin_i.ack and adc0_trigin_wt;
adc0_trigin_rack <= adc0_trigin_i.ack and adc0_trigin_rt;
adc0_trigin_o.adr <= ((19 downto 0 => '0') & rd_adr_d0(11 downto 2)) & (1 downto 0 => '0');
adc0_trigin_o.sel <= wr_sel_d0;
adc0_trigin_o.we <= adc0_trigin_wt;
adc0_trigin_o.dat <= wr_dat_d0;
-- Interface adc0_trigout
adc0_trigout_tr <= adc0_trigout_wt or adc0_trigout_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
adc0_trigout_rt <= '0';
adc0_trigout_wt <= '0';
else
adc0_trigout_rt <= (adc0_trigout_rt or adc0_trigout_re) and not adc0_trigout_rack;
adc0_trigout_wt <= (adc0_trigout_wt or adc0_trigout_we) and not adc0_trigout_wack;
end if;
end if;
end process;
adc0_trigout_o.cyc <= adc0_trigout_tr;
adc0_trigout_o.stb <= adc0_trigout_tr;
adc0_trigout_wack <= adc0_trigout_i.ack and adc0_trigout_wt;
adc0_trigout_rack <= adc0_trigout_i.ack and adc0_trigout_rt;
adc0_trigout_o.adr <= ((19 downto 0 => '0') & rd_adr_d0(11 downto 2)) & (1 downto 0 => '0');
adc0_trigout_o.sel <= wr_sel_d0;
adc0_trigout_o.we <= adc0_trigout_wt;
adc0_trigout_o.dat <= wr_dat_d0;
-- Interface adc1_trigin
adc1_trigin_tr <= adc1_trigin_wt or adc1_trigin_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
adc1_trigin_rt <= '0';
adc1_trigin_wt <= '0';
else
adc1_trigin_rt <= (adc1_trigin_rt or adc1_trigin_re) and not adc1_trigin_rack;
adc1_trigin_wt <= (adc1_trigin_wt or adc1_trigin_we) and not adc1_trigin_wack;
end if;
end if;
end process;
adc1_trigin_o.cyc <= adc1_trigin_tr;
adc1_trigin_o.stb <= adc1_trigin_tr;
adc1_trigin_wack <= adc1_trigin_i.ack and adc1_trigin_wt;
adc1_trigin_rack <= adc1_trigin_i.ack and adc1_trigin_rt;
adc1_trigin_o.adr <= ((19 downto 0 => '0') & rd_adr_d0(11 downto 2)) & (1 downto 0 => '0');
adc1_trigin_o.sel <= wr_sel_d0;
adc1_trigin_o.we <= adc1_trigin_wt;
adc1_trigin_o.dat <= wr_dat_d0;
-- Interface adc1_trigout
adc1_trigout_tr <= adc1_trigout_wt or adc1_trigout_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
adc1_trigout_rt <= '0';
adc1_trigout_wt <= '0';
else
adc1_trigout_rt <= (adc1_trigout_rt or adc1_trigout_re) and not adc1_trigout_rack;
adc1_trigout_wt <= (adc1_trigout_wt or adc1_trigout_we) and not adc1_trigout_wack;
end if;
end if;
end process;
adc1_trigout_o.cyc <= adc1_trigout_tr;
adc1_trigout_o.stb <= adc1_trigout_tr;
adc1_trigout_wack <= adc1_trigout_i.ack and adc1_trigout_wt;
adc1_trigout_rack <= adc1_trigout_i.ack and adc1_trigout_rt;
adc1_trigout_o.adr <= ((19 downto 0 => '0') & rd_adr_d0(11 downto 2)) & (1 downto 0 => '0');
adc1_trigout_o.sel <= wr_sel_d0;
adc1_trigout_o.we <= adc1_trigout_wt;
adc1_trigout_o.dat <= wr_dat_d0;
-- Process for write requests.
process (rd_adr_d0, wr_req_d0, adc0_trigin_wack, adc0_trigout_wack, adc1_trigin_wack, adc1_trigout_wack) begin
adc0_trigin_we <= '0';
adc0_trigout_we <= '0';
adc1_trigin_we <= '0';
adc1_trigout_we <= '0';
case rd_adr_d0(13 downto 12) is
when "00" =>
-- Submap adc0_trigin
adc0_trigin_we <= wr_req_d0;
wr_ack_d0 <= adc0_trigin_wack;
when "01" =>
-- Submap adc0_trigout
adc0_trigout_we <= wr_req_d0;
wr_ack_d0 <= adc0_trigout_wack;
when "10" =>
-- Submap adc1_trigin
adc1_trigin_we <= wr_req_d0;
wr_ack_d0 <= adc1_trigin_wack;
when "11" =>
-- Submap adc1_trigout
adc1_trigout_we <= wr_req_d0;
wr_ack_d0 <= adc1_trigout_wack;
when others =>
wr_ack_d0 <= wr_req_d0;
end case;
end process;
-- Process for read requests.
process (rd_adr_d0, rd_req_d0, adc0_trigin_i.dat, adc0_trigin_rack, adc0_trigout_i.dat, adc0_trigout_rack, adc1_trigin_i.dat, adc1_trigin_rack, adc1_trigout_i.dat, adc1_trigout_rack) begin
-- By default ack read requests
rd_dat_d0 <= (others => 'X');
adc0_trigin_re <= '0';
adc0_trigout_re <= '0';
adc1_trigin_re <= '0';
adc1_trigout_re <= '0';
case rd_adr_d0(13 downto 12) is
when "00" =>
-- Submap adc0_trigin
adc0_trigin_re <= rd_req_d0;
rd_dat_d0 <= adc0_trigin_i.dat;
rd_ack_d0 <= adc0_trigin_rack;
when "01" =>
-- Submap adc0_trigout
adc0_trigout_re <= rd_req_d0;
rd_dat_d0 <= adc0_trigout_i.dat;
rd_ack_d0 <= adc0_trigout_rack;
when "10" =>
-- Submap adc1_trigin
adc1_trigin_re <= rd_req_d0;
rd_dat_d0 <= adc1_trigin_i.dat;
rd_ack_d0 <= adc1_trigin_rack;
when "11" =>
-- Submap adc1_trigout
adc1_trigout_re <= rd_req_d0;
rd_dat_d0 <= adc1_trigout_i.dat;
rd_ack_d0 <= adc1_trigout_rack;
when others =>
rd_ack_d0 <= rd_req_d0;
end case;
end process;
end syn;
# SPDX-FileCopyrightText: 2020 CERN (home.cern)
#
# SPDX-License-Identifier: CC-BY-SA-4.0 OR CERN-OHL-W-2.0+ OR GPL-2.0-or-later
memory-map:
name: wrtd_adc_x2_host_map
bus: wb-32-be
description: WRTD FMC-ADC-100M memory map
size: 0x40000
x-hdl:
busgroup: True
pipeline: wr,rd
children:
- submap:
name: metadata
address: 0x4000
size: 0x40
interface: wb-32-be
x-hdl:
busgroup: True
description: a ROM containing the application metadata
- submap:
name: adc0
address: 0x6000
size: 0x2000
description: FMC ADC Mezzanine slot 1
interface: wb-32-be
x-hdl:
busgroup: True
- submap:
name: adc1
address: 0x8000
size: 0x2000
description: FMC ADC Mezzanine slot 2
interface: wb-32-be
x-hdl:
busgroup: True
- submap:
name: mt
address: 0x20000
size: 0x20000
description: Mock-turtle
interface: wb-32-be
x-hdl:
busgroup: True
-- Do not edit. Generated on Thu Feb 25 09:14:33 2021 by tgingold
-- With Cheby 1.4.dev0 and these options:
-- --gen-hdl=wrtd_adc_x2_host_map.vhd -i wrtd_adc_x2_host_map.cheby
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
entity wrtd_adc_x2_host_map is
port (
rst_n_i : in std_logic;
clk_i : in std_logic;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out;
-- a ROM containing the application metadata
metadata_i : in t_wishbone_master_in;
metadata_o : out t_wishbone_master_out;
-- FMC ADC Mezzanine slot 1
adc0_i : in t_wishbone_master_in;
adc0_o : out t_wishbone_master_out;
-- FMC ADC Mezzanine slot 2
adc1_i : in t_wishbone_master_in;
adc1_o : out t_wishbone_master_out;
-- Mock-turtle
mt_i : in t_wishbone_master_in;
mt_o : out t_wishbone_master_out
);
end wrtd_adc_x2_host_map;
architecture syn of wrtd_adc_x2_host_map is
signal adr_int : std_logic_vector(17 downto 2);
signal rd_req_int : std_logic;
signal wr_req_int : std_logic;
signal rd_ack_int : std_logic;
signal wr_ack_int : std_logic;
signal wb_en : std_logic;
signal ack_int : std_logic;
signal wb_rip : std_logic;
signal wb_wip : std_logic;
signal metadata_re : std_logic;
signal metadata_we : std_logic;
signal metadata_wt : std_logic;
signal metadata_rt : std_logic;
signal metadata_tr : std_logic;
signal metadata_wack : std_logic;
signal metadata_rack : std_logic;
signal adc0_re : std_logic;
signal adc0_we : std_logic;
signal adc0_wt : std_logic;
signal adc0_rt : std_logic;
signal adc0_tr : std_logic;
signal adc0_wack : std_logic;
signal adc0_rack : std_logic;
signal adc1_re : std_logic;
signal adc1_we : std_logic;
signal adc1_wt : std_logic;
signal adc1_rt : std_logic;
signal adc1_tr : std_logic;
signal adc1_wack : std_logic;
signal adc1_rack : std_logic;
signal mt_re : std_logic;
signal mt_we : std_logic;
signal mt_wt : std_logic;
signal mt_rt : std_logic;
signal mt_tr : std_logic;
signal mt_wack : std_logic;
signal mt_rack : std_logic;
signal rd_req_d0 : std_logic;
signal rd_adr_d0 : std_logic_vector(17 downto 2);
signal rd_ack_d0 : std_logic;
signal rd_dat_d0 : std_logic_vector(31 downto 0);
signal wr_req_d0 : std_logic;
signal wr_dat_d0 : std_logic_vector(31 downto 0);
signal wr_sel_d0 : std_logic_vector(3 downto 0);
signal wr_ack_d0 : std_logic;
begin
-- WB decode signals
adr_int <= wb_i.adr(17 downto 2);
wb_en <= wb_i.cyc and wb_i.stb;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_rip <= '0';
else
wb_rip <= (wb_rip or (wb_en and not wb_i.we)) and not rd_ack_int;
end if;
end if;
end process;
rd_req_int <= (wb_en and not wb_i.we) and not wb_rip;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_wip <= '0';
else
wb_wip <= (wb_wip or (wb_en and wb_i.we)) and not wr_ack_int;
end if;
end if;
end process;
wr_req_int <= (wb_en and wb_i.we) and not wb_wip;
ack_int <= rd_ack_int or wr_ack_int;
wb_o.ack <= ack_int;
wb_o.stall <= not ack_int and wb_en;
wb_o.rty <= '0';
wb_o.err <= '0';
-- pipelining for rd-in+rd-out+wr-in+wr-out
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
rd_req_d0 <= '0';
rd_ack_int <= '0';
wr_req_d0 <= '0';
wr_ack_int <= '0';
else
rd_req_d0 <= rd_req_int;
rd_adr_d0 <= adr_int;
rd_ack_int <= rd_ack_d0;
wb_o.dat <= rd_dat_d0;
wr_req_d0 <= wr_req_int;
wr_dat_d0 <= wb_i.dat;
wr_sel_d0 <= wb_i.sel;
wr_ack_int <= wr_ack_d0;
end if;
end if;
end process;
-- Interface metadata
metadata_tr <= metadata_wt or metadata_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
metadata_rt <= '0';
metadata_wt <= '0';
else
metadata_rt <= (metadata_rt or metadata_re) and not metadata_rack;
metadata_wt <= (metadata_wt or metadata_we) and not metadata_wack;
end if;
end if;
end process;
metadata_o.cyc <= metadata_tr;
metadata_o.stb <= metadata_tr;
metadata_wack <= metadata_i.ack and metadata_wt;
metadata_rack <= metadata_i.ack and metadata_rt;
metadata_o.adr <= ((25 downto 0 => '0') & rd_adr_d0(5 downto 2)) & (1 downto 0 => '0');
metadata_o.sel <= wr_sel_d0;
metadata_o.we <= metadata_wt;
metadata_o.dat <= wr_dat_d0;
-- Interface adc0
adc0_tr <= adc0_wt or adc0_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
adc0_rt <= '0';
adc0_wt <= '0';
else
adc0_rt <= (adc0_rt or adc0_re) and not adc0_rack;
adc0_wt <= (adc0_wt or adc0_we) and not adc0_wack;
end if;
end if;
end process;
adc0_o.cyc <= adc0_tr;
adc0_o.stb <= adc0_tr;
adc0_wack <= adc0_i.ack and adc0_wt;
adc0_rack <= adc0_i.ack and adc0_rt;
adc0_o.adr <= ((18 downto 0 => '0') & rd_adr_d0(12 downto 2)) & (1 downto 0 => '0');
adc0_o.sel <= wr_sel_d0;
adc0_o.we <= adc0_wt;
adc0_o.dat <= wr_dat_d0;
-- Interface adc1
adc1_tr <= adc1_wt or adc1_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
adc1_rt <= '0';
adc1_wt <= '0';
else
adc1_rt <= (adc1_rt or adc1_re) and not adc1_rack;
adc1_wt <= (adc1_wt or adc1_we) and not adc1_wack;
end if;
end if;
end process;
adc1_o.cyc <= adc1_tr;
adc1_o.stb <= adc1_tr;
adc1_wack <= adc1_i.ack and adc1_wt;
adc1_rack <= adc1_i.ack and adc1_rt;
adc1_o.adr <= ((18 downto 0 => '0') & rd_adr_d0(12 downto 2)) & (1 downto 0 => '0');
adc1_o.sel <= wr_sel_d0;
adc1_o.we <= adc1_wt;
adc1_o.dat <= wr_dat_d0;
-- Interface mt
mt_tr <= mt_wt or mt_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
mt_rt <= '0';
mt_wt <= '0';
else
mt_rt <= (mt_rt or mt_re) and not mt_rack;
mt_wt <= (mt_wt or mt_we) and not mt_wack;
end if;
end if;
end process;
mt_o.cyc <= mt_tr;
mt_o.stb <= mt_tr;
mt_wack <= mt_i.ack and mt_wt;
mt_rack <= mt_i.ack and mt_rt;
mt_o.adr <= ((14 downto 0 => '0') & rd_adr_d0(16 downto 2)) & (1 downto 0 => '0');
mt_o.sel <= wr_sel_d0;
mt_o.we <= mt_wt;
mt_o.dat <= wr_dat_d0;
-- Process for write requests.
process (rd_adr_d0, wr_req_d0, metadata_wack, adc0_wack, adc1_wack, mt_wack) begin
metadata_we <= '0';
adc0_we <= '0';
adc1_we <= '0';
mt_we <= '0';
case rd_adr_d0(17 downto 17) is
when "0" =>
case rd_adr_d0(16 downto 13) is
when "0010" =>
-- Submap metadata
metadata_we <= wr_req_d0;
wr_ack_d0 <= metadata_wack;
when "0011" =>
-- Submap adc0
adc0_we <= wr_req_d0;
wr_ack_d0 <= adc0_wack;
when "0100" =>
-- Submap adc1
adc1_we <= wr_req_d0;
wr_ack_d0 <= adc1_wack;
when others =>
wr_ack_d0 <= wr_req_d0;
end case;
when "1" =>
-- Submap mt
mt_we <= wr_req_d0;
wr_ack_d0 <= mt_wack;
when others =>
wr_ack_d0 <= wr_req_d0;
end case;
end process;
-- Process for read requests.
process (rd_adr_d0, rd_req_d0, metadata_i.dat, metadata_rack, adc0_i.dat, adc0_rack, adc1_i.dat, adc1_rack, mt_i.dat, mt_rack) begin
-- By default ack read requests
rd_dat_d0 <= (others => 'X');
metadata_re <= '0';
adc0_re <= '0';
adc1_re <= '0';
mt_re <= '0';
case rd_adr_d0(17 downto 17) is
when "0" =>
case rd_adr_d0(16 downto 13) is
when "0010" =>
-- Submap metadata
metadata_re <= rd_req_d0;
rd_dat_d0 <= metadata_i.dat;
rd_ack_d0 <= metadata_rack;
when "0011" =>
-- Submap adc0
adc0_re <= rd_req_d0;
rd_dat_d0 <= adc0_i.dat;
rd_ack_d0 <= adc0_rack;
when "0100" =>
-- Submap adc1
adc1_re <= rd_req_d0;
rd_dat_d0 <= adc1_i.dat;
rd_ack_d0 <= adc1_rack;
when others =>
rd_ack_d0 <= rd_req_d0;
end case;
when "1" =>
-- Submap mt
mt_re <= rd_req_d0;
rd_dat_d0 <= mt_i.dat;
rd_ack_d0 <= mt_rack;
when others =>
rd_ack_d0 <= rd_req_d0;
end case;
end process;
end syn;
-------------------------------------------------------------------------------
-- SPDX-License-Identifier: CERN-OHL-W-2.0+
-- Title : FMC ADC 100Ms/s SVEC top-level
-- Project : FMC ADC 100M 14B 4CHA gateware
-- URL : http://www.ohwr.org/projects/fmc-adc-100m14b4cha-gw
-------------------------------------------------------------------------------
-- File : svec_ref_fmc_adc_100Ms.vhd
-- Company : CERN (BE-CO-HT)
-- Created : 2013-07-04
-- Standard : VHDL'93/02
-------------------------------------------------------------------------------
-- Description: Top entity of FMC ADC 100Ms/s design for Simple VME FMC
-- Carrier (SVEC). See also: http://www.ohwr.org/projects/svec
-------------------------------------------------------------------------------
-- Copyright (c) 2013-2020 CERN (BE-CO-HT)
-------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
library UNISIM;
use UNISIM.vcomponents.all;
library work;
use work.gencores_pkg.all;
use work.wishbone_pkg.all;
use work.fmc_adc_mezzanine_pkg.all;
use work.wr_board_pkg.all;
use work.mt_mqueue_pkg.all;
use work.mock_turtle_pkg.all;
use work.wr_fabric_pkg.all;
entity wrtd_ref_svec_adc_x2 is
generic(
g_SIMULATION : integer := 0;
g_NB_FMC_SLOTS : natural := 2;
g_MULTISHOT_RAM_SIZE : natural := 8192;
g_WRPC_INITF : string := "../../../../wr-cores/bin/wrpc/wrc_phy8.bram";
g_MT_CPU0_INITF : string := "../../../software/firmware/adc-x2/wrtd-rt-adc-x2.bram");
port
(
-- Reset from system fpga
rst_n_i : in std_logic;
-- Local oscillators
clk_20m_vcxo_i : in std_logic; -- 20MHz VCXO clock
clk_125m_pllref_p_i : in std_logic; -- 125 MHz PLL reference
clk_125m_pllref_n_i : in std_logic;
clk_125m_gtp_n_i : in std_logic; -- 125 MHz GTP reference
clk_125m_gtp_p_i : in std_logic;
-- DAC interface (20MHz and 25MHz VCXO)
pll20dac_din_o : out std_logic;
pll20dac_sclk_o : out std_logic;
pll20dac_sync_n_o : out std_logic;
pll25dac_din_o : out std_logic;
pll25dac_sclk_o : out std_logic;
pll25dac_sync_n_o : out std_logic;
-- Carrier front panel LEDs
fp_led_line_oen_o : out std_logic_vector(1 downto 0);
fp_led_line_o : out std_logic_vector(1 downto 0);
fp_led_column_o : out std_logic_vector(3 downto 0);
-- Carrier I2C eeprom
carrier_scl_b : inout std_logic;
carrier_sda_b : inout std_logic;
-- PCB revision
pcbrev_i : in std_logic_vector(4 downto 0);
-- Carrier 1-wire interface (DS18B20 thermometer + unique ID)
onewire_b : inout std_logic;
-- SFP
sfp_txp_o : out std_logic;
sfp_txn_o : out std_logic;
sfp_rxp_i : in std_logic;
sfp_rxn_i : in std_logic;
sfp_mod_def0_i : in std_logic; -- sfp detect
sfp_mod_def1_b : inout std_logic; -- scl
sfp_mod_def2_b : inout std_logic; -- sda
sfp_rate_select_o : out std_logic;
sfp_tx_fault_i : in std_logic;
sfp_tx_disable_o : out std_logic;
sfp_los_i : in std_logic;
-- SPI
spi_sclk_o : out std_logic;
spi_ncs_o : out std_logic;
spi_mosi_o : out std_logic;
spi_miso_i : in std_logic := 'L';
-- UART
uart_rxd_i : in std_logic;
uart_txd_o : out std_logic;
-- GPIO
fp_gpio1_b : out std_logic; -- PPS output
fp_gpio2_b : out std_logic; -- not used
fp_gpio3_b : in std_logic; -- ext 10MHz clock input
fp_gpio4_b : in std_logic; -- ext PPS input
fp_term_en_o : out std_logic_vector(4 downto 1);
fp_gpio1_a2b_o : out std_logic;
fp_gpio2_a2b_o : out std_logic;
fp_gpio34_a2b_o : out std_logic;
------------------------------------------
-- VME interface
------------------------------------------
vme_write_n_i : in std_logic;
vme_sysreset_n_i : in std_logic;
vme_retry_oe_o : out std_logic;
vme_retry_n_o : out std_logic;
vme_lword_n_b : inout std_logic;
vme_iackout_n_o : out std_logic;
vme_iackin_n_i : in std_logic;
vme_iack_n_i : in std_logic;
vme_gap_i : in std_logic;
vme_dtack_oe_o : out std_logic;
vme_dtack_n_o : out std_logic;
vme_ds_n_i : in std_logic_vector(1 downto 0);
vme_data_oe_n_o : out std_logic;
vme_data_dir_o : out std_logic;
vme_berr_o : out std_logic;
vme_as_n_i : in std_logic;
vme_addr_oe_n_o : out std_logic;
vme_addr_dir_o : out std_logic;
vme_irq_o : out std_logic_vector(7 downto 1);
vme_ga_i : in std_logic_vector(4 downto 0);
vme_data_b : inout std_logic_vector(31 downto 0);
vme_am_i : in std_logic_vector(5 downto 0);
vme_addr_b : inout std_logic_vector(31 downto 1);
------------------------------------------
-- DDR (banks 4 and 5)
------------------------------------------
ddr4_a_o : out std_logic_vector(13 downto 0);
ddr4_ba_o : out std_logic_vector(2 downto 0);
ddr4_cas_n_o : out std_logic;
ddr4_ck_n_o : out std_logic;
ddr4_ck_p_o : out std_logic;
ddr4_cke_o : out std_logic;
ddr4_dq_b : inout std_logic_vector(15 downto 0);
ddr4_ldm_o : out std_logic;
ddr4_ldqs_n_b : inout std_logic;
ddr4_ldqs_p_b : inout std_logic;
ddr4_odt_o : out std_logic;
ddr4_ras_n_o : out std_logic;
ddr4_reset_n_o : out std_logic;
ddr4_rzq_b : inout std_logic;
ddr4_udm_o : out std_logic;
ddr4_udqs_n_b : inout std_logic;
ddr4_udqs_p_b : inout std_logic;
ddr4_we_n_o : out std_logic;
ddr5_a_o : out std_logic_vector(13 downto 0);
ddr5_ba_o : out std_logic_vector(2 downto 0);
ddr5_cas_n_o : out std_logic;
ddr5_ck_n_o : out std_logic;
ddr5_ck_p_o : out std_logic;
ddr5_cke_o : out std_logic;
ddr5_dq_b : inout std_logic_vector(15 downto 0);
ddr5_ldm_o : out std_logic;
ddr5_ldqs_n_b : inout std_logic;
ddr5_ldqs_p_b : inout std_logic;
ddr5_odt_o : out std_logic;
ddr5_ras_n_o : out std_logic;
ddr5_reset_n_o : out std_logic;
ddr5_rzq_b : inout std_logic;
ddr5_udm_o : out std_logic;
ddr5_udqs_n_b : inout std_logic;
ddr5_udqs_p_b : inout std_logic;
ddr5_we_n_o : out std_logic;
------------------------------------------
-- FMC slots
------------------------------------------
adc_ext_trigger_p_i : in std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- External trigger
adc_ext_trigger_n_i : in std_logic_vector(g_NB_FMC_SLOTS-1 downto 0);
adc_dco_p_i : in std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- ADC data clock
adc_dco_n_i : in std_logic_vector(g_NB_FMC_SLOTS-1 downto 0);
adc_fr_p_i : in std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- ADC frame start
adc_fr_n_i : in std_logic_vector(g_NB_FMC_SLOTS-1 downto 0);
adc_outa_p_i : in std_logic_vector(4*g_NB_FMC_SLOTS-1 downto 0); -- ADC serial data (odd bits)
adc_outa_n_i : in std_logic_vector(4*g_NB_FMC_SLOTS-1 downto 0);
adc_outb_p_i : in std_logic_vector(4*g_NB_FMC_SLOTS-1 downto 0); -- ADC serial data (even bits)
adc_outb_n_i : in std_logic_vector(4*g_NB_FMC_SLOTS-1 downto 0);
adc_spi_din_i : in std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- SPI data from FMC
adc_spi_dout_o : out std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- SPI data to FMC
adc_spi_sck_o : out std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- SPI clock
adc_spi_cs_adc_n_o : out std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- SPI ADC chip select (active low)
adc_spi_cs_dac1_n_o : out std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- SPI channel 1 offset DAC chip select (active low)
adc_spi_cs_dac2_n_o : out std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- SPI channel 2 offset DAC chip select (active low)
adc_spi_cs_dac3_n_o : out std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- SPI channel 3 offset DAC chip select (active low)
adc_spi_cs_dac4_n_o : out std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- SPI channel 4 offset DAC chip select (active low)
adc_gpio_dac_clr_n_o : out std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- offset DACs clear (active low)
adc_gpio_led_acq_o : out std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- Mezzanine front panel power LED (PWR)
adc_gpio_led_trig_o : out std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- Mezzanine front panel trigger LED (TRIG)
adc_gpio_ssr_ch1_o : out std_logic_vector(7*g_NB_FMC_SLOTS-1 downto 0); -- Channel 1 solid state relays control
adc_gpio_ssr_ch2_o : out std_logic_vector(7*g_NB_FMC_SLOTS-1 downto 0); -- Channel 2 solid state relays control
adc_gpio_ssr_ch3_o : out std_logic_vector(7*g_NB_FMC_SLOTS-1 downto 0); -- Channel 3 solid state relays control
adc_gpio_ssr_ch4_o : out std_logic_vector(7*g_NB_FMC_SLOTS-1 downto 0); -- Channel 4 solid state relays control
adc_gpio_si570_oe_o : out std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- Si570 (programmable oscillator) output enable
adc_si570_scl_b : inout std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- I2C bus clock (Si570)
adc_si570_sda_b : inout std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- I2C bus data (Si570)
adc_one_wire_b : inout std_logic_vector(g_NB_FMC_SLOTS-1 downto 0); -- Mezzanine 1-wire interface (DS18B20 thermometer + unique ID)
------------------------------------------
-- FMC slot management
------------------------------------------
fmc0_prsnt_m2c_n_i : in std_logic;
fmc1_prsnt_m2c_n_i : in std_logic;
fmc0_scl_b : inout std_logic;
fmc0_sda_b : inout std_logic;
fmc1_scl_b : inout std_logic;
fmc1_sda_b : inout std_logic);
end wrtd_ref_svec_adc_x2;
architecture arch of wrtd_ref_svec_adc_x2 is
-- WRTD Node identification (WTN2)
constant c_WRTD_NODE_ID : std_logic_vector(31 downto 0) := x"5754_4E05";
-- Convention metadata base address
constant c_METADATA_ADDR : t_wishbone_address := x"0000_4000";
constant c_MT_CONFIG : t_mt_config :=
(
app_id => c_WRTD_NODE_ID,
cpu_count => 1,
cpu_config => (
0 => (
memsize => 4096,
hmq_config => (
slot_count => 1,
slot_config => (
0 => (
entries_bits => 4,
width_bits => 7,
header_bits => 2,
endpoint_id => x"0000_0000",
enable_config_space => FALSE),
others => c_DUMMY_MT_MQUEUE_SLOT)),
rmq_config => (
slot_count => 1,
slot_config => (
0 => (
entries_bits => 4,
width_bits => 7,
header_bits => 4,
endpoint_id => x"0000_0000",
enable_config_space => TRUE),
others => c_DUMMY_MT_MQUEUE_SLOT))),
others => (
0, c_MT_DEFAULT_MQUEUE_CONFIG, c_MT_DEFAULT_MQUEUE_CONFIG)),
shared_mem_size => 256
);
------------------------------------------------------------------------------
-- Signals declaration
------------------------------------------------------------------------------
subtype t_fmc_slot_vec is std_logic_vector(g_NB_FMC_SLOTS-1 downto 0);
-- Clocks and resets
signal clk_sys_62m5 : std_logic;
signal clk_ref_125m : std_logic;
signal clk_ext_ref : std_logic;
signal rst_sys_62m5_n : std_logic := '0';
signal rst_ref_125m_n : std_logic := '0';
signal areset_n : std_logic := '0';
-- MT endpoints
signal rmq_endpoint_out : t_mt_rmq_endpoint_iface_out;
signal rmq_endpoint_in : t_mt_rmq_endpoint_iface_in;
signal rmq_src_in : t_mt_stream_source_in;
signal rmq_src_out : t_mt_stream_source_out;
signal rmq_src_cfg_in : t_mt_stream_config_in;
signal rmq_src_cfg_out : t_mt_stream_config_out;
signal rmq_snk_in : t_mt_stream_sink_in;
signal rmq_snk_out : t_mt_stream_sink_out;
signal rmq_snk_cfg_in : t_mt_stream_config_in;
signal rmq_snk_cfg_out : t_mt_stream_config_out;
-- MT fabric.
signal eth_tx_out : t_wrf_source_out;
signal eth_tx_in : t_wrf_source_in;
signal eth_rx_out : t_wrf_sink_out;
signal eth_rx_in : t_wrf_sink_in;
-- MT Dedicated WB interfaces to FMCs
signal fmc_dp_wb_out : t_wishbone_master_out_array(0 to 0);
signal fmc_dp_wb_in : t_wishbone_master_in_array(0 to 0);
-- Wishbone buse(s) from master(s) to crossbar slave port(s)
signal host_wb_out : t_wishbone_master_out;
signal host_wb_in : t_wishbone_master_in;
signal mt_wb_out : t_wishbone_master_out;
signal mt_wb_in : t_wishbone_master_in;
signal metadata_wb_out : t_wishbone_master_out;
signal metadata_wb_in : t_wishbone_master_in;
-- Wishbone buse(s) from crossbar master port(s) to slave(s)
signal adc_wb_out : t_wishbone_slave_out_array(1 downto 0);
signal adc_wb_in : t_wishbone_slave_in_array(1 downto 0);
-- Wishbone bus from cross-clocking module to FMC mezzanines
signal cnx_fmc_sync_master_out : t_wishbone_master_out_array(g_NB_FMC_SLOTS-1 downto 0);
signal cnx_fmc_sync_master_in : t_wishbone_master_in_array(g_NB_FMC_SLOTS-1 downto 0);
-- Wishbone buses from FMC ADC cores to DDR controller
signal fmc_wb_ddr_in : t_wishbone_master_data64_in_array(g_NB_FMC_SLOTS-1 downto 0);
signal fmc_wb_ddr_out : t_wishbone_master_data64_out_array(g_NB_FMC_SLOTS-1 downto 0);
-- Wishbone bus from MT cpus to adc.
signal wb_adc_trigin_slave_out : t_wishbone_slave_out_array(g_NB_FMC_SLOTS - 1 downto 0);
signal wb_adc_trigin_slave_in : t_wishbone_slave_in_array(g_NB_FMC_SLOTS - 1 downto 0);
signal wb_adc_trigout_slave_out : t_wishbone_slave_out_array(g_NB_FMC_SLOTS - 1 downto 0);
signal wb_adc_trigout_slave_in : t_wishbone_slave_in_array(g_NB_FMC_SLOTS - 1 downto 0);
type t_fmc_acq_led is array (0 to g_NB_FMC_SLOTS-1) of std_logic_vector(1 downto 0);
-- Interrupts and status
signal ddr_wr_fifo_empty : t_fmc_slot_vec;
signal ddr_wr_fifo_empty_sync : t_fmc_slot_vec;
signal fmc_irq : t_fmc_slot_vec;
signal fmc_acq_trig : t_fmc_slot_vec;
signal fmc_acq_trig_sync : t_fmc_slot_vec;
signal fmc_acq_cfg_ok : t_fmc_slot_vec;
signal fmc_acq_cfg_ok_sync : t_fmc_slot_vec;
signal fmc_acq_led : t_fmc_acq_led;
signal irq_vector : std_logic_vector(5 downto 0);
signal vme_access : std_logic;
-- Front panel LED control
signal svec_led : std_logic_vector(15 downto 0);
-- WR PTP core timing interface
signal tm_link_up : std_logic;
signal tm_tai : std_logic_vector(39 downto 0);
signal tm_cycles : std_logic_vector(27 downto 0);
signal tm_time_valid : std_logic;
signal tm_time_valid_sync : std_logic;
signal wrabbit_en : std_logic;
signal pps : std_logic;
signal pps_led : std_logic;
signal pps_ext_in : std_logic;
signal wr_led_link : std_logic;
signal wr_led_act : std_logic;
-- MT TM interface
signal tm : t_mt_timing_if;
begin -- architecture arch
areset_n <= vme_sysreset_n_i and rst_n_i;
------------------------------------------------------------------------------
-- Application-specific metadata ROM
------------------------------------------------------------------------------
cmp_xwb_metadata : entity work.xwb_metadata
generic map (
g_VENDOR_ID => x"0000_10DC",
g_DEVICE_ID => c_WRTD_NODE_ID,
g_VERSION => x"0500_0002",
g_CAPABILITIES => x"0000_0000",
g_COMMIT_ID => (others => '0'))
port map (
clk_i => clk_sys_62m5,
rst_n_i => rst_sys_62m5_n,
wb_i => metadata_wb_out,
wb_o => metadata_wb_in);
inst_svec_base : entity work.svec_base_wr
generic map (
g_DECODE_AM => FALSE,
g_WITH_VIC => TRUE,
g_WITH_ONEWIRE => FALSE,
g_WITH_SPI => FALSE,
g_WITH_WR => TRUE,
g_WITH_DDR4 => TRUE,
g_WITH_DDR5 => TRUE,
g_APP_OFFSET => c_METADATA_ADDR,
g_NUM_USER_IRQ => 6,
g_DPRAM_INITF => g_WRPC_INITF,
g_AUX_CLKS => 0,
g_FABRIC_IFACE => plain,
g_SIMULATION => g_SIMULATION)
port map (
rst_n_i => areset_n,
clk_125m_pllref_p_i => clk_125m_pllref_p_i,
clk_125m_pllref_n_i => clk_125m_pllref_n_i,
clk_20m_vcxo_i => clk_20m_vcxo_i,
clk_125m_gtp_n_i => clk_125m_gtp_n_i,
clk_125m_gtp_p_i => clk_125m_gtp_p_i,
clk_10m_ext_i => clk_ext_ref,
pps_ext_i => pps_ext_in,
vme_write_n_i => vme_write_n_i,
vme_sysreset_n_i => vme_sysreset_n_i,
vme_retry_oe_o => vme_retry_oe_o,
vme_retry_n_o => vme_retry_n_o,
vme_lword_n_b => vme_lword_n_b,
vme_iackout_n_o => vme_iackout_n_o,
vme_iackin_n_i => vme_iackin_n_i,
vme_iack_n_i => vme_iack_n_i,
vme_gap_i => vme_gap_i,
vme_dtack_oe_o => vme_dtack_oe_o,
vme_dtack_n_o => vme_dtack_n_o,
vme_ds_n_i => vme_ds_n_i,
vme_data_oe_n_o => vme_data_oe_n_o,
vme_data_dir_o => vme_data_dir_o,
vme_berr_o => vme_berr_o,
vme_as_n_i => vme_as_n_i,
vme_addr_oe_n_o => vme_addr_oe_n_o,
vme_addr_dir_o => vme_addr_dir_o,
vme_irq_o => vme_irq_o,
vme_ga_i => vme_ga_i,
vme_data_b => vme_data_b,
vme_am_i => vme_am_i,
vme_addr_b => vme_addr_b,
fmc0_scl_b => fmc0_scl_b,
fmc0_sda_b => fmc0_sda_b,
fmc1_scl_b => fmc1_scl_b,
fmc1_sda_b => fmc1_sda_b,
fmc0_prsnt_m2c_n_i => fmc0_prsnt_m2c_n_i,
fmc1_prsnt_m2c_n_i => fmc1_prsnt_m2c_n_i,
onewire_b => onewire_b,
carrier_scl_b => carrier_scl_b,
carrier_sda_b => carrier_sda_b,
spi_sclk_o => spi_sclk_o,
spi_ncs_o => spi_ncs_o,
spi_mosi_o => spi_mosi_o,
spi_miso_i => spi_miso_i,
uart_rxd_i => uart_rxd_i,
uart_txd_o => uart_txd_o,
plldac_sclk_o => pll20dac_sclk_o,
plldac_din_o => pll20dac_din_o,
pll20dac_din_o => pll20dac_din_o,
pll20dac_sclk_o => pll20dac_sclk_o,
pll20dac_sync_n_o => pll20dac_sync_n_o,
pll25dac_din_o => pll25dac_din_o,
pll25dac_sclk_o => pll25dac_sclk_o,
pll25dac_sync_n_o => pll25dac_sync_n_o,
sfp_txp_o => sfp_txp_o,
sfp_txn_o => sfp_txn_o,
sfp_rxp_i => sfp_rxp_i,
sfp_rxn_i => sfp_rxn_i,
sfp_mod_def0_i => sfp_mod_def0_i,
sfp_mod_def1_b => sfp_mod_def1_b,
sfp_mod_def2_b => sfp_mod_def2_b,
sfp_rate_select_o => sfp_rate_select_o,
sfp_tx_fault_i => sfp_tx_fault_i,
sfp_tx_disable_o => sfp_tx_disable_o,
sfp_los_i => sfp_los_i,
ddr4_a_o => ddr4_a_o,
ddr4_ba_o => ddr4_ba_o,
ddr4_cas_n_o => ddr4_cas_n_o,
ddr4_ck_n_o => ddr4_ck_n_o,
ddr4_ck_p_o => ddr4_ck_p_o,
ddr4_cke_o => ddr4_cke_o,
ddr4_dq_b => ddr4_dq_b,
ddr4_ldm_o => ddr4_ldm_o,
ddr4_ldqs_n_b => ddr4_ldqs_n_b,
ddr4_ldqs_p_b => ddr4_ldqs_p_b,
ddr4_odt_o => ddr4_odt_o,
ddr4_ras_n_o => ddr4_ras_n_o,
ddr4_reset_n_o => ddr4_reset_n_o,
ddr4_rzq_b => ddr4_rzq_b,
ddr4_udm_o => ddr4_udm_o,
ddr4_udqs_n_b => ddr4_udqs_n_b,
ddr4_udqs_p_b => ddr4_udqs_p_b,
ddr4_we_n_o => ddr4_we_n_o,
ddr5_a_o => ddr5_a_o,
ddr5_ba_o => ddr5_ba_o,
ddr5_cas_n_o => ddr5_cas_n_o,
ddr5_ck_n_o => ddr5_ck_n_o,
ddr5_ck_p_o => ddr5_ck_p_o,
ddr5_cke_o => ddr5_cke_o,
ddr5_dq_b => ddr5_dq_b,
ddr5_ldm_o => ddr5_ldm_o,
ddr5_ldqs_n_b => ddr5_ldqs_n_b,
ddr5_ldqs_p_b => ddr5_ldqs_p_b,
ddr5_odt_o => ddr5_odt_o,
ddr5_ras_n_o => ddr5_ras_n_o,
ddr5_reset_n_o => ddr5_reset_n_o,
ddr5_rzq_b => ddr5_rzq_b,
ddr5_udm_o => ddr5_udm_o,
ddr5_udqs_n_b => ddr5_udqs_n_b,
ddr5_udqs_p_b => ddr5_udqs_p_b,
ddr5_we_n_o => ddr5_we_n_o,
pcbrev_i => pcbrev_i,
ddr4_clk_i => clk_ref_125m,
ddr4_rst_n_i => rst_ref_125m_n,
ddr4_wb_i => fmc_wb_ddr_out(0),
ddr4_wb_o => fmc_wb_ddr_in(0),
ddr5_clk_i => clk_ref_125m,
ddr5_rst_n_i => rst_ref_125m_n,
ddr5_wb_i => fmc_wb_ddr_out(1),
ddr5_wb_o => fmc_wb_ddr_in(1),
ddr4_wr_fifo_empty_o => ddr_wr_fifo_empty(0),
ddr5_wr_fifo_empty_o => ddr_wr_fifo_empty(1),
clk_sys_62m5_o => clk_sys_62m5,
rst_sys_62m5_n_o => rst_sys_62m5_n,
clk_ref_125m_o => clk_ref_125m,
rst_ref_125m_n_o => rst_ref_125m_n,
irq_user_i => irq_vector,
wrf_src_o => eth_rx_in,
wrf_src_i => eth_rx_out,
wrf_snk_o => eth_tx_in,
wrf_snk_i => eth_tx_out,
tm_link_up_o => tm_link_up,
tm_time_valid_o => tm_time_valid,
tm_tai_o => tm_tai,
tm_cycles_o => tm_cycles,
pps_p_o => pps,
pps_led_o => pps_led,
link_ok_o => wrabbit_en,
led_link_o => wr_led_link,
led_act_o => wr_led_act,
app_wb_o => host_wb_out,
app_wb_i => host_wb_in);
------------------------------------------------------------------------------
-- Primary wishbone crossbar
------------------------------------------------------------------------------
inst_host_map : entity work.wrtd_adc_x2_host_map
port map (
rst_n_i => rst_sys_62m5_n,
clk_i => clk_sys_62m5,
wb_i => host_wb_out,
wb_o => host_wb_in,
metadata_i => metadata_wb_in,
metadata_o => metadata_wb_out,
adc0_i => adc_wb_out(0),
adc0_o => adc_wb_in(0),
adc1_i => adc_wb_out(1),
adc1_o => adc_wb_in(1),
mt_i => mt_wb_in,
mt_o => mt_wb_out);
-----------------------------------------------------------------------------
-- Mock Turtle (WB Slave)
-----------------------------------------------------------------------------
cmp_mock_turtle : entity work.mock_turtle_core
generic map (
g_CONFIG => c_MT_CONFIG,
g_CPU0_IRAM_INITF => g_MT_CPU0_INITF,
g_WITH_WHITE_RABBIT => TRUE)
port map (
clk_i => clk_sys_62m5,
rst_n_i => rst_sys_62m5_n,
sp_master_o => open,
sp_master_i => c_DUMMY_WB_MASTER_IN,
dp_master_o => fmc_dp_wb_out,
dp_master_i => fmc_dp_wb_in,
rmq_endpoint_o => rmq_endpoint_out,
rmq_endpoint_i => rmq_endpoint_in,
host_slave_i => mt_wb_out,
host_slave_o => mt_wb_in,
clk_ref_i => clk_ref_125m,
tm_i => tm,
hmq_in_irq_o => irq_vector(2),
hmq_out_irq_o => irq_vector(3),
notify_irq_o => irq_vector(5),
console_irq_o => irq_vector(4));
tm.cycles <= tm_cycles;
tm.tai <= tm_tai;
tm.time_valid <= tm_time_valid;
tm.link_up <= tm_link_up;
tm.aux_locked(7 downto 0) <= (others => '0');
cmp_eth_endpoint : entity work.mt_ep_ethernet_single
port map (
clk_i => clk_sys_62m5,
rst_n_i => rst_sys_62m5_n,
rmq_src_i => rmq_src_in,
rmq_src_o => rmq_src_out,
rmq_src_config_i => rmq_snk_cfg_out,
rmq_src_config_o => rmq_snk_cfg_in,
rmq_snk_i => rmq_snk_in,
rmq_snk_o => rmq_snk_out,
rmq_snk_config_i => rmq_src_cfg_out,
rmq_snk_config_o => rmq_src_cfg_in,
eth_src_o => eth_tx_out,
eth_src_i => eth_tx_in,
eth_snk_o => eth_rx_out,
eth_snk_i => eth_rx_in);
p_rmq_assign : process (rmq_endpoint_out, rmq_snk_cfg_in, rmq_snk_out,
rmq_src_cfg_in, rmq_src_out) is
begin
rmq_endpoint_in <= c_MT_RMQ_ENDPOINT_IFACE_IN_DEFAULT_VALUE;
-- WR->MT (RX, to MT CPU0)
rmq_src_in <= rmq_endpoint_out.snk_out(0)(0);
rmq_endpoint_in.snk_in(0)(0) <= rmq_src_out;
rmq_snk_cfg_out <= rmq_endpoint_out.snk_config_out(0)(0);
rmq_endpoint_in.snk_config_in(0)(0) <= rmq_snk_cfg_in;
-- MT->WR (TX, from MT CPU0)
rmq_snk_in <= rmq_endpoint_out.src_out(0)(0);
rmq_endpoint_in.src_in(0)(0) <= rmq_snk_out;
rmq_src_cfg_out <= rmq_endpoint_out.src_config_out(0)(0);
rmq_endpoint_in.src_config_in(0)(0) <= rmq_src_cfg_in;
end process p_rmq_assign;
inst_fmc_map: entity work.wrtd_adc_x2_fmc_map
port map (
rst_n_i => rst_sys_62m5_n,
clk_i => clk_sys_62m5,
wb_i => fmc_dp_wb_out(0),
wb_o => fmc_dp_wb_in(0),
adc0_trigin_i => wb_adc_trigin_slave_out(0),
adc0_trigin_o => wb_adc_trigin_slave_in(0),
adc0_trigout_i => wb_adc_trigout_slave_out(0),
adc0_trigout_o => wb_adc_trigout_slave_in(0),
adc1_trigin_i => wb_adc_trigin_slave_out(1),
adc1_trigin_o => wb_adc_trigin_slave_in(1),
adc1_trigout_i => wb_adc_trigout_slave_out(1),
adc1_trigout_o => wb_adc_trigout_slave_in(1)
);
------------------------------------------------------------------------------
-- FMC ADC mezzanines (wb bridge with cross-clocking)
-- Mezzanine system managment I2C master
-- Mezzanine SPI master
-- Mezzanine I2C
-- ADC core
-- Mezzanine 1-wire master
------------------------------------------------------------------------------
cmp_tm_time_valid_sync : gc_sync
port map (
clk_i => clk_ref_125m,
rst_n_a_i => '1',
d_i => tm_time_valid,
q_o => tm_time_valid_sync);
gen_fmc_mezzanine : for I in 0 to g_NB_FMC_SLOTS - 1 generate
cmp_xwb_clock_bridge : xwb_clock_bridge
generic map (
g_SLAVE_PORT_WB_MODE => CLASSIC,
g_MASTER_PORT_WB_MODE => PIPELINED)
port map (
slave_clk_i => clk_sys_62m5,
slave_rst_n_i => rst_sys_62m5_n,
slave_i => adc_wb_in(I),
slave_o => adc_wb_out(I),
master_clk_i => clk_ref_125m,
master_rst_n_i => rst_ref_125m_n,
master_i => cnx_fmc_sync_master_in(I),
master_o => cnx_fmc_sync_master_out(I));
cmp_fmc_ddr_wr_fifo_sync : gc_sync
port map (
clk_i => clk_ref_125m,
rst_n_a_i => '1',
d_i => ddr_wr_fifo_empty(I),
q_o => ddr_wr_fifo_empty_sync(I));
cmp_fmc_irq_sync : gc_sync
port map (
clk_i => clk_sys_62m5,
rst_n_a_i => '1',
d_i => fmc_irq(I),
q_o => irq_vector(I));
cmp_fmc_adc_mezzanine : entity work.fmc_adc_mezzanine
generic map (
g_MULTISHOT_RAM_SIZE => g_MULTISHOT_RAM_SIZE,
g_SPARTAN6_USE_PLL => TRUE,
g_FMC_ADC_NR => I,
-- g_BYTE_SWAP => True,
g_WB_MODE => PIPELINED,
g_WB_GRANULARITY => BYTE)
port map (
sys_clk_i => clk_ref_125m,
sys_rst_n_i => rst_ref_125m_n,
wb_csr_slave_i => cnx_fmc_sync_master_out(I),
wb_csr_slave_o => cnx_fmc_sync_master_in(I),
wb_ddr_clk_i => clk_ref_125m,
wb_ddr_rst_n_i => rst_ref_125m_n,
wb_ddr_master_i => fmc_wb_ddr_in(I),
wb_ddr_master_o => fmc_wb_ddr_out(I),
ddr_wr_fifo_empty_i => ddr_wr_fifo_empty_sync(I),
trig_irq_o => fmc_acq_trig(I),
acq_end_irq_o => open,
eic_irq_o => fmc_irq(I),
acq_cfg_ok_o => fmc_acq_cfg_ok(I),
wb_trigin_slave_i => wb_adc_trigin_slave_in(I),
wb_trigin_slave_o => wb_adc_trigin_slave_out(I),
wb_trigout_slave_i => wb_adc_trigout_slave_in(I),
wb_trigout_slave_o => wb_adc_trigout_slave_out(I),
ext_trigger_p_i => adc_ext_trigger_p_i(I),
ext_trigger_n_i => adc_ext_trigger_n_i(I),
adc_dco_p_i => adc_dco_p_i(I),
adc_dco_n_i => adc_dco_n_i(I),
adc_fr_p_i => adc_fr_p_i(I),
adc_fr_n_i => adc_fr_n_i(I),
adc_outa_p_i => adc_outa_p_i(4*(I+1)-1 downto 4*I),
adc_outa_n_i => adc_outa_n_i(4*(I+1)-1 downto 4*I),
adc_outb_p_i => adc_outb_p_i(4*(I+1)-1 downto 4*I),
adc_outb_n_i => adc_outb_n_i(4*(I+1)-1 downto 4*I),
gpio_dac_clr_n_o => adc_gpio_dac_clr_n_o(I),
gpio_led_acq_o => adc_gpio_led_acq_o(I),
gpio_led_trig_o => adc_gpio_led_trig_o(I),
gpio_ssr_ch1_o => adc_gpio_ssr_ch1_o(7*(I+1)-1 downto 7*I),
gpio_ssr_ch2_o => adc_gpio_ssr_ch2_o(7*(I+1)-1 downto 7*I),
gpio_ssr_ch3_o => adc_gpio_ssr_ch3_o(7*(I+1)-1 downto 7*I),
gpio_ssr_ch4_o => adc_gpio_ssr_ch4_o(7*(I+1)-1 downto 7*I),
gpio_si570_oe_o => adc_gpio_si570_oe_o(I),
spi_din_i => adc_spi_din_i(I),
spi_dout_o => adc_spi_dout_o(I),
spi_sck_o => adc_spi_sck_o(I),
spi_cs_adc_n_o => adc_spi_cs_adc_n_o(I),
spi_cs_dac1_n_o => adc_spi_cs_dac1_n_o(I),
spi_cs_dac2_n_o => adc_spi_cs_dac2_n_o(I),
spi_cs_dac3_n_o => adc_spi_cs_dac3_n_o(I),
spi_cs_dac4_n_o => adc_spi_cs_dac4_n_o(I),
si570_scl_b => adc_si570_scl_b(I),
si570_sda_b => adc_si570_sda_b(I),
mezz_one_wire_b => adc_one_wire_b(I),
wr_tm_link_up_i => tm_link_up,
wr_tm_time_valid_i => tm_time_valid_sync,
wr_tm_tai_i => tm_tai,
wr_tm_cycles_i => tm_cycles,
wr_enable_i => wrabbit_en);
end generate gen_fmc_mezzanine;
------------------------------------------------------------------------------
-- Carrier front panel LEDs and LEMOs
------------------------------------------------------------------------------
cmp_led_controller : gc_bicolor_led_ctrl
generic map(
g_nb_column => 4,
g_nb_line => 2,
g_clk_freq => 62500000, -- in Hz
g_refresh_rate => 250) -- in Hz
port map(
rst_n_i => rst_sys_62m5_n,
clk_i => clk_sys_62m5,
led_intensity_i => "1100100", -- in %
led_state_i => svec_led,
column_o => fp_led_column_o,
line_o => fp_led_line_o,
line_oen_o => fp_led_line_oen_o);
cmp_vme_access_led : gc_extend_pulse
generic map (
g_width => 2500000)
port map (
clk_i => clk_sys_62m5,
rst_n_i => rst_sys_62m5_n,
pulse_i => host_wb_out.cyc,
extended_o => vme_access);
gen_fmc_led : for I in 0 to g_NB_FMC_SLOTS - 1 generate
cmp_fmc_cfg_ok_sync : gc_sync
port map (
clk_i => clk_sys_62m5,
rst_n_a_i => '1',
d_i => fmc_acq_cfg_ok(I),
q_o => fmc_acq_cfg_ok_sync(I));
cmp_fmc_trig_sync : gc_sync
port map (
clk_i => clk_sys_62m5,
rst_n_a_i => '1',
d_i => fmc_acq_trig(I),
q_o => fmc_acq_trig_sync(I));
p_fmc_acq_led: process (fmc_acq_cfg_ok_sync, fmc_acq_trig_sync) is
begin
if fmc_acq_cfg_ok_sync(I) = '0' then
fmc_acq_led(I) <= c_LED_RED;
elsif fmc_acq_trig_sync(I) = '1' then
fmc_acq_led(I) <= c_LED_RED_GREEN;
else
fmc_acq_led(I) <= c_LED_GREEN;
end if;
end process p_fmc_acq_led;
end generate gen_fmc_led;
-- LED order on front panel (top to bottom)
-- 1..0 | 9..8
-- 3..2 | 11..10
-- 5..4 | 13..12
-- 7..6 | 15..14
svec_led(1 downto 0) <= c_LED_GREEN when wr_led_link = '1' else c_LED_RED;
svec_led(3 downto 2) <= fmc_acq_led(1);
svec_led(5 downto 4) <= c_LED_GREEN when tm_time_valid = '1'else c_LED_RED;
svec_led(7 downto 6) <= c_LED_RED_GREEN when vme_access = '1' else c_LED_OFF;
svec_led(9 downto 8) <= c_LED_RED_GREEN when wr_led_act = '1' else c_LED_OFF;
svec_led(11 downto 10) <= fmc_acq_led(0);
svec_led(13 downto 12) <= c_LED_OFF;
svec_led(15 downto 14) <= c_LED_GREEN when pps_led = '1' else c_LED_OFF;
-- Front panel IO configuration
fp_gpio1_b <= pps;
fp_gpio2_b <= '0';
clk_ext_ref <= fp_gpio3_b;
pps_ext_in <= fp_gpio4_b;
fp_term_en_o <= (others => '0');
fp_gpio1_a2b_o <= '1';
fp_gpio2_a2b_o <= '1';
fp_gpio34_a2b_o <= '0';
end architecture arch;
files = [
"wrtd_ref_svec_fd_x2.vhd",
"wrtd_fd_x2_host_map.vhd",
]
fetchto = "../../../dependencies"
modules = {
"git" : [
"https://ohwr.org/project/svec.git",
"https://ohwr.org/project/general-cores.git",
"https://ohwr.org/project/wr-cores.git",
"https://ohwr.org/project/vme64x-core.git",
"https://ohwr.org/project/urv-core.git",
"https://ohwr.org/project/mock-turtle.git",
"https://ohwr.org/project/fmc-delay-1ns-8cha.git",
"https://ohwr.org/project/ddr3-sp6-core.git",
],
}
memory-map:
name: wrtd_fd_x2_host_map
bus: wb-32-be
size: 0x80000
x-hdl:
busgroup: True
children:
- submap:
name: metadata
description: a ROM containing the carrier metadata
address: 0x4000
size: 0x40
interface: wb-32-be
x-hdl:
busgroup: True
- submap:
name: fd
description: FD
address: 0x10000
size: 0x10000
interface: wb-32-be
x-hdl:
busgroup: True
- submap:
name: mt
description: Mock Turtle
address: 0x20000
size: 0x20000
interface: wb-32-be
x-hdl:
busgroup: True
-- Do not edit. Generated on Tue Feb 23 14:50:12 2021 by tgingold
-- With Cheby 1.4.dev0 and these options:
-- --gen-hdl -i wrtd_fd_x2_host_map.cheby
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
entity wrtd_fd_x2_host_map is
port (
rst_n_i : in std_logic;
clk_i : in std_logic;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out;
-- a ROM containing the carrier metadata
metadata_i : in t_wishbone_master_in;
metadata_o : out t_wishbone_master_out;
-- FD
fd_i : in t_wishbone_master_in;
fd_o : out t_wishbone_master_out;
-- Mock Turtle
mt_i : in t_wishbone_master_in;
mt_o : out t_wishbone_master_out
);
end wrtd_fd_x2_host_map;
architecture syn of wrtd_fd_x2_host_map is
signal adr_int : std_logic_vector(18 downto 2);
signal rd_req_int : std_logic;
signal wr_req_int : std_logic;
signal rd_ack_int : std_logic;
signal wr_ack_int : std_logic;
signal wb_en : std_logic;
signal ack_int : std_logic;
signal wb_rip : std_logic;
signal wb_wip : std_logic;
signal metadata_re : std_logic;
signal metadata_we : std_logic;
signal metadata_wt : std_logic;
signal metadata_rt : std_logic;
signal metadata_tr : std_logic;
signal metadata_wack : std_logic;
signal metadata_rack : std_logic;
signal fd_re : std_logic;
signal fd_we : std_logic;
signal fd_wt : std_logic;
signal fd_rt : std_logic;
signal fd_tr : std_logic;
signal fd_wack : std_logic;
signal fd_rack : std_logic;
signal mt_re : std_logic;
signal mt_we : std_logic;
signal mt_wt : std_logic;
signal mt_rt : std_logic;
signal mt_tr : std_logic;
signal mt_wack : std_logic;
signal mt_rack : std_logic;
signal rd_ack_d0 : std_logic;
signal rd_dat_d0 : std_logic_vector(31 downto 0);
signal wr_req_d0 : std_logic;
signal wr_adr_d0 : std_logic_vector(18 downto 2);
signal wr_dat_d0 : std_logic_vector(31 downto 0);
signal wr_sel_d0 : std_logic_vector(3 downto 0);
begin
-- WB decode signals
adr_int <= wb_i.adr(18 downto 2);
wb_en <= wb_i.cyc and wb_i.stb;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_rip <= '0';
else
wb_rip <= (wb_rip or (wb_en and not wb_i.we)) and not rd_ack_int;
end if;
end if;
end process;
rd_req_int <= (wb_en and not wb_i.we) and not wb_rip;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_wip <= '0';
else
wb_wip <= (wb_wip or (wb_en and wb_i.we)) and not wr_ack_int;
end if;
end if;
end process;
wr_req_int <= (wb_en and wb_i.we) and not wb_wip;
ack_int <= rd_ack_int or wr_ack_int;
wb_o.ack <= ack_int;
wb_o.stall <= not ack_int and wb_en;
wb_o.rty <= '0';
wb_o.err <= '0';
-- pipelining for wr-in+rd-out
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
rd_ack_int <= '0';
wr_req_d0 <= '0';
else
rd_ack_int <= rd_ack_d0;
wb_o.dat <= rd_dat_d0;
wr_req_d0 <= wr_req_int;
wr_adr_d0 <= adr_int;
wr_dat_d0 <= wb_i.dat;
wr_sel_d0 <= wb_i.sel;
end if;
end if;
end process;
-- Interface metadata
metadata_tr <= metadata_wt or metadata_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
metadata_rt <= '0';
metadata_wt <= '0';
else
metadata_rt <= (metadata_rt or metadata_re) and not metadata_rack;
metadata_wt <= (metadata_wt or metadata_we) and not metadata_wack;
end if;
end if;
end process;
metadata_o.cyc <= metadata_tr;
metadata_o.stb <= metadata_tr;
metadata_wack <= metadata_i.ack and metadata_wt;
metadata_rack <= metadata_i.ack and metadata_rt;
metadata_o.adr <= ((25 downto 0 => '0') & adr_int(5 downto 2)) & (1 downto 0 => '0');
metadata_o.sel <= wr_sel_d0;
metadata_o.we <= metadata_wt;
metadata_o.dat <= wr_dat_d0;
-- Interface fd
fd_tr <= fd_wt or fd_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
fd_rt <= '0';
fd_wt <= '0';
else
fd_rt <= (fd_rt or fd_re) and not fd_rack;
fd_wt <= (fd_wt or fd_we) and not fd_wack;
end if;
end if;
end process;
fd_o.cyc <= fd_tr;
fd_o.stb <= fd_tr;
fd_wack <= fd_i.ack and fd_wt;
fd_rack <= fd_i.ack and fd_rt;
fd_o.adr <= ((15 downto 0 => '0') & adr_int(15 downto 2)) & (1 downto 0 => '0');
fd_o.sel <= wr_sel_d0;
fd_o.we <= fd_wt;
fd_o.dat <= wr_dat_d0;
-- Interface mt
mt_tr <= mt_wt or mt_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
mt_rt <= '0';
mt_wt <= '0';
else
mt_rt <= (mt_rt or mt_re) and not mt_rack;
mt_wt <= (mt_wt or mt_we) and not mt_wack;
end if;
end if;
end process;
mt_o.cyc <= mt_tr;
mt_o.stb <= mt_tr;
mt_wack <= mt_i.ack and mt_wt;
mt_rack <= mt_i.ack and mt_rt;
mt_o.adr <= ((14 downto 0 => '0') & adr_int(16 downto 2)) & (1 downto 0 => '0');
mt_o.sel <= wr_sel_d0;
mt_o.we <= mt_wt;
mt_o.dat <= wr_dat_d0;
-- Process for write requests.
process (wr_adr_d0, wr_req_d0, metadata_wack, fd_wack, mt_wack) begin
metadata_we <= '0';
fd_we <= '0';
mt_we <= '0';
case wr_adr_d0(18 downto 17) is
when "00" =>
case wr_adr_d0(16 downto 16) is
when "0" =>
-- Submap metadata
metadata_we <= wr_req_d0;
wr_ack_int <= metadata_wack;
when "1" =>
-- Submap fd
fd_we <= wr_req_d0;
wr_ack_int <= fd_wack;
when others =>
wr_ack_int <= wr_req_d0;
end case;
when "01" =>
-- Submap mt
mt_we <= wr_req_d0;
wr_ack_int <= mt_wack;
when others =>
wr_ack_int <= wr_req_d0;
end case;
end process;
-- Process for read requests.
process (adr_int, rd_req_int, metadata_i.dat, metadata_rack, fd_i.dat, fd_rack, mt_i.dat, mt_rack) begin
-- By default ack read requests
rd_dat_d0 <= (others => 'X');
metadata_re <= '0';
fd_re <= '0';
mt_re <= '0';
case adr_int(18 downto 17) is
when "00" =>
case adr_int(16 downto 16) is
when "0" =>
-- Submap metadata
metadata_re <= rd_req_int;
rd_dat_d0 <= metadata_i.dat;
rd_ack_d0 <= metadata_rack;
when "1" =>
-- Submap fd
fd_re <= rd_req_int;
rd_dat_d0 <= fd_i.dat;
rd_ack_d0 <= fd_rack;
when others =>
rd_ack_d0 <= rd_req_int;
end case;
when "01" =>
-- Submap mt
mt_re <= rd_req_int;
rd_dat_d0 <= mt_i.dat;
rd_ack_d0 <= mt_rack;
when others =>
rd_ack_d0 <= rd_req_int;
end case;
end process;
end syn;
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- White Rabbit Trigger Distribution
-- https://ohwr-gitlab.cern.ch/projects/wrtd
--------------------------------------------------------------------------------
--
-- unit name: wrtd_ref_svec_tdc_fd
--
-- description: Top entity for WRTD reference design
--
-- Top level design of the SVEC-based WRTD node, with
-- an FMC TDC in slot 1 and an FMC Fine Delay in slot 2.
--
-- This is the standard pulse-in/pulse-out WRTD node, with the FMC TDC
-- injecting pulses into the WR network in the form of WRTD messages and
-- the FMC Fine Delay converting those messages back to pulses at the
-- destination.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2014-2019
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.gencores_pkg.all;
use work.wishbone_pkg.all;
use work.mt_mqueue_pkg.all;
use work.mock_turtle_pkg.all;
use work.wr_board_pkg.all;
use work.wr_fabric_pkg.all;
library unisim;
use unisim.vcomponents.all;
entity wrtd_ref_svec_fd_x2 is
generic (
g_WRPC_INITF : string := "../../../../wr-cores/bin/wrpc/wrc_phy8.bram";
g_MT_CPU0_INITF : string := "../../../software/firmware/fd-x2/wrtd-rt-fd-x2.bram";
-- Simulation-mode enable parameter. Set by default (synthesis) to 0, and
-- changed to non-zero in the instantiation of the top level DUT in the
-- testbench. Its purpose is to reduce some internal counters/timeouts
-- to speed up simulations.
g_SIMULATION : integer := 0);
port (
---------------------------------------------------------------------------
-- Clocks/resets
---------------------------------------------------------------------------
-- Reset from system fpga
rst_n_i : in std_logic;
-- Local oscillators
clk_20m_vcxo_i : in std_logic; -- 20MHz VCXO clock
clk_125m_pllref_p_i : in std_logic; -- 125 MHz PLL reference
clk_125m_pllref_n_i : in std_logic;
clk_125m_gtp_n_i : in std_logic; -- 125 MHz GTP reference
clk_125m_gtp_p_i : in std_logic;
---------------------------------------------------------------------------
-- VME interface
---------------------------------------------------------------------------
vme_write_n_i : in std_logic;
vme_sysreset_n_i : in std_logic;
vme_retry_oe_o : out std_logic;
vme_retry_n_o : out std_logic;
vme_lword_n_b : inout std_logic;
vme_iackout_n_o : out std_logic;
vme_iackin_n_i : in std_logic;
vme_iack_n_i : in std_logic;
vme_gap_i : in std_logic;
vme_dtack_oe_o : out std_logic;
vme_dtack_n_o : out std_logic;
vme_ds_n_i : in std_logic_vector(1 downto 0);
vme_data_oe_n_o : out std_logic;
vme_data_dir_o : out std_logic;
vme_berr_o : out std_logic;
vme_as_n_i : in std_logic;
vme_addr_oe_n_o : out std_logic;
vme_addr_dir_o : out std_logic;
vme_irq_o : out std_logic_vector(7 downto 1);
vme_ga_i : in std_logic_vector(4 downto 0);
vme_data_b : inout std_logic_vector(31 downto 0);
vme_am_i : in std_logic_vector(5 downto 0);
vme_addr_b : inout std_logic_vector(31 downto 1);
---------------------------------------------------------------------------
-- SPI interfaces to DACs
---------------------------------------------------------------------------
pll20dac_din_o : out std_logic;
pll20dac_sclk_o : out std_logic;
pll20dac_sync_n_o : out std_logic;
pll25dac_din_o : out std_logic;
pll25dac_sclk_o : out std_logic;
pll25dac_sync_n_o : out std_logic;
---------------------------------------------------------------------------
-- SFP I/O for transceiver
---------------------------------------------------------------------------
sfp_txp_o : out std_logic;
sfp_txn_o : out std_logic;
sfp_rxp_i : in std_logic;
sfp_rxn_i : in std_logic;
sfp_mod_def0_i : in std_logic; -- sfp detect
sfp_mod_def1_b : inout std_logic; -- scl
sfp_mod_def2_b : inout std_logic; -- sda
sfp_rate_select_o : out std_logic;
sfp_tx_fault_i : in std_logic;
sfp_tx_disable_o : out std_logic;
sfp_los_i : in std_logic;
---------------------------------------------------------------------------
-- Carrier I2C EEPROM
---------------------------------------------------------------------------
carrier_scl_b : inout std_logic;
carrier_sda_b : inout std_logic;
---------------------------------------------------------------------------
-- PCB version
---------------------------------------------------------------------------
pcbrev_i : in std_logic_vector(4 downto 0);
---------------------------------------------------------------------------
-- Onewire interface
---------------------------------------------------------------------------
onewire_b : inout std_logic;
---------------------------------------------------------------------------
-- UART
---------------------------------------------------------------------------
uart_rxd_i : in std_logic;
uart_txd_o : out std_logic;
---------------------------------------------------------------------------
-- SPI (flash is connected to SFPGA and routed to AFPGA
-- once the boot process is complete)
---------------------------------------------------------------------------
spi_sclk_o : out std_logic;
spi_ncs_o : out std_logic;
spi_mosi_o : out std_logic;
spi_miso_i : in std_logic;
---------------------------------------------------------------------------
-- Carrier front panel LEDs and IOs
---------------------------------------------------------------------------
fp_led_line_oen_o : out std_logic_vector(1 downto 0);
fp_led_line_o : out std_logic_vector(1 downto 0);
fp_led_column_o : out std_logic_vector(3 downto 0);
fp_gpio1_b : out std_logic; -- PPS output
fp_gpio2_b : out std_logic; -- not used
fp_gpio3_b : in std_logic; -- ext 10MHz clock input
fp_gpio4_b : in std_logic; -- ext PPS input
fp_term_en_o : out std_logic_vector(4 downto 1);
fp_gpio1_a2b_o : out std_logic;
fp_gpio2_a2b_o : out std_logic;
fp_gpio34_a2b_o : out std_logic;
---------------------------------------------------------------------------
-- FMC slot 1 pins (FDELAY mezzanine)
---------------------------------------------------------------------------
fmc0_fd_tdc_start_p_i : in std_logic;
fmc0_fd_tdc_start_n_i : in std_logic;
fmc0_fd_clk_ref_p_i : in std_logic;
fmc0_fd_clk_ref_n_i : in std_logic;
fmc0_fd_trig_a_i : in std_logic;
fmc0_fd_tdc_cal_pulse_o : out std_logic;
fmc0_fd_tdc_d_b : inout std_logic_vector(27 downto 0);
fmc0_fd_tdc_emptyf_i : in std_logic;
fmc0_fd_tdc_alutrigger_o : out std_logic;
fmc0_fd_tdc_wr_n_o : out std_logic;
fmc0_fd_tdc_rd_n_o : out std_logic;
fmc0_fd_tdc_oe_n_o : out std_logic;
fmc0_fd_led_trig_o : out std_logic;
fmc0_fd_tdc_start_dis_o : out std_logic;
fmc0_fd_tdc_stop_dis_o : out std_logic;
fmc0_fd_spi_cs_dac_n_o : out std_logic;
fmc0_fd_spi_cs_pll_n_o : out std_logic;
fmc0_fd_spi_cs_gpio_n_o : out std_logic;
fmc0_fd_spi_sclk_o : out std_logic;
fmc0_fd_spi_mosi_o : out std_logic;
fmc0_fd_spi_miso_i : in std_logic;
fmc0_fd_delay_len_o : out std_logic_vector(3 downto 0);
fmc0_fd_delay_val_o : out std_logic_vector(9 downto 0);
fmc0_fd_delay_pulse_o : out std_logic_vector(3 downto 0);
fmc0_fd_dmtd_clk_o : out std_logic;
fmc0_fd_dmtd_fb_in_i : in std_logic;
fmc0_fd_dmtd_fb_out_i : in std_logic;
fmc0_fd_pll_status_i : in std_logic;
fmc0_fd_ext_rst_n_o : out std_logic;
fmc0_fd_onewire_b : inout std_logic;
fmc0_prsnt_m2c_n_i : in std_logic;
fmc0_scl_b : inout std_logic;
fmc0_sda_b : inout std_logic;
---------------------------------------------------------------------------
-- FMC slot 2 pins (FDELAY mezzanine)
---------------------------------------------------------------------------
fmc1_fd_tdc_start_p_i : in std_logic;
fmc1_fd_tdc_start_n_i : in std_logic;
fmc1_fd_clk_ref_p_i : in std_logic;
fmc1_fd_clk_ref_n_i : in std_logic;
fmc1_fd_trig_a_i : in std_logic;
fmc1_fd_tdc_cal_pulse_o : out std_logic;
fmc1_fd_tdc_d_b : inout std_logic_vector(27 downto 0);
fmc1_fd_tdc_emptyf_i : in std_logic;
fmc1_fd_tdc_alutrigger_o : out std_logic;
fmc1_fd_tdc_wr_n_o : out std_logic;
fmc1_fd_tdc_rd_n_o : out std_logic;
fmc1_fd_tdc_oe_n_o : out std_logic;
fmc1_fd_led_trig_o : out std_logic;
fmc1_fd_tdc_start_dis_o : out std_logic;
fmc1_fd_tdc_stop_dis_o : out std_logic;
fmc1_fd_spi_cs_dac_n_o : out std_logic;
fmc1_fd_spi_cs_pll_n_o : out std_logic;
fmc1_fd_spi_cs_gpio_n_o : out std_logic;
fmc1_fd_spi_sclk_o : out std_logic;
fmc1_fd_spi_mosi_o : out std_logic;
fmc1_fd_spi_miso_i : in std_logic;
fmc1_fd_delay_len_o : out std_logic_vector(3 downto 0);
fmc1_fd_delay_val_o : out std_logic_vector(9 downto 0);
fmc1_fd_delay_pulse_o : out std_logic_vector(3 downto 0);
fmc1_fd_dmtd_clk_o : out std_logic;
fmc1_fd_dmtd_fb_in_i : in std_logic;
fmc1_fd_dmtd_fb_out_i : in std_logic;
fmc1_fd_pll_status_i : in std_logic;
fmc1_fd_ext_rst_n_o : out std_logic;
fmc1_fd_onewire_b : inout std_logic;
fmc1_prsnt_m2c_n_i : in std_logic;
fmc1_scl_b : inout std_logic;
fmc1_sda_b : inout std_logic);
end entity wrtd_ref_svec_fd_x2;
architecture arch of wrtd_ref_svec_fd_x2 is
-- WRTD Node identification (WTN2)
constant c_WRTD_NODE_ID : std_logic_vector(31 downto 0) := x"5754_4E04";
-- Convention metadata base address
constant c_METADATA_ADDR : t_wishbone_address := x"0000_4000";
constant c_FMC_MUX_ADDR : t_wishbone_address_array(1 downto 0) :=
(0 => x"0000_0000",
1 => x"0000_8000");
constant c_FMC_MUX_MASK : t_wishbone_address_array(1 downto 0) :=
(0 => x"0000_8000",
1 => x"0000_8000");
constant c_MT_CONFIG : t_mt_config :=
(
app_id => c_WRTD_NODE_ID,
cpu_count => 1,
cpu_config => (
0 => (
memsize => 8192,
hmq_config => (
slot_count => 1,
slot_config => (
0 => (
entries_bits => 4,
width_bits => 7,
header_bits => 2,
endpoint_id => x"0000_0000",
enable_config_space => FALSE),
others => c_DUMMY_MT_MQUEUE_SLOT)),
rmq_config => (
slot_count => 1,
slot_config => (
0 => (
entries_bits => 4,
width_bits => 7,
header_bits => 4,
endpoint_id => x"0000_0000",
enable_config_space => TRUE),
others => c_DUMMY_MT_MQUEUE_SLOT))),
others => (
0, c_MT_DEFAULT_MQUEUE_CONFIG, c_MT_DEFAULT_MQUEUE_CONFIG)),
shared_mem_size => 256
);
-----------------------------------------------------------------------------
-- Signals
-----------------------------------------------------------------------------
-- Wishbone buse(s) from masters attached to crossbar
signal fdx2_wb_out : t_wishbone_master_out_array(1 downto 0);
signal fdx2_wb_in : t_wishbone_master_in_array(1 downto 0);
-- clock and reset
signal areset_n : std_logic;
signal clk_sys_62m5 : std_logic;
signal rst_sys_62m5_n : std_logic;
signal clk_ref_125m : std_logic;
signal clk_ext_ref : std_logic;
signal clk_dmtd_125m : std_logic;
signal dcm1_clk_ref_0 : std_logic;
signal dcm1_clk_ref_180 : std_logic;
signal dcm0_clk_ref_0 : std_logic;
signal dcm0_clk_ref_180 : std_logic;
attribute keep : string;
attribute keep of dcm0_clk_ref_0 : signal is "TRUE";
attribute keep of dcm1_clk_ref_0 : signal is "TRUE";
signal vme_access_led : std_logic;
-- LEDs and GPIO
signal pps : std_logic;
signal pps_led : std_logic;
signal pps_ext_in : std_logic;
signal svec_led : std_logic_vector(15 downto 0);
signal wr_led_link : std_logic;
signal wr_led_act : std_logic;
-- Interrupts
signal irq_vector : std_logic_vector(5 downto 0);
-- MT endpoints
signal rmq_endpoint_out : t_mt_rmq_endpoint_iface_out;
signal rmq_endpoint_in : t_mt_rmq_endpoint_iface_in;
signal rmq_src_in : t_mt_stream_source_in;
signal rmq_src_out : t_mt_stream_source_out;
signal rmq_src_cfg_in : t_mt_stream_config_in;
signal rmq_src_cfg_out : t_mt_stream_config_out;
signal rmq_snk_in : t_mt_stream_sink_in;
signal rmq_snk_out : t_mt_stream_sink_out;
signal rmq_snk_cfg_in : t_mt_stream_config_in;
signal rmq_snk_cfg_out : t_mt_stream_config_out;
-- MT fabric.
signal eth_tx_out : t_wrf_source_out;
signal eth_tx_in : t_wrf_source_in;
signal eth_rx_out : t_wrf_sink_out;
signal eth_rx_in : t_wrf_sink_in;
-- MT Dedicated WB interfaces to FMCs
signal fmc_dp_wb_out : t_wishbone_master_out_array(0 to 0);
signal fmc_dp_wb_in : t_wishbone_master_in_array(0 to 0);
signal host_wb_out : t_wishbone_master_out;
signal host_wb_in : t_wishbone_master_in;
signal metadata_wb_out : t_wishbone_master_out;
signal metadata_wb_in : t_wishbone_master_in;
signal fd_wb_out : t_wishbone_master_out;
signal fd_wb_in : t_wishbone_master_in;
signal mt_wb_out : t_wishbone_master_out;
signal mt_wb_in : t_wishbone_master_in;
-- WRPC TM interface and aux clocks
signal tm_link_up : std_logic;
signal tm_tai : std_logic_vector(39 downto 0);
signal tm_cycles : std_logic_vector(27 downto 0);
signal tm_time_valid : std_logic;
signal tm_clk_aux_lock_en : std_logic_vector(1 downto 0);
signal tm_clk_aux_locked : std_logic_vector(1 downto 0);
signal tm_dac_value : std_logic_vector(23 downto 0);
signal tm_dac_wr : std_logic_vector(1 downto 0);
-- MT TM interface
signal tm : t_mt_timing_if;
-- Misc FMC signals
signal fmc1_fd_tdc_start : std_logic;
signal ddr1_pll_reset : std_logic;
signal ddr1_pll_locked : std_logic;
signal fmc1_fd_pll_status : std_logic;
signal fmc1_fd_tdc_data_out : std_logic_vector(27 downto 0);
signal fmc1_fd_tdc_data_in : std_logic_vector(27 downto 0);
signal fmc1_fd_tdc_data_oe : std_logic;
signal fmc1_fd_owr_en, fmc1_fd_owr_in : std_logic;
signal fmc0_fd_tdc_start : std_logic;
signal ddr0_pll_reset : std_logic;
signal ddr0_pll_locked : std_logic;
signal fmc0_fd_pll_status : std_logic;
signal fmc0_fd_tdc_data_out : std_logic_vector(27 downto 0);
signal fmc0_fd_tdc_data_in : std_logic_vector(27 downto 0);
signal fmc0_fd_tdc_data_oe : std_logic;
signal fmc0_fd_owr_en, fmc0_fd_owr_in : std_logic;
attribute iob : string;
attribute iob of pps : signal is "FORCE";
begin -- architecture arch
areset_n <= vme_sysreset_n_i and rst_n_i;
cmp_xwb_metadata : entity work.xwb_metadata
generic map (
g_VENDOR_ID => x"0000_10DC",
g_DEVICE_ID => c_WRTD_NODE_ID,
g_VERSION => x"0100_0000",
g_CAPABILITIES => x"0000_0000",
g_COMMIT_ID => (others => '0'))
port map (
clk_i => clk_sys_62m5,
rst_n_i => rst_sys_62m5_n,
wb_i => metadata_wb_out,
wb_o => metadata_wb_in);
inst_svec_base : entity work.svec_base_wr
generic map (
g_WITH_VIC => TRUE,
g_WITH_ONEWIRE => FALSE,
g_WITH_SPI => FALSE,
g_WITH_WR => TRUE,
g_WITH_DDR4 => FALSE,
g_WITH_DDR5 => FALSE,
g_APP_OFFSET => c_METADATA_ADDR,
g_NUM_USER_IRQ => 6,
g_DPRAM_INITF => g_WRPC_INITF,
g_AUX_CLKS => 2,
g_FABRIC_IFACE => plain,
g_SIMULATION => g_SIMULATION,
g_VERBOSE => FALSE)
port map (
rst_n_i => areset_n,
clk_125m_pllref_p_i => clk_125m_pllref_p_i,
clk_125m_pllref_n_i => clk_125m_pllref_n_i,
clk_20m_vcxo_i => clk_20m_vcxo_i,
clk_125m_gtp_n_i => clk_125m_gtp_n_i,
clk_125m_gtp_p_i => clk_125m_gtp_p_i,
clk_aux_i(0) => dcm0_clk_ref_0,
clk_aux_i(1) => dcm1_clk_ref_0,
clk_10m_ext_i => clk_ext_ref,
pps_ext_i => pps_ext_in,
vme_write_n_i => vme_write_n_i,
vme_sysreset_n_i => vme_sysreset_n_i,
vme_retry_oe_o => vme_retry_oe_o,
vme_retry_n_o => vme_retry_n_o,
vme_lword_n_b => vme_lword_n_b,
vme_iackout_n_o => vme_iackout_n_o,
vme_iackin_n_i => vme_iackin_n_i,
vme_iack_n_i => vme_iack_n_i,
vme_gap_i => vme_gap_i,
vme_dtack_oe_o => vme_dtack_oe_o,
vme_dtack_n_o => vme_dtack_n_o,
vme_ds_n_i => vme_ds_n_i,
vme_data_oe_n_o => vme_data_oe_n_o,
vme_data_dir_o => vme_data_dir_o,
vme_berr_o => vme_berr_o,
vme_as_n_i => vme_as_n_i,
vme_addr_oe_n_o => vme_addr_oe_n_o,
vme_addr_dir_o => vme_addr_dir_o,
vme_irq_o => vme_irq_o,
vme_ga_i => vme_ga_i,
vme_data_b => vme_data_b,
vme_am_i => vme_am_i,
vme_addr_b => vme_addr_b,
fmc0_scl_b => fmc0_scl_b,
fmc0_sda_b => fmc0_sda_b,
fmc1_scl_b => fmc1_scl_b,
fmc1_sda_b => fmc1_sda_b,
fmc0_prsnt_m2c_n_i => fmc0_prsnt_m2c_n_i,
fmc1_prsnt_m2c_n_i => fmc1_prsnt_m2c_n_i,
onewire_b => onewire_b,
carrier_scl_b => carrier_scl_b,
carrier_sda_b => carrier_sda_b,
spi_sclk_o => spi_sclk_o,
spi_ncs_o => spi_ncs_o,
spi_mosi_o => spi_mosi_o,
spi_miso_i => spi_miso_i,
uart_rxd_i => uart_rxd_i,
uart_txd_o => uart_txd_o,
plldac_sclk_o => pll20dac_sclk_o,
plldac_din_o => pll20dac_din_o,
pll20dac_din_o => pll20dac_din_o,
pll20dac_sclk_o => pll20dac_sclk_o,
pll20dac_sync_n_o => pll20dac_sync_n_o,
pll25dac_din_o => pll25dac_din_o,
pll25dac_sclk_o => pll25dac_sclk_o,
pll25dac_sync_n_o => pll25dac_sync_n_o,
sfp_txp_o => sfp_txp_o,
sfp_txn_o => sfp_txn_o,
sfp_rxp_i => sfp_rxp_i,
sfp_rxn_i => sfp_rxn_i,
sfp_mod_def0_i => sfp_mod_def0_i,
sfp_mod_def1_b => sfp_mod_def1_b,
sfp_mod_def2_b => sfp_mod_def2_b,
sfp_rate_select_o => sfp_rate_select_o,
sfp_tx_fault_i => sfp_tx_fault_i,
sfp_tx_disable_o => sfp_tx_disable_o,
sfp_los_i => sfp_los_i,
pcbrev_i => pcbrev_i,
clk_dmtd_125m_o => clk_dmtd_125m,
clk_sys_62m5_o => clk_sys_62m5,
rst_sys_62m5_n_o => rst_sys_62m5_n,
clk_ref_125m_o => clk_ref_125m,
rst_ref_125m_n_o => open,
irq_user_i => irq_vector,
wrf_src_o => eth_rx_in,
wrf_src_i => eth_rx_out,
wrf_snk_o => eth_tx_in,
wrf_snk_i => eth_tx_out,
tm_link_up_o => tm_link_up,
tm_time_valid_o => tm_time_valid,
tm_tai_o => tm_tai,
tm_cycles_o => tm_cycles,
tm_dac_value_o => tm_dac_value,
tm_dac_wr_o => tm_dac_wr,
tm_clk_aux_lock_en_i => tm_clk_aux_lock_en,
tm_clk_aux_locked_o => tm_clk_aux_locked,
pps_p_o => pps,
pps_led_o => pps_led,
link_ok_o => open,
led_link_o => wr_led_link,
led_act_o => wr_led_act,
app_wb_o => host_wb_out,
app_wb_i => host_wb_in);
-----------------------------------------------------------------------------
-- Primary wishbone Crossbar
-----------------------------------------------------------------------------
inst_host_map: entity work.wrtd_fd_x2_host_map
port map (
rst_n_i => rst_sys_62m5_n,
clk_i => clk_sys_62m5,
wb_i => host_wb_out,
wb_o => host_wb_in,
metadata_i => metadata_wb_in,
metadata_o => metadata_wb_out,
fd_i => fd_wb_in,
fd_o => fd_wb_out,
mt_i => mt_wb_in,
mt_o => mt_wb_out
);
cmp_fmc0_wb_mux : xwb_crossbar
generic map (
g_VERBOSE => FALSE,
g_NUM_MASTERS => 2,
g_NUM_SLAVES => 2,
g_REGISTERED => TRUE,
g_ADDRESS => c_FMC_MUX_ADDR,
g_MASK => c_FMC_MUX_MASK)
port map (
clk_sys_i => clk_sys_62m5,
rst_n_i => rst_sys_62m5_n,
slave_i(0) => fmc_dp_wb_out(0),
slave_i(1) => fd_wb_out,
slave_o(0) => fmc_dp_wb_in(0),
slave_o(1) => fd_wb_in,
master_i => fdx2_wb_in,
master_o => fdx2_wb_out);
cmp_vme_led_extend : gc_extend_pulse
generic map (
g_width => 5000000)
port map (
clk_i => clk_sys_62m5,
rst_n_i => rst_sys_62m5_n,
pulse_i => host_wb_out.cyc,
extended_o => vme_access_led);
-----------------------------------------------------------------------------
-- Mock Turtle (WB Slave)
-----------------------------------------------------------------------------
cmp_mock_turtle : entity work.mock_turtle_core
generic map (
g_CONFIG => c_MT_CONFIG,
g_CPU0_IRAM_INITF => g_MT_CPU0_INITF,
g_WITH_WHITE_RABBIT => TRUE)
port map (
clk_i => clk_sys_62m5,
rst_n_i => rst_sys_62m5_n,
sp_master_o => open,
sp_master_i => c_DUMMY_WB_MASTER_IN,
dp_master_o => fmc_dp_wb_out,
dp_master_i => fmc_dp_wb_in,
rmq_endpoint_o => rmq_endpoint_out,
rmq_endpoint_i => rmq_endpoint_in,
host_slave_i => mt_wb_out,
host_slave_o => mt_wb_in,
clk_ref_i => clk_ref_125m,
tm_i => tm,
hmq_in_irq_o => irq_vector(2),
hmq_out_irq_o => irq_vector(3),
notify_irq_o => irq_vector(5),
console_irq_o => irq_vector(4));
tm.cycles <= tm_cycles;
tm.tai <= tm_tai;
tm.time_valid <= tm_time_valid;
tm.link_up <= tm_link_up;
tm.aux_locked(1 downto 0) <= tm_clk_aux_locked;
tm.aux_locked(7 downto 2) <= (others => '0');
cmp_eth_endpoint : entity work.mt_ep_ethernet_single
port map (
clk_i => clk_sys_62m5,
rst_n_i => rst_sys_62m5_n,
rmq_src_i => rmq_src_in,
rmq_src_o => rmq_src_out,
rmq_src_config_i => rmq_snk_cfg_out,
rmq_src_config_o => rmq_snk_cfg_in,
rmq_snk_i => rmq_snk_in,
rmq_snk_o => rmq_snk_out,
rmq_snk_config_i => rmq_src_cfg_out,
rmq_snk_config_o => rmq_src_cfg_in,
eth_src_o => eth_tx_out,
eth_src_i => eth_tx_in,
eth_snk_o => eth_rx_out,
eth_snk_i => eth_rx_in);
p_rmq_assign : process (rmq_endpoint_out, rmq_snk_cfg_in, rmq_snk_out,
rmq_src_cfg_in, rmq_src_out) is
begin
rmq_endpoint_in <= c_MT_RMQ_ENDPOINT_IFACE_IN_DEFAULT_VALUE;
-- WR->MT (RX, to MT CPU0)
rmq_src_in <= rmq_endpoint_out.snk_out(0)(0);
rmq_endpoint_in.snk_in(0)(0) <= rmq_src_out;
rmq_snk_cfg_out <= rmq_endpoint_out.snk_config_out(0)(0);
rmq_endpoint_in.snk_config_in(0)(0) <= rmq_snk_cfg_in;
-- MT->WR (TX, from MT CPU1)
rmq_snk_in <= rmq_endpoint_out.src_out(1)(0);
rmq_endpoint_in.src_in(1)(0) <= rmq_snk_out;
rmq_src_cfg_out <= rmq_endpoint_out.src_config_out(1)(0);
rmq_endpoint_in.src_config_in(1)(0) <= rmq_src_cfg_in;
end process p_rmq_assign;
-----------------------------------------------------------------------------
-- FMC FDELAY (SVEC slot #1)
-----------------------------------------------------------------------------
cmp_fd_tdc_start0 : IBUFDS
generic map (
DIFF_TERM => TRUE,
IBUF_LOW_PWR => FALSE)
port map (
O => fmc0_fd_tdc_start,
I => fmc0_fd_tdc_start_p_i,
IB => fmc0_fd_tdc_start_n_i);
U_DDR_PLL0 : entity work.fd_ddr_pll
port map (
RST => ddr0_pll_reset,
LOCKED => ddr0_pll_locked,
CLK_IN1_P => fmc0_fd_clk_ref_p_i,
CLK_IN1_N => fmc0_fd_clk_ref_n_i,
CLK_OUT1 => dcm0_clk_ref_0,
CLK_OUT2 => dcm0_clk_ref_180);
ddr0_pll_reset <= not fmc0_fd_pll_status_i;
fmc0_fd_pll_status <= fmc0_fd_pll_status_i and ddr0_pll_locked;
inst_FineDelay_Core0 : entity work.fine_delay_core
generic map (
g_FMC_SLOT_ID => 0,
g_WITH_WR_CORE => TRUE,
g_SIMULATION => f_int2bool(g_SIMULATION),
g_INTERFACE_MODE => PIPELINED,
g_ADDRESS_GRANULARITY => BYTE)
port map (
clk_ref_0_i => dcm0_clk_ref_0,
clk_ref_180_i => dcm0_clk_ref_180,
clk_sys_i => clk_sys_62m5,
clk_dmtd_i => clk_dmtd_125m,
rst_n_i => rst_sys_62m5_n,
dcm_reset_o => open,
dcm_locked_i => ddr0_pll_locked,
trig_a_i => fmc0_fd_trig_a_i,
tdc_cal_pulse_o => fmc0_fd_tdc_cal_pulse_o,
tdc_start_i => fmc0_fd_tdc_start,
dmtd_fb_in_i => fmc0_fd_dmtd_fb_in_i,
dmtd_fb_out_i => fmc0_fd_dmtd_fb_out_i,
dmtd_samp_o => fmc0_fd_dmtd_clk_o,
led_trig_o => fmc0_fd_led_trig_o,
ext_rst_n_o => fmc0_fd_ext_rst_n_o,
pll_status_i => fmc0_fd_pll_status,
acam_d_o => fmc0_fd_tdc_data_out,
acam_d_i => fmc0_fd_tdc_data_in,
acam_d_oen_o => fmc0_fd_tdc_data_oe,
acam_emptyf_i => fmc0_fd_tdc_emptyf_i,
acam_alutrigger_o => fmc0_fd_tdc_alutrigger_o,
acam_wr_n_o => fmc0_fd_tdc_wr_n_o,
acam_rd_n_o => fmc0_fd_tdc_rd_n_o,
acam_start_dis_o => fmc0_fd_tdc_start_dis_o,
acam_stop_dis_o => fmc0_fd_tdc_stop_dis_o,
spi_cs_dac_n_o => fmc0_fd_spi_cs_dac_n_o,
spi_cs_pll_n_o => fmc0_fd_spi_cs_pll_n_o,
spi_cs_gpio_n_o => fmc0_fd_spi_cs_gpio_n_o,
spi_sclk_o => fmc0_fd_spi_sclk_o,
spi_mosi_o => fmc0_fd_spi_mosi_o,
spi_miso_i => fmc0_fd_spi_miso_i,
delay_len_o => fmc0_fd_delay_len_o,
delay_val_o => fmc0_fd_delay_val_o,
delay_pulse_o => fmc0_fd_delay_pulse_o,
tm_link_up_i => tm_link_up,
tm_time_valid_i => tm_time_valid,
tm_cycles_i => tm_cycles,
tm_utc_i => tm_tai,
tm_clk_aux_lock_en_o => tm_clk_aux_lock_en(0),
tm_clk_aux_locked_i => tm_clk_aux_locked(0),
tm_clk_dmtd_locked_i => '1',
tm_dac_value_i => tm_dac_value,
tm_dac_wr_i => tm_dac_wr(0),
owr_en_o => fmc0_fd_owr_en,
owr_i => fmc0_fd_owr_in,
i2c_scl_oen_o => open,
i2c_scl_i => '0',
i2c_sda_oen_o => open,
i2c_sda_i => '0',
fmc_present_n_i => '0',
wb_adr_i => fdx2_wb_out(0).adr,
wb_dat_i => fdx2_wb_out(0).dat,
wb_dat_o => fdx2_wb_in(0).dat,
wb_sel_i => fdx2_wb_out(0).sel,
wb_cyc_i => fdx2_wb_out(0).cyc,
wb_stb_i => fdx2_wb_out(0).stb,
wb_we_i => fdx2_wb_out(0).we,
wb_ack_o => fdx2_wb_in(0).ack,
wb_stall_o => fdx2_wb_in(0).stall,
wb_irq_o => irq_vector(0));
fdx2_wb_in(0).err <= '0';
fdx2_wb_in(0).rty <= '0';
-- tristate buffer for the TDC data bus:
fmc0_fd_tdc_d_b <= fmc0_fd_tdc_data_out when fmc0_fd_tdc_data_oe = '1' else (others => 'Z');
fmc0_fd_tdc_oe_n_o <= '1';
fmc0_fd_tdc_data_in <= fmc0_fd_tdc_d_b;
fmc0_fd_onewire_b <= '0' when fmc0_fd_owr_en = '1' else 'Z';
fmc0_fd_owr_in <= fmc1_fd_onewire_b;
-----------------------------------------------------------------------------
-- FMC FDELAY (SVEC slot #2)
-----------------------------------------------------------------------------
cmp_fd_tdc_start1 : IBUFDS
generic map (
DIFF_TERM => TRUE,
IBUF_LOW_PWR => FALSE)
port map (
O => fmc1_fd_tdc_start,
I => fmc1_fd_tdc_start_p_i,
IB => fmc1_fd_tdc_start_n_i);
U_DDR_PLL1 : entity work.fd_ddr_pll
port map (
RST => ddr1_pll_reset,
LOCKED => ddr1_pll_locked,
CLK_IN1_P => fmc1_fd_clk_ref_p_i,
CLK_IN1_N => fmc1_fd_clk_ref_n_i,
CLK_OUT1 => dcm1_clk_ref_0,
CLK_OUT2 => dcm1_clk_ref_180);
ddr1_pll_reset <= not fmc1_fd_pll_status_i;
fmc1_fd_pll_status <= fmc1_fd_pll_status_i and ddr1_pll_locked;
inst_FineDelay_Core1 : entity work.fine_delay_core
generic map (
g_FMC_SLOT_ID => 1,
g_WITH_WR_CORE => TRUE,
g_SIMULATION => f_int2bool(g_SIMULATION),
g_INTERFACE_MODE => PIPELINED,
g_ADDRESS_GRANULARITY => BYTE)
port map (
clk_ref_0_i => dcm1_clk_ref_0,
clk_ref_180_i => dcm1_clk_ref_180,
clk_sys_i => clk_sys_62m5,
clk_dmtd_i => clk_dmtd_125m,
rst_n_i => rst_sys_62m5_n,
dcm_reset_o => open,
dcm_locked_i => ddr1_pll_locked,
trig_a_i => fmc1_fd_trig_a_i,
tdc_cal_pulse_o => fmc1_fd_tdc_cal_pulse_o,
tdc_start_i => fmc1_fd_tdc_start,
dmtd_fb_in_i => fmc1_fd_dmtd_fb_in_i,
dmtd_fb_out_i => fmc1_fd_dmtd_fb_out_i,
dmtd_samp_o => fmc1_fd_dmtd_clk_o,
led_trig_o => fmc1_fd_led_trig_o,
ext_rst_n_o => fmc1_fd_ext_rst_n_o,
pll_status_i => fmc1_fd_pll_status,
acam_d_o => fmc1_fd_tdc_data_out,
acam_d_i => fmc1_fd_tdc_data_in,
acam_d_oen_o => fmc1_fd_tdc_data_oe,
acam_emptyf_i => fmc1_fd_tdc_emptyf_i,
acam_alutrigger_o => fmc1_fd_tdc_alutrigger_o,
acam_wr_n_o => fmc1_fd_tdc_wr_n_o,
acam_rd_n_o => fmc1_fd_tdc_rd_n_o,
acam_start_dis_o => fmc1_fd_tdc_start_dis_o,
acam_stop_dis_o => fmc1_fd_tdc_stop_dis_o,
spi_cs_dac_n_o => fmc1_fd_spi_cs_dac_n_o,
spi_cs_pll_n_o => fmc1_fd_spi_cs_pll_n_o,
spi_cs_gpio_n_o => fmc1_fd_spi_cs_gpio_n_o,
spi_sclk_o => fmc1_fd_spi_sclk_o,
spi_mosi_o => fmc1_fd_spi_mosi_o,
spi_miso_i => fmc1_fd_spi_miso_i,
delay_len_o => fmc1_fd_delay_len_o,
delay_val_o => fmc1_fd_delay_val_o,
delay_pulse_o => fmc1_fd_delay_pulse_o,
tm_link_up_i => tm_link_up,
tm_time_valid_i => tm_time_valid,
tm_cycles_i => tm_cycles,
tm_utc_i => tm_tai,
tm_clk_aux_lock_en_o => tm_clk_aux_lock_en(1),
tm_clk_aux_locked_i => tm_clk_aux_locked(1),
tm_clk_dmtd_locked_i => '1',
tm_dac_value_i => tm_dac_value,
tm_dac_wr_i => tm_dac_wr(1),
owr_en_o => fmc1_fd_owr_en,
owr_i => fmc1_fd_owr_in,
i2c_scl_oen_o => open,
i2c_scl_i => '0',
i2c_sda_oen_o => open,
i2c_sda_i => '0',
fmc_present_n_i => '0',
wb_adr_i => fdx2_wb_out(1).adr,
wb_dat_i => fdx2_wb_out(1).dat,
wb_dat_o => fdx2_wb_in(1).dat,
wb_sel_i => fdx2_wb_out(1).sel,
wb_cyc_i => fdx2_wb_out(1).cyc,
wb_stb_i => fdx2_wb_out(1).stb,
wb_we_i => fdx2_wb_out(1).we,
wb_ack_o => fdx2_wb_in(1).ack,
wb_stall_o => fdx2_wb_in(1).stall,
wb_irq_o => irq_vector(1));
fdx2_wb_in(1).err <= '0';
fdx2_wb_in(1).rty <= '0';
-- tristate buffer for the TDC data bus:
fmc1_fd_tdc_d_b <= fmc1_fd_tdc_data_out when fmc1_fd_tdc_data_oe = '1' else (others => 'Z');
fmc1_fd_tdc_oe_n_o <= '1';
fmc1_fd_tdc_data_in <= fmc1_fd_tdc_d_b;
fmc1_fd_onewire_b <= '0' when fmc1_fd_owr_en = '1' else 'Z';
fmc1_fd_owr_in <= fmc1_fd_onewire_b;
-----------------------------------------------------------------------------
-- Carrier front panel LEDs and LEMOs
-----------------------------------------------------------------------------
cmp_led_controller : gc_bicolor_led_ctrl
generic map(
g_NB_COLUMN => 4,
g_NB_LINE => 2,
g_CLK_FREQ => 62500000, -- in Hz
g_REFRESH_RATE => 250 -- in Hz
)
port map(
rst_n_i => rst_sys_62m5_n,
clk_i => clk_sys_62m5,
led_intensity_i => "1100100", -- in %
led_state_i => svec_led,
column_o => fp_led_column_o,
line_o => fp_led_line_o,
line_oen_o => fp_led_line_oen_o);
-- LED 4
svec_led(1 downto 0) <= c_LED_GREEN when wr_led_link = '1' else c_LED_RED;
-- LED 3
svec_led(3 downto 2) <= c_LED_GREEN when tm_clk_aux_locked(1) = '1' else c_LED_RED;
-- LED 2
svec_led(5 downto 4) <= c_LED_GREEN when tm_time_valid = '1' else c_LED_RED;
-- LED 1
svec_led(7 downto 6) <= c_LED_RED_GREEN when vme_access_led = '1' else c_LED_OFF;
-- LED 8
svec_led(9 downto 8) <= c_LED_RED_GREEN when wr_led_act = '1' else c_LED_OFF;
-- LED 7
svec_led(11 downto 10) <= c_LED_GREEN when tm_clk_aux_locked(0) = '1' else c_LED_RED;
-- LED 6
svec_led(13 downto 12) <= c_LED_OFF;
-- LED 5
svec_led(15 downto 14) <= c_LED_GREEN when pps_led = '1' else c_LED_OFF;
-- Front panel IO configuration
fp_gpio1_b <= pps;
fp_gpio2_b <= '0';
clk_ext_ref <= fp_gpio3_b;
pps_ext_in <= fp_gpio4_b;
fp_term_en_o <= (others => '0');
fp_gpio1_a2b_o <= '1';
fp_gpio2_a2b_o <= '1';
fp_gpio34_a2b_o <= '0';
end architecture arch;
......@@ -12,7 +12,7 @@ modules = {
"https://ohwr.org/project/vme64x-core.git",
"https://ohwr.org/project/urv-core.git",
"https://ohwr.org/project/mock-turtle.git",
"https://ohwr.org/project/fmc-tdc-1ns-5cha-gw.git",
"https://ohwr.org/project/fmc-tdc.git",
"https://ohwr.org/project/fmc-delay-1ns-8cha.git",
"https://ohwr.org/project/ddr3-sp6-core.git",
],
......
......@@ -312,7 +312,7 @@ architecture arch of wrtd_ref_svec_tdc_fd is
constant c_WB_SLAVE_MT : integer := 3;
-- Convention metadata base address
constant c_METADATA_ADDR : t_wishbone_address := x"0000_2000";
constant c_METADATA_ADDR : t_wishbone_address := x"0000_4000";
-- Primary wishbone crossbar layout
constant c_WB_LAYOUT_ADDR :
......@@ -392,29 +392,8 @@ architecture arch of wrtd_ref_svec_tdc_fd is
attribute keep of tdc_clk_125m : signal is "TRUE";
attribute keep of dcm1_clk_ref_0 : signal is "TRUE";
-- I2C EEPROM
signal eeprom_sda_in : std_logic;
signal eeprom_sda_out : std_logic;
signal eeprom_scl_in : std_logic;
signal eeprom_scl_out : std_logic;
-- VME
signal vme_data_b_out : std_logic_vector(31 downto 0);
signal vme_addr_b_out : std_logic_vector(31 downto 1);
signal vme_lword_n_b_out : std_logic;
signal vme_data_dir_int : std_logic;
signal vme_addr_dir_int : std_logic;
signal vme_ga : std_logic_vector(5 downto 0);
signal vme_berr_n : std_logic;
signal vme_irq_n : std_logic_vector(7 downto 1);
signal vme_access_led : std_logic;
-- SFP
signal sfp_sda_in : std_logic;
signal sfp_sda_out : std_logic;
signal sfp_scl_in : std_logic;
signal sfp_scl_out : std_logic;
-- LEDs and GPIO
signal pps : std_logic;
signal pps_led : std_logic;
......@@ -488,7 +467,7 @@ begin -- architecture arch
generic map (
g_VENDOR_ID => x"0000_10DC",
g_DEVICE_ID => c_WRTD_NODE_ID,
g_VERSION => x"0100_0000",
g_VERSION => x"0100_0001",
g_CAPABILITIES => x"0000_0000",
g_COMMIT_ID => (others => '0'))
port map (
......@@ -722,6 +701,8 @@ begin -- architecture arch
clk_sys_i => clk_sys_62m5,
rst_sys_n_i => rst_sys_62m5_n,
rst_n_a_i => rst_sys_62m5_n,
fmc_id_i => '0',
fmc_present_n_i => fmc0_prsnt_m2c_n_i,
pll_sclk_o => fmc0_tdc_pll_sclk_o,
pll_sdi_o => fmc0_tdc_pll_sdi_o,
pll_cs_o => fmc0_tdc_pll_cs_n_o,
......@@ -751,17 +732,18 @@ begin -- architecture arch
term_en_3_o => fmc0_tdc_term_en_3_o,
term_en_4_o => fmc0_tdc_term_en_4_o,
term_en_5_o => fmc0_tdc_term_en_5_o,
tdc_led_status_o => fmc0_tdc_led_status_o,
tdc_led_trig1_o => fmc0_tdc_led_trig1_o,
tdc_led_trig2_o => fmc0_tdc_led_trig2_o,
tdc_led_trig3_o => fmc0_tdc_led_trig3_o,
tdc_led_trig4_o => fmc0_tdc_led_trig4_o,
tdc_led_trig5_o => fmc0_tdc_led_trig5_o,
tdc_led_stat_o => fmc0_tdc_led_status_o,
tdc_led_trig_o(0) => fmc0_tdc_led_trig1_o,
tdc_led_trig_o(1) => fmc0_tdc_led_trig2_o,
tdc_led_trig_o(2) => fmc0_tdc_led_trig3_o,
tdc_led_trig_o(3) => fmc0_tdc_led_trig4_o,
tdc_led_trig_o(4) => fmc0_tdc_led_trig5_o,
mezz_scl_i => '0',
mezz_sda_i => '0',
mezz_scl_o => open,
mezz_sda_o => open,
mezz_one_wire_b => fmc0_tdc_one_wire_b,
fmc_present_n_i => '0',
tm_link_up_i => tm_link_up,
tm_time_valid_i => tm_time_valid,
tm_cycles_i => tm_cycles,
......@@ -860,7 +842,7 @@ begin -- architecture arch
i2c_scl_i => '0',
i2c_sda_oen_o => open,
i2c_sda_i => '0',
fmc_present_n_i => '0',
fmc_present_n_i => fmc1_prsnt_m2c_n_i,
wb_adr_i => fmc1_mux_wb_out.adr,
wb_dat_i => fmc1_mux_wb_out.dat,
wb_dat_o => fmc1_mux_wb_in.dat,
......
files = [
"wrtd_ref_svec_tdc_x2.vhd",
"wrtd_tdc_x2_host_map.vhd",
"wrtd_tdc_x2_fmc_map.vhd",
]
fetchto = "../../../dependencies"
modules = {
"git" : [
"https://ohwr.org/project/svec.git",
"https://ohwr.org/project/general-cores.git",
"https://ohwr.org/project/wr-cores.git",
"https://ohwr.org/project/vme64x-core.git",
"https://ohwr.org/project/urv-core.git",
"https://ohwr.org/project/mock-turtle.git",
"https://ohwr.org/project/fmc-tdc.git",
"https://ohwr.org/project/fmc-delay-1ns-8cha.git",
"https://ohwr.org/project/ddr3-sp6-core.git",
],
}
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- White Rabbit Trigger Distribution
-- https://ohwr-gitlab.cern.ch/projects/wrtd
--------------------------------------------------------------------------------
--
-- unit name: wrtd_ref_svec_tdc_fd
--
-- description: Top entity for WRTD reference design
--
-- Top level design of the SVEC-based WRTD node, with
-- an FMC TDC in slot 1 and an FMC Fine Delay in slot 2.
--
-- This is the standard pulse-in/pulse-out WRTD node, with the FMC TDC
-- injecting pulses into the WR network in the form of WRTD messages and
-- the FMC Fine Delay converting those messages back to pulses at the
-- destination.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2014-2019
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.gencores_pkg.all;
use work.wishbone_pkg.all;
use work.mt_mqueue_pkg.all;
use work.mock_turtle_pkg.all;
use work.wr_board_pkg.all;
use work.wr_fabric_pkg.all;
library unisim;
use unisim.vcomponents.all;
entity wrtd_ref_svec_tdc_x2 is
generic (
g_WRPC_INITF : string := "../../../dependencies/wr-cores/bin/wrpc/wrc_phy8.bram";
g_MT_CPU0_INITF : string := "../../../software/firmware/tdc-x2/wrtd-rt-tdc-x2.bram";
-- Simulation-mode enable parameter. Set by default (synthesis) to 0, and
-- changed to non-zero in the instantiation of the top level DUT in the
-- testbench. Its purpose is to reduce some internal counters/timeouts
-- to speed up simulations.
g_SIMULATION : integer := 0);
port (
---------------------------------------------------------------------------
-- Clocks/resets
---------------------------------------------------------------------------
-- Reset from system fpga
rst_n_i : in std_logic;
-- Local oscillators
clk_20m_vcxo_i : in std_logic; -- 20MHz VCXO clock
clk_125m_pllref_p_i : in std_logic; -- 125 MHz PLL reference
clk_125m_pllref_n_i : in std_logic;
clk_125m_gtp_n_i : in std_logic; -- 125 MHz GTP reference
clk_125m_gtp_p_i : in std_logic;
---------------------------------------------------------------------------
-- VME interface
---------------------------------------------------------------------------
vme_write_n_i : in std_logic;
vme_sysreset_n_i : in std_logic;
vme_retry_oe_o : out std_logic;
vme_retry_n_o : out std_logic;
vme_lword_n_b : inout std_logic;
vme_iackout_n_o : out std_logic;
vme_iackin_n_i : in std_logic;
vme_iack_n_i : in std_logic;
vme_gap_i : in std_logic;
vme_dtack_oe_o : out std_logic;
vme_dtack_n_o : out std_logic;
vme_ds_n_i : in std_logic_vector(1 downto 0);
vme_data_oe_n_o : out std_logic;
vme_data_dir_o : out std_logic;
vme_berr_o : out std_logic;
vme_as_n_i : in std_logic;
vme_addr_oe_n_o : out std_logic;
vme_addr_dir_o : out std_logic;
vme_irq_o : out std_logic_vector(7 downto 1);
vme_ga_i : in std_logic_vector(4 downto 0);
vme_data_b : inout std_logic_vector(31 downto 0);
vme_am_i : in std_logic_vector(5 downto 0);
vme_addr_b : inout std_logic_vector(31 downto 1);
---------------------------------------------------------------------------
-- SPI interfaces to DACs
---------------------------------------------------------------------------
pll20dac_din_o : out std_logic;
pll20dac_sclk_o : out std_logic;
pll20dac_sync_n_o : out std_logic;
pll25dac_din_o : out std_logic;
pll25dac_sclk_o : out std_logic;
pll25dac_sync_n_o : out std_logic;
---------------------------------------------------------------------------
-- SFP I/O for transceiver
---------------------------------------------------------------------------
sfp_txp_o : out std_logic;
sfp_txn_o : out std_logic;
sfp_rxp_i : in std_logic;
sfp_rxn_i : in std_logic;
sfp_mod_def0_i : in std_logic; -- sfp detect
sfp_mod_def1_b : inout std_logic; -- scl
sfp_mod_def2_b : inout std_logic; -- sda
sfp_rate_select_o : out std_logic;
sfp_tx_fault_i : in std_logic;
sfp_tx_disable_o : out std_logic;
sfp_los_i : in std_logic;
---------------------------------------------------------------------------
-- Carrier I2C EEPROM
---------------------------------------------------------------------------
carrier_scl_b : inout std_logic;
carrier_sda_b : inout std_logic;
---------------------------------------------------------------------------
-- PCB version
---------------------------------------------------------------------------
pcbrev_i : in std_logic_vector(4 downto 0);
---------------------------------------------------------------------------
-- Onewire interface
---------------------------------------------------------------------------
onewire_b : inout std_logic;
---------------------------------------------------------------------------
-- UART
---------------------------------------------------------------------------
uart_rxd_i : in std_logic;
uart_txd_o : out std_logic;
---------------------------------------------------------------------------
-- SPI (flash is connected to SFPGA and routed to AFPGA
-- once the boot process is complete)
---------------------------------------------------------------------------
spi_sclk_o : out std_logic;
spi_ncs_o : out std_logic;
spi_mosi_o : out std_logic;
spi_miso_i : in std_logic;
---------------------------------------------------------------------------
-- Carrier front panel LEDs and IOs
---------------------------------------------------------------------------
fp_led_line_oen_o : out std_logic_vector(1 downto 0);
fp_led_line_o : out std_logic_vector(1 downto 0);
fp_led_column_o : out std_logic_vector(3 downto 0);
fp_gpio1_b : out std_logic; -- PPS output
fp_gpio2_b : out std_logic; -- not used
fp_gpio3_b : in std_logic; -- ext 10MHz clock input
fp_gpio4_b : in std_logic; -- ext PPS input
fp_term_en_o : out std_logic_vector(4 downto 1);
fp_gpio1_a2b_o : out std_logic;
fp_gpio2_a2b_o : out std_logic;
fp_gpio34_a2b_o : out std_logic;
---------------------------------------------------------------------------
-- FMC slot 1 pins (TDC mezzanine)
---------------------------------------------------------------------------
-- TDC1 PLL AD9516 and DAC AD5662 interface
fmc0_tdc_pll_sclk_o : out std_logic;
fmc0_tdc_pll_sdi_o : out std_logic;
fmc0_tdc_pll_cs_n_o : out std_logic;
fmc0_tdc_pll_dac_sync_o : out std_logic;
fmc0_tdc_pll_sdo_i : in std_logic;
fmc0_tdc_pll_status_i : in std_logic;
fmc0_tdc_clk_125m_p_i : in std_logic;
fmc0_tdc_clk_125m_n_i : in std_logic;
fmc0_tdc_acam_refclk_p_i : in std_logic;
fmc0_tdc_acam_refclk_n_i : in std_logic;
-- TDC1 ACAM timing interface
fmc0_tdc_start_from_fpga_o : out std_logic;
fmc0_tdc_err_flag_i : in std_logic;
fmc0_tdc_int_flag_i : in std_logic;
fmc0_tdc_start_dis_o : out std_logic;
fmc0_tdc_stop_dis_o : out std_logic;
-- TDC1 ACAM data interface
fmc0_tdc_data_bus_io : inout std_logic_vector(27 downto 0);
fmc0_tdc_address_o : out std_logic_vector(3 downto 0);
fmc0_tdc_cs_n_o : out std_logic;
fmc0_tdc_oe_n_o : out std_logic;
fmc0_tdc_rd_n_o : out std_logic;
fmc0_tdc_wr_n_o : out std_logic;
fmc0_tdc_ef1_i : in std_logic;
fmc0_tdc_ef2_i : in std_logic;
-- TDC1 Input Logic
fmc0_tdc_enable_inputs_o : out std_logic;
fmc0_tdc_term_en_1_o : out std_logic;
fmc0_tdc_term_en_2_o : out std_logic;
fmc0_tdc_term_en_3_o : out std_logic;
fmc0_tdc_term_en_4_o : out std_logic;
fmc0_tdc_term_en_5_o : out std_logic;
-- TDC1 1-wire UniqueID & Thermometer
fmc0_onewire_b : inout std_logic;
-- TDC1 EEPROM I2C
fmc0_tdc_scl_b : inout std_logic;
fmc0_tdc_sda_b : inout std_logic;
-- TDC1 LEDs
fmc0_tdc_led_status_o : out std_logic;
fmc0_tdc_led_trig1_o : out std_logic;
fmc0_tdc_led_trig2_o : out std_logic;
fmc0_tdc_led_trig3_o : out std_logic;
fmc0_tdc_led_trig4_o : out std_logic;
fmc0_tdc_led_trig5_o : out std_logic;
fmc0_prsnt_m2c_n_i : in std_logic;
fmc0_scl_b : inout std_logic;
fmc0_sda_b : inout std_logic;
---------------------------------------------------------------------------
-- FMC slot 2 pins (TDC mezzanine)
---------------------------------------------------------------------------
-- TDC1 PLL AD9516 and DAC AD5662 interface
fmc1_tdc_pll_sclk_o : out std_logic;
fmc1_tdc_pll_sdi_o : out std_logic;
fmc1_tdc_pll_cs_n_o : out std_logic;
fmc1_tdc_pll_dac_sync_o : out std_logic;
fmc1_tdc_pll_sdo_i : in std_logic;
fmc1_tdc_pll_status_i : in std_logic;
fmc1_tdc_clk_125m_p_i : in std_logic;
fmc1_tdc_clk_125m_n_i : in std_logic;
fmc1_tdc_acam_refclk_p_i : in std_logic;
fmc1_tdc_acam_refclk_n_i : in std_logic;
-- TDC1 ACAM timing interface
fmc1_tdc_start_from_fpga_o : out std_logic;
fmc1_tdc_err_flag_i : in std_logic;
fmc1_tdc_int_flag_i : in std_logic;
fmc1_tdc_start_dis_o : out std_logic;
fmc1_tdc_stop_dis_o : out std_logic;
-- TDC1 ACAM data interface
fmc1_tdc_data_bus_io : inout std_logic_vector(27 downto 0);
fmc1_tdc_address_o : out std_logic_vector(3 downto 0);
fmc1_tdc_cs_n_o : out std_logic;
fmc1_tdc_oe_n_o : out std_logic;
fmc1_tdc_rd_n_o : out std_logic;
fmc1_tdc_wr_n_o : out std_logic;
fmc1_tdc_ef1_i : in std_logic;
fmc1_tdc_ef2_i : in std_logic;
-- TDC1 Input Logic
fmc1_tdc_enable_inputs_o : out std_logic;
fmc1_tdc_term_en_1_o : out std_logic;
fmc1_tdc_term_en_2_o : out std_logic;
fmc1_tdc_term_en_3_o : out std_logic;
fmc1_tdc_term_en_4_o : out std_logic;
fmc1_tdc_term_en_5_o : out std_logic;
-- TDC1 1-wire UniqueID & Thermometer
fmc1_onewire_b : inout std_logic;
-- TDC1 EEPROM I2C
fmc1_tdc_scl_b : inout std_logic;
fmc1_tdc_sda_b : inout std_logic;
-- TDC1 LEDs
fmc1_tdc_led_status_o : out std_logic;
fmc1_tdc_led_trig1_o : out std_logic;
fmc1_tdc_led_trig2_o : out std_logic;
fmc1_tdc_led_trig3_o : out std_logic;
fmc1_tdc_led_trig4_o : out std_logic;
fmc1_tdc_led_trig5_o : out std_logic;
fmc1_prsnt_m2c_n_i : in std_logic;
fmc1_scl_b : inout std_logic;
fmc1_sda_b : inout std_logic);
end entity wrtd_ref_svec_tdc_x2;
architecture arch of wrtd_ref_svec_tdc_x2 is
-- WRTD Node identification (WTN2)
constant c_WRTD_NODE_ID : std_logic_vector(31 downto 0) := x"5754_4E03";
-- Convention metadata base address
constant c_METADATA_ADDR : t_wishbone_address := x"0000_4000";
constant c_MT_CONFIG : t_mt_config :=
(
app_id => c_WRTD_NODE_ID,
cpu_count => 1,
cpu_config => (
0 => (
memsize => 8192,
hmq_config => (
slot_count => 1,
slot_config => (
0 => (
entries_bits => 4,
width_bits => 7,
header_bits => 2,
endpoint_id => x"0000_0000",
enable_config_space => FALSE),
others => c_DUMMY_MT_MQUEUE_SLOT)),
rmq_config => (
slot_count => 1,
slot_config => (
0 => (
entries_bits => 4,
width_bits => 7,
header_bits => 4,
endpoint_id => x"0000_0000",
enable_config_space => TRUE),
others => c_DUMMY_MT_MQUEUE_SLOT))),
others => (
0, c_MT_DEFAULT_MQUEUE_CONFIG, c_MT_DEFAULT_MQUEUE_CONFIG)),
shared_mem_size => 256
);
-----------------------------------------------------------------------------
-- Signals
-----------------------------------------------------------------------------
signal master_wb_out : t_wishbone_master_out;
signal master_wb_in : t_wishbone_master_in;
signal metadata_wb_out : t_wishbone_slave_out;
signal metadata_wb_in : t_wishbone_slave_in;
signal tdc0_wb_out : t_wishbone_slave_out;
signal tdc0_wb_in : t_wishbone_slave_in;
signal tdc1_wb_out : t_wishbone_slave_out;
signal tdc1_wb_in : t_wishbone_slave_in;
signal mt_wb_out : t_wishbone_slave_out;
signal mt_wb_in : t_wishbone_slave_in;
-- clock and reset
signal areset_n : std_logic;
signal clk_sys_62m5 : std_logic;
signal rst_sys_62m5_n : std_logic;
signal clk_ref_125m : std_logic;
signal clk_ext_ref : std_logic;
signal tdc0_clk_125m : std_logic;
signal tdc1_clk_125m : std_logic;
attribute keep : string;
attribute keep of tdc0_clk_125m : signal is "TRUE";
attribute keep of tdc1_clk_125m : signal is "TRUE";
-- VME
signal vme_access_led : std_logic;
-- LEDs and GPIO
signal pps : std_logic;
signal pps_led : std_logic;
signal pps_ext_in : std_logic;
signal svec_led : std_logic_vector(15 downto 0);
signal wr_led_link : std_logic;
signal wr_led_act : std_logic;
-- Interrupts
signal irq_vector : std_logic_vector(5 downto 0);
-- MT endpoints
signal rmq_endpoint_out : t_mt_rmq_endpoint_iface_out;
signal rmq_endpoint_in : t_mt_rmq_endpoint_iface_in;
signal rmq_src_in : t_mt_stream_source_in;
signal rmq_src_out : t_mt_stream_source_out;
signal rmq_src_cfg_in : t_mt_stream_config_in;
signal rmq_src_cfg_out : t_mt_stream_config_out;
signal rmq_snk_in : t_mt_stream_sink_in;
signal rmq_snk_out : t_mt_stream_sink_out;
signal rmq_snk_cfg_in : t_mt_stream_config_in;
signal rmq_snk_cfg_out : t_mt_stream_config_out;
-- MT fabric.
signal eth_tx_out : t_wrf_source_out;
signal eth_tx_in : t_wrf_source_in;
signal eth_rx_out : t_wrf_sink_out;
signal eth_rx_in : t_wrf_sink_in;
-- MT Dedicated WB interfaces to FMCs
signal fmc_dp_wb_out : t_wishbone_master_out;
signal fmc_dp_wb_in : t_wishbone_master_in;
signal tdc0_dp_wb_out : t_wishbone_slave_out;
signal tdc0_dp_wb_in : t_wishbone_slave_in;
signal tdc1_dp_wb_out : t_wishbone_slave_out;
signal tdc1_dp_wb_in : t_wishbone_slave_in;
-- WRPC TM interface and aux clocks
signal tm_link_up : std_logic;
signal tm_tai : std_logic_vector(39 downto 0);
signal tm_cycles : std_logic_vector(27 downto 0);
signal tm_time_valid : std_logic;
signal tm_clk_aux_lock_en : std_logic_vector(1 downto 0);
signal tm_clk_aux_locked : std_logic_vector(1 downto 0);
signal tm_dac_value : std_logic_vector(23 downto 0);
signal tm_dac_wr : std_logic_vector(1 downto 0);
-- MT TM interface
signal tm : t_mt_timing_if;
attribute iob : string;
attribute iob of pps : signal is "FORCE";
begin -- architecture arch
areset_n <= vme_sysreset_n_i and rst_n_i;
cmp_xwb_metadata : entity work.xwb_metadata
generic map (
g_VENDOR_ID => x"0000_10DC",
g_DEVICE_ID => c_WRTD_NODE_ID,
g_VERSION => x"0100_0001",
g_CAPABILITIES => x"0000_0000",
g_COMMIT_ID => (others => '0'))
port map (
clk_i => clk_sys_62m5,
rst_n_i => rst_sys_62m5_n,
wb_i => metadata_wb_in,
wb_o => metadata_wb_out);
inst_svec_base : entity work.svec_base_wr
generic map (
g_WITH_VIC => TRUE,
g_WITH_ONEWIRE => FALSE,
g_WITH_SPI => FALSE,
g_WITH_WR => TRUE,
g_WITH_DDR4 => FALSE,
g_WITH_DDR5 => FALSE,
g_APP_OFFSET => c_METADATA_ADDR,
g_NUM_USER_IRQ => 6,
g_DPRAM_INITF => g_WRPC_INITF,
g_AUX_CLKS => 2,
g_FABRIC_IFACE => plain,
g_SIMULATION => g_SIMULATION,
g_VERBOSE => FALSE)
port map (
rst_n_i => areset_n,
clk_125m_pllref_p_i => clk_125m_pllref_p_i,
clk_125m_pllref_n_i => clk_125m_pllref_n_i,
clk_20m_vcxo_i => clk_20m_vcxo_i,
clk_125m_gtp_n_i => clk_125m_gtp_n_i,
clk_125m_gtp_p_i => clk_125m_gtp_p_i,
clk_aux_i(0) => tdc0_clk_125m,
clk_aux_i(1) => tdc1_clk_125m,
clk_10m_ext_i => clk_ext_ref,
pps_ext_i => pps_ext_in,
vme_write_n_i => vme_write_n_i,
vme_sysreset_n_i => vme_sysreset_n_i,
vme_retry_oe_o => vme_retry_oe_o,
vme_retry_n_o => vme_retry_n_o,
vme_lword_n_b => vme_lword_n_b,
vme_iackout_n_o => vme_iackout_n_o,
vme_iackin_n_i => vme_iackin_n_i,
vme_iack_n_i => vme_iack_n_i,
vme_gap_i => vme_gap_i,
vme_dtack_oe_o => vme_dtack_oe_o,
vme_dtack_n_o => vme_dtack_n_o,
vme_ds_n_i => vme_ds_n_i,
vme_data_oe_n_o => vme_data_oe_n_o,
vme_data_dir_o => vme_data_dir_o,
vme_berr_o => vme_berr_o,
vme_as_n_i => vme_as_n_i,
vme_addr_oe_n_o => vme_addr_oe_n_o,
vme_addr_dir_o => vme_addr_dir_o,
vme_irq_o => vme_irq_o,
vme_ga_i => vme_ga_i,
vme_data_b => vme_data_b,
vme_am_i => vme_am_i,
vme_addr_b => vme_addr_b,
fmc0_scl_b => fmc0_scl_b,
fmc0_sda_b => fmc0_sda_b,
fmc1_scl_b => fmc1_scl_b,
fmc1_sda_b => fmc1_sda_b,
fmc0_prsnt_m2c_n_i => fmc0_prsnt_m2c_n_i,
fmc1_prsnt_m2c_n_i => fmc1_prsnt_m2c_n_i,
onewire_b => onewire_b,
carrier_scl_b => carrier_scl_b,
carrier_sda_b => carrier_sda_b,
spi_sclk_o => spi_sclk_o,
spi_ncs_o => spi_ncs_o,
spi_mosi_o => spi_mosi_o,
spi_miso_i => spi_miso_i,
uart_rxd_i => uart_rxd_i,
uart_txd_o => uart_txd_o,
plldac_sclk_o => pll20dac_sclk_o,
plldac_din_o => pll20dac_din_o,
pll20dac_din_o => pll20dac_din_o,
pll20dac_sclk_o => pll20dac_sclk_o,
pll20dac_sync_n_o => pll20dac_sync_n_o,
pll25dac_din_o => pll25dac_din_o,
pll25dac_sclk_o => pll25dac_sclk_o,
pll25dac_sync_n_o => pll25dac_sync_n_o,
sfp_txp_o => sfp_txp_o,
sfp_txn_o => sfp_txn_o,
sfp_rxp_i => sfp_rxp_i,
sfp_rxn_i => sfp_rxn_i,
sfp_mod_def0_i => sfp_mod_def0_i,
sfp_mod_def1_b => sfp_mod_def1_b,
sfp_mod_def2_b => sfp_mod_def2_b,
sfp_rate_select_o => sfp_rate_select_o,
sfp_tx_fault_i => sfp_tx_fault_i,
sfp_tx_disable_o => sfp_tx_disable_o,
sfp_los_i => sfp_los_i,
pcbrev_i => pcbrev_i,
clk_sys_62m5_o => clk_sys_62m5,
rst_sys_62m5_n_o => rst_sys_62m5_n,
clk_ref_125m_o => clk_ref_125m,
rst_ref_125m_n_o => open,
irq_user_i => irq_vector,
wrf_src_o => eth_rx_in,
wrf_src_i => eth_rx_out,
wrf_snk_o => eth_tx_in,
wrf_snk_i => eth_tx_out,
tm_link_up_o => tm_link_up,
tm_time_valid_o => tm_time_valid,
tm_tai_o => tm_tai,
tm_cycles_o => tm_cycles,
tm_dac_value_o => tm_dac_value,
tm_dac_wr_o => tm_dac_wr,
tm_clk_aux_lock_en_i => tm_clk_aux_lock_en,
tm_clk_aux_locked_o => tm_clk_aux_locked,
pps_p_o => pps,
pps_led_o => pps_led,
link_ok_o => open,
led_link_o => wr_led_link,
led_act_o => wr_led_act,
app_wb_o => master_wb_out,
app_wb_i => master_wb_in);
-----------------------------------------------------------------------------
-- Primary wishbone Crossbar
-----------------------------------------------------------------------------
inst_host_memmap: entity work.wrtd_tdc_x2_host_map
port map (
rst_n_i => rst_sys_62m5_n,
clk_i => clk_sys_62m5,
wb_i => master_wb_out,
wb_o => master_wb_in,
metadata_i => metadata_wb_out,
metadata_o => metadata_wb_in,
tdc0_i => tdc0_wb_out,
tdc0_o => tdc0_wb_in,
tdc1_i => tdc1_wb_out,
tdc1_o => tdc1_wb_in,
mt_i => mt_wb_out,
mt_o => mt_wb_in);
cmp_vme_led_extend : gc_extend_pulse
generic map (
g_width => 5000000)
port map (
clk_i => clk_sys_62m5,
rst_n_i => rst_sys_62m5_n,
pulse_i => master_wb_out.cyc,
extended_o => vme_access_led);
-----------------------------------------------------------------------------
-- Mock Turtle (WB Slave)
-----------------------------------------------------------------------------
inst_mock_turtle : entity work.mock_turtle_core
generic map (
g_CONFIG => c_MT_CONFIG,
g_CPU0_IRAM_INITF => g_MT_CPU0_INITF,
g_WITH_WHITE_RABBIT => TRUE)
port map (
clk_i => clk_sys_62m5,
rst_n_i => rst_sys_62m5_n,
sp_master_o => open,
sp_master_i => c_DUMMY_WB_MASTER_IN,
dp_master_o(0) => fmc_dp_wb_out,
dp_master_i(0) => fmc_dp_wb_in,
rmq_endpoint_o => rmq_endpoint_out,
rmq_endpoint_i => rmq_endpoint_in,
host_slave_i => mt_wb_in,
host_slave_o => mt_wb_out,
clk_ref_i => clk_ref_125m,
tm_i => tm,
hmq_in_irq_o => irq_vector(2),
hmq_out_irq_o => irq_vector(3),
notify_irq_o => irq_vector(5),
console_irq_o => irq_vector(4));
tm.cycles <= tm_cycles;
tm.tai <= tm_tai;
tm.time_valid <= tm_time_valid;
tm.link_up <= tm_link_up;
tm.aux_locked(1 downto 0) <= tm_clk_aux_locked;
tm.aux_locked(7 downto 2) <= (others => '0');
cmp_eth_endpoint : entity work.mt_ep_ethernet_single
port map (
clk_i => clk_sys_62m5,
rst_n_i => rst_sys_62m5_n,
rmq_src_i => rmq_src_in,
rmq_src_o => rmq_src_out,
rmq_src_config_i => rmq_snk_cfg_out,
rmq_src_config_o => rmq_snk_cfg_in,
rmq_snk_i => rmq_snk_in,
rmq_snk_o => rmq_snk_out,
rmq_snk_config_i => rmq_src_cfg_out,
rmq_snk_config_o => rmq_src_cfg_in,
eth_src_o => eth_tx_out,
eth_src_i => eth_tx_in,
eth_snk_o => eth_rx_out,
eth_snk_i => eth_rx_in);
p_rmq_assign : process (rmq_endpoint_out, rmq_snk_cfg_in, rmq_snk_out,
rmq_src_cfg_in, rmq_src_out) is
begin
rmq_endpoint_in <= c_MT_RMQ_ENDPOINT_IFACE_IN_DEFAULT_VALUE;
-- WR->MT (RX, to MT CPU1)
rmq_src_in <= rmq_endpoint_out.snk_out(1)(0);
rmq_endpoint_in.snk_in(1)(0) <= rmq_src_out;
rmq_snk_cfg_out <= rmq_endpoint_out.snk_config_out(1)(0);
rmq_endpoint_in.snk_config_in(1)(0) <= rmq_snk_cfg_in;
-- MT->WR (TX, from MT CPU0)
rmq_snk_in <= rmq_endpoint_out.src_out(0)(0);
rmq_endpoint_in.src_in(0)(0) <= rmq_snk_out;
rmq_src_cfg_out <= rmq_endpoint_out.src_config_out(0)(0);
rmq_endpoint_in.src_config_in(0)(0) <= rmq_src_cfg_in;
end process p_rmq_assign;
my_inst: entity work.wrtd_tdc_x2_fmc_map
port map (
rst_n_i => rst_sys_62m5_n,
clk_i => clk_sys_62m5,
wb_i => fmc_dp_wb_out,
wb_o => fmc_dp_wb_in,
tdc0_i => tdc0_dp_wb_out,
tdc0_o => tdc0_dp_wb_in,
tdc1_i => tdc1_dp_wb_out,
tdc1_o => tdc1_dp_wb_in
);
-----------------------------------------------------------------------------
-- FMC TDC (SVEC slot #1)
-----------------------------------------------------------------------------
U_TDC_Core0 : entity work.fmc_tdc_wrapper
generic map (
g_SIMULATION => f_int2bool(g_SIMULATION),
g_PULSE_WIDTH_FILTER => FALSE,
g_USE_FIFO_READOUT => FALSE,
g_USE_DMA_READOUT => FALSE,
g_WITH_DIRECT_READOUT => TRUE)
port map (
clk_sys_i => clk_sys_62m5,
rst_sys_n_i => rst_sys_62m5_n,
rst_n_a_i => rst_sys_62m5_n,
fmc_id_i => '0',
fmc_present_n_i => fmc0_prsnt_m2c_n_i,
pll_sclk_o => fmc0_tdc_pll_sclk_o,
pll_sdi_o => fmc0_tdc_pll_sdi_o,
pll_cs_o => fmc0_tdc_pll_cs_n_o,
pll_dac_sync_o => fmc0_tdc_pll_dac_sync_o,
pll_sdo_i => fmc0_tdc_pll_sdo_i,
pll_status_i => fmc0_tdc_pll_status_i,
tdc_clk_125m_p_i => fmc0_tdc_clk_125m_p_i,
tdc_clk_125m_n_i => fmc0_tdc_clk_125m_n_i,
acam_refclk_p_i => fmc0_tdc_acam_refclk_p_i,
acam_refclk_n_i => fmc0_tdc_acam_refclk_n_i,
start_from_fpga_o => fmc0_tdc_start_from_fpga_o,
err_flag_i => fmc0_tdc_err_flag_i,
int_flag_i => fmc0_tdc_int_flag_i,
start_dis_o => fmc0_tdc_start_dis_o,
stop_dis_o => fmc0_tdc_stop_dis_o,
data_bus_io => fmc0_tdc_data_bus_io,
address_o => fmc0_tdc_address_o,
cs_n_o => fmc0_tdc_cs_n_o,
oe_n_o => fmc0_tdc_oe_n_o,
rd_n_o => fmc0_tdc_rd_n_o,
wr_n_o => fmc0_tdc_wr_n_o,
ef1_i => fmc0_tdc_ef1_i,
ef2_i => fmc0_tdc_ef2_i,
enable_inputs_o => fmc0_tdc_enable_inputs_o,
term_en_1_o => fmc0_tdc_term_en_1_o,
term_en_2_o => fmc0_tdc_term_en_2_o,
term_en_3_o => fmc0_tdc_term_en_3_o,
term_en_4_o => fmc0_tdc_term_en_4_o,
term_en_5_o => fmc0_tdc_term_en_5_o,
tdc_led_stat_o => fmc0_tdc_led_status_o,
tdc_led_trig_o(0) => fmc0_tdc_led_trig1_o,
tdc_led_trig_o(1) => fmc0_tdc_led_trig2_o,
tdc_led_trig_o(2) => fmc0_tdc_led_trig3_o,
tdc_led_trig_o(3) => fmc0_tdc_led_trig4_o,
tdc_led_trig_o(4) => fmc0_tdc_led_trig5_o,
mezz_scl_i => '0',
mezz_sda_i => '0',
mezz_scl_o => open,
mezz_sda_o => open,
mezz_one_wire_b => fmc0_onewire_b,
tm_link_up_i => tm_link_up,
tm_time_valid_i => tm_time_valid,
tm_cycles_i => tm_cycles,
tm_tai_i => tm_tai,
tm_clk_aux_lock_en_o => tm_clk_aux_lock_en(0),
tm_clk_aux_locked_i => tm_clk_aux_locked(0),
tm_clk_dmtd_locked_i => '1',
tm_dac_value_i => tm_dac_value,
tm_dac_wr_i => tm_dac_wr(0),
direct_slave_i => tdc0_dp_wb_in,
direct_slave_o => tdc0_dp_wb_out,
slave_i => tdc0_wb_in,
slave_o => tdc0_wb_out,
irq_o => irq_vector(0),
clk_125m_tdc_o => tdc0_clk_125m);
-----------------------------------------------------------------------------
-- FMC TDC (SVEC slot #2)
-----------------------------------------------------------------------------
U_TDC_Core1 : entity work.fmc_tdc_wrapper
generic map (
g_SIMULATION => f_int2bool(g_SIMULATION),
g_PULSE_WIDTH_FILTER => FALSE,
g_USE_FIFO_READOUT => FALSE,
g_USE_DMA_READOUT => FALSE,
g_WITH_DIRECT_READOUT => TRUE)
port map (
clk_sys_i => clk_sys_62m5,
rst_sys_n_i => rst_sys_62m5_n,
rst_n_a_i => rst_sys_62m5_n,
fmc_id_i => '1',
fmc_present_n_i => fmc1_prsnt_m2c_n_i,
pll_sclk_o => fmc1_tdc_pll_sclk_o,
pll_sdi_o => fmc1_tdc_pll_sdi_o,
pll_cs_o => fmc1_tdc_pll_cs_n_o,
pll_dac_sync_o => fmc1_tdc_pll_dac_sync_o,
pll_sdo_i => fmc1_tdc_pll_sdo_i,
pll_status_i => fmc1_tdc_pll_status_i,
tdc_clk_125m_p_i => fmc1_tdc_clk_125m_p_i,
tdc_clk_125m_n_i => fmc1_tdc_clk_125m_n_i,
acam_refclk_p_i => fmc1_tdc_acam_refclk_p_i,
acam_refclk_n_i => fmc1_tdc_acam_refclk_n_i,
start_from_fpga_o => fmc1_tdc_start_from_fpga_o,
err_flag_i => fmc1_tdc_err_flag_i,
int_flag_i => fmc1_tdc_int_flag_i,
start_dis_o => fmc1_tdc_start_dis_o,
stop_dis_o => fmc1_tdc_stop_dis_o,
data_bus_io => fmc1_tdc_data_bus_io,
address_o => fmc1_tdc_address_o,
cs_n_o => fmc1_tdc_cs_n_o,
oe_n_o => fmc1_tdc_oe_n_o,
rd_n_o => fmc1_tdc_rd_n_o,
wr_n_o => fmc1_tdc_wr_n_o,
ef1_i => fmc1_tdc_ef1_i,
ef2_i => fmc1_tdc_ef2_i,
enable_inputs_o => fmc1_tdc_enable_inputs_o,
term_en_1_o => fmc1_tdc_term_en_1_o,
term_en_2_o => fmc1_tdc_term_en_2_o,
term_en_3_o => fmc1_tdc_term_en_3_o,
term_en_4_o => fmc1_tdc_term_en_4_o,
term_en_5_o => fmc1_tdc_term_en_5_o,
tdc_led_stat_o => fmc1_tdc_led_status_o,
tdc_led_trig_o(0) => fmc1_tdc_led_trig1_o,
tdc_led_trig_o(1) => fmc1_tdc_led_trig2_o,
tdc_led_trig_o(2) => fmc1_tdc_led_trig3_o,
tdc_led_trig_o(3) => fmc1_tdc_led_trig4_o,
tdc_led_trig_o(4) => fmc1_tdc_led_trig5_o,
mezz_scl_i => '0',
mezz_sda_i => '0',
mezz_scl_o => open,
mezz_sda_o => open,
mezz_one_wire_b => fmc1_onewire_b,
tm_link_up_i => tm_link_up,
tm_time_valid_i => tm_time_valid,
tm_cycles_i => tm_cycles,
tm_tai_i => tm_tai,
tm_clk_aux_lock_en_o => tm_clk_aux_lock_en(1),
tm_clk_aux_locked_i => tm_clk_aux_locked(1),
tm_clk_dmtd_locked_i => '1',
tm_dac_value_i => tm_dac_value,
tm_dac_wr_i => tm_dac_wr(1),
direct_slave_i => tdc1_dp_wb_in,
direct_slave_o => tdc1_dp_wb_out,
slave_i => tdc1_wb_in,
slave_o => tdc1_wb_out,
irq_o => irq_vector(1),
clk_125m_tdc_o => tdc1_clk_125m);
-----------------------------------------------------------------------------
-- Carrier front panel LEDs and LEMOs
-----------------------------------------------------------------------------
cmp_led_controller : gc_bicolor_led_ctrl
generic map(
g_NB_COLUMN => 4,
g_NB_LINE => 2,
g_CLK_FREQ => 62500000, -- in Hz
g_REFRESH_RATE => 250 -- in Hz
)
port map(
rst_n_i => rst_sys_62m5_n,
clk_i => clk_sys_62m5,
led_intensity_i => "1100100", -- in %
led_state_i => svec_led,
column_o => fp_led_column_o,
line_o => fp_led_line_o,
line_oen_o => fp_led_line_oen_o);
-- LED 4
svec_led(1 downto 0) <= c_LED_GREEN when wr_led_link = '1' else c_LED_RED;
-- LED 3
svec_led(3 downto 2) <= c_LED_GREEN when tm_clk_aux_locked(1) = '1' else c_LED_RED;
-- LED 2
svec_led(5 downto 4) <= c_LED_GREEN when tm_time_valid = '1' else c_LED_RED;
-- LED 1
svec_led(7 downto 6) <= c_LED_RED_GREEN when vme_access_led = '1' else c_LED_OFF;
-- LED 8
svec_led(9 downto 8) <= c_LED_RED_GREEN when wr_led_act = '1' else c_LED_OFF;
-- LED 7
svec_led(11 downto 10) <= c_LED_GREEN when tm_clk_aux_locked(0) = '1' else c_LED_RED;
-- LED 6
svec_led(13 downto 12) <= c_LED_OFF;
-- LED 5
svec_led(15 downto 14) <= c_LED_GREEN when pps_led = '1' else c_LED_OFF;
-- Front panel IO configuration
fp_gpio1_b <= pps;
fp_gpio2_b <= '0';
clk_ext_ref <= fp_gpio3_b;
pps_ext_in <= fp_gpio4_b;
fp_term_en_o <= (others => '0');
fp_gpio1_a2b_o <= '1';
fp_gpio2_a2b_o <= '1';
fp_gpio34_a2b_o <= '0';
end architecture arch;
memory-map:
name: wrtd_tdc_x2_fmc_map
bus: wb-32-be
size: 0x20000
x-hdl:
busgroup: True
children:
- submap:
name: tdc0
description: TDC0
address: 0x00000
size: 0x10000
interface: wb-32-be
x-hdl:
busgroup: True
- submap:
name: tdc1
description: TDC1
address: 0x10000
size: 0x10000
interface: wb-32-be
x-hdl:
busgroup: True
-- Do not edit. Generated on Tue Feb 16 14:11:11 2021 by tgingold
-- With Cheby 1.4.dev0 and these options:
-- --gen-hdl wrtd_tdc_x2_fmc_map.vhd -i wrtd_tdc_x2_fmc_map.cheby
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
entity wrtd_tdc_x2_fmc_map is
port (
rst_n_i : in std_logic;
clk_i : in std_logic;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out;
-- TDC0
tdc0_i : in t_wishbone_master_in;
tdc0_o : out t_wishbone_master_out;
-- TDC1
tdc1_i : in t_wishbone_master_in;
tdc1_o : out t_wishbone_master_out
);
end wrtd_tdc_x2_fmc_map;
architecture syn of wrtd_tdc_x2_fmc_map is
signal adr_int : std_logic_vector(16 downto 2);
signal rd_req_int : std_logic;
signal wr_req_int : std_logic;
signal rd_ack_int : std_logic;
signal wr_ack_int : std_logic;
signal wb_en : std_logic;
signal ack_int : std_logic;
signal wb_rip : std_logic;
signal wb_wip : std_logic;
signal tdc0_re : std_logic;
signal tdc0_we : std_logic;
signal tdc0_wt : std_logic;
signal tdc0_rt : std_logic;
signal tdc0_tr : std_logic;
signal tdc0_wack : std_logic;
signal tdc0_rack : std_logic;
signal tdc1_re : std_logic;
signal tdc1_we : std_logic;
signal tdc1_wt : std_logic;
signal tdc1_rt : std_logic;
signal tdc1_tr : std_logic;
signal tdc1_wack : std_logic;
signal tdc1_rack : std_logic;
signal rd_ack_d0 : std_logic;
signal rd_dat_d0 : std_logic_vector(31 downto 0);
signal wr_req_d0 : std_logic;
signal wr_adr_d0 : std_logic_vector(16 downto 2);
signal wr_dat_d0 : std_logic_vector(31 downto 0);
signal wr_sel_d0 : std_logic_vector(3 downto 0);
begin
-- WB decode signals
adr_int <= wb_i.adr(16 downto 2);
wb_en <= wb_i.cyc and wb_i.stb;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_rip <= '0';
else
wb_rip <= (wb_rip or (wb_en and not wb_i.we)) and not rd_ack_int;
end if;
end if;
end process;
rd_req_int <= (wb_en and not wb_i.we) and not wb_rip;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_wip <= '0';
else
wb_wip <= (wb_wip or (wb_en and wb_i.we)) and not wr_ack_int;
end if;
end if;
end process;
wr_req_int <= (wb_en and wb_i.we) and not wb_wip;
ack_int <= rd_ack_int or wr_ack_int;
wb_o.ack <= ack_int;
wb_o.stall <= not ack_int and wb_en;
wb_o.rty <= '0';
wb_o.err <= '0';
-- pipelining for wr-in+rd-out
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
rd_ack_int <= '0';
wr_req_d0 <= '0';
else
rd_ack_int <= rd_ack_d0;
wb_o.dat <= rd_dat_d0;
wr_req_d0 <= wr_req_int;
wr_adr_d0 <= adr_int;
wr_dat_d0 <= wb_i.dat;
wr_sel_d0 <= wb_i.sel;
end if;
end if;
end process;
-- Interface tdc0
tdc0_tr <= tdc0_wt or tdc0_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
tdc0_rt <= '0';
tdc0_wt <= '0';
else
tdc0_rt <= (tdc0_rt or tdc0_re) and not tdc0_rack;
tdc0_wt <= (tdc0_wt or tdc0_we) and not tdc0_wack;
end if;
end if;
end process;
tdc0_o.cyc <= tdc0_tr;
tdc0_o.stb <= tdc0_tr;
tdc0_wack <= tdc0_i.ack and tdc0_wt;
tdc0_rack <= tdc0_i.ack and tdc0_rt;
tdc0_o.adr <= ((15 downto 0 => '0') & adr_int(15 downto 2)) & (1 downto 0 => '0');
tdc0_o.sel <= wr_sel_d0;
tdc0_o.we <= tdc0_wt;
tdc0_o.dat <= wr_dat_d0;
-- Interface tdc1
tdc1_tr <= tdc1_wt or tdc1_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
tdc1_rt <= '0';
tdc1_wt <= '0';
else
tdc1_rt <= (tdc1_rt or tdc1_re) and not tdc1_rack;
tdc1_wt <= (tdc1_wt or tdc1_we) and not tdc1_wack;
end if;
end if;
end process;
tdc1_o.cyc <= tdc1_tr;
tdc1_o.stb <= tdc1_tr;
tdc1_wack <= tdc1_i.ack and tdc1_wt;
tdc1_rack <= tdc1_i.ack and tdc1_rt;
tdc1_o.adr <= ((15 downto 0 => '0') & adr_int(15 downto 2)) & (1 downto 0 => '0');
tdc1_o.sel <= wr_sel_d0;
tdc1_o.we <= tdc1_wt;
tdc1_o.dat <= wr_dat_d0;
-- Process for write requests.
process (wr_adr_d0, wr_req_d0, tdc0_wack, tdc1_wack) begin
tdc0_we <= '0';
tdc1_we <= '0';
case wr_adr_d0(16 downto 16) is
when "0" =>
-- Submap tdc0
tdc0_we <= wr_req_d0;
wr_ack_int <= tdc0_wack;
when "1" =>
-- Submap tdc1
tdc1_we <= wr_req_d0;
wr_ack_int <= tdc1_wack;
when others =>
wr_ack_int <= wr_req_d0;
end case;
end process;
-- Process for read requests.
process (adr_int, rd_req_int, tdc0_i.dat, tdc0_rack, tdc1_i.dat, tdc1_rack) begin
-- By default ack read requests
rd_dat_d0 <= (others => 'X');
tdc0_re <= '0';
tdc1_re <= '0';
case adr_int(16 downto 16) is
when "0" =>
-- Submap tdc0
tdc0_re <= rd_req_int;
rd_dat_d0 <= tdc0_i.dat;
rd_ack_d0 <= tdc0_rack;
when "1" =>
-- Submap tdc1
tdc1_re <= rd_req_int;
rd_dat_d0 <= tdc1_i.dat;
rd_ack_d0 <= tdc1_rack;
when others =>
rd_ack_d0 <= rd_req_int;
end case;
end process;
end syn;
memory-map:
name: wrtd_tdc_x2_host_map
bus: wb-32-be
size: 0x80000
x-hdl:
busgroup: True
children:
- submap:
name: metadata
description: a ROM containing the carrier metadata
address: 0x4000
size: 0x40
interface: wb-32-be
x-hdl:
busgroup: True
- submap:
name: tdc0
description: TDC0
address: 0x10000
size: 0x10000
interface: wb-32-be
x-hdl:
busgroup: True
- submap:
name: tdc1
description: TDC1
address: 0x20000
size: 0x10000
interface: wb-32-be
x-hdl:
busgroup: True
- submap:
name: mt
description: Mock Turtle
address: 0x40000
size: 0x20000
interface: wb-32-be
x-hdl:
busgroup: True
-- Do not edit. Generated on Tue Feb 16 11:24:52 2021 by tgingold
-- With Cheby 1.4.dev0 and these options:
-- --gen-hdl wrtd_tdc_x2_host_map.vhd -i wrtd_tdc_x2_host_map.cheby
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
entity wrtd_tdc_x2_host_map is
port (
rst_n_i : in std_logic;
clk_i : in std_logic;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out;
-- a ROM containing the carrier metadata
metadata_i : in t_wishbone_master_in;
metadata_o : out t_wishbone_master_out;
-- TDC0
tdc0_i : in t_wishbone_master_in;
tdc0_o : out t_wishbone_master_out;
-- TDC1
tdc1_i : in t_wishbone_master_in;
tdc1_o : out t_wishbone_master_out;
-- Mock Turtle
mt_i : in t_wishbone_master_in;
mt_o : out t_wishbone_master_out
);
end wrtd_tdc_x2_host_map;
architecture syn of wrtd_tdc_x2_host_map is
signal adr_int : std_logic_vector(18 downto 2);
signal rd_req_int : std_logic;
signal wr_req_int : std_logic;
signal rd_ack_int : std_logic;
signal wr_ack_int : std_logic;
signal wb_en : std_logic;
signal ack_int : std_logic;
signal wb_rip : std_logic;
signal wb_wip : std_logic;
signal metadata_re : std_logic;
signal metadata_we : std_logic;
signal metadata_wt : std_logic;
signal metadata_rt : std_logic;
signal metadata_tr : std_logic;
signal metadata_wack : std_logic;
signal metadata_rack : std_logic;
signal tdc0_re : std_logic;
signal tdc0_we : std_logic;
signal tdc0_wt : std_logic;
signal tdc0_rt : std_logic;
signal tdc0_tr : std_logic;
signal tdc0_wack : std_logic;
signal tdc0_rack : std_logic;
signal tdc1_re : std_logic;
signal tdc1_we : std_logic;
signal tdc1_wt : std_logic;
signal tdc1_rt : std_logic;
signal tdc1_tr : std_logic;
signal tdc1_wack : std_logic;
signal tdc1_rack : std_logic;
signal mt_re : std_logic;
signal mt_we : std_logic;
signal mt_wt : std_logic;
signal mt_rt : std_logic;
signal mt_tr : std_logic;
signal mt_wack : std_logic;
signal mt_rack : std_logic;
signal rd_ack_d0 : std_logic;
signal rd_dat_d0 : std_logic_vector(31 downto 0);
signal wr_req_d0 : std_logic;
signal wr_adr_d0 : std_logic_vector(18 downto 2);
signal wr_dat_d0 : std_logic_vector(31 downto 0);
signal wr_sel_d0 : std_logic_vector(3 downto 0);
begin
-- WB decode signals
adr_int <= wb_i.adr(18 downto 2);
wb_en <= wb_i.cyc and wb_i.stb;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_rip <= '0';
else
wb_rip <= (wb_rip or (wb_en and not wb_i.we)) and not rd_ack_int;
end if;
end if;
end process;
rd_req_int <= (wb_en and not wb_i.we) and not wb_rip;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_wip <= '0';
else
wb_wip <= (wb_wip or (wb_en and wb_i.we)) and not wr_ack_int;
end if;
end if;
end process;
wr_req_int <= (wb_en and wb_i.we) and not wb_wip;
ack_int <= rd_ack_int or wr_ack_int;
wb_o.ack <= ack_int;
wb_o.stall <= not ack_int and wb_en;
wb_o.rty <= '0';
wb_o.err <= '0';
-- pipelining for wr-in+rd-out
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
rd_ack_int <= '0';
wr_req_d0 <= '0';
else
rd_ack_int <= rd_ack_d0;
wb_o.dat <= rd_dat_d0;
wr_req_d0 <= wr_req_int;
wr_adr_d0 <= adr_int;
wr_dat_d0 <= wb_i.dat;
wr_sel_d0 <= wb_i.sel;
end if;
end if;
end process;
-- Interface metadata
metadata_tr <= metadata_wt or metadata_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
metadata_rt <= '0';
metadata_wt <= '0';
else
metadata_rt <= (metadata_rt or metadata_re) and not metadata_rack;
metadata_wt <= (metadata_wt or metadata_we) and not metadata_wack;
end if;
end if;
end process;
metadata_o.cyc <= metadata_tr;
metadata_o.stb <= metadata_tr;
metadata_wack <= metadata_i.ack and metadata_wt;
metadata_rack <= metadata_i.ack and metadata_rt;
metadata_o.adr <= ((25 downto 0 => '0') & adr_int(5 downto 2)) & (1 downto 0 => '0');
metadata_o.sel <= wr_sel_d0;
metadata_o.we <= metadata_wt;
metadata_o.dat <= wr_dat_d0;
-- Interface tdc0
tdc0_tr <= tdc0_wt or tdc0_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
tdc0_rt <= '0';
tdc0_wt <= '0';
else
tdc0_rt <= (tdc0_rt or tdc0_re) and not tdc0_rack;
tdc0_wt <= (tdc0_wt or tdc0_we) and not tdc0_wack;
end if;
end if;
end process;
tdc0_o.cyc <= tdc0_tr;
tdc0_o.stb <= tdc0_tr;
tdc0_wack <= tdc0_i.ack and tdc0_wt;
tdc0_rack <= tdc0_i.ack and tdc0_rt;
tdc0_o.adr <= ((15 downto 0 => '0') & adr_int(15 downto 2)) & (1 downto 0 => '0');
tdc0_o.sel <= wr_sel_d0;
tdc0_o.we <= tdc0_wt;
tdc0_o.dat <= wr_dat_d0;
-- Interface tdc1
tdc1_tr <= tdc1_wt or tdc1_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
tdc1_rt <= '0';
tdc1_wt <= '0';
else
tdc1_rt <= (tdc1_rt or tdc1_re) and not tdc1_rack;
tdc1_wt <= (tdc1_wt or tdc1_we) and not tdc1_wack;
end if;
end if;
end process;
tdc1_o.cyc <= tdc1_tr;
tdc1_o.stb <= tdc1_tr;
tdc1_wack <= tdc1_i.ack and tdc1_wt;
tdc1_rack <= tdc1_i.ack and tdc1_rt;
tdc1_o.adr <= ((15 downto 0 => '0') & adr_int(15 downto 2)) & (1 downto 0 => '0');
tdc1_o.sel <= wr_sel_d0;
tdc1_o.we <= tdc1_wt;
tdc1_o.dat <= wr_dat_d0;
-- Interface mt
mt_tr <= mt_wt or mt_rt;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
mt_rt <= '0';
mt_wt <= '0';
else
mt_rt <= (mt_rt or mt_re) and not mt_rack;
mt_wt <= (mt_wt or mt_we) and not mt_wack;
end if;
end if;
end process;
mt_o.cyc <= mt_tr;
mt_o.stb <= mt_tr;
mt_wack <= mt_i.ack and mt_wt;
mt_rack <= mt_i.ack and mt_rt;
mt_o.adr <= ((14 downto 0 => '0') & adr_int(16 downto 2)) & (1 downto 0 => '0');
mt_o.sel <= wr_sel_d0;
mt_o.we <= mt_wt;
mt_o.dat <= wr_dat_d0;
-- Process for write requests.
process (wr_adr_d0, wr_req_d0, metadata_wack, tdc0_wack, tdc1_wack, mt_wack) begin
metadata_we <= '0';
tdc0_we <= '0';
tdc1_we <= '0';
mt_we <= '0';
case wr_adr_d0(18 downto 17) is
when "00" =>
case wr_adr_d0(16 downto 16) is
when "0" =>
-- Submap metadata
metadata_we <= wr_req_d0;
wr_ack_int <= metadata_wack;
when "1" =>
-- Submap tdc0
tdc0_we <= wr_req_d0;
wr_ack_int <= tdc0_wack;
when others =>
wr_ack_int <= wr_req_d0;
end case;
when "01" =>
-- Submap tdc1
tdc1_we <= wr_req_d0;
wr_ack_int <= tdc1_wack;
when "10" =>
-- Submap mt
mt_we <= wr_req_d0;
wr_ack_int <= mt_wack;
when others =>
wr_ack_int <= wr_req_d0;
end case;
end process;
-- Process for read requests.
process (adr_int, rd_req_int, metadata_i.dat, metadata_rack, tdc0_i.dat, tdc0_rack, tdc1_i.dat, tdc1_rack, mt_i.dat, mt_rack) begin
-- By default ack read requests
rd_dat_d0 <= (others => 'X');
metadata_re <= '0';
tdc0_re <= '0';
tdc1_re <= '0';
mt_re <= '0';
case adr_int(18 downto 17) is
when "00" =>
case adr_int(16 downto 16) is
when "0" =>
-- Submap metadata
metadata_re <= rd_req_int;
rd_dat_d0 <= metadata_i.dat;
rd_ack_d0 <= metadata_rack;
when "1" =>
-- Submap tdc0
tdc0_re <= rd_req_int;
rd_dat_d0 <= tdc0_i.dat;
rd_ack_d0 <= tdc0_rack;
when others =>
rd_ack_d0 <= rd_req_int;
end case;
when "01" =>
-- Submap tdc1
tdc1_re <= rd_req_int;
rd_dat_d0 <= tdc1_i.dat;
rd_ack_d0 <= tdc1_rack;
when "10" =>
-- Submap mt
mt_re <= rd_req_int;
rd_dat_d0 <= mt_i.dat;
rd_ack_d0 <= mt_rack;
when others =>
rd_ack_d0 <= rd_req_int;
end case;
end process;
end syn;
# SPDX-FileCopyrightText: 2022 CERN (home.cern)
# SPDX-License-Identifier: CC0-1.0
__pycache__/
# SPDX-FileCopyrightText: 2022 CERN (home.cern)
# SPDX-License-Identifier: CC0-1.0
[pytest]
addopts = -v
testpaths =
tests
filterwarnings =
ignore::pytest.PytestCacheWarning
# SPDX-FileCopyrightText: 2022 CERN (home.cern)
# SPDX-License-Identifier: TODO
from PyWrtd import PyWrtd
from PyAdcLib import *
import time
class FmcAdc100m(PyFmcAdc100m14b4ch):
def __init__(self, adc_id):
PyFmcAdc100m14b4ch.__init__(self, adc_id)
for ch in range(4):
conf = PyAdcConf(PyAdcConf.ADC_CONF_TYPE_CHN, ch)
conf.value_set(PyAdcConf.ADC_CONF_CHN_RANGE,
self.ADC_CONF_100M14B4CHA_CHN_RANGE_10V)
conf.value_set(PyAdcConf.ADC_CONF_CHN_TERMINATION, 1)
conf.value_set(PyAdcConf.ADC_CONF_CHN_OFFSET, 0)
conf.value_set(PyAdcConf.ADC_CONF_CHN_SATURATION, 0x7FFF)
self.apply_config(conf, 0)
self.disable_triggers()
def disable_triggers(self):
for ch in range(4):
conf = PyAdcConf(PyAdcConf.ADC_CONF_TYPE_TRG_THR, ch)
conf.value_set(PyAdcConf.ADC_CONF_TRG_THR_ENABLE, 0)
self.apply_config(conf, 0)
conf = PyAdcConf(PyAdcConf.ADC_CONF_TYPE_TRG_EXT, 0)
conf.value_set(PyAdcConf.ADC_CONF_TRG_EXT_ENABLE, 0)
self.apply_config(conf, 0)
def enable_ext_trigger(self):
conf = PyAdcConf(PyAdcConf.ADC_CONF_TYPE_TRG_EXT, 0)
conf.value_set(PyAdcConf.ADC_CONF_TRG_EXT_ENABLE, 1)
self.apply_config(conf, 0)
def enable_int_trigger(self, ch):
conf = PyAdcConf(PyAdcConf.ADC_CONF_TYPE_TRG_THR, ch)
conf.value_set(PyAdcConf.ADC_CONF_TRG_THR_THRESHOLD, 2000)
conf.value_set(PyAdcConf.ADC_CONF_TRG_THR_ENABLE, 1)
self.apply_config(conf, 0)
def start_acquisition(self, pre, post, nshot=1):
conf = PyAdcConf(PyAdcConf.ADC_CONF_TYPE_ACQ, 0)
conf.value_set(PyAdcConf.ADC_CONF_ACQ_PRE_SAMP, pre)
conf.value_set(PyAdcConf.ADC_CONF_ACQ_POST_SAMP, post)
conf.value_set(PyAdcConf.ADC_CONF_ACQ_N_SHOTS, nshot)
self.apply_config(conf, 0)
self.acq_start(PyFmcAdc100m14b4ch.ADC_F_FLUSH, timeval(0,0))
def acquisition_complete(self):
try:
self.acq_poll(0, timeval(1,0))
return True
except OSError:
return False
class WrtdTestNode(PyWrtd):
def __init__(self, node_id, fw_name):
PyWrtd.__init__(self, node_id)
self.node_id = node_id
self.expected_fw_name = fw_name
self.disable_all_alarms()
self.remove_all_alarms()
self.disable_all_rules()
self.remove_all_rules()
self.set_attr_bool(self.WRTD_GLOBAL_REP_CAP_ID,
self.WRTD_ATTR_EVENT_LOG_ENABLED,
False)
self.clear_event_log_entries()
self.set_attr_bool(self.WRTD_GLOBAL_REP_CAP_ID,
self.WRTD_ATTR_EVENT_LOG_ENABLED,
True)
def set_attr_tstamp(self, rep_cap_id, id,
seconds = 0, ns = 0, frac = 0):
sec_normalised = seconds
ns_normalised = ns
while (ns_normalised >= 1000000000):
ns_normalised -= 1000000000
sec_normalised += 1
while (ns_normalised < 0):
ns_normalised += 1000000000
sec_normalised -= 1
PyWrtd.set_attr_tstamp(self, rep_cap_id, id,
sec_normalised, ns_normalised, frac)
def add_rule_enabled(self, name, src, dst, ns_delay = 0, repeat = 0):
self.add_rule(name)
self.set_attr_tstamp(name, self.WRTD_ATTR_RULE_DELAY, ns = ns_delay)
self.set_attr_string(name, self.WRTD_ATTR_RULE_SOURCE, src)
self.set_attr_string(name, self.WRTD_ATTR_RULE_DESTINATION, dst)
self.set_attr_int32(name, self.WRTD_ATTR_RULE_REPEAT_COUNT, repeat)
self.set_attr_bool(name, self.WRTD_ATTR_RULE_ENABLED, True)
def check_log_entry(self, pattern, timeout = 1.0):
remaining = timeout
while self.get_attr_bool(self.WRTD_GLOBAL_REP_CAP_ID,
self.WRTD_ATTR_EVENT_LOG_EMPTY):
assert remaining > 0
time.sleep(0.1)
remaining -= 0.1
entry = self.get_next_event_log_entry()
log_fields = [ x.strip() for x in entry.split('|')]
assert len(log_fields) == 6
log = dict()
log['id'] = log_fields[0].lstrip('Id:')
log['seq'] = log_fields[1].lstrip('Seq:')
log['log_tstamp'] = log_fields[2]
log['event_tstamp'] = log_fields[3]
log['log_type'] = log_fields[4]
log['log_reason'] = log_fields[5]
for key in pattern:
assert key in log
assert log[key] == pattern[key]
return log
# SPDX-FileCopyrightText: 2022 CERN (home.cern)
# SPDX-License-Identifier: todo
import pytest
def pytest_addoption(parser):
parser.addoption("--adc-node", required=True, type=int,
help="WRTD node ID for the ADC board")
parser.addoption("--tdc-node", required=True, type=int,
help="WRTD node ID for the TDC board")
parser.addoption("--fd-node", required=True, type=int,
help="WRTD node ID for the FD board")
parser.addoption("--fmc-adc-id1", required=True, type=lambda x : int(x, 16),
help="FMC-ADC ID (in hex) for the ADC in FMC slot 1")
parser.addoption("--fmc-adc-id2", required=True, type=lambda x : int(x, 16),
help="FMC-ADC ID (in hex) for the ADC in FMC slot 2")
def pytest_configure(config):
pytest.adc_node = config.getoption("--adc-node")
pytest.tdc_node = config.getoption("--tdc-node")
pytest.fd_node = config.getoption("--fd-node")
pytest.fmc_adc1 = config.getoption("--fmc-adc-id1")
pytest.fmc_adc2 = config.getoption("--fmc-adc-id2")
# SPDX-FileCopyrightText: 2022 CERN (home.cern)
# SPDX-License-Identifier: TODO
import pytest
from WrtdTestHelper import *
@pytest.fixture()
def fmc_adc():
fmc_adc_list = [FmcAdc100m(pytest.fmc_adc1), FmcAdc100m(pytest.fmc_adc2)]
yield fmc_adc_list
for dev in fmc_adc_list:
dev.acq_stop(0)
dev.disable_triggers()
@pytest.fixture()
def adc():
return WrtdTestNode(pytest.adc_node, 'wrtd-adc-x2')
@pytest.fixture()
def tdc():
return WrtdTestNode(pytest.tdc_node, 'wrtd-tdc-x2')
@pytest.fixture()
def fdelay():
return WrtdTestNode(pytest.fd_node, 'wrtd-fd-x2')
class TestWrtdRefDesigns(object):
"""
Collection of tests for the WRTD reference designs
"""
def test_node_count(self):
node_count = PyWrtd.get_node_count()
assert node_count == 3
@pytest.mark.parametrize('node', ['adc', 'tdc', 'fdelay'])
def test_fw_name(self, node, request, adc, tdc, fdelay):
wrtd = request.getfixturevalue(node)
assert wrtd.get_fw_name(0) == wrtd.expected_fw_name
@pytest.mark.parametrize('tx_node, rx_nodes',
[('adc', ['fdelay']),
('tdc', ['adc', 'fdelay'])],
ids=['adc->fdelay', 'tdc->adc/fdelay'])
def test_alarm_log_and_net(self, tx_node, rx_nodes, request, adc, tdc, fdelay):
"""
Schedule an alarm in tx_node, send an event and check the logs to
see that the alarm triggered, the event was sent out and that it was
received by all rx_nodes
"""
transmitter = request.getfixturevalue(tx_node)
transmitter.add_alarm('alarm1')
transmitter.add_rule('rule1')
transmitter.set_attr_tstamp('rule1', transmitter.WRTD_ATTR_RULE_DELAY, ns = 500000)
transmitter.set_attr_string('rule1', transmitter.WRTD_ATTR_RULE_SOURCE, 'alarm1')
transmitter.set_attr_string('rule1', transmitter.WRTD_ATTR_RULE_DESTINATION, 'net0')
transmitter.set_attr_bool('rule1', transmitter.WRTD_ATTR_RULE_ENABLED, True)
ts_alarm = transmitter.get_attr_tstamp(transmitter.WRTD_GLOBAL_REP_CAP_ID,
transmitter.WRTD_ATTR_SYS_TIME)
ts_alarm['ns'] += 10000000
transmitter.set_attr_tstamp('alarm1', transmitter.WRTD_ATTR_ALARM_TIME,
seconds = ts_alarm['seconds'],
ns = ts_alarm['ns'],
frac = ts_alarm['frac'])
transmitter.set_attr_bool('alarm1', transmitter.WRTD_ATTR_ALARM_ENABLED, True)
transmitter.check_log_entry({'id': 'alarm1', 'log_type': 'GENERATED'})
transmitter.check_log_entry({'id': 'net0', 'log_type': 'NETWORK', 'log_reason': 'TX'})
for rx_node in rx_nodes:
receiver = request.getfixturevalue(rx_node)
receiver.check_log_entry({'id': 'net0', 'log_type': 'NETWORK', 'log_reason': 'RX'})
@pytest.mark.parametrize('channel', [1, 2, 3, 4], ids=lambda i: f'ch{i}')
@pytest.mark.parametrize('fmc', [0, 1], ids=lambda i: f'fmc{i+1}')
def test_fd_out_tdc_in(self, tdc, fdelay, fmc, channel):
"""
Schedule an alarm on fdelay, generate pulse on output, check that
it goes out and that it is received by the tdc. FD out 4 is wired
to both TDC in 4 and 5.
"""
fdelay.add_alarm('alarm1')
fd_channel = f'LC-O{4*fmc+channel}'
fdelay.add_rule_enabled('rule1', 'alarm1', fd_channel, 500000)
ts_alarm = fdelay.get_attr_tstamp(fdelay.WRTD_GLOBAL_REP_CAP_ID,
fdelay.WRTD_ATTR_SYS_TIME)
ts_alarm['ns'] += 10000000
fdelay.set_attr_tstamp('alarm1', fdelay.WRTD_ATTR_ALARM_TIME,
seconds = ts_alarm['seconds'],
ns = ts_alarm['ns'],
frac = ts_alarm['frac'])
fdelay.set_attr_bool('alarm1', fdelay.WRTD_ATTR_ALARM_ENABLED, True)
fdelay.check_log_entry({'id': 'alarm1', 'log_type': 'GENERATED'})
fdelay.check_log_entry({'id': fd_channel, 'log_type': 'CONSUMED', 'log_reason': 'START'})
fdelay.check_log_entry({'id': fd_channel, 'log_type': 'CONSUMED', 'log_reason': 'DONE'})
tdc_channel = f'LC-I{5*fmc+channel}'
tdc.check_log_entry({'id': tdc_channel, 'log_type': 'GENERATED'})
if channel == 4:
tdc_channel = f'LC-I{5*(fmc+1)}'
tdc.check_log_entry({'id': tdc_channel, 'log_type': 'GENERATED'})
@pytest.mark.parametrize('fmc', [0, 1], ids=lambda i: f'fmc{i+1}')
def test_fd_tdc_snake_adc_trigin(self, tdc, fdelay, adc, fmc, fmc_adc):
"""
Schedule an alarm on fdelay, generate pulse on FD output 1, receive
on TDC input 1, generate event, add rule to generate pulse on FD
output 2, etc. TDC input 4 should cause one last pulse on FD output 1
and TDC input 5 should trigger the ADC over the network.
"""
for channel in [1, 2, 3, 4, 5]:
tdc_channel = f'LC-I{5*fmc+channel}'
rule_name = f'rule.{tdc_channel}'
tdc.add_rule_enabled(rule_name, tdc_channel, f'net{tdc_channel}', 500000, 1)
if channel < 5:
if channel == 4:
fd_channel = f'LC-O{4*fmc+1}'
else:
fd_channel = f'LC-O{4*fmc+channel+1}'
rule_name = f'rule.{fd_channel}'
fdelay.add_rule_enabled(rule_name, f'net{tdc_channel}', fd_channel)
else:
adc_channel = f'LC-O{fmc+1}'
rule_name = f'rule.{adc_channel}'
adc.add_rule_enabled(rule_name, f'net{tdc_channel}', adc_channel)
fmc_adc[fmc].start_acquisition(pre=1, post=2)
fdelay.add_alarm('alarm1')
fd_channel = f'LC-O{4*fmc+1}'
fdelay.add_rule_enabled('rule-alarm', 'alarm1', fd_channel, 500000)
ts_alarm = fdelay.get_attr_tstamp(fdelay.WRTD_GLOBAL_REP_CAP_ID,
fdelay.WRTD_ATTR_SYS_TIME)
ts_alarm['ns'] += 10000000
fdelay.set_attr_tstamp('alarm1', fdelay.WRTD_ATTR_ALARM_TIME,
seconds = ts_alarm['seconds'],
ns = ts_alarm['ns'],
frac = ts_alarm['frac'])
fdelay.set_attr_bool('alarm1', fdelay.WRTD_ATTR_ALARM_ENABLED, True)
fdelay.check_log_entry({'id': 'alarm1', 'log_type': 'GENERATED'})
fd_channel = f'LC-O{4*fmc+1}'
fdelay.check_log_entry({'id': fd_channel, 'log_type': 'CONSUMED', 'log_reason': 'START'})
fdelay.check_log_entry({'id': fd_channel, 'log_type': 'CONSUMED', 'log_reason': 'DONE'})
for channel in [1, 2, 3, 4]:
tdc_channel = f'LC-I{5*fmc+channel}'
tdc.check_log_entry({'id': tdc_channel, 'log_type': 'GENERATED'})
event_name = f'net{tdc_channel}'
tdc.check_log_entry({'id': event_name, 'log_type': 'NETWORK', 'log_reason': 'TX'})
fdelay.check_log_entry({'id': event_name, 'log_type': 'NETWORK', 'log_reason': 'RX'})
adc.check_log_entry({'id': event_name, 'log_type': 'NETWORK', 'log_reason': 'RX'})
if channel == 4:
fd_channel = f'LC-O{4*fmc+1}'
else:
fd_channel = f'LC-O{4*fmc+channel+1}'
fdelay.check_log_entry({'id': fd_channel, 'log_type': 'CONSUMED',
'log_reason': 'START'})
# two events will arrive from TDC in 4 and 5 almost simultaneously
if channel == 4:
event_name =f'netLC-I{5*(fmc+1)}'
fdelay.check_log_entry({'id': event_name, 'log_type': 'NETWORK',
'log_reason': 'RX'})
adc.check_log_entry({'id': event_name, 'log_type': 'NETWORK', 'log_reason': 'RX'})
fdelay.check_log_entry({'id': fd_channel, 'log_type': 'CONSUMED', 'log_reason': 'DONE'})
adc_channel = f'LC-O{fmc+1}'
adc.check_log_entry({'id': adc_channel, 'log_type': 'CONSUMED', 'log_reason': 'START'})
adc.check_log_entry({'id': adc_channel, 'log_type': 'CONSUMED', 'log_reason': 'DONE'})
assert fmc_adc[fmc].acquisition_complete(), "acquisition timeout"
@pytest.mark.parametrize('fmc', [0, 1], ids=lambda i: f'fmc{i+1}')
def test_fd_adc_snake(self, fdelay, adc, fmc, fmc_adc):
"""
Schedule an alarm on fdelay, generate pulse on FD output 1, receive
on ADC channel 1, trigger and generate event, add rule to generate pulse
on FD output 2, etc.
"""
for channel in [1, 2, 3, 4]:
adc_channel = f'LC-I{5*fmc+channel}'
rule_name = f'rule.{adc_channel}'
adc.add_rule_enabled(rule_name, adc_channel, f'net{adc_channel}', 500000, 1)
if channel < 4:
fd_channel = f'LC-O{4*fmc+channel+1}'
rule_name = f'rule.{fd_channel}'
fdelay.add_rule_enabled(rule_name, f'net{adc_channel}', fd_channel)
fmc_adc[fmc].enable_int_trigger(channel-1)
fmc_adc[fmc].start_acquisition(pre=1, post=2, nshot=4)
fdelay.add_alarm('alarm1')
fd_channel = f'LC-O{4*fmc+1}'
fdelay.add_rule_enabled('rule-alarm', 'alarm1', fd_channel, 500000)
ts_alarm = fdelay.get_attr_tstamp(fdelay.WRTD_GLOBAL_REP_CAP_ID,
fdelay.WRTD_ATTR_SYS_TIME)
ts_alarm['ns'] += 10000000
fdelay.set_attr_tstamp('alarm1', fdelay.WRTD_ATTR_ALARM_TIME,
seconds = ts_alarm['seconds'],
ns = ts_alarm['ns'],
frac = ts_alarm['frac'])
fdelay.set_attr_bool('alarm1', fdelay.WRTD_ATTR_ALARM_ENABLED, True)
fdelay.check_log_entry({'id': 'alarm1', 'log_type': 'GENERATED'})
fd_channel = f'LC-O{4*fmc+1}'
fdelay.check_log_entry({'id': fd_channel, 'log_type': 'CONSUMED', 'log_reason': 'START'})
fdelay.check_log_entry({'id': fd_channel, 'log_type': 'CONSUMED', 'log_reason': 'DONE'})
for channel in [1, 2, 3, 4]:
adc_channel = f'LC-I{5*fmc+channel}'
adc.check_log_entry({'id': adc_channel, 'log_type': 'GENERATED'})
event_name = f'net{adc_channel}'
adc.check_log_entry({'id': event_name, 'log_type': 'NETWORK', 'log_reason': 'TX'})
fdelay.check_log_entry({'id': event_name, 'log_type': 'NETWORK', 'log_reason': 'RX'})
if channel < 4:
fd_channel = f'LC-O{4*fmc+channel+1}'
fdelay.check_log_entry({'id': fd_channel, 'log_type': 'CONSUMED',
'log_reason': 'START'})
fdelay.check_log_entry({'id': fd_channel, 'log_type': 'CONSUMED',
'log_reason': 'DONE'})
assert fmc_adc[fmc].acquisition_complete(), "acquisition timeout"
......@@ -10,16 +10,19 @@ REPO_PARENT ?= $(CURDIR)/..
# on Mock Turtle.
WRTD_DEP_TRTL ?= $(CURDIR)/../dependencies/mock-turtle
DIRS = $(WRTD_DEP_TRTL)/software drivers lib firmware
DIRS = $(WRTD_DEP_TRTL)/software drivers lib lib/python tools
all clean: $(DIRS)
all clean install: $(DIRS)
tools: lib
.PHONY: all clean $(DIRS)
.PHONY: all clean install $(DIRS) firmware
clean: TARGET = clean
modules: TARGET = modules
clean: TARGET = clean
install: TARGET = install
$(DIRS):
$(MAKE) -C $@ $(TARGET)
firmware:
$(MAKE) -C firmware
......@@ -7,12 +7,22 @@ endif
endif
# add versions of used submodules
KBUILD_EXTRA_SYMBOLS += $(FMC_EXTRA_SYMBOLS-y)
ccflags-y += -DADDITIONAL_VERSIONS="$(SUBMODULE_VERSIONS)"
ccflags-y += -DDRV_VERSION=\"$(DRV_VERSION)\"
ccflags-y += -Wall -Werror
ccflags-y += -I$(FMC_ABS)/include
ccflags-y += -I$(ADC_ABS)/software/kernel
obj-m := wrtd-ref-spec150t-adc.o
obj-m += wrtd-ref-svec-tdc-fd.o
obj-m += wrtd-ref-svec-tdc-x2.o
obj-m += wrtd-ref-svec-fd-x2.o
obj-m += wrtd-ref-svec-adc-x2.o
wrtd-ref-spec150t-adc-objs := wrtd-ref-spec150t-adc-core.o
wrtd-ref-svec-tdc-fd-objs := wrtd-ref-svec-tdc-fd-core.o
wrtd-ref-svec-tdc-x2-objs := wrtd-ref-svec-tdc-x2-core.o
wrtd-ref-svec-fd-x2-objs := wrtd-ref-svec-fd-x2-core.o
wrtd-ref-svec-adc-x2-objs := wrtd-ref-svec-adc-x2-core.o
......@@ -7,14 +7,30 @@ REPO_PARENT ?= $(shell /bin/pwd)/../..
LINUX ?= /lib/modules/$(shell uname -r)/build
ifdef REPO_PARENT
FMC ?= $(REPO_PARENT)/fmc-sw
endif
DRV_VERSION := $(shell git describe --always --dirty --long --tags)
FMC_ABS ?= $(abspath $(FMC))
FMC_EXTRA_SYMBOLS-y = $(FMC_ABS)/drivers/fmc/Module.symvers
ADC_ABS ?= $(abspath $(FETCHTO)/fmc-adc-100m14b4cha)
all: modules
.PHONY: all modules clean help install modules_install
modules help install modules_install:
$(MAKE) -C $(LINUX) M=$(shell pwd) DRV_VERSION=$(DRV_VERSION) $@
modules help modules_install:
$(MAKE) -C $(LINUX) M=$(shell pwd) DRV_VERSION=$(DRV_VERSION) \
FMC_ABS=$(FMC_ABS) ADC_ABS=$(ADC_ABS) \
FMC_EXTRA_SYMBOLS-y=$(FMC_EXTRA_SYMBOLS-y) $@
install:
$(MAKE) -C $(LINUX) M=$(shell pwd) DRV_VERSION=$(DRV_VERSION) \
FMC_ABS=$(FMC_ABS) ADC_ABS=$(ADC_ABS) modules_install
# be able to run the "clean" rule even if $(LINUX) is not valid
clean:
rm -rf *.o *~ .*.cmd *.ko *.mod.c .tmp_versions Module.symvers \
......
......@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/mod_devicetable.h>
enum wrtd_s150a_dev_offsets {
WRTD_S150A_FA100_MEM_START = 0x00002000,
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/fmc.h>
#include "platform_data/fmc-adc-100m14b4cha.h"
#define SVEC_FMC_SLOTS 2
/*
* From SVEC but we do not want to add a dependency for these 4 registers
* which should never change by design. If they do, and you end up here:
* sorry! It shouldn't have happened.
*/
#define SVEC_BASE_REGS_CSR 0x40UL
#define SVEC_FPGA_CSR_DDR4_ADDR (SVEC_BASE_REGS_CSR + 0x18)
#define SVEC_FPGA_DDR4_DMA (0x2000)
#define SVEC_FPGA_CSR_DDR5_ADDR (SVEC_BASE_REGS_CSR + 0x1C)
#define SVEC_FPGA_DDR5_DMA (0x3000)
enum wrtd_adcx2_dev_offsets {
WRTD_ADCX2_ADC_META_START = 0x00000000,
WRTD_ADCX2_ADC_META_END = 0x00000040,
WRTD_ADCX2_ADC1_MEM_START = 0x00002000,
WRTD_ADCX2_ADC1_MEM_END = 0x00003fff,
WRTD_ADCX2_ADC2_MEM_START = 0x00004000,
WRTD_ADCX2_ADC2_MEM_END = 0x00005fff,
WRTD_ADCX2_TRTL_MEM_START = 0x0001C000,
WRTD_ADCX2_TRTL_MEM_END = 0x0003bfff,
};
static inline struct platform_device *platform_device_register_resndata_mask(
struct device *parent, const char *name, int id,
const struct resource *res, unsigned int num,
const void *data, size_t size, u64 dma_mask) {
struct platform_device_info pdevinfo = {
.parent = parent,
.name = name,
.id = id,
.res = res,
.num_res = num,
.data = data,
.size_data = size,
.dma_mask = dma_mask,
};
return platform_device_register_full(&pdevinfo);
}
static struct fmc_adc_platform_data wrtd_adcx2_pdata[] = {
{
.flags = FMC_ADC_BIG_ENDIAN |
FMC_ADC_SVEC |
FMC_ADC_NOSQUASH_SCATTERLIST,
.vme_reg_offset = SVEC_FPGA_CSR_DDR4_ADDR,
.vme_dma_offset = SVEC_FPGA_DDR4_DMA,
.calib_trig_time = 0,
.calib_trig_threshold = 0,
.calib_trig_internal = 0,
}, {
.flags = FMC_ADC_BIG_ENDIAN |
FMC_ADC_SVEC |
FMC_ADC_NOSQUASH_SCATTERLIST,
.vme_reg_offset = SVEC_FPGA_CSR_DDR5_ADDR,
.vme_dma_offset = SVEC_FPGA_DDR5_DMA,
.calib_trig_time = 0,
.calib_trig_threshold = 0,
.calib_trig_internal = 0,
}
};
static struct resource wrtd_adcx2_res1[] = {
{
.name = "fmc-adc-100m-mem.1",
.flags = IORESOURCE_MEM,
.start = WRTD_ADCX2_ADC1_MEM_START,
.end = WRTD_ADCX2_ADC1_MEM_END,
},
{
.name = "fmc-adc-100m-dma.1",
.flags = IORESOURCE_DMA,
},
{
.name = "fmc-adc-100m-irq.1",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 0,
.end = 0,
},
{
.name = "fmc-adc-100m-meta.1",
.flags = IORESOURCE_MEM,
.start = WRTD_ADCX2_ADC_META_START,
.end = WRTD_ADCX2_ADC_META_END,
},
};
static struct resource wrtd_adcx2_res2[] = {
{
.name = "fmc-adc-100m-mem.2",
.flags = IORESOURCE_MEM,
.start = WRTD_ADCX2_ADC2_MEM_START,
.end = WRTD_ADCX2_ADC2_MEM_END,
},
{
.name = "fmc-adc-100m-dma.2",
.flags = IORESOURCE_DMA,
},
{
.name = "fmc-adc-100m-irq.2",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 1,
.end = 1,
},
{
.name = "fmc-adc-100m-meta.2",
.flags = IORESOURCE_MEM,
.start = WRTD_ADCX2_ADC_META_START,
.end = WRTD_ADCX2_ADC_META_END,
},
};
static struct resource wrtd_adcx2_trtl_res[] = {
{
.name = "mock-turtle-mem",
.flags = IORESOURCE_MEM,
.start = WRTD_ADCX2_TRTL_MEM_START,
.end = WRTD_ADCX2_TRTL_MEM_END,
}, {
.name = "mock-turtle-irq_in",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 2,
}, {
.name = "mock-turtle-irq_out",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 3,
}, {
.name = "mock-turtle-irq_con",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 4,
}, {
.name = "mock-turtle-irq_not",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 5,
},
};
static struct resource *wrtd_adcx2_res[] = {
wrtd_adcx2_res1,
wrtd_adcx2_res2,
};
struct wrtd_adcx2_data {
struct platform_device *adc[2];
struct platform_device *trtl;
};
static int wrtd_adcx2_probe(struct platform_device *pdev)
{
struct wrtd_adcx2_data *pdev_data;
struct resource *rmem;
int irq;
int i;
rmem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!rmem) {
dev_err(&pdev->dev, "Missing memory resource\n");
return -EINVAL;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "Missing IRQ number\n");
return -EINVAL;
}
pdev_data = kzalloc(sizeof(*pdev_data), GFP_KERNEL);
if (!pdev_data)
return -ENOMEM;
for (i = 0; i < SVEC_FMC_SLOTS; ++i) {
unsigned int res_n = ARRAY_SIZE(wrtd_adcx2_res1);
struct resource res[res_n];
struct fmc_slot *slot = fmc_slot_get(pdev->dev.parent, i + 1);
int present;
struct resource *rdma;
if (IS_ERR(slot)) {
dev_err(&pdev->dev,
"Can't find FMC slot %d err: %ld\n",
i + 1, PTR_ERR(slot));
continue;
}
rdma = platform_get_resource(pdev, IORESOURCE_DMA, i);
if (rdma)
res[1].start = rdma->start;
present = fmc_slot_present(slot);
fmc_slot_put(slot);
dev_dbg(&pdev->dev, "FMC slot: %d, present: %d\n",
i + 1, present);
if (!present)
continue;
memcpy(res, wrtd_adcx2_res[i], sizeof(res));
res[0].parent = rmem;
res[0].start += rmem->start;
res[0].end += rmem->start;
res[2].start += irq;
res[3].parent = rmem;
res[3].start += rmem->start;
res[3].end += rmem->start;
pr_info("FMC slot %d: irq=%u\n", i + 1, (unsigned)res[2].start);
pdev_data->adc[i] = platform_device_register_resndata_mask(&pdev->dev,
"fmc-adc-100m",
PLATFORM_DEVID_AUTO,
res,
res_n,
&wrtd_adcx2_pdata[i],
sizeof(wrtd_adcx2_pdata[i]),
DMA_BIT_MASK(32));
if (IS_ERR(pdev_data->adc[i])) {
dev_err(&pdev->dev,
"Faild to register ADC instance %d\n",
i);
pdev_data->adc[i] = NULL;
}
}
/* Mockturtle */
{
unsigned int res_n = ARRAY_SIZE(wrtd_adcx2_trtl_res);
struct resource res[res_n];
memcpy(res, wrtd_adcx2_trtl_res, sizeof(res));
res[0].parent = rmem;
res[0].start += rmem->start;
res[0].end += rmem->start;
res[1].start += irq;
res[2].start += irq;
res[3].start += irq;
res[4].start += irq;
pdev_data->trtl = platform_device_register_resndata(&pdev->dev,
"mock-turtle",
PLATFORM_DEVID_AUTO,
res, res_n,
NULL, 0);
if (IS_ERR(pdev_data->trtl)) {
dev_err(&pdev->dev,
"Faild to register TRTL instance\n");
pdev_data->trtl = NULL;
}
}
platform_set_drvdata(pdev, pdev_data);
return 0;
}
static int wrtd_adcx2_remove(struct platform_device *pdev)
{
struct wrtd_adcx2_data *pdev_data = platform_get_drvdata(pdev);
int i;
if (!pdev_data)
return 0;
for (i = 0; i < SVEC_FMC_SLOTS; ++i)
if (pdev_data->adc[i])
platform_device_unregister(pdev_data->adc[i]);
platform_device_unregister(pdev_data->trtl);
kfree(pdev_data);
return 0;
}
/**
* List of supported platform
*/
enum wrtd_adcx2_version {
WRTD_ADCX2_VER = 0,
};
static const struct platform_device_id wrtd_adcx2_id_table[] = {
{
.name = "wrtd-adcx2",
.driver_data = WRTD_ADCX2_VER,
}, {
.name = "id:000010DC57544E05",
.driver_data = WRTD_ADCX2_VER,
}, {
.name = "id:000010dc57544e05",
.driver_data = WRTD_ADCX2_VER,
},
{},
};
static struct platform_driver wrtd_adcx2_driver = {
.driver = {
.name = "wrtd-adcx2",
.owner = THIS_MODULE,
},
.id_table = wrtd_adcx2_id_table,
.probe = wrtd_adcx2_probe,
.remove = wrtd_adcx2_remove,
};
module_platform_driver(wrtd_adcx2_driver);
MODULE_AUTHOR("Federico Vaga <federico.vaga@cern.ch>");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Driver for the WRTD SVEC ADCx2");
MODULE_DEVICE_TABLE(platform, wrtd_adcx2_id_table);
MODULE_SOFTDEP("pre: svec_fmc_carrier mockturtle fmc-adc-100m14b4ch");
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#include <linux/module.h>
#include<linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/mod_devicetable.h>
static char *drivers = "";
module_param(drivers, charp, 0444);
MODULE_PARM_DESC(drivers,
"Extra drivers to load: fd (fmc-fine-delay)\n");
enum wrtd_fdx2_dev_offsets {
WRTD_FDX2_FD0_MEM_START = 0x0000C000,
WRTD_FDX2_FD0_MEM_END = 0x0000C1FF,
WRTD_FDX2_FD1_MEM_START = 0x00014000,
WRTD_FDX2_FD1_MEM_END = 0x000141FF,
WRTD_FDX2_TRTL_MEM_START = 0x0001C000,
WRTD_FDX2_TRTL_MEM_END = 0x0003C000,
};
/* MFD devices */
static struct resource wrtd_fdx2_fd0_res[] = {
{
.name = "fmc-fdelay0-mem",
.flags = IORESOURCE_MEM,
.start = WRTD_FDX2_FD0_MEM_START,
.end = WRTD_FDX2_FD0_MEM_END,
}, {
.name = "fmc-fdelay0-irq",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 0,
.end = 0,
},
};
static struct resource wrtd_fdx2_fd1_res[] = {
{
.name = "fmc-fdelay1-mem",
.flags = IORESOURCE_MEM,
.start = WRTD_FDX2_FD1_MEM_START,
.end = WRTD_FDX2_FD1_MEM_END,
}, {
.name = "fmc-fdelay1-irq",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 1,
.end = 1,
},
};
static struct resource wrtd_fdx2_trtl_res[] = {
{
.name = "mock-turtle-mem",
.flags = IORESOURCE_MEM,
.start = WRTD_FDX2_TRTL_MEM_START,
.end = WRTD_FDX2_TRTL_MEM_END,
}, {
.name = "mock-turtle-irq_in",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 2,
}, {
.name = "mock-turtle-irq_out",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 3,
}, {
.name = "mock-turtle-irq_con",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 4,
}, {
.name = "mock-turtle-irq_not",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 5,
},
};
#define MFD_CELL_TRTL { \
.name = "mock-turtle", \
.platform_data = NULL, \
.pdata_size = 0, \
.num_resources = ARRAY_SIZE(wrtd_fdx2_trtl_res), \
.resources = wrtd_fdx2_trtl_res, \
}
#define MFD_CELL_FD0 { \
.name = "fmc-fdelay0", \
.platform_data = NULL, \
.pdata_size = 0, \
.num_resources = ARRAY_SIZE(wrtd_fdx2_fd0_res), \
.resources = wrtd_fdx2_fd0_res, \
}
#define MFD_CELL_FD1 { \
.name = "fmc-fdelay1", \
.platform_data = NULL, \
.pdata_size = 0, \
.num_resources = ARRAY_SIZE(wrtd_fdx2_fd1_res), \
.resources = wrtd_fdx2_fd1_res, \
}
static const struct mfd_cell __wrtd_fdx2_mfd_devs_base[] = {
MFD_CELL_TRTL,
};
static const struct mfd_cell __wrtd_fdx2_mfd_devs_fdt[] = {
MFD_CELL_TRTL,
MFD_CELL_FD0,
MFD_CELL_FD1,
};
static const struct mfd_cell *wrtd_fdx2_mfd_cells(const char *extra)
{
if (strncmp("fd", extra, 2) == 0)
return __wrtd_fdx2_mfd_devs_fdt;
else
return __wrtd_fdx2_mfd_devs_base;
}
static unsigned int wrtd_fdx2_mfd_count(const char *extra)
{
if (strncmp("fd", extra, 2) == 0)
return 3;
else
return 1;
}
static int wrtd_fdx2_probe(struct platform_device *pdev)
{
struct resource *rmem;
int irq;
rmem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!rmem) {
dev_err(&pdev->dev, "Missing memory resource\n");
return -EINVAL;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "Missing IRQ number\n");
return -EINVAL;
}
/*
* We know that this design uses the HTVIC IRQ controller.
* This IRQ controller has a linear mapping, so it is enough
* to give the first one as input
*/
return mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
wrtd_fdx2_mfd_cells(drivers),
wrtd_fdx2_mfd_count(drivers),
rmem, irq, NULL);
}
static int wrtd_fdx2_remove(struct platform_device *pdev)
{
mfd_remove_devices(&pdev->dev);
return 0;
}
/**
* List of supported platform
*/
enum wrtd_fdx2_version {
WRTD_FDX2_VER = 0,
};
static const struct platform_device_id wrtd_fdx2_id_table[] = {
{
.name = "wrtd-fdx2",
.driver_data = WRTD_FDX2_VER,
}, {
.name = "id:000010DC57544E04",
.driver_data = WRTD_FDX2_VER,
}, {
.name = "id:000010dc57544e04",
.driver_data = WRTD_FDX2_VER,
},
{},
};
static struct platform_driver wrtd_fdx2_driver = {
.driver = {
.name = "wrtd-fdx2",
.owner = THIS_MODULE,
},
.id_table = wrtd_fdx2_id_table,
.probe = wrtd_fdx2_probe,
.remove = wrtd_fdx2_remove,
};
module_platform_driver(wrtd_fdx2_driver);
MODULE_AUTHOR("Federico Vaga <federico.vaga@cern.ch>");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Driver for the WRTD SVEC Fine-Delay x2");
MODULE_DEVICE_TABLE(platform, wrtd_fdx2_id_table);
MODULE_SOFTDEP("pre: svec_fmc_carrier mockturtle");
......@@ -8,6 +8,7 @@
#include<linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/mod_devicetable.h>
static char *drivers = "";
module_param(drivers, charp, 0444);
......@@ -15,12 +16,12 @@ MODULE_PARM_DESC(drivers,
"Extra drivers to load: fd (fmc-fine-delay), tdc (fmc-tdc), fdtdc (fmc-fine-delay and fmc-tdc)\n");
enum wrtd_stf_dev_offsets {
WRTD_STF_FDT_MEM_START = 0x00006000,
WRTD_STF_FDT_MEM_END = 0x000061FF,
WRTD_STF_TDC_MEM_START = 0x0000E000,
WRTD_STF_TDC_MEM_END = 0x00001DFFF,
WRTD_STF_TRTL_MEM_START = 0x0001E000,
WRTD_STF_TRTL_MEM_END = 0x0003E000,
WRTD_STF_FDT_MEM_START = 0x00004000,
WRTD_STF_FDT_MEM_END = 0x000041FF,
WRTD_STF_TDC_MEM_START = 0x0000C000,
WRTD_STF_TDC_MEM_END = 0x00001BFFF,
WRTD_STF_TRTL_MEM_START = 0x0001C000,
WRTD_STF_TRTL_MEM_END = 0x0003C000,
};
/* MFD devices */
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#include <linux/module.h>
#include<linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
static char *drivers = "";
module_param(drivers, charp, 0444);
MODULE_PARM_DESC(drivers,
"Extra drivers to load: tdc (fmc-tdc)\n");
/* stx2: SVEC TDC x2. */
enum wrtd_stx2_dev_offsets {
WRTD_STX2_TDC0_MEM_START = 0x0000c000,
WRTD_STX2_TDC0_MEM_END = 0x0001bFFF,
WRTD_STX2_TDC1_MEM_START = 0x0001c000,
WRTD_STX2_TDC1_MEM_END = 0x0002bFFF,
WRTD_STX2_TRTL_MEM_START = 0x0003c000,
WRTD_STX2_TRTL_MEM_END = 0x0005bfff,
};
/* MFD devices */
static struct resource wrtd_stx2_tdc0_res[] = {
{
.name = "fmc-tdc0-mem",
.flags = IORESOURCE_MEM,
.start = WRTD_STX2_TDC0_MEM_START,
.end = WRTD_STX2_TDC0_MEM_END,
}, {
.name = "fmc-tdc0-irq",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 0,
.end = 0,
},
};
static struct resource wrtd_stx2_tdc1_res[] = {
{
.name = "fmc-tdc1-mem",
.flags = IORESOURCE_MEM,
.start = WRTD_STX2_TDC1_MEM_START,
.end = WRTD_STX2_TDC1_MEM_END,
}, {
.name = "fmc-tdc1-irq",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 1,
.end = 1,
},
};
static struct resource wrtd_stx2_trtl_res[] = {
{
.name = "mock-turtle-mem",
.flags = IORESOURCE_MEM,
.start = WRTD_STX2_TRTL_MEM_START,
.end = WRTD_STX2_TRTL_MEM_END,
}, {
.name = "mock-turtle-irq_in",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 2,
}, {
.name = "mock-turtle-irq_out",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 3,
}, {
.name = "mock-turtle-irq_con",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 4,
}, {
.name = "mock-turtle-irq_not",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 5,
},
};
#define MFD_CELL_TRTL { \
.name = "mock-turtle", \
.platform_data = NULL, \
.pdata_size = 0, \
.num_resources = ARRAY_SIZE(wrtd_stx2_trtl_res), \
.resources = wrtd_stx2_trtl_res, \
}
#define MFD_CELL_FDT { \
.name = "fmc-fdelay-tdc", \
.platform_data = NULL, \
.pdata_size = 0, \
.num_resources = ARRAY_SIZE(wrtd_stx2_fdt_res), \
.resources = wrtd_stx2_fdt_res, \
}
#define MFD_CELL_TDC0 { \
.name = "fmc-tdc0", \
.platform_data = NULL, \
.pdata_size = 0, \
.num_resources = ARRAY_SIZE(wrtd_stx2_tdc0_res), \
.resources = wrtd_stx2_tdc0_res, \
}
#define MFD_CELL_TDC1 { \
.name = "fmc-tdc1", \
.platform_data = NULL, \
.pdata_size = 0, \
.num_resources = ARRAY_SIZE(wrtd_stx2_tdc1_res), \
.resources = wrtd_stx2_tdc1_res, \
}
static const struct mfd_cell __wrtd_stx2_mfd_devs_base[] = {
MFD_CELL_TRTL,
};
static const struct mfd_cell __wrtd_stx2_mfd_devs_tdc[] = {
MFD_CELL_TRTL,
MFD_CELL_TDC0,
MFD_CELL_TDC1,
};
static const struct mfd_cell *wrtd_stx2_mfd_cells(const char *extra)
{
if (strncmp("tdc", extra, 3) == 0)
return __wrtd_stx2_mfd_devs_tdc;
else
return __wrtd_stx2_mfd_devs_base;
}
static unsigned int wrtd_stx2_mfd_count(const char *extra)
{
if (strncmp("tdc", extra, 3) == 0)
return 3;
else
return 1;
}
static int wrtd_stx2_probe(struct platform_device *pdev)
{
struct resource *rmem;
int irq;
rmem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!rmem) {
dev_err(&pdev->dev, "Missing memory resource\n");
return -EINVAL;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "Missing IRQ number\n");
return -EINVAL;
}
/*
* We know that this design uses the HTVIC IRQ controller.
* This IRQ controller has a linear mapping, so it is enough
* to give the first one as input
*/
return mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
wrtd_stx2_mfd_cells(drivers),
wrtd_stx2_mfd_count(drivers),
rmem, irq, NULL);
}
static int wrtd_stx2_remove(struct platform_device *pdev)
{
mfd_remove_devices(&pdev->dev);
return 0;
}
/**
* List of supported platform
*/
enum wrtd_stx2_version {
WRTD_STX2_VER = 0,
};
static const struct platform_device_id wrtd_stx2_id_table[] = {
{
.name = "wrtd-stx2",
.driver_data = WRTD_STX2_VER,
}, {
.name = "id:000010DC57544E03",
.driver_data = WRTD_STX2_VER,
}, {
.name = "id:000010dc57544e03",
.driver_data = WRTD_STX2_VER,
},
{},
};
static struct platform_driver wrtd_stx2_driver = {
.driver = {
.name = "wrtd-stx2",
.owner = THIS_MODULE,
},
.id_table = wrtd_stx2_id_table,
.probe = wrtd_stx2_probe,
.remove = wrtd_stx2_remove,
};
module_platform_driver(wrtd_stx2_driver);
MODULE_AUTHOR("Federico Vaga <federico.vaga@cern.ch>");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Driver for the WRTD SVEC TDC x2");
MODULE_DEVICE_TABLE(platform, wrtd_stx2_id_table);
MODULE_SOFTDEP("pre: svec_fmc_carrier mockturtle");
-include Makefile.specific
DIRS := tdc fd adc
DIRS := tdc fd adc tdc-x2 fd-x2 adc-x2
all clean cleanall modules install modules_install: $(DIRS)
......
mainmenu "WRTD ADC firmware configuration"
comment "Project specific configuration"
# include Mock Turtle's Kconfig
source "Kconfig.mt"
-include Makefile.specific
CUR_DIR := $(shell pwd)
FETCHTO=$(CUR_DIR)/../../../dependencies
WRTD_DEP_TRTL ?= $(FETCHTO)/mock-turtle
WRTD_DEP_TRTL_SW ?= $(WRTD_DEP_TRTL)/software
WRTD_DEP_TRTL_FW ?= $(WRTD_DEP_TRTL_SW)/firmware
WRTD_DEP_FMC_ADC ?= $(FETCHTO)/fmc-adc-100m14b4cha
WRTD_DEP_GEN_CORES ?= $(FETCHTO)/general-cores
EXTRA2_CFLAGS += # To be set by user on make line
EXTRA_CFLAGS += $(EXTRA2_CFLAGS)
EXTRA_CFLAGS += -I$(CUR_DIR)/../../include
EXTRA_CFLAGS += -I$(CUR_DIR)/../common
EXTRA_CFLAGS += -I$(WRTD_DEP_FMC_ADC)/software/include/hw
EXTRA_CFLAGS += -I$(CUR_DIR)/../adc
all:
# Redirect all rules to MockTurtle
%:
$(MAKE) -C $(WRTD_DEP_TRTL_FW) M=$(CUR_DIR) \
GEN_CORES=$(WRTD_DEP_GEN_CORES) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" $@
OBJS := wrtd-rt-adc-x2.o
OUTPUT = wrtd-rt-adc-x2
#
# Automatically generated file; DO NOT EDIT.
#
#
# Project specific configuration
#
#
# Mock Turtle configuration
#
CONFIG_FPGA_APPLICATION_ID=0
CONFIG_RT_APPLICATION_ID=0
CONFIG_CFLAGS_OPT="-Os"
CONFIG_CFLAGS_EXTRA="-ggdb"
#
# Mock Turtle framework configuration
#
CONFIG_MOCKTURTLE_FRAMEWORK_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_ACTION_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_VARIABLE_ENABLE=n
CONFIG_MOCKTURTLE_FRAMEWORK_BUFFER_ENABLE=n
CONFIG_MOCKTURTLE_FRAMEWORK_PING_ENABLE=n
CONFIG_MOCKTURTLE_FRAMEWORK_VERSION_ENABLE=y
#
# Mock Turtle library configuration
#
CONFIG_MOCKTURTLE_LIBRARY_PRINT_ENABLE=y
# CONFIG_MOCKTURTLE_LIBRARY_PRINT_DEBUG_ENABLE is not set
# CONFIG_MOCKTURTLE_LIBRARY_PRINT_ERROR_ENABLE is not set
# CONFIG_MOCKTURTLE_LIBRARY_PRINT_MESSAGE_ENABLE is not set
../common/trtl-memory.ld
\ No newline at end of file
/**
* @file wrtd-rt-adc.c
*
* Copyright (c) 2018-2019 CERN (home.cern)
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include "mockturtle-rt.h"
#include <mockturtle-framework.h>
#include "wrtd-common.h"
#include "fmc_adc_aux_trigout.h"
#define NBR_CPUS 1
#define CPU_IDX 0
#define NBR_RULES 16
#define NBR_DEVICES 2
#define NBR_ALARMS 1
#define DEVICES_NBR_CHS { 2*5, 2*1, 0, 0}
#define DEVICES_CHS_DIR { WRTD_CH_DIR_IN, WRTD_CH_DIR_OUT, 0, 0}
#define APP_ID 0x35B0
#define APP_VER RT_VERSION(2, 0)
#define APP_NAME "wrtd-adc-x2"
#define WRTD_NET_TX 1
#define WRTD_NET_RX 1
#define WRTD_LOCAL_TX 1
#define WRTD_LOCAL_RX 1
#include "wrtd-rt-common.h"
#include "wrtd-adcout.c"
#include "wrtd-adcin.c"
static struct wrtd_adcin_dev adcin[2] =
{
{.io_addr = 0x1000, .ch = 0},
{.io_addr = 0x3000, .ch = 5},
};
static struct wrtd_adcout_dev adcout[2] =
{
{.io_addr = 0x0000},
{.io_addr = 0x2000},
};
static inline int wr_link_up(void)
{
/* Same link for everyone. */
return adcin_wr_link_up(&adcin[0]);
}
static inline int wr_time_ready(void)
{
/* Same time for everyone. */
return adcin_wr_time_ready(&adcin[0]);
}
static inline void wr_enable_lock(int enable)
{
/* No lock. */
}
static inline int wr_aux_locked(void)
{
/* No aux clock. */
return 1;
}
static inline int wr_sync_timeout(void)
{
/* No timeout. */
return 0;
}
static int wrtd_local_output(struct wrtd_event *ev, unsigned ch)
{
if ((ch & 15) == 0)
return adcout_local_output(&adcout[0], ev, 0);
else
return adcout_local_output(&adcout[1], ev, 0);
}
static int wrtd_user_init(void)
{
unsigned i;
for (i = 0; i < 2; i++) {
adcin_init(&adcin[i]);
adcout_init(&adcout[i]);
}
wr_enable_lock(0);
pr_debug("rt-adc firmware initialized.\n\r");
return 0;
}
static void wrtd_io(void)
{
unsigned i;
for (i = 0; i < 2; i++) {
adcin_input(&adcin[i]);
adcout_output(&adcout[i]);
}
}
......@@ -2,9 +2,12 @@
CUR_DIR := $(shell pwd)
WRTD_DEP_TRTL_FW ?= $(CUR_DIR)/../../../dependencies/mock-turtle/software/firmware
WRTD_DEP_FMC_ADC ?= $(CUR_DIR)/../../../dependencies/fmc-adc-100m14b4cha-gw
WRTD_DEP_GEN_CORES ?= $(CUR_DIR)/../../../dependencies/general-cores
FETCHTO=$(CUR_DIR)/../../../dependencies
WRTD_DEP_TRTL ?= $(FETCHTO)/mock-turtle
WRTD_DEP_TRTL_SW ?= $(WRTD_DEP_TRTL)/software
WRTD_DEP_TRTL_FW ?= $(WRTD_DEP_TRTL_SW)/firmware
WRTD_DEP_FMC_ADC ?= $(FETCHTO)/fmc-adc-100m14b4cha
WRTD_DEP_GEN_CORES ?= $(FETCHTO)/general-cores
EXTRA2_CFLAGS += # To be set by user on make line
EXTRA_CFLAGS += $(EXTRA2_CFLAGS)
......@@ -16,5 +19,5 @@ all:
# Redirect all rules to MockTurtle
%:
$(MAKE) -C $(WRTD_DEP_TRTL_FW) M=$(shell /bin/pwd) \
GEN_CORES=$(WRTD_DEP_GEN_CORES) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" $@
$(MAKE) -C $(WRTD_DEP_TRTL_FW) M=$(CUR_DIR) \
GEN_CORES=$(WRTD_DEP_GEN_CORES) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" $@
......@@ -19,8 +19,8 @@ CONFIG_CFLAGS_EXTRA="-ggdb"
#
CONFIG_MOCKTURTLE_FRAMEWORK_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_ACTION_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_VARIABLE_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_BUFFER_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_VARIABLE_ENABLE=n
CONFIG_MOCKTURTLE_FRAMEWORK_BUFFER_ENABLE=n
CONFIG_MOCKTURTLE_FRAMEWORK_PING_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_VERSION_ENABLE=y
......
......@@ -9,11 +9,13 @@
*/
#include "mockturtle-rt.h"
#include "fmc_adc_aux_trigout.h"
#define ADCIN_NUM_CHANNELS 5
struct wrtd_adcin_dev {
uint32_t io_addr;
unsigned char ch;
};
static inline void adcin_writel(const struct wrtd_adcin_dev *dev,
......@@ -32,16 +34,6 @@ static inline int adcin_wr_link_up(struct wrtd_adcin_dev *adcin)
return adcin_readl(adcin, AUX_TRIGOUT_STATUS) & AUX_TRIGOUT_WR_LINK;
}
static inline int adcin_wr_time_locked(struct wrtd_adcin_dev *adcin)
{
return 1;
}
static void adcin_wr_enable_lock(struct wrtd_adcin_dev *dev, int enable)
{
return;
}
static inline int adcin_wr_time_ready(struct wrtd_adcin_dev *adcin)
{
return adcin_readl(adcin, AUX_TRIGOUT_STATUS) & AUX_TRIGOUT_WR_VALID;
......@@ -72,6 +64,7 @@ static void adcin_input(struct wrtd_adcin_dev *adcin)
ev.ts.frac = 0;
for (i = 0; i < ADCIN_NUM_CHANNELS; i++) {
unsigned ch = adcin->ch + i;
/* The last channel is the ext trigger with a different mask */
if ( i == ADCIN_NUM_CHANNELS - 1 ) {
......@@ -81,17 +74,22 @@ static void adcin_input(struct wrtd_adcin_dev *adcin)
else if (!(mask & ((AUX_TRIGOUT_CH1_MASK >> 32) << i)))
continue;
memset(ev.id, 0, WRTD_ID_LEN);
ev.id[0] = 'L';
ev.id[1] = 'C';
ev.id[2] = '-';
ev.id[3] = 'I';
ev.id[4] = '1' + i;
zero_id(&ev.id);
ev.id.c[0] = 'L';
ev.id.c[1] = 'C';
ev.id.c[2] = '-';
ev.id.c[3] = 'I';
if (ch < 9)
ev.id.c[4] = '1' + ch;
else {
ev.id.c[4] = '1';
ev.id.c[5] = '0' + ch - 9;
}
ev.flags = 0;
wrtd_log(WRTD_LOG_MSG_EV_GENERATED,
WRTD_LOG_GENERATED_DEVICE + (i * 8),
NULL, &ev, NULL);
&ev, NULL);
/* Pass to wrtd. */
wrtd_route_in(&ev);
......
......@@ -28,37 +28,6 @@ struct wrtd_adcout_dev {
struct adcout_out_queue queue;
};
static inline int adcout_wr_present(struct wrtd_adcout_dev *fd)
{
return 1;
}
static inline int adcout_wr_link_up(struct wrtd_adcout_dev *fd)
{
return 1;
}
static inline int adcout_wr_time_locked(struct wrtd_adcout_dev *fd)
{
return 1;
}
static inline int adcout_wr_time_ready(struct wrtd_adcout_dev *fd)
{
return 1;
}
static inline int adcout_wr_sync_timeout(void)
{
return 0;
}
static void adcout_wr_enable_lock(struct wrtd_adcout_dev *fd, int enable)
{
return;
}
static inline void adcout_writel(struct wrtd_adcout_dev *dev, uint32_t value,
uint32_t reg)
{
......@@ -93,7 +62,7 @@ static void adcout_drop_trigger(struct wrtd_adcout_dev *dev,
/* Disarm the ADC output */
adcout_writel(dev, 0, AUX_TRIGIN_CTRL);
wrtd_log(WRTD_LOG_MSG_EV_DISCARDED, reason, NULL, ev, now);
wrtd_log(WRTD_LOG_MSG_EV_DISCARDED, reason, ev, now);
}
......@@ -110,13 +79,6 @@ static void adcout_output (struct wrtd_adcout_dev *dev)
/* Check if the output has triggered */
if (!dev->idle) {
#if 0
if (!wr_is_timing_ok()) {
/* Timing has been lost. */
drop_trigger(out, ev, q, WRTD_LOG_DISCARD_NO_SYNC);
return;
}
#endif
if (ctrl & AUX_TRIGIN_CTRL_ENABLE) {
/* Armed but still waiting for trigger */
struct wrtd_tstamp now;
......@@ -128,8 +90,7 @@ static void adcout_output (struct wrtd_adcout_dev *dev)
} else {
/* Has been triggered. */
wrtd_log(WRTD_LOG_MSG_EV_CONSUMED,
WRTD_LOG_CONSUMED_DONE,
NULL, ev, NULL);
WRTD_LOG_CONSUMED_DONE, ev, NULL);
adcout_out_queue_pop(q);
dev->idle = 1;
......@@ -152,8 +113,7 @@ static void adcout_output (struct wrtd_adcout_dev *dev)
adcout_writel(dev, ev->ts.ns / 8, AUX_TRIGIN_CYCLES);
adcout_writel(dev, AUX_TRIGIN_CTRL_ENABLE, AUX_TRIGIN_CTRL);
wrtd_log(WRTD_LOG_MSG_EV_CONSUMED, WRTD_LOG_CONSUMED_START,
NULL, ev, NULL);
wrtd_log(WRTD_LOG_MSG_EV_CONSUMED, WRTD_LOG_CONSUMED_START, ev, NULL);
ts_add3_ns (&ts, &ev->ts, 8000);
......@@ -176,7 +136,7 @@ static int adcout_local_output(struct wrtd_adcout_dev *dev,
return -EOVERFLOW;
}
*pq_ev = *ev;
copy_event(pq_ev, ev);
return 0;
}
......
......@@ -9,7 +9,6 @@
#include "mockturtle-rt.h"
#include <mockturtle-framework.h>
#include "wrtd-common.h"
#include "fmc_adc_aux_trigout.h"
#define NBR_CPUS 1
#define CPU_IDX 0
......@@ -45,17 +44,6 @@ static inline int wr_link_up(void)
{
if (!adcin_wr_link_up(&adcin0))
return 0;
if (!adcout_wr_link_up(&adcout0))
return 0;
return 1;
}
static inline int wr_time_locked(void)
{
if (!adcin_wr_time_locked(&adcin0))
return 0;
if (!adcout_wr_time_locked(&adcout0))
return 0;
return 1;
}
......@@ -63,32 +51,22 @@ static inline int wr_time_ready(void)
{
if (!adcin_wr_time_ready(&adcin0))
return 0;
if (!adcout_wr_time_ready(&adcout0))
return 0;
return 1;
}
static inline void wr_enable_lock(int enable)
{
adcin_wr_enable_lock(&adcin0, enable);
adcout_wr_enable_lock(&adcout0, enable);
/* No aux clock on ADC boards */
}
static inline int wr_aux_locked(void)
{
return 1;
}
static inline int wr_sync_timeout(void)
{
#ifdef SIMULATION
return 0;
#else
int res, val;
res = 0;
val = adcin_wr_sync_timeout();
res = val > res ? val : res;
val = adcout_wr_sync_timeout();
res = val > res ? val : res;
return res;
#endif
}
static int wrtd_local_output(struct wrtd_event *ev, unsigned ch)
......
......@@ -13,15 +13,16 @@
* #define NBR_RULES xxx
* #define NBR_DEVICES xxx
* #define NBR_ALARMS xxx
* #define DEVICES_NBR_CHS { xxx, 0, 0, 0}
* #define DEVICES_CHS_DIR { WRTD_CH_DIR_IN, 0, 0, 0}
* #define DEVICES_NBR_CHS { xxx, 0, 0, 0} // Number of channels
* #define DEVICES_CHS_DIR { WRTD_CH_DIR_IN, 0, 0, 0} // Direction
* #define APP_ID WRTD_APP_xxx
* #define APP_VER RT_VERSION(xxx, 0)
* #define APP_NAME xxx
* #define WRTD_NET_RX x // 1 = enabled, 0 = disabled
* #define WRTD_NET_TX x
* #define WRTD_LOCAL_RX x
* #define WRTD_LOCAL_TX x
* // 1 = enabled, 0 = disabled
* #define WRTD_NET_RX x // 1 if receive events from the network
* #define WRTD_NET_TX x // 1 if transmit events to the network
* #define WRTD_LOCAL_RX x // 1 if consume events
* #define WRTD_LOCAL_TX x // 1 if generate events
* #include "wrtd-rt-common.h"
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
......@@ -46,30 +47,34 @@
* @return ``1`` if true, ``0`` otherwise.
*/
static int wr_link_up(void);
/**
* Check whether the application is locked to the WR clock or not.
* Check whether the WR time is valid.
*
* If the application does not need this, write a function that returns always ``1``.
*
* @return ``1`` if true, ``0`` otherwise.
*/
static int wr_time_locked(void);
static int wr_time_ready(void);
/**
* Check whether the WR time is valid.
* Check whether the application clock is locked to the WR clock or not.
*
* If the application does not need this, write a function that returns always ``1``.
*
* @return ``1`` if true, ``0`` otherwise.
*/
static int wr_time_ready(void);
static int wr_aux_locked(void);
/**
* Enable/disable locking of the application to the WR clock.
* Enable/disable locking of the application clock to the WR clock.
*
* If the application does not need this, write a function that does nothing.
*
* @param[in] enable set to ``1`` to enable, set to ``0`` to disable.
*/
static void wr_enable_lock(int enable);
/**
* Generate an output Event on a Local Channel.
*
......@@ -80,6 +85,7 @@ static void wr_enable_lock(int enable);
* @return ``0`` on success, or error code otherwise.
*/
static int wrtd_local_output(struct wrtd_event *ev, unsigned ch);
/**
* Return the delay in seconds that the application should wait before
* considering the WR link synced.
......@@ -89,6 +95,7 @@ static int wrtd_local_output(struct wrtd_event *ev, unsigned ch);
* @return Integer number of seconds to wait.
*/
static int wr_sync_timeout(void);
/**
* Function to perform any apllication-specific initialisation (runs once after reset).
*
......@@ -97,6 +104,7 @@ static int wr_sync_timeout(void);
* @return ``0`` on success, or error code otherwise.
*/
static int wrtd_user_init(void);
/**
* Function to perform the main tasks of the application. This will run in a loop.
*
......@@ -170,7 +178,7 @@ static void wr_update_link(void)
}
break;
case WR_LINK_SYNCING:
if (wr_time_locked()) {
if (wr_aux_locked()) {
pr_debug("sync detected, waiting for plumbing to catch up...\n\r");
root.wr_state = WR_LINK_WAIT;
tai_start = lr_readl(MT_CPU_LR_REG_TAI_SEC);
......@@ -309,7 +317,7 @@ static inline void ts_sub3_ps(struct wrtd_tstamp *dest,
dest->ns = src->ns - ps_ns;
dest->frac = src->frac - (WRTD_TSTAMP_FRAC_PS * ps_left);
if ((ps / 1000) > src->ns)
if (ps_ns > src->ns)
dest->seconds--;
if ((WRTD_TSTAMP_FRAC_PS * ps_left) > src->frac)
......@@ -344,39 +352,72 @@ static void ts_now(struct wrtd_tstamp *now)
now->frac = 0;
}
static void wrtd_log(uint32_t type, uint32_t reason,
struct wrtd_rule *rule,
const struct wrtd_event *ev,
const struct wrtd_tstamp *ts)
/* Clear an id. Like memset but denser. */
static inline void zero_id(union wrtd_id *id)
{
id->w[0] = 0;
id->w[1] = 0;
id->w[2] = 0;
id->w[3] = 0;
}
/* Copy an id. Like memcpy but denser. */
static inline void copy_id(union wrtd_id *dest, const union wrtd_id *src)
{
dest->w[0] = src->w[0];
dest->w[1] = src->w[1];
dest->w[2] = src->w[2];
dest->w[3] = src->w[3];
}
/* Clear an event. Like memset but denser. */
static inline void zero_event(struct wrtd_event *ev)
{
ev->ts.seconds = 0;
ev->ts.ns = 0;
ev->ts.frac = 0;
zero_id(&ev->id);
ev->seq = 0;
ev->flags = 0;
}
static inline void copy_tstamp(struct wrtd_tstamp *dest,
const struct wrtd_tstamp *src)
{
dest->seconds = src->seconds;
dest->ns = src->ns;
dest->frac = src->frac;
}
/* Copy an id. Like memcpy but denser. */
static inline void copy_event(struct wrtd_event *dest,
const struct wrtd_event *src)
{
copy_tstamp(&dest->ts, &src->ts);
copy_id(&dest->id, &src->id);
dest->seq = src->seq;
dest->flags = src->flags;
}
/* Returns true iff L is the same id as R. */
static inline int wrtd_id_eq(const union wrtd_id *l, const union wrtd_id *r)
{
return !((l->w[0] ^ r->w[0])
| (l->w[1] ^ r->w[1])
| (l->w[2] ^ r->w[2])
| (l->w[3] ^ r->w[3]));
}
static void wrtd_log_1(uint32_t type, uint32_t reason,
const struct wrtd_event *ev,
const struct wrtd_tstamp *ts)
{
struct wrtd_log_entry *log;
struct trtl_fw_msg msg;
int ret;
if (root.log_flags == 0)
return;
/* First, handle statistics */
if ((type == WRTD_LOG_MSG_EV_DISCARDED) && (rule != NULL)) {
rule->stat.miss_last = ev->ts;
switch (reason) {
case WRTD_LOG_DISCARD_NO_SYNC:
rule->stat.miss_nosync++;
break;
case WRTD_LOG_DISCARD_HOLDOFF:
rule->stat.miss_holdoff++;
break;
case WRTD_LOG_DISCARD_TIMEOUT:
rule->stat.miss_late++;
break;
case WRTD_LOG_DISCARD_OVERFLOW:
rule->stat.miss_overflow++;
break;
default:
break;
}
}
ret = mq_claim(TRTL_HMQ, WRTD_HMQ);
if (ret == -EBUSY) {
return;
......@@ -391,13 +432,10 @@ static void wrtd_log(uint32_t type, uint32_t reason,
log = (struct wrtd_log_entry *)msg.payload;
log->type = type;
log->reason = reason;
if (ev != NULL)
log->event = *ev;
else
memset(&log->event, 0, sizeof(struct wrtd_event));
copy_event(&log->event, ev);
if (ts != NULL)
log->ts = *ts;
copy_tstamp(&log->ts, ts);
else
ts_now(&log->ts);
......@@ -405,6 +443,27 @@ static void wrtd_log(uint32_t type, uint32_t reason,
}
/* Send a log message (only if log is enabled).
If TS is NULL, use the current time as time stamp. */
static inline void wrtd_log(uint32_t type, uint32_t reason,
const struct wrtd_event *ev,
const struct wrtd_tstamp *ts)
{
if (root.log_flags == 0)
return;
wrtd_log_1(type, reason, ev, ts);
}
static void wrtd_log_discard(struct wrtd_rule *rule,
uint32_t reason,
const struct wrtd_event *ev,
const struct wrtd_tstamp *ts)
{
copy_tstamp(&rule->stat.miss_last, &ev->ts);
wrtd_log(WRTD_LOG_MSG_EV_DISCARDED, reason, ev, ts);
}
#if WRTD_NET_TX > 0
static void wrtd_init_tx(void)
{
......@@ -443,7 +502,7 @@ static int wrtd_send_network(struct wrtd_event *ev)
msg->hw_detect[1] = 'X';
msg->hw_detect[2] = 'I';
msg->domain = 0;
memcpy((unsigned char *)msg->event_id, ev->id, WRTD_ID_LEN);
copy_id((union wrtd_id *)&msg->event_id, &ev->id);
msg->seq = ev->seq;
msg->ts_sec = ev->ts.seconds;
msg->ts_ns = ev->ts.ns;
......@@ -456,7 +515,7 @@ static int wrtd_send_network(struct wrtd_event *ev)
mq_send(TRTL_RMQ, WRTD_RMQ);
wrtd_log(WRTD_LOG_MSG_EV_NETWORK, WRTD_LOG_NETWORK_TX, NULL, ev, NULL);
wrtd_log(WRTD_LOG_MSG_EV_NETWORK, WRTD_LOG_NETWORK_TX, ev, NULL);
return 0;
}
......@@ -473,9 +532,9 @@ static void wrtd_route(struct wrtd_rule *rule, const struct wrtd_event *ev)
one. */
if (rule->conf.hold_off_ns) {
if (ts_cmp(&ev->ts, &rule->stat.hold_off) < 0) {
wrtd_log(WRTD_LOG_MSG_EV_DISCARDED,
WRTD_LOG_DISCARD_HOLDOFF,
rule, ev, NULL);
rule->stat.miss_holdoff++;
wrtd_log_discard(rule, WRTD_LOG_DISCARD_HOLDOFF,
ev, NULL);
return;
}
......@@ -486,13 +545,13 @@ static void wrtd_route(struct wrtd_rule *rule, const struct wrtd_event *ev)
/* Event was received. */
rule->stat.rx_events++;
rule->stat.rx_last = ev->ts;
copy_tstamp(&rule->stat.rx_last, &ev->ts);
/* Delay. */
if (rule->conf.delay_ns)
ts_add3_ns(&tev.ts, &ev->ts, rule->conf.delay_ns);
else
tev.ts = ev->ts;
copy_tstamp(&tev.ts, &ev->ts);
/* Resync. */
if (rule->conf.resync_period_ns) {
......@@ -514,16 +573,15 @@ static void wrtd_route(struct wrtd_rule *rule, const struct wrtd_event *ev)
}
/* Rename event. */
memcpy(tev.id, rule->conf.dest_id, WRTD_ID_LEN);
copy_id(&tev.id, &rule->conf.dest_id);
tev.seq = rule->stat.seq++;
uint32_t res = 0;
/* Check timing. */
if (!wr_is_timing_ok()) {
wrtd_log(WRTD_LOG_MSG_EV_DISCARDED,
WRTD_LOG_DISCARD_NO_SYNC,
rule, ev, NULL);
rule->stat.miss_nosync++;
wrtd_log_discard(rule, WRTD_LOG_DISCARD_NO_SYNC, ev, NULL);
return;
}
......@@ -534,9 +592,9 @@ static void wrtd_route(struct wrtd_rule *rule, const struct wrtd_event *ev)
|| (tev.ts.seconds == now.seconds
&& tev.ts.ns < now.ns)) {
/* Too late... */
wrtd_log(WRTD_LOG_MSG_EV_DISCARDED,
WRTD_LOG_DISCARD_TIMEOUT,
rule, ev, &now);
rule->stat.miss_late++;
wrtd_log_discard(rule, WRTD_LOG_DISCARD_TIMEOUT,
ev, &now);
return;
}
}
......@@ -545,9 +603,12 @@ static void wrtd_route(struct wrtd_rule *rule, const struct wrtd_event *ev)
if (rule->conf.dest_ch == WRTD_DEST_CH_NET) {
#if WRTD_NET_TX > 0
res = wrtd_send_network(&tev);
#else
#elif NBR_CPUS > 1
res = wrtd_remote_output
(&tev, rule->conf.dest_cpu, WRTD_DEST_CH_NET);
#else
/* Event cannot be consumed. */
res = -EOVERFLOW;
#endif
}
else {
......@@ -562,13 +623,12 @@ static void wrtd_route(struct wrtd_rule *rule, const struct wrtd_event *ev)
}
}
if (res == -EOVERFLOW) {
wrtd_log(WRTD_LOG_MSG_EV_DISCARDED,
WRTD_LOG_DISCARD_OVERFLOW,
rule, ev, NULL);
rule->stat.miss_overflow++;
wrtd_log_discard(rule, WRTD_LOG_DISCARD_OVERFLOW, ev, NULL);
}
else if (res == 0) {
rule->stat.tx_events++;
rule->stat.tx_last = ev->ts;
copy_tstamp(&rule->stat.tx_last, &ev->ts);
}
/* Compute latency. */
......@@ -610,7 +670,7 @@ static void wrtd_route(struct wrtd_rule *rule, const struct wrtd_event *ev)
static void wrtd_route_in(struct wrtd_event *ev)
{
struct wrtd_rule *rule;
unsigned int hash = wrtd_id_hash(ev->id) % NBR_RULES;
unsigned int hash = wrtd_id_hash(&ev->id) % NBR_RULES;
rule = &rules[hash];
while (1) {
......@@ -618,7 +678,7 @@ static void wrtd_route_in(struct wrtd_event *ev)
if (!rule->conf.enabled)
break;
if (memcmp(ev->id, rule->conf.source_id, WRTD_ID_LEN) == 0)
if (wrtd_id_eq(&ev->id, &rule->conf.source_id))
wrtd_route(rule, ev);
if (rule->conf.hash_chain == -1)
......@@ -664,13 +724,13 @@ static void wrtd_recv_network(void)
ev.ts.ns = msg->ts_ns;
ev.ts.frac = msg->ts_frac << 16;
memcpy(ev.id, (char *)msg->event_id, WRTD_ID_LEN);
copy_id(&ev.id, (union wrtd_id*)&msg->event_id);
ev.flags = msg->flags;
mq_discard(TRTL_RMQ, WRTD_RMQ);
wrtd_log(WRTD_LOG_MSG_EV_NETWORK, WRTD_LOG_NETWORK_RX, NULL, &ev, NULL);
wrtd_log(WRTD_LOG_MSG_EV_NETWORK, WRTD_LOG_NETWORK_RX, &ev, NULL);
wrtd_route_in(&ev);
......@@ -692,11 +752,14 @@ static void wrtd_alarms(void)
if (!al->enabled)
continue;
/* Wait until the setup time is over. */
if (ts_cmp(&al->setup_time, &now) > 0)
continue;
/* TODO/FIXME: discard if the alarm time is over ? */
wrtd_log(WRTD_LOG_MSG_EV_GENERATED, WRTD_LOG_GENERATED_ALARM,
NULL, &al->event, &now);
&al->event, &now);
/* Trigger. */
wrtd_route_in(&al->event);
......
mainmenu "WRTD Fine Delay firmware configuration"
comment "Project specific configuration"
# include Mock Turtle's Kconfig
source "Kconfig.mt"
-include Makefile.specific
CUR_DIR := $(shell pwd)
FETCHTO=$(CUR_DIR)/../../../dependencies
WRTD_DEP_TRTL ?= $(FETCHTO)/mock-turtle
WRTD_DEP_TRTL_SW ?= $(WRTD_DEP_TRTL)/software
WRTD_DEP_TRTL_FW ?= $(WRTD_DEP_TRTL_SW)/firmware
WRTD_DEP_GEN_CORES ?= $(FETCHTO)/general-cores
EXTRA2_CFLAGS += # To be set by user on make line
EXTRA_CFLAGS += $(EXTRA2_CFLAGS)
EXTRA_CFLAGS += -I$(CUR_DIR)/../../include
EXTRA_CFLAGS += -I$(CUR_DIR)/../common
EXTRA_CFLAGS += -I$(CUR_DIR)/../fd
all:
# Redirect all rules to MockTurtle
%:
$(MAKE) -C $(WRTD_DEP_TRTL_FW) M=$(CUR_DIR) \
GEN_CORES=$(WRTD_DEP_GEN_CORES) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" $@
OBJS := wrtd-rt-fd-x2.o
OUTPUT = wrtd-rt-fd-x2
#
# Automatically generated file; DO NOT EDIT.
#
#
# Project specific configuration
#
#
# Mock Turtle configuration
#
CONFIG_FPGA_APPLICATION_ID=0
CONFIG_RT_APPLICATION_ID=0
CONFIG_CFLAGS_OPT="-Os"
CONFIG_CFLAGS_EXTRA="-ggdb"
#
# Mock Turtle framework configuration
#
CONFIG_MOCKTURTLE_FRAMEWORK_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_ACTION_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_VARIABLE_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_BUFFER_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_PING_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_VERSION_ENABLE=y
#
# Mock Turtle library configuration
#
CONFIG_MOCKTURTLE_LIBRARY_PRINT_ENABLE=y
# CONFIG_MOCKTURTLE_LIBRARY_PRINT_DEBUG_ENABLE is not set
# CONFIG_MOCKTURTLE_LIBRARY_PRINT_ERROR_ENABLE is not set
# CONFIG_MOCKTURTLE_LIBRARY_PRINT_MESSAGE_ENABLE is not set
../common/trtl-memory.ld
\ No newline at end of file
/**
* @file wrtd-rt-fd.c
*
* Copyright (c) 2018-2019 CERN (home.cern)
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include "mockturtle-rt.h"
#include <mockturtle-framework.h>
#include "wrtd-common.h"
#include "wrtd-fd.h"
#define NBR_CPUS 1
#define CPU_IDX 0
#define NBR_RULES 16
#define NBR_DEVICES 1
#define NBR_ALARMS 1
#define DEVICES_NBR_CHS { 2 * FD_NUM_CHANNELS, 0, 0, 0}
#define DEVICES_CHS_DIR { WRTD_CH_DIR_OUT, 0, 0, 0}
#define APP_ID 0x35E0
#define APP_VER RT_VERSION(2, 0)
#define APP_NAME "wrtd-fd-x2"
#define WRTD_NET_TX 0
#define WRTD_NET_RX 1
#define WRTD_LOCAL_TX 1
#define WRTD_LOCAL_RX 0
#include "wrtd-rt-common.h"
#include "wrtd-fd.c"
#include "fd-acam.c"
#include "fd-gpio.c"
#include "fd-pll.c"
#include "fd-i2c.c"
#include "fd-calibrate.c"
#include "fd-init.c"
struct wrtd_fd_dev fd0 = {
.io_addr = 0x0
};
struct wrtd_fd_dev fd1 = {
.io_addr = 0x8000
};
static int wr_link_up(void)
{
return fd_wr_link_up(&fd0);
}
static int wr_time_ready(void)
{
return fd_wr_time_ready(&fd0);
}
static void wr_enable_lock(int enable)
{
fd_wr_enable_lock(&fd0, enable);
fd_wr_enable_lock(&fd1, enable);
}
static int wr_aux_locked(void)
{
return fd_wr_aux_locked(&fd0) && fd_wr_aux_locked(&fd1);
}
static inline int wr_sync_timeout(void)
{
#ifdef SIMULATION
return 0;
#else
return fd_wr_sync_timeout();
#endif
}
static int wrtd_local_output(struct wrtd_event *ev, unsigned ch)
{
if (ch < 4)
return fd_local_output(&fd0, ev, ch);
else
return fd_local_output(&fd1, ev, ch - 4);
}
/**
* Initialize data structures, RT application and variables
*/
static int wrtd_user_init(void)
{
if (!fd_wr_present(&fd0)) {
pr_error("WhiteRabbit not found\n\r");
return -EINVAL;
}
wr_enable_lock(0);
/* Channels */
wrtd_fd_data_init(&fd0);
wrtd_fd_data_init(&fd1);
#ifdef SIMULATION
fd_sim_init(&fd0);
fd_sim_init(&fd1);
#else
fd_init(&fd0);
fd_init(&fd1);
#endif
pr_debug("rt-output firmware initialized.\n\r");
return 0;
}
static void wrtd_io(void)
{
fd_outputs(&fd0);
fd_outputs(&fd1);
}
......@@ -2,8 +2,11 @@
CUR_DIR := $(shell pwd)
WRTD_DEP_TRTL_FW ?= $(CUR_DIR)/../../../dependencies/mock-turtle/software/firmware
WRTD_DEP_GEN_CORES ?= $(CUR_DIR)/../../../dependencies/general-cores
FETCHTO=$(CUR_DIR)/../../../dependencies
WRTD_DEP_TRTL ?= $(FETCHTO)/mock-turtle
WRTD_DEP_TRTL_SW ?= $(WRTD_DEP_TRTL)/software
WRTD_DEP_TRTL_FW ?= $(WRTD_DEP_TRTL_SW)/firmware
WRTD_DEP_GEN_CORES ?= $(FETCHTO)/general-cores
EXTRA2_CFLAGS += # To be set by user on make line
EXTRA_CFLAGS += $(EXTRA2_CFLAGS)
......@@ -14,5 +17,5 @@ all:
# Redirect all rules to MockTurtle
%:
$(MAKE) -C $(WRTD_DEP_TRTL_FW) M=$(shell /bin/pwd) \
GEN_CORES=$(WRTD_DEP_GEN_CORES) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" $@
$(MAKE) -C $(WRTD_DEP_TRTL_FW) M=$(CUR_DIR) \
GEN_CORES=$(WRTD_DEP_GEN_CORES) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" $@
......@@ -19,8 +19,8 @@ CONFIG_CFLAGS_EXTRA="-ggdb"
#
CONFIG_MOCKTURTLE_FRAMEWORK_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_ACTION_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_VARIABLE_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_BUFFER_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_VARIABLE_ENABLE=n
CONFIG_MOCKTURTLE_FRAMEWORK_BUFFER_ENABLE=n
CONFIG_MOCKTURTLE_FRAMEWORK_PING_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_VERSION_ENABLE=y
......
......@@ -20,7 +20,7 @@
#include "hw/fd_channel_regs.h"
/* This is the same as in ./acam.c: use only at init time */
static void acam_set_bypass(struct wrtd_fd_dev *fd, int on)
static void set_acam_bypass(struct wrtd_fd_dev *fd, int on)
{
fd_writel(fd, on ? FD_GCR_BYPASS : 0, FD_REG_GCR);
}
......@@ -124,7 +124,7 @@ int fd_calibrate_outputs(struct wrtd_fd_dev *fd)
int ch;
int measured;
acam_set_bypass(fd, 1); /* not useful */
set_acam_bypass(fd, 1); /* not useful */
fd_writel(fd, FD_TDCSR_START_EN | FD_TDCSR_STOP_EN, FD_REG_TDCSR);
for (ch = 0; ch < FD_NUM_CHANNELS; ch++) {
......
......@@ -25,7 +25,7 @@ struct wrtd_fd_calibration calib = {
static inline int fd_wr_present(struct wrtd_fd_dev *fd)
{
return !!(fd_readl(fd, FD_REG_TCR) & FD_TCR_WR_PRESENT);
return fd_readl(fd, FD_REG_TCR) & FD_TCR_WR_PRESENT;
}
static inline int fd_wr_link_up(struct wrtd_fd_dev *fd)
......@@ -33,14 +33,14 @@ static inline int fd_wr_link_up(struct wrtd_fd_dev *fd)
return fd_readl(fd, FD_REG_TCR) & FD_TCR_WR_LINK;
}
static inline int fd_wr_time_locked(struct wrtd_fd_dev *fd)
static inline int fd_wr_aux_locked(struct wrtd_fd_dev *fd)
{
return fd_readl(fd, FD_REG_TCR) & FD_TCR_WR_LOCKED;
}
static inline int fd_wr_time_ready(struct wrtd_fd_dev *fd)
{
return 1;
return fd_readl(fd, FD_REG_TCR) & FD_TCR_WR_READY;
}
static inline int fd_wr_sync_timeout(void)
......@@ -188,7 +188,7 @@ static void drop_trigger(struct wrtd_fd_channel *out,
/* Disarm the FD output */
fd_ch_writel(out, FD_DCR_MODE, FD_REG_DCR);
wrtd_log(WRTD_LOG_MSG_EV_DISCARDED, reason, NULL, ev, NULL);
wrtd_log(WRTD_LOG_MSG_EV_DISCARDED, reason, ev, NULL);
}
......@@ -221,8 +221,7 @@ static void fd_output (struct wrtd_fd_dev *fd, unsigned channel)
} else {
/* Has been triggered. */
wrtd_log(WRTD_LOG_MSG_EV_CONSUMED,
WRTD_LOG_CONSUMED_DONE,
NULL, ev, NULL);
WRTD_LOG_CONSUMED_DONE, ev, NULL);
pulse_queue_pop(q);
out->idle = 1;
......@@ -266,8 +265,7 @@ static void fd_output (struct wrtd_fd_dev *fd, unsigned channel)
fd_ch_writel(out, FD_DCR_MODE | FD_DCR_PG_ARM | FD_DCR_ENABLE,
FD_REG_DCR);
wrtd_log(WRTD_LOG_MSG_EV_CONSUMED, WRTD_LOG_CONSUMED_START,
NULL, ev, NULL);
wrtd_log(WRTD_LOG_MSG_EV_CONSUMED, WRTD_LOG_CONSUMED_START, ev, NULL);
ts_add2_ns (&ts, 8000);
......
......@@ -40,11 +40,6 @@ static int wr_link_up(void)
return fd_wr_link_up(&fd0);
}
static int wr_time_locked(void)
{
return fd_wr_time_locked(&fd0);
}
static int wr_time_ready(void)
{
return fd_wr_time_ready(&fd0);
......@@ -55,6 +50,11 @@ static void wr_enable_lock(int enable)
fd_wr_enable_lock(&fd0, enable);
}
static int wr_aux_locked(void)
{
return fd_wr_aux_locked(&fd0);
}
static inline int wr_sync_timeout(void)
{
#ifdef SIMULATION
......
mainmenu "WRTD TDC firmware configuration"
comment "Project specific configuration"
# include Mock Turtle's Kconfig
source "Kconfig.mt"
-include Makefile.specific
CUR_DIR := $(shell pwd)
FETCHTO=$(CUR_DIR)/../../../dependencies
WRTD_DEP_TRTL ?= $(FETCHTO)/mock-turtle
WRTD_DEP_TRTL_SW ?= $(WRTD_DEP_TRTL)/software
WRTD_DEP_TRTL_FW ?= $(WRTD_DEP_TRTL_SW)/firmware
WRTD_DEP_GEN_CORES ?= $(FETCHTO)/general-cores
EXTRA2_CFLAGS += # To be set by user on make line
EXTRA_CFLAGS += $(EXTRA2_CFLAGS)
EXTRA_CFLAGS += -I$(CUR_DIR)/../../include -I$(CUR_DIR)/../common -I$(CUR_DIR)/../tdc
all:
# Redirect all rules to MockTurtle
%:
$(MAKE) -C $(WRTD_DEP_TRTL_FW) M=$(CUR_DIR) \
GEN_CORES=$(WRTD_DEP_GEN_CORES) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" $@
OBJS := wrtd-rt-tdc-x2.o
OUTPUT = wrtd-rt-tdc-x2
#
# Automatically generated file; DO NOT EDIT.
#
#
# Project specific configuration
#
#
# Mock Turtle configuration
#
CONFIG_FPGA_APPLICATION_ID=0
CONFIG_RT_APPLICATION_ID=0
CONFIG_CFLAGS_OPT="-Os"
CONFIG_CFLAGS_EXTRA="-ggdb"
#
# Mock Turtle framework configuration
#
CONFIG_MOCKTURTLE_FRAMEWORK_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_ACTION_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_VARIABLE_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_BUFFER_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_PING_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_VERSION_ENABLE=y
#
# Mock Turtle library configuration
#
CONFIG_MOCKTURTLE_LIBRARY_PRINT_ENABLE=y
# CONFIG_MOCKTURTLE_LIBRARY_PRINT_DEBUG_ENABLE is not set
# CONFIG_MOCKTURTLE_LIBRARY_PRINT_ERROR_ENABLE is not set
# CONFIG_MOCKTURTLE_LIBRARY_PRINT_MESSAGE_ENABLE is not set
../common/trtl-memory.ld
\ No newline at end of file
/**
* @file wrtd-rt-tdc.c
*
* Copyright (c) 2018-2019 CERN (home.cern)
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include "mockturtle-rt.h"
#include <mockturtle-framework.h>
#include "wrtd-common.h"
#include "hw/fmctdc-direct.h"
#define NBR_CPUS 1
#define CPU_IDX 0
#define NBR_RULES 16
#define NBR_DEVICES 2
#define NBR_ALARMS 1
#define DEVICES_NBR_CHS { 5, 5, 0, 0}
#define DEVICES_CHS_DIR { WRTD_CH_DIR_IN, WRTD_CH_DIR_IN, 0, 0}
#define APP_ID 0x35D2
#define APP_VER RT_VERSION(2, 0)
#define APP_NAME "wrtd-tdc-x2"
#define WRTD_NET_TX 1
#define WRTD_NET_RX 0
#define WRTD_LOCAL_TX 0
#define WRTD_LOCAL_RX 1
#include "wrtd-rt-common.h"
#include "wrtd-tdc.c"
static struct wrtd_tdc_dev tdc0 =
{
.io_addr = 0x0,
.ch = 0,
};
static struct wrtd_tdc_dev tdc1 =
{
.io_addr = 0x10000,
.ch = 5,
};
static inline int wr_link_up(void)
{
// Same value for tdc0 and tdc1.
return tdc_wr_link_up(&tdc0);
}
static inline int wr_time_ready(void)
{
// Same value for tdc0 and tdc1.
return tdc_wr_time_ready(&tdc0);
}
static inline void wr_enable_lock(int enable)
{
tdc_wr_enable_lock(&tdc0, enable);
tdc_wr_enable_lock(&tdc1, enable);
}
static inline int wr_aux_locked(void)
{
return tdc_wr_aux_locked(&tdc0) && tdc_wr_aux_locked(&tdc1);
}
static inline int wr_sync_timeout(void)
{
#ifdef SIMULATION
return 0;
#else
return tdc_wr_sync_timeout();
#endif
}
static int wrtd_local_output(struct wrtd_event *ev, unsigned ch)
{
/* No output. */
return 0;
}
static int wrtd_user_init(void)
{
tdc_init(&tdc0);
tdc_init(&tdc1);
wr_enable_lock(0);
pr_debug("rt-tdc firmware initialized.\n\r");
return 0;
}
static void wrtd_io(void)
{
tdc_input(&tdc0);
tdc_input(&tdc1);
}
......@@ -2,8 +2,11 @@
CUR_DIR := $(shell pwd)
WRTD_DEP_TRTL_FW ?= $(CUR_DIR)/../../../dependencies/mock-turtle/software/firmware
WRTD_DEP_GEN_CORES ?= $(CUR_DIR)/../../../dependencies/general-cores
FETCHTO=$(CUR_DIR)/../../../dependencies
WRTD_DEP_TRTL ?= $(FETCHTO)/mock-turtle
WRTD_DEP_TRTL_SW ?= $(WRTD_DEP_TRTL)/software
WRTD_DEP_TRTL_FW ?= $(WRTD_DEP_TRTL_SW)/firmware
WRTD_DEP_GEN_CORES ?= $(FETCHTO)/general-cores
EXTRA2_CFLAGS += # To be set by user on make line
EXTRA_CFLAGS += $(EXTRA2_CFLAGS)
......@@ -14,5 +17,7 @@ all:
# Redirect all rules to MockTurtle
%:
$(MAKE) -C $(WRTD_DEP_TRTL_FW) M=$(shell /bin/pwd) \
GEN_CORES=$(WRTD_DEP_GEN_CORES) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" $@
$(MAKE) -C $(WRTD_DEP_TRTL_FW) M=$(CUR_DIR) \
GEN_CORES=$(WRTD_DEP_GEN_CORES) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" $@
......@@ -19,8 +19,8 @@ CONFIG_CFLAGS_EXTRA="-ggdb"
#
CONFIG_MOCKTURTLE_FRAMEWORK_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_ACTION_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_VARIABLE_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_BUFFER_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_VARIABLE_ENABLE=n
CONFIG_MOCKTURTLE_FRAMEWORK_BUFFER_ENABLE=n
CONFIG_MOCKTURTLE_FRAMEWORK_PING_ENABLE=y
CONFIG_MOCKTURTLE_FRAMEWORK_VERSION_ENABLE=y
......
......@@ -3,7 +3,7 @@
* File : fmctdc-direct.h
* Author : auto-generated by wbgen2 from fmc_tdc_direct_readout_slave.wb
* Created : Thu May 15 14:23:14 2014
* Created : Wed Mar 24 09:22:15 2021
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE fmc_tdc_direct_readout_slave.wb
......@@ -14,7 +14,11 @@
#ifndef __WBGEN2_REGDEFS_FMC_TDC_DIRECT_READOUT_SLAVE_WB
#define __WBGEN2_REGDEFS_FMC_TDC_DIRECT_READOUT_SLAVE_WB
#ifdef __KERNEL__
#include <linux/types.h>
#else
#include <inttypes.h>
#endif
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
......@@ -35,6 +39,8 @@
/* definitions for register: Dead Time Register */
/* definitions for register: Status Register */
/* definitions for register: FIFO 'Readout FIFO' data output register 0 */
/* definitions for field: Seconds in reg: FIFO 'Readout FIFO' data output register 0 */
......@@ -85,12 +91,14 @@
#define DR_REG_CHAN_ENABLE 0x00000000
/* [0x4]: REG Dead Time Register */
#define DR_REG_DEAD_TIME 0x00000004
/* [0x8]: REG FIFO 'Readout FIFO' data output register 0 */
#define DR_REG_FIFO_R0 0x00000008
/* [0xc]: REG FIFO 'Readout FIFO' data output register 1 */
#define DR_REG_FIFO_R1 0x0000000c
/* [0x10]: REG FIFO 'Readout FIFO' data output register 2 */
#define DR_REG_FIFO_R2 0x00000010
/* [0x14]: REG FIFO 'Readout FIFO' control/status register */
#define DR_REG_FIFO_CSR 0x00000014
/* [0x8]: REG Status Register */
#define DR_REG_STATUS 0x00000008
/* [0xc]: REG FIFO 'Readout FIFO' data output register 0 */
#define DR_REG_FIFO_R0 0x0000000c
/* [0x10]: REG FIFO 'Readout FIFO' data output register 1 */
#define DR_REG_FIFO_R1 0x00000010
/* [0x14]: REG FIFO 'Readout FIFO' data output register 2 */
#define DR_REG_FIFO_R2 0x00000014
/* [0x18]: REG FIFO 'Readout FIFO' control/status register */
#define DR_REG_FIFO_CSR 0x00000018
#endif
......@@ -23,10 +23,13 @@
#define TDC_REG_IRQ_TIMEOUT 0x0094
#define TDC_REG_DAC_TUNE 0x0098
#define TDC_REG_CURRENT_UTC 0x00a0
#define TDC_REG_BUFFER_PTR 0x00a8
#define TDC_REG_CTRL 0x00fc
#define TDC_REG_WR_CTRL 0x00b4
#define TDC_REG_CORE_STATUS 0x00ac
#define TDC_REG_WR_STAT 0x00b0
#define TDC_REG_WR_CTRL 0x00b4
#define TDC_REG_CTRL 0x00fc
#define TDC_CORE_STATUS_FMC_ID BIT(2)
#define TDC_CORE_STATUS_PRES BIT(3)
#define TDC_WR_CTRL_ENABLE BIT(0)
......
......@@ -40,11 +40,6 @@ static inline int wr_link_up(void)
return tdc_wr_link_up(&tdc0);
}
static inline int wr_time_locked(void)
{
return tdc_wr_time_locked(&tdc0);
}
static inline int wr_time_ready(void)
{
return tdc_wr_time_ready(&tdc0);
......@@ -55,6 +50,11 @@ static inline void wr_enable_lock(int enable)
tdc_wr_enable_lock(&tdc0, enable);
}
static inline int wr_aux_locked(void)
{
return tdc_wr_aux_locked(&tdc0);
}
static inline int wr_sync_timeout(void)
{
#ifdef SIMULATION
......
......@@ -14,14 +14,19 @@
#include "wrtd-tdc.h"
struct wrtd_tdc_calibration calib = {
static const struct wrtd_tdc_calibration calib = {
.offset_tai = { 0, 0, 0, 0, 0},
.offset_coarse = { -94, -94, -94, -94, -94},
.offset_frac = { 200, 200, 400, 400, 400},
};
struct wrtd_tdc_dev {
/* Offset (in dedicated memory) of the TDC. */
uint32_t io_addr;
/* First channel for the TDC input 0. */
uint8_t ch;
/* True if FMC is present. */
uint8_t present;
};
static inline void tdc_writel(const struct wrtd_tdc_dev *dev,
......@@ -179,6 +184,7 @@ static inline void tdc_apply_calibration(struct wrtd_tdc_dev *tdc, int index)
static int tdc_init(struct wrtd_tdc_dev *tdc)
{
int err, i;
unsigned v;
pr_debug("%s: Initializing the TDC...\n\r", __func__);
......@@ -186,6 +192,15 @@ static int tdc_init(struct wrtd_tdc_dev *tdc)
tdc_writel(tdc, 0x0, BASE_DP_TDC_DIRECT + DR_REG_CHAN_ENABLE);
tdc_writel(tdc, DEFAULT_DEAD_TIME, BASE_DP_TDC_DIRECT + DR_REG_DEAD_TIME);
/* Check presence */
tdc->present = 1;
v = tdc_readl(tdc, BASE_DP_TDC_DIRECT + DR_REG_STATUS);
if (!(v & 1)) {
pr_debug("%s: ACAM not present\n",__func__);
tdc->present = 0;
return 0;
}
tdc_enable_acquisition(tdc, 0);
#ifndef SIMULATION
......@@ -219,16 +234,22 @@ static int tdc_init(struct wrtd_tdc_dev *tdc)
static inline int tdc_wr_link_up(struct wrtd_tdc_dev *tdc)
{
if (!tdc->present)
return 1;
return tdc_readl(tdc, BASE_DP_TDC_REGS + TDC_REG_WR_STAT) & TDC_WR_STAT_LINK;
}
static inline int tdc_wr_time_locked(struct wrtd_tdc_dev *tdc)
static inline int tdc_wr_aux_locked(struct wrtd_tdc_dev *tdc)
{
if (!tdc->present)
return 1;
return tdc_readl(tdc, BASE_DP_TDC_REGS + TDC_REG_WR_STAT) & TDC_WR_STAT_AUX_LOCKED;
}
static void tdc_wr_enable_lock(struct wrtd_tdc_dev *tdc, int enable)
{
if (!tdc->present)
return;
tdc_writel(tdc, TDC_CTRL_DIS_ACQ, BASE_DP_TDC_REGS + TDC_REG_CTRL);
tdc_writel(tdc, enable ? TDC_WR_CTRL_ENABLE : 0, BASE_DP_TDC_REGS + TDC_REG_WR_CTRL);
tdc_writel(tdc, TDC_CTRL_EN_ACQ, BASE_DP_TDC_REGS + TDC_REG_CTRL);
......@@ -236,6 +257,8 @@ static void tdc_wr_enable_lock(struct wrtd_tdc_dev *tdc, int enable)
static inline int tdc_wr_time_ready(struct wrtd_tdc_dev *tdc)
{
if (!tdc->present)
return 1;
return tdc_readl(tdc, BASE_DP_TDC_REGS + TDC_REG_WR_STAT) & TDC_WR_STAT_TIME_VALID;
}
......@@ -254,7 +277,8 @@ static void tdc_input(struct wrtd_tdc_dev *tdc)
struct wrtd_event ev;
int meta;
/* Poll the FIFO and read the timestamp */
/* Poll the FIFO and read the timestamp.
No need to check for presence: no channels enabled. */
if(fifo_sr & DR_FIFO_CSR_EMPTY)
return;
......@@ -262,6 +286,9 @@ static void tdc_input(struct wrtd_tdc_dev *tdc)
ev.ts.ns = tdc_readl(tdc, BASE_DP_TDC_DIRECT + DR_REG_FIFO_R1) * 8;
meta = tdc_readl(tdc, BASE_DP_TDC_DIRECT + DR_REG_FIFO_R2);
if (ev.ts.seconds == 0)
return;
/* Conversion from ACAM TDC bins to WR already done in gateware
(including overflow checks), result is in 2**-12 8ns ticks */
uint32_t frac = meta & 0x00fff;
......@@ -272,18 +299,26 @@ static void tdc_input(struct wrtd_tdc_dev *tdc)
ev.ts.frac = frac << (32 - 9);
int channel = (meta >> 19) & 0x7;
memset(ev.id, 0, WRTD_ID_LEN);
ev.id[0] = 'L';
ev.id[1] = 'C';
ev.id[2] = '-';
ev.id[3] = 'I';
ev.id[4] = '1' + channel; /* channel starts from 0. */
channel += tdc->ch;
zero_id(&ev.id);
ev.id.c[0] = 'L';
ev.id.c[1] = 'C';
ev.id.c[2] = '-';
ev.id.c[3] = 'I';
if (channel >= 9) {
/* channel starts from 0. */
ev.id.c[4] = '1';
ev.id.c[5] = '0' + channel - 9;
}
else {
/* channel starts from 0. */
ev.id.c[4] = '1' + channel;
}
ev.flags = 0;
wrtd_log(WRTD_LOG_MSG_EV_GENERATED,
WRTD_LOG_GENERATED_DEVICE + (channel * 8),
NULL, &ev, NULL);
WRTD_LOG_GENERATED_DEVICE + (channel * 8), &ev, NULL);
/* Pass to wrtd. */
wrtd_route_in(&ev);
......
......@@ -20,6 +20,14 @@
#define WRTD_ID_NET 0xff
/**
* WRTD identifier.
*/
union wrtd_id {
char c[WRTD_ID_LEN];
uint32_t w[WRTD_ID_LEN/4];
};
/**
* WRTD timestamp format
*/
......@@ -43,7 +51,7 @@ struct wrtd_event {
struct wrtd_tstamp ts;
/** Event id. */
char id[WRTD_ID_LEN];
union wrtd_id id;
/** Sequence number. */
uint32_t seq;
......@@ -52,10 +60,10 @@ struct wrtd_event {
unsigned char flags;
};
inline static unsigned char wrtd_id_hash(const char *id)
inline static unsigned char wrtd_id_hash(union wrtd_id *id)
{
/* This assumes ID is properly padded. */
return id[0] ^ id[3] ^ id[4] ^ id[7];
return id->c[0] ^ id->c[3] ^ id->c[4] ^ id->c[7];
}
#define WRTD_DEST_CPU_LOCAL 0xfe
......@@ -63,11 +71,11 @@ inline static unsigned char wrtd_id_hash(const char *id)
struct wrtd_rule_config {
/* Id of the rule. */
char id[WRTD_ID_LEN];
union wrtd_id id;
char source_id[WRTD_ID_LEN];
union wrtd_id source_id;
char dest_id[WRTD_ID_LEN];
union wrtd_id dest_id;
/* Device destination. */
uint8_t dest_cpu;
......@@ -135,7 +143,7 @@ struct wrtd_alarm {
struct wrtd_message {
unsigned char hw_detect[3]; /* LXI */
unsigned char domain; /* 0 */
unsigned char event_id[WRTD_ID_LEN];
union wrtd_id event_id;
uint32_t seq;
uint32_t ts_sec;
uint32_t ts_ns;
......@@ -242,6 +250,11 @@ enum wrtd_log_reason_type {
WRTD_LOG_GENERATED_DEVICE_5 = WRTD_LOG_GENERATED_DEVICE + 40,
WRTD_LOG_GENERATED_DEVICE_6 = WRTD_LOG_GENERATED_DEVICE + 48,
WRTD_LOG_GENERATED_DEVICE_7 = WRTD_LOG_GENERATED_DEVICE + 56,
WRTD_LOG_GENERATED_DEVICE_8 = WRTD_LOG_GENERATED_DEVICE + 64,
WRTD_LOG_GENERATED_DEVICE_9 = WRTD_LOG_GENERATED_DEVICE + 72,
WRTD_LOG_GENERATED_DEVICE_10 = WRTD_LOG_GENERATED_DEVICE + 80,
WRTD_LOG_GENERATED_DEVICE_11 = WRTD_LOG_GENERATED_DEVICE + 88,
WRTD_LOG_GENERATED_DEVICE_12 = WRTD_LOG_GENERATED_DEVICE + 96,
/* For CONSUMED: */
WRTD_LOG_CONSUMED_START = 1,
......
......@@ -9,7 +9,7 @@ REPO_PARENT ?= ..
-include $(REPO_PARENT)/parent_common.mk
GIT_VERSION := $(shell git describe --always --dirty --long --tags)
SO_VERSION_XYZ := $(shell git describe --always --abbrev=0 | grep -o -E "[0-9]+\.[0-9]+\.[0-9]")
SO_VERSION_XYZ := $(shell git describe --tags --abbrev=0 | grep -o -E "[0-9]+\.[0-9]+\.[0-9]")
ifeq ($(SO_VERSION_XYZ),)
SO_VERSION_XYZ := 0
......@@ -20,7 +20,6 @@ DESTLIBDIR ?= $(PREFIX)/lib
WRTD_DEP_TRTL ?= ../../dependencies/mock-turtle/
MTLIB = $(WRTD_DEP_TRTL)/software/lib/libmockturtle.a
LIBSO = libwrtd.so
LIBSO_XYZ = $(LIBSO).$(SO_VERSION_XYZ)
LIB = libwrtd.a
......@@ -30,24 +29,18 @@ INCFLAGS=-I. -I../include -I$(WRTD_DEP_TRTL)/software/include \
-I$(WRTD_DEP_TRTL)/software/lib
CFLAGS += -fno-strict-aliasing $(INCFLAGS)
CFLAGS += -Wall -Werror
CFLAGS += -g
CFLAGS += -fPIC
CFLAGS += -Wall -Werror -fPIC
CFLAGS += -DVERSION="\"$(GIT_VERSION)\""
CFLAGS += $(EXTRACFLAGS)
ARFLAGS = rc
ARFLAGS = rcv
all: $(LIB) $(LIBSO)
$(LIB): $(OBJS)
$(AR) $(ARFLAGS) $@ $^
$(MTLIB):
cd $(@D) && $(MAKE) $(@F)
$(LIBSO_XYZ): $(LIB) $(MTLIB)
$(CC) -shared -o $@ -Wl,--whole-archive,-soname,$@ $^ \
-Wl,--no-whole-archive
$(LIBSO_XYZ): $(OBJS)
$(CC) -shared $^ -L$(WRTD_DEP_TRTL)/software/lib -lmockturtle -o $@
$(LIBSO): $(LIBSO_XYZ)
ln -sf $< $@
......@@ -61,7 +54,7 @@ clean:
install: $(LIBSO) $(LIBSO_XYZ)
install -d $(DESTLIBDIR)
install -m 0755 $(LIBSO_XYZ) $(DESTLIBDIR)
test -e $(DESTLIBDIR)/$(LIBSO) || ln -s $(LIBSO_XYZ) $(DESTLIBDIR)/$(LIBSO)
ln -sf $(LIBSO_XYZ) $(DESTLIBDIR)/$(LIBSO)
uninstall:
rm -f $(DESTLIBDIR)/$(LIBSO) $(DESTLIBDIR)/$(LIBSO_XYZ)
......
......@@ -6,6 +6,7 @@
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include <stddef.h>
#include <errno.h>
#include "libwrtd.h"
#include "libwrtd-private.h"
......@@ -191,7 +192,7 @@ enum wrtd_status wrtd_attr_get_alarm_count(struct wrtd_dev *wrtd,
res = 0;
for (i = 0; i < wrtd->nbr_alarms; i++)
if (!wrtd_id_null(wrtd->alarms[i].alarm.event.id))
if (!wrtd_id_null(&wrtd->alarms[i].alarm.event.id))
res++;
*value = res;
return WRTD_SUCCESS;
......@@ -404,9 +405,9 @@ enum wrtd_status wrtd_attr_set_rule_repeat_count(struct wrtd_dev *wrtd,
status = wrtd_rule_check_disabled(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
wrtd->rules[idx].rule.conf.repeat_count = value;
wrtd->rules[idx].conf.repeat_count = value;
status = wrtd_write_rule(wrtd, idx, __func__);
status = wrtd_write_rule_conf(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
return WRTD_SUCCESS;
......@@ -422,7 +423,7 @@ enum wrtd_status wrtd_attr_get_rule_repeat_count(struct wrtd_dev *wrtd,
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
*value = wrtd->rules[idx].rule.conf.repeat_count;
*value = wrtd->rules[idx].conf.repeat_count;
return WRTD_SUCCESS;
}
......@@ -509,7 +510,7 @@ enum wrtd_status wrtd_attr_get_rule_count(struct wrtd_dev *wrtd,
res = 0;
for (i = 0; i < wrtd->nbr_rules; i++)
if (!wrtd_id_null(wrtd->rules[i].rule.conf.id))
if (!wrtd_id_null(&wrtd->rules[i].conf.id))
res++;
*value = res;
return WRTD_SUCCESS;
......@@ -538,9 +539,9 @@ enum wrtd_status wrtd_attr_set_rule_source(struct wrtd_dev *wrtd,
status = wrtd_rule_check_disabled(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
wrtd_id_copy(wrtd->rules[idx].rule.conf.source_id, src);
wrtd_id_build(&wrtd->rules[idx].conf.source_id, src);
status = wrtd_write_rule(wrtd, idx, __func__);
status = wrtd_write_rule_conf(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
return WRTD_SUCCESS;
......@@ -558,7 +559,7 @@ enum wrtd_status wrtd_attr_get_rule_source(struct wrtd_dev *wrtd,
WRTD_RETURN_IF_ERROR(status);
status = wrtd_id_copy_buf(wrtd, dst, buffer_size,
wrtd->rules[idx].rule.conf.source_id,
wrtd->rules[idx].conf.source_id.c,
__func__);
WRTD_RETURN_IF_ERROR(status);
......@@ -581,9 +582,9 @@ enum wrtd_status wrtd_attr_set_rule_destination(struct wrtd_dev *wrtd,
status = wrtd_rule_check_disabled(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
wrtd_id_copy(wrtd->rules[idx].rule.conf.dest_id, dst);
wrtd_id_build(&wrtd->rules[idx].conf.dest_id, dst);
status = wrtd_write_rule(wrtd, idx, __func__);
status = wrtd_write_rule_conf(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
return WRTD_SUCCESS;
......@@ -601,7 +602,7 @@ enum wrtd_status wrtd_attr_get_rule_destination(struct wrtd_dev *wrtd,
WRTD_RETURN_IF_ERROR(status);
status = wrtd_id_copy_buf(wrtd, dst, buffer_size,
wrtd->rules[idx].rule.conf.dest_id,
wrtd->rules[idx].conf.dest_id.c,
__func__);
WRTD_RETURN_IF_ERROR(status);
......@@ -627,9 +628,9 @@ enum wrtd_status wrtd_attr_set_rule_delay(struct wrtd_dev *wrtd,
status = wrtd_rule_check_disabled(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
wrtd->rules[idx].rule.conf.delay_ns = value->ns;
wrtd->rules[idx].conf.delay_ns = value->ns;
status = wrtd_write_rule(wrtd, idx, __func__);
status = wrtd_write_rule_conf(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
return WRTD_SUCCESS;
......@@ -646,7 +647,7 @@ enum wrtd_status wrtd_attr_get_rule_delay(struct wrtd_dev *wrtd,
WRTD_RETURN_IF_ERROR(status);
memset(value, 0, sizeof(struct wrtd_tstamp));
wrtd_ts_add_ns(value, wrtd->rules[idx].rule.conf.delay_ns);
wrtd_ts_add_ns(value, wrtd->rules[idx].conf.delay_ns);
return WRTD_SUCCESS;
}
......@@ -670,9 +671,9 @@ enum wrtd_status wrtd_attr_set_rule_holdoff(struct wrtd_dev *wrtd,
status = wrtd_rule_check_disabled(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
wrtd->rules[idx].rule.conf.hold_off_ns = value->ns;
wrtd->rules[idx].conf.hold_off_ns = value->ns;
status = wrtd_write_rule(wrtd, idx, __func__);
status = wrtd_write_rule_conf(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
return WRTD_SUCCESS;
......@@ -689,7 +690,7 @@ enum wrtd_status wrtd_attr_get_rule_holdoff(struct wrtd_dev *wrtd,
WRTD_RETURN_IF_ERROR(status);
memset(value, 0, sizeof(struct wrtd_tstamp));
wrtd_ts_add_ns(value, wrtd->rules[idx].rule.conf.hold_off_ns);
wrtd_ts_add_ns(value, wrtd->rules[idx].conf.hold_off_ns);
return WRTD_SUCCESS;
}
......@@ -713,9 +714,9 @@ enum wrtd_status wrtd_attr_set_rule_resync_period(struct wrtd_dev *wrtd,
status = wrtd_rule_check_disabled(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
wrtd->rules[idx].rule.conf.resync_period_ns = value->ns;
wrtd->rules[idx].conf.resync_period_ns = value->ns;
status = wrtd_write_rule(wrtd, idx, __func__);
status = wrtd_write_rule_conf(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
return WRTD_SUCCESS;
......@@ -732,7 +733,7 @@ enum wrtd_status wrtd_attr_get_rule_resync_period(struct wrtd_dev *wrtd,
WRTD_RETURN_IF_ERROR(status);
memset(value, 0, sizeof(struct wrtd_tstamp));
wrtd_ts_add_ns(value, wrtd->rules[idx].rule.conf.resync_period_ns);
wrtd_ts_add_ns(value, wrtd->rules[idx].conf.resync_period_ns);
return WRTD_SUCCESS;
}
......@@ -747,9 +748,10 @@ enum wrtd_status wrtd_attr_get_stat_rule_rx_last(struct wrtd_dev *wrtd,
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
*value = wrtd->rules[idx].rule.stat.rx_last;
return WRTD_SUCCESS;
return wrtd_read_rule_stat
(wrtd, idx,
offsetof(struct wrtd_rule_stats, rx_last),
sizeof(struct wrtd_tstamp), value, __func__);
}
enum wrtd_status wrtd_attr_get_stat_rule_tx_last(struct wrtd_dev *wrtd,
......@@ -762,9 +764,10 @@ enum wrtd_status wrtd_attr_get_stat_rule_tx_last(struct wrtd_dev *wrtd,
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
*value = wrtd->rules[idx].rule.stat.tx_last;
return WRTD_SUCCESS;
return wrtd_read_rule_stat
(wrtd, idx,
offsetof(struct wrtd_rule_stats, tx_last),
sizeof(struct wrtd_tstamp), value, __func__);
}
enum wrtd_status wrtd_attr_get_stat_rule_missed_last(struct wrtd_dev *wrtd,
......@@ -777,9 +780,10 @@ enum wrtd_status wrtd_attr_get_stat_rule_missed_last(struct wrtd_dev *wrtd,
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
*value = wrtd->rules[idx].rule.stat.miss_last;
return WRTD_SUCCESS;
return wrtd_read_rule_stat
(wrtd, idx,
offsetof(struct wrtd_rule_stats, miss_last),
sizeof(struct wrtd_tstamp), value, __func__);
}
enum wrtd_status wrtd_attr_get_stat_rule_rx_latency_min(struct wrtd_dev *wrtd,
......@@ -788,12 +792,19 @@ enum wrtd_status wrtd_attr_get_stat_rule_rx_latency_min(struct wrtd_dev *wrtd,
{
enum wrtd_status status;
unsigned int idx;
uint32_t val;
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
status = wrtd_read_rule_stat
(wrtd, idx,
offsetof(struct wrtd_rule_stats, lat_min_ns), sizeof(int32_t),
&val, __func__);
WRTD_RETURN_IF_ERROR(status);
memset(value, 0, sizeof(struct wrtd_tstamp));
wrtd_ts_add_ns(value, wrtd->rules[idx].rule.stat.lat_min_ns);
wrtd_ts_add_ns(value, val);
return WRTD_SUCCESS;
}
......@@ -804,12 +815,19 @@ enum wrtd_status wrtd_attr_get_stat_rule_rx_latency_max(struct wrtd_dev *wrtd,
{
enum wrtd_status status;
unsigned int idx;
uint32_t val;
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
status = wrtd_read_rule_stat
(wrtd, idx,
offsetof(struct wrtd_rule_stats, lat_max_ns), sizeof(int32_t),
&val, __func__);
WRTD_RETURN_IF_ERROR(status);
memset(value, 0, sizeof(struct wrtd_tstamp));
wrtd_ts_add_ns(value, wrtd->rules[idx].rule.stat.lat_max_ns);
wrtd_ts_add_ns(value, val);
return WRTD_SUCCESS;
}
......@@ -821,17 +839,22 @@ enum wrtd_status wrtd_attr_get_stat_rule_rx_latency_avg(struct wrtd_dev *wrtd,
enum wrtd_status status;
unsigned int idx;
uint64_t latency;
struct wrtd_rule_stats stats;
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
status = wrtd_read_rule_stat
(wrtd, idx, 0, sizeof(stats), &stats, __func__);
WRTD_RETURN_IF_ERROR(status);
memset(value, 0, sizeof(struct wrtd_tstamp));
if (wrtd->rules[idx].rule.stat.lat_nbr != 0) {
latency = wrtd->rules[idx].rule.stat.lat_hi_ns;
if (stats.lat_nbr != 0) {
latency = stats.lat_hi_ns;
latency <<= 32;
latency |= wrtd->rules[idx].rule.stat.lat_lo_ns;
latency /= wrtd->rules[idx].rule.stat.lat_nbr;
latency |= stats.lat_lo_ns;
latency /= stats.lat_nbr;
wrtd_ts_add_ns(value, latency & 0xffffffff);
}
......@@ -851,9 +874,9 @@ enum wrtd_status wrtd_attr_set_rule_resync_factor(struct wrtd_dev *wrtd,
status = wrtd_rule_check_disabled(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
wrtd->rules[idx].rule.conf.resync_factor = value;
wrtd->rules[idx].conf.resync_factor = value;
status = wrtd_write_rule(wrtd, idx, __func__);
status = wrtd_write_rule_conf(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
return WRTD_SUCCESS;
......@@ -869,7 +892,7 @@ enum wrtd_status wrtd_attr_get_rule_resync_factor(struct wrtd_dev *wrtd,
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
*value = wrtd->rules[idx].rule.conf.resync_factor;
*value = wrtd->rules[idx].conf.resync_factor;
return WRTD_SUCCESS;
}
......@@ -884,9 +907,10 @@ enum wrtd_status wrtd_attr_get_stat_rule_rx_events(struct wrtd_dev *wrtd,
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
*value = wrtd->rules[idx].rule.stat.rx_events;
return WRTD_SUCCESS;
return wrtd_read_rule_stat
(wrtd, idx,
offsetof(struct wrtd_rule_stats, rx_events), sizeof(int32_t),
value, __func__);
}
enum wrtd_status wrtd_attr_get_stat_rule_tx_events(struct wrtd_dev *wrtd,
......@@ -899,9 +923,10 @@ enum wrtd_status wrtd_attr_get_stat_rule_tx_events(struct wrtd_dev *wrtd,
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
*value = wrtd->rules[idx].rule.stat.tx_events;
return WRTD_SUCCESS;
return wrtd_read_rule_stat
(wrtd, idx,
offsetof(struct wrtd_rule_stats, tx_events), sizeof(int32_t),
value, __func__);
}
enum wrtd_status wrtd_attr_get_stat_rule_missed_late(struct wrtd_dev *wrtd,
......@@ -914,9 +939,10 @@ enum wrtd_status wrtd_attr_get_stat_rule_missed_late(struct wrtd_dev *wrtd,
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
*value = wrtd->rules[idx].rule.stat.miss_late;
return WRTD_SUCCESS;
return wrtd_read_rule_stat
(wrtd, idx,
offsetof(struct wrtd_rule_stats, miss_late), sizeof(int32_t),
value, __func__);
}
enum wrtd_status wrtd_attr_get_stat_rule_missed_holdoff(struct wrtd_dev *wrtd,
......@@ -929,9 +955,10 @@ enum wrtd_status wrtd_attr_get_stat_rule_missed_holdoff(struct wrtd_dev *wrtd,
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
*value = wrtd->rules[idx].rule.stat.miss_holdoff;
return WRTD_SUCCESS;
return wrtd_read_rule_stat
(wrtd, idx,
offsetof(struct wrtd_rule_stats, miss_holdoff), sizeof(int32_t),
value, __func__);
}
enum wrtd_status wrtd_attr_get_stat_rule_missed_nosync(struct wrtd_dev *wrtd,
......@@ -944,9 +971,10 @@ enum wrtd_status wrtd_attr_get_stat_rule_missed_nosync(struct wrtd_dev *wrtd,
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
*value = wrtd->rules[idx].rule.stat.miss_nosync;
return WRTD_SUCCESS;
return wrtd_read_rule_stat
(wrtd, idx,
offsetof(struct wrtd_rule_stats, miss_nosync), sizeof(int32_t),
value, __func__);
}
enum wrtd_status wrtd_attr_get_stat_rule_missed_overflow(struct wrtd_dev *wrtd,
......@@ -959,9 +987,10 @@ enum wrtd_status wrtd_attr_get_stat_rule_missed_overflow(struct wrtd_dev *wrtd,
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
*value = wrtd->rules[idx].rule.stat.miss_overflow;
return WRTD_SUCCESS;
return wrtd_read_rule_stat
(wrtd, idx,
offsetof(struct wrtd_rule_stats, miss_overflow), sizeof(int32_t),
value, __func__);
}
enum wrtd_status wrtd_attr_set_rule_enable(struct wrtd_dev *wrtd,
......@@ -970,13 +999,22 @@ enum wrtd_status wrtd_attr_set_rule_enable(struct wrtd_dev *wrtd,
{
enum wrtd_status status;
unsigned int idx;
struct wrtd_lib_rule *rule;
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
if (wrtd->rules[idx].rule.conf.enabled != value) {
wrtd->rules[idx].rule.conf.enabled = value;
wrtd->rules[idx].modified = 1;
rule = &wrtd->rules[idx];
status = wrtd_validate_id(wrtd, rule->conf.source_id.c, __func__);
WRTD_RETURN_IF_ERROR(status);
status = wrtd_validate_id(wrtd, rule->conf.dest_id.c, __func__);
WRTD_RETURN_IF_ERROR(status);
if (rule->conf.enabled != value) {
rule->conf.enabled = value;
rule->modified = 1;
status = wrtd_reconfigure(wrtd, __func__);
WRTD_RETURN_IF_ERROR(status);
......@@ -995,7 +1033,7 @@ enum wrtd_status wrtd_attr_get_rule_enable(struct wrtd_dev *wrtd,
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
*value = wrtd->rules[idx].rule.conf.enabled != 0;
*value = wrtd->rules[idx].conf.enabled != 0;
return WRTD_SUCCESS;
}
......@@ -1013,10 +1051,10 @@ enum wrtd_status wrtd_attr_set_rule_send_late(struct wrtd_dev *wrtd,
status = wrtd_rule_check_disabled(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
if (wrtd->rules[idx].rule.conf.send_late != value) {
wrtd->rules[idx].rule.conf.send_late = value;
if (wrtd->rules[idx].conf.send_late != value) {
wrtd->rules[idx].conf.send_late = value;
status = wrtd_write_rule(wrtd, idx, __func__);
status = wrtd_write_rule_conf(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
}
......@@ -1033,7 +1071,7 @@ enum wrtd_status wrtd_attr_get_rule_send_late(struct wrtd_dev *wrtd,
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
*value = wrtd->rules[idx].rule.conf.send_late != 0;
*value = wrtd->rules[idx].conf.send_late != 0;
return WRTD_SUCCESS;
}
......@@ -1044,9 +1082,8 @@ enum wrtd_status wrtd_attr_get_sys_time(struct wrtd_dev *wrtd,
enum wrtd_status status;
struct wrtd_config_msg msg;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
/* Always use CPU #0 (it does exist!). */
status = wrtd_msg_get_config(wrtd, 0, &msg, __func__);
......@@ -1064,7 +1101,7 @@ enum wrtd_status wrtd_attr_get_sys_time(struct wrtd_dev *wrtd,
enum wrtd_status wrtd_attr_global(struct wrtd_dev *wrtd,
const char *rep_cap_id)
{
if (!wrtd_id_eq(rep_cap_id, WRTD_GLOBAL_REP_CAP_ID))
if (strcmp(rep_cap_id, WRTD_GLOBAL_REP_CAP_ID))
return wrtd_return_error(wrtd, WRTD_ERROR_ATTR_GLOBAL,
"Global attributes require the "
"global repeated capability ID");
......
......@@ -15,35 +15,39 @@
#include "libwrtd-private.h"
#include "mockturtle/libmockturtle.h"
inline bool wrtd_id_eq(const char *l, const char *r)
bool wrtd_id_str_eq(const union wrtd_id *l, const char *r)
{
return strncmp(l, r, WRTD_ID_LEN) == 0;
return strncmp(l->c, r, WRTD_ID_LEN) == 0;
}
inline bool wrtd_id_null(const char *id)
bool wrtd_id_eq(const union wrtd_id *l, const union wrtd_id *r)
{
return id[0] == 0;
return memcmp(l->c, r->c, WRTD_ID_LEN) == 0;
}
inline void wrtd_id_copy(char *dst, const char *src)
bool wrtd_id_null(const union wrtd_id *id)
{
strncpy(dst, src, WRTD_ID_LEN);
return id->c[0] == 0;
}
void wrtd_id_build(union wrtd_id *dst, const char *src)
{
strncpy(dst->c, src, WRTD_ID_LEN);
}
enum wrtd_status wrtd_id_copy_buf(struct wrtd_dev *wrtd,
char *dst, int32_t dst_buffer_size,
const char *id, const char *caller_func)
{
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
/* If buffer_size is zero, just report on necessary
buffer size. According to IVI 3.2, section 3.1.2.1. */
if (dst_buffer_size == 0)
return WRTD_ID_LEN;
if(dst == NULL){
if (dst == NULL) {
return wrtd_return_error
(wrtd, WRTD_ERROR_NULL_POINTER,
"Null pointer passed for function %s/%s, "
......@@ -72,11 +76,10 @@ enum wrtd_status wrtd_id_copy_buf(struct wrtd_dev *wrtd,
enum wrtd_status wrtd_validate_id(struct wrtd_dev *wrtd, const char *rep_cap_id,
const char *caller_func)
{
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
if ((wrtd_id_null(rep_cap_id)) || (strlen(rep_cap_id) > WRTD_ID_LEN))
if (rep_cap_id[0] == 0 || strlen(rep_cap_id) > WRTD_ID_LEN)
return wrtd_return_error
(wrtd, WRTD_ERROR_BADLY_FORMED_SELECTOR,
"%s/%s: Badly-formed selector",
......@@ -91,9 +94,8 @@ enum wrtd_status wrtd_return_error(struct wrtd_dev *dev,
{
va_list args;
if(dev == NULL){
if (dev == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
va_start(args, format);
dev->err = error_code;
......@@ -111,9 +113,8 @@ enum wrtd_status wrtd_log_read(struct wrtd_dev *wrtd,
struct polltrtl p[WRTD_MAX_CPUS];
int ret, i;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
for (i = 0; i < wrtd->nbr_cpus; ++i) {
p[i].trtl = wrtd->trtl;
......@@ -167,9 +168,8 @@ enum wrtd_status wrtd_msg_get_config(struct wrtd_dev *wrtd, unsigned cpu,
struct trtl_msg msg;
int err;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
memset(&msg.hdr, 0, sizeof(struct trtl_hmq_header));
msg.hdr.flags = TRTL_HMQ_HEADER_FLAG_RPC;
......@@ -204,9 +204,8 @@ enum wrtd_status wrtd_msg_readw(struct wrtd_dev *wrtd, unsigned cpu,
uint32_t addr, uint32_t count,
uint32_t *dest, const char *caller_func)
{
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
while (count > 0) {
uint32_t tlen;
......@@ -257,9 +256,8 @@ enum wrtd_status wrtd_msg_writew(struct wrtd_dev *wrtd, unsigned cpu,
uint32_t addr, uint32_t count,
const uint32_t *src, const char *caller_func)
{
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
while (count > 0) {
uint32_t tlen;
......@@ -309,9 +307,8 @@ enum wrtd_status wrtd_fill_roots(struct wrtd_dev *wrtd, const char *caller_func)
enum wrtd_status status;
unsigned cpu;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
if (wrtd->roots[0].ver_major != 0)
return WRTD_SUCCESS;
......@@ -353,9 +350,8 @@ enum wrtd_status wrtd_fill_alarms(struct wrtd_dev *wrtd, const char *caller_func
unsigned cpu;
unsigned n;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
if (wrtd->alarms != NULL)
return WRTD_SUCCESS;
......@@ -406,9 +402,8 @@ enum wrtd_status wrtd_alloc_rules(struct wrtd_dev *wrtd,
unsigned n;
unsigned cpu;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
rules = (struct wrtd_lib_rule *)
calloc(wrtd->nbr_rules, sizeof(struct wrtd_lib_rule));
......@@ -440,9 +435,8 @@ enum wrtd_status wrtd_fill_rules(struct wrtd_dev *wrtd, const char *caller_func)
unsigned i;
unsigned cpu;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
if (wrtd->rules != NULL)
return WRTD_SUCCESS;
......@@ -450,7 +444,7 @@ enum wrtd_status wrtd_fill_rules(struct wrtd_dev *wrtd, const char *caller_func)
status = wrtd_fill_roots(wrtd, caller_func);
WRTD_RETURN_IF_ERROR(status);
/* Count number of rules. */
/* Count number of rules (whether set or not set). */
assert(wrtd->nbr_rules == 0);
for (cpu = 0; cpu < wrtd->nbr_cpus; cpu++)
wrtd->nbr_rules += wrtd->roots[cpu].nbr_rules;
......@@ -459,7 +453,7 @@ enum wrtd_status wrtd_fill_rules(struct wrtd_dev *wrtd, const char *caller_func)
status = wrtd_alloc_rules(wrtd, &wrtd->rules, caller_func);
WRTD_RETURN_IF_ERROR(status);
/* Read rules from cpus. */
/* Read all rules from cpus. */
for (i = 0; i < wrtd->nbr_rules; i++) {
unsigned cpu = wrtd->rules[i].cpu;
unsigned int addr;
......@@ -467,8 +461,8 @@ enum wrtd_status wrtd_fill_rules(struct wrtd_dev *wrtd, const char *caller_func)
addr = (wrtd->roots[cpu].rules_addr
+ wrtd->rules[i].local_idx * sizeof(struct wrtd_rule));
status = wrtd_msg_readw
(wrtd, cpu, addr, sizeof(struct wrtd_rule) / 4,
(uint32_t *)&wrtd->rules[i].rule, caller_func);
(wrtd, cpu, addr, sizeof(struct wrtd_rule_config) / 4,
(uint32_t *)&wrtd->rules[i].conf, caller_func);
if (status != WRTD_SUCCESS) {
free(wrtd->rules);
wrtd->rules = NULL;
......@@ -479,15 +473,38 @@ enum wrtd_status wrtd_fill_rules(struct wrtd_dev *wrtd, const char *caller_func)
return WRTD_SUCCESS;
}
enum wrtd_status wrtd_read_rule_stat(struct wrtd_dev *wrtd, unsigned idx,
unsigned off, unsigned len, void *dest,
const char *caller_func)
{
enum wrtd_status status;
struct wrtd_lib_rule *rule;
assert(len % 4 == 0);
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
rule = &wrtd->rules[idx];
status = wrtd_msg_readw
(wrtd, rule->cpu,
(wrtd->roots[rule->cpu].rules_addr
+ rule->local_idx * sizeof(struct wrtd_rule)
+ sizeof(struct wrtd_rule_config) + off),
len / 4,
(uint32_t *)dest, caller_func);
return status;
}
enum wrtd_status wrtd_write_alarm(struct wrtd_dev *wrtd, unsigned idx,
const char *caller_func)
{
enum wrtd_status status;
struct wrtd_lib_alarm *al;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
al = &wrtd->alarms[idx];
......@@ -501,15 +518,14 @@ enum wrtd_status wrtd_write_alarm(struct wrtd_dev *wrtd, unsigned idx,
return status;
}
enum wrtd_status wrtd_write_rule(struct wrtd_dev *wrtd, unsigned idx,
const char *caller_func)
enum wrtd_status wrtd_write_rule_conf(struct wrtd_dev *wrtd, unsigned idx,
const char *caller_func)
{
enum wrtd_status status;
struct wrtd_lib_rule *rule;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
rule = &wrtd->rules[idx];
......@@ -517,8 +533,32 @@ enum wrtd_status wrtd_write_rule(struct wrtd_dev *wrtd, unsigned idx,
(wrtd, rule->cpu,
(wrtd->roots[rule->cpu].rules_addr
+ rule->local_idx * sizeof(struct wrtd_rule)),
sizeof(struct wrtd_rule) / 4,
(uint32_t *)&rule->rule, caller_func);
sizeof(struct wrtd_rule_config) / 4,
(uint32_t *)&rule->conf, caller_func);
return status;
}
enum wrtd_status wrtd_write_rule_stats(struct wrtd_dev *wrtd, unsigned idx,
struct wrtd_rule_stats *stats,
const char *caller_func)
{
enum wrtd_status status;
struct wrtd_lib_rule *rule;
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
rule = &wrtd->rules[idx];
status = wrtd_msg_writew
(wrtd, rule->cpu,
(wrtd->roots[rule->cpu].rules_addr
+ rule->local_idx * sizeof(struct wrtd_rule)
+ sizeof(struct wrtd_rule_config)),
sizeof(struct wrtd_rule_stats) / 4,
(uint32_t *)stats, __func__);
return status;
}
......@@ -528,9 +568,8 @@ enum wrtd_status wrtd_write_root_flags(struct wrtd_dev *wrtd, unsigned cpu,
{
enum wrtd_status status;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_msg_writew
(wrtd, cpu,
......@@ -549,9 +588,8 @@ enum wrtd_status wrtd_find_alarm(struct wrtd_dev *wrtd,
enum wrtd_status status;
unsigned i;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
/* 1. Validate rep_cap_id. */
status = wrtd_validate_id(wrtd, rep_cap_id, caller_func);
......@@ -563,7 +601,8 @@ enum wrtd_status wrtd_find_alarm(struct wrtd_dev *wrtd,
/* 3. Search it. */
for (i = 0; i < wrtd->nbr_alarms; i++)
if (wrtd_id_eq(wrtd->alarms[i].alarm.event.id, rep_cap_id)) {
if (wrtd_id_str_eq(&wrtd->alarms[i].alarm.event.id,
rep_cap_id)) {
*idx = i;
return WRTD_SUCCESS;
}
......@@ -581,9 +620,8 @@ enum wrtd_status wrtd_find_rule(struct wrtd_dev *wrtd,
enum wrtd_status status;
unsigned i;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
/* 1. Validate rep_cap_id. */
status = wrtd_validate_id(wrtd, rep_cap_id, caller_func);
......@@ -595,7 +633,7 @@ enum wrtd_status wrtd_find_rule(struct wrtd_dev *wrtd,
/* 3. Search it. */
for (i = 0; i < wrtd->nbr_rules; i++)
if (wrtd_id_eq(wrtd->rules[i].rule.conf.id, rep_cap_id)) {
if (wrtd_id_str_eq(&wrtd->rules[i].conf.id, rep_cap_id)) {
*idx = i;
return WRTD_SUCCESS;
}
......@@ -618,7 +656,7 @@ inline enum wrtd_status wrtd_alarm_check_disabled(struct wrtd_dev *wrtd, unsigne
inline enum wrtd_status wrtd_rule_check_disabled(struct wrtd_dev *wrtd, unsigned idx,
const char *caller_func)
{
if (wrtd->rules[idx].rule.conf.enabled)
if (wrtd->rules[idx].conf.enabled)
return wrtd_return_error(wrtd, WRTD_ERROR_RESOURCE_ACTIVE,
"%s/%s: Resource is enabled.",
caller_func, __func__);
......@@ -633,9 +671,8 @@ enum wrtd_status wrtd_find_fw(struct wrtd_dev *wrtd,
enum wrtd_status status;
unsigned i;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
/* 1. Validate rep_cap_id. */
status = wrtd_validate_id(wrtd, rep_cap_id, caller_func);
......@@ -647,7 +684,7 @@ enum wrtd_status wrtd_find_fw(struct wrtd_dev *wrtd,
/* 3. Search it. */
for (i = 0; i < wrtd->nbr_cpus; i++)
if (wrtd_id_eq(wrtd->roots[i].fw_name, rep_cap_id)) {
if (!strncmp(wrtd->roots[i].fw_name, rep_cap_id, WRTD_ID_LEN)) {
*idx = i;
return WRTD_SUCCESS;
}
......
......@@ -11,7 +11,8 @@
#include "mockturtle/libmockturtle.h"
#define WRTD_RETURN_IF_ERROR(status) if(status != WRTD_SUCCESS) return status
#define WRTD_RETURN_IF_ERROR(status) \
do { if (status != WRTD_SUCCESS) return status; } while (0)
#define WRTD_DEFAULT_TIMEOUT 1000
......@@ -21,10 +22,7 @@
static inline int wrtd_node_id_match(uint32_t id)
{
if ((id & WRTD_NODE_ID_MASK) == WRTD_NODE_ID)
return 1;
else
return 0;
return ((id & WRTD_NODE_ID_MASK) == WRTD_NODE_ID);
}
/* Add nanoseconds to an existing wrtd timestamp */
......@@ -50,11 +48,11 @@ struct wrtd_lib_alarm {
struct wrtd_lib_rule {
/* MT CPU on which the rule is placed. */
unsigned int cpu;
/* Rule index on the local MT cpu. */
/* Rule index on the local MT cpu (physical index). */
unsigned int local_idx;
unsigned char modified;
/* Rule. */
struct wrtd_rule rule;
/* Rule (the config part). */
struct wrtd_rule_config conf;
};
struct wrtd_dev {
......@@ -125,6 +123,12 @@ enum wrtd_status wrtd_validate_id(struct wrtd_dev *wrtd,
enum wrtd_status wrtd_fill_roots(struct wrtd_dev *wrtd,
const char *caller_func);
/* Read a statistic field for rule IDX.
OFF is the offset in the wrtd_rule_stat (in bytes), LEN in bytes. */
enum wrtd_status wrtd_read_rule_stat(struct wrtd_dev *wrtd, unsigned idx,
unsigned off, unsigned len, void *dest,
const char *caller_func);
enum wrtd_status wrtd_write_root_flags(struct wrtd_dev *wrtd, unsigned cpu,
const char *caller_func);
......@@ -153,9 +157,14 @@ enum wrtd_status wrtd_alloc_rules(struct wrtd_dev *wrtd,
struct wrtd_lib_rule **rulesp,
const char *caller_func);
/* Write-back rule. */
enum wrtd_status wrtd_write_rule(struct wrtd_dev *wrtd, unsigned idx,
const char *caller_func);
/* Write-back rule configuration. */
enum wrtd_status wrtd_write_rule_conf(struct wrtd_dev *wrtd, unsigned idx,
const char *caller_func);
/* Write rule statistics. */
enum wrtd_status wrtd_write_rule_stats(struct wrtd_dev *wrtd, unsigned idx,
struct wrtd_rule_stats *stats,
const char *caller_func);
/* Ensure the rules have been fetched from the CPUs. */
enum wrtd_status wrtd_fill_rules(struct wrtd_dev *wrtd,
......@@ -170,9 +179,11 @@ enum wrtd_status wrtd_find_fw(struct wrtd_dev *wrtd,
/* Reconfigure route tables and write-back rules. */
enum wrtd_status wrtd_reconfigure(struct wrtd_dev *wrtd, const char *caller_func);
bool wrtd_id_eq(const char *l, const char *r);
bool wrtd_id_null(const char *id);
void wrtd_id_copy(char *dst, const char *src);
bool wrtd_id_str_eq(const union wrtd_id *l, const char *r);
bool wrtd_id_eq(const union wrtd_id *l, const union wrtd_id *r);
bool wrtd_id_null(const union wrtd_id *id);
void wrtd_id_copy(union wrtd_id *dst, const union wrtd_id *src);
void wrtd_id_build(union wrtd_id *dst, const char *src);
enum wrtd_status wrtd_alarm_check_disabled(struct wrtd_dev *wrtd, unsigned idx,
const char *caller_func);
enum wrtd_status wrtd_rule_check_disabled(struct wrtd_dev *wrtd, unsigned idx,
......
......@@ -13,7 +13,12 @@
#include "libwrtd-private.h"
struct rule_map {
/* Rule. */
struct wrtd_lib_rule *rule;
struct wrtd_rule_stats stats;
/* Rule index before reconfiguration. */
int old_idx;
/* It's assigned cpu and index; -1 means unassigned. */
int cpu;
int global_idx;
};
......@@ -31,15 +36,22 @@ struct device_map {
unsigned int dev_idx;
};
/* The global configuration. */
struct conf_map {
/* The rules.
NBR_RULES is the number of valid rules. */
unsigned nbr_rules;
struct rule_map *rules;
/* The devices. */
unsigned nbr_devs;
struct device_map *devs;
unsigned free_rule_slots[WRTD_MAX_CPUS];
};
/* Allocate and fill MAP. */
static enum wrtd_status wrtd_reconfigure_alloc_map(struct wrtd_dev *wrtd,
struct conf_map *map,
const char *caller_func)
......@@ -81,9 +93,11 @@ static enum wrtd_status wrtd_reconfigure_alloc_map(struct wrtd_dev *wrtd,
/* Fill rules. */
n = 0;
for (i = 0; i < wrtd->nbr_rules; i++) {
if (wrtd_id_null(wrtd->rules[i].rule.conf.id))
if (wrtd_id_null(&wrtd->rules[i].conf.id))
continue;
memset(&map->rules[n].stats, 0, sizeof(struct wrtd_rule_stats));
map->rules[n].rule = &wrtd->rules[i];
map->rules[n].old_idx = i;
map->rules[n].cpu = -1;
map->rules[n].global_idx = -1;
n++;
......@@ -120,32 +134,25 @@ static enum wrtd_status wrtd_reconfigure_alloc_map(struct wrtd_dev *wrtd,
static enum wrtd_status wrtd_find_channel(struct wrtd_dev *wrtd,
const struct conf_map *map,
const char *id, unsigned int dir,
const union wrtd_id *id,
unsigned int dir,
unsigned *res_dev,
unsigned *res_ch)
{
unsigned i;
unsigned j;
char dev_id[WRTD_ID_LEN];
union wrtd_id dev_id;
for (i = 0; i < map->nbr_devs; i++) {
struct device_map *d = &map->devs[i];
for (j = 0; j < d->nbr_chs; j++) {
memset (dev_id, 0, WRTD_ID_LEN);
dev_id[0] = 'L';
dev_id[1] = 'C';
dev_id[2] = '-';
if (d->chs_dir == WRTD_CH_DIR_IN) {
dev_id[3] = 'I';
dev_id[4] = '1' + d->chs_idx + j;
}
else {
dev_id[3] = 'O';
dev_id[4] = '1' + d->chs_idx + j;
}
memset (&dev_id.c, 0, WRTD_ID_LEN);
snprintf(&dev_id.c[0], WRTD_ID_LEN, "LC-%c%d",
(d->chs_dir == WRTD_CH_DIR_IN) ? 'I' : 'O',
1 + d->chs_idx + j);
if (d->chs_dir == dir
&& wrtd_id_eq(dev_id, id)) {
&& wrtd_id_eq(&dev_id, id)) {
*res_dev = i;
*res_ch = (d->dev_idx << 4) + j;
return WRTD_SUCCESS;
......@@ -174,12 +181,13 @@ static enum wrtd_status wrtd_reconfigure_place_rule(struct wrtd_dev *wrtd,
map->rules[rule_num].cpu = cpu;
map->free_rule_slots[cpu]--;
if (map->rules[rule_num].rule->rule.conf.dest_cpu == cpu)
map->rules[rule_num].rule->rule.conf.dest_cpu = WRTD_DEST_CPU_LOCAL;
if (map->rules[rule_num].rule->conf.dest_cpu == cpu)
map->rules[rule_num].rule->conf.dest_cpu = WRTD_DEST_CPU_LOCAL;
return WRTD_SUCCESS;
}
/* Place all rules: assign a cpu and the rule index. */
static enum wrtd_status wrtd_reconfigure_place(struct wrtd_dev *wrtd,
struct conf_map *map,
const char *caller_func)
......@@ -193,25 +201,25 @@ static enum wrtd_status wrtd_reconfigure_place(struct wrtd_dev *wrtd,
/* Assign enabled rules to cpu. */
for (i = 0; i < map->nbr_rules; i++) {
struct rule_map *m = &map->rules[i];
struct wrtd_rule *rule = &m->rule->rule;
struct wrtd_rule_config *rule = &m->rule->conf;
unsigned dev;
unsigned ch;
signed cpu_affinity;
/* Skip disabled rules. */
if (!rule->conf.enabled)
if (!rule->enabled)
continue;
/* Place the rule on the same CPU as the input source. */
status = wrtd_find_channel(wrtd, map, rule->conf.source_id,
status = wrtd_find_channel(wrtd, map, &rule->source_id,
WRTD_CH_DIR_IN, &dev, &ch);
if (status == WRTD_SUCCESS) {
/* Input channel. */
cpu_affinity = map->devs[dev].cpu;
}
else {
status = wrtd_find_alarm(
wrtd, rule->conf.source_id, &ch, caller_func);
status = wrtd_find_alarm(wrtd, rule->source_id.c,
&ch, caller_func);
if (status == WRTD_SUCCESS) {
/* Alarm. */
cpu_affinity = wrtd->alarms[ch].cpu;
......@@ -224,18 +232,18 @@ static enum wrtd_status wrtd_reconfigure_place(struct wrtd_dev *wrtd,
struct wrtd_root *root;
/* Set destination cpu and channel. */
status = wrtd_find_channel(wrtd, map, rule->conf.dest_id,
status = wrtd_find_channel(wrtd, map, &rule->dest_id,
WRTD_CH_DIR_OUT, &dev, &ch);
if (status == WRTD_SUCCESS) {
/* Output device. */
rule->conf.dest_cpu = map->devs[dev].cpu;
rule->conf.dest_ch = ch;
rule->dest_cpu = map->devs[dev].cpu;
rule->dest_ch = ch;
/* If source is network message and this cpu can receive from
network, set cpu affinity to this cpu */
root = &wrtd->roots[rule->conf.dest_cpu];
root = &wrtd->roots[rule->dest_cpu];
if ((cpu_affinity < 0) &&
(root->capabilities & WRTD_CAP_NET_RX))
cpu_affinity = rule->conf.dest_cpu;
cpu_affinity = rule->dest_cpu;
/* Otherwise find the first cpu that is capable of net RX */
else {
for (cpu = 0; cpu < wrtd->nbr_cpus; cpu++) {
......@@ -249,19 +257,20 @@ static enum wrtd_status wrtd_reconfigure_place(struct wrtd_dev *wrtd,
}
else {
/* Network. */
rule->conf.dest_ch = WRTD_DEST_CH_NET;
rule->dest_ch = WRTD_DEST_CH_NET;
/* If source cpu can also send to
network, set dest cpu affinity to that cpu */
if (cpu_affinity >=0)
root = NULL;
if (cpu_affinity >= 0)
root = &wrtd->roots[cpu_affinity];
if ((root) && (root->capabilities & WRTD_CAP_NET_TX))
rule->conf.dest_cpu = cpu_affinity;
rule->dest_cpu = cpu_affinity;
/* Otherwise find the first cpu that is capable of net TX */
else {
for (cpu = 0; cpu < wrtd->nbr_cpus; cpu++) {
root = &wrtd->roots[cpu];
if (root->capabilities & WRTD_CAP_NET_TX) {
rule->conf.dest_cpu = cpu;
rule->dest_cpu = cpu;
break;
}
}
......@@ -272,9 +281,9 @@ static enum wrtd_status wrtd_reconfigure_place(struct wrtd_dev *wrtd,
network" event. Check if destination CPU can also receive and use it, otherwise
find the first cpu that is capable of net RX*/
if (cpu_affinity < 0) {
root = &wrtd->roots[rule->conf.dest_cpu];
root = &wrtd->roots[rule->dest_cpu];
if (root->capabilities & WRTD_CAP_NET_RX)
cpu_affinity = rule->conf.dest_cpu;
cpu_affinity = rule->dest_cpu;
else {
for (cpu = 0; cpu < wrtd->nbr_cpus; cpu++) {
root = &wrtd->roots[cpu];
......@@ -321,11 +330,11 @@ static enum wrtd_status wrtd_reconfigure_place(struct wrtd_dev *wrtd,
if (m->cpu != cpu)
continue;
hash = wrtd_id_hash(m->rule->rule.conf.source_id)
hash = wrtd_id_hash(&m->rule->conf.source_id)
% nbr_cpu_rules;
m->global_idx = cpu_offset + hash;
m->rule->rule.conf.hash_chain = -1;
m->rule->conf.hash_chain = -1;
if (slots[hash] == -1)
slots[hash] = i;
}
......@@ -356,9 +365,9 @@ static enum wrtd_status wrtd_reconfigure_place(struct wrtd_dev *wrtd,
slots[free_slot_idx] = i;
/* Chain. */
m->rule->rule.conf.hash_chain =
map->rules[head_rule].rule->rule.conf.hash_chain;
map->rules[head_rule].rule->rule.conf.hash_chain =
m->rule->conf.hash_chain =
map->rules[head_rule].rule->conf.hash_chain;
map->rules[head_rule].rule->conf.hash_chain =
free_slot_idx;
free_slot_idx++;
......@@ -368,7 +377,7 @@ static enum wrtd_status wrtd_reconfigure_place(struct wrtd_dev *wrtd,
while(1) {
/* Find next disabled rule. */
while (disable_idx < map->nbr_rules
&& map->rules[disable_idx].rule->rule.conf.enabled)
&& map->rules[disable_idx].rule->conf.enabled)
disable_idx++;
if (disable_idx >= map->nbr_rules)
break;
......@@ -401,27 +410,52 @@ static enum wrtd_status wrtd_reconfigure_write(struct wrtd_dev *wrtd,
struct wrtd_lib_rule *old_rules;
unsigned i;
/* FIXME: atomic update (using the freeze flag) ? */
old_rules = wrtd->rules;
/* Copy rules. */
for(i = 0; i < map->nbr_rules; i++)
new_rules[map->rules[i].global_idx].rule =
map->rules[i].rule->rule;
/* Read stats. */
for (i = 0; i < map->nbr_rules; i++) {
status = wrtd_read_rule_stat
(wrtd, map->rules[i].old_idx,
0, sizeof(struct wrtd_rule_stats),
&map->rules[i].stats, __func__);
WRTD_RETURN_IF_ERROR(status);
}
/* Copy rules. */
for (i = 0; i < map->nbr_rules; i++)
new_rules[map->rules[i].global_idx].conf =
map->rules[i].rule->conf;
wrtd->rules = new_rules;
for(i = 0; i < wrtd->nbr_rules; i++) {
if (wrtd_id_null(new_rules[i].rule.conf.id)
&& wrtd_id_null(old_rules[i].rule.conf.id))
for (i = 0; i < wrtd->nbr_rules; i++) {
if (wrtd_id_null(&new_rules[i].conf.id)
&& wrtd_id_null(&old_rules[i].conf.id)) {
/* Slot was unused, and it still unused. */
continue;
}
if (!old_rules[i].modified &&
(wrtd_id_eq(new_rules[i].rule.conf.id,
old_rules[i].rule.conf.id)))
(wrtd_id_eq(&new_rules[i].conf.id,
&old_rules[i].conf.id))) {
/* Slot used by the same rule, and not modified. */
continue;
status = wrtd_write_rule(wrtd, i, caller_func);
}
/* Write the new rule. */
status = wrtd_write_rule_conf(wrtd, i, caller_func);
WRTD_RETURN_IF_ERROR(status);
}
/* Write stats. */
for (i = 0; i < map->nbr_rules; i++) {
int nidx = map->rules[i].global_idx;
status = wrtd_write_rule_stats
(wrtd, nidx, &map->rules[i].stats, __func__);
WRTD_RETURN_IF_ERROR(status);
}
free(old_rules);
return WRTD_SUCCESS;
......@@ -440,21 +474,21 @@ enum wrtd_status wrtd_reconfigure(struct wrtd_dev *wrtd, const char *caller_func
status = wrtd_fill_alarms(wrtd, caller_func);
WRTD_RETURN_IF_ERROR(status);
/* Count number of rules. */
/* Count number of rules, initialiaze the maps. */
status = wrtd_reconfigure_alloc_map(wrtd, &map, caller_func);
WRTD_RETURN_IF_ERROR(status);
/* Place rules. */
status = wrtd_reconfigure_place(wrtd, &map, caller_func);
/* Allocate a new array of rules. */
new_rules = NULL;
if (status == WRTD_SUCCESS)
status = wrtd_alloc_rules(wrtd, &new_rules, caller_func);
if (status == WRTD_SUCCESS)
status = wrtd_reconfigure_write(wrtd, &map, new_rules, caller_func);
if (status != WRTD_SUCCESS)
free(new_rules);
free(map.rules);
free(map.devs);
......
......@@ -191,9 +191,8 @@ wrtd_status wrtd_init(uint32_t node_id,
*/
wrtd_status wrtd_close(wrtd_dev *wrtd)
{
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
trtl_close(wrtd->trtl);
......@@ -214,9 +213,8 @@ wrtd_status wrtd_reset(wrtd_dev *wrtd)
{
wrtd_status status;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_disable_all_alarms(wrtd);
WRTD_RETURN_IF_ERROR(status);
......@@ -256,12 +254,11 @@ wrtd_status wrtd_get_error(wrtd_dev *wrtd,
wrtd_status status;
int ret;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
char error_message[256];
memset(error_message, 0, 256);
char error_message[WRTD_ERR_MSG_BUF_SIZE];
memset(error_message, 0, WRTD_ERR_MSG_BUF_SIZE);
status = wrtd_error_message(wrtd, wrtd->err, error_message);
WRTD_RETURN_IF_ERROR(status);
......@@ -274,7 +271,7 @@ wrtd_status wrtd_get_error(wrtd_dev *wrtd,
if (error_description_buffer_size == 0)
return required_buffer_size;
if(error_description == NULL){
if (error_description == NULL) {
return wrtd_return_error
(wrtd, WRTD_ERROR_NULL_POINTER,
"Null pointer passed for function %s, "
......@@ -290,9 +287,8 @@ wrtd_status wrtd_get_error(wrtd_dev *wrtd,
"parameter error_description_buffer_size",
error_description_buffer_size, __func__);
if(error_code != NULL){
if (error_code != NULL)
*error_code = wrtd->err;
}
ret = snprintf(error_description, error_description_buffer_size,
"%s %s", error_message, wrtd->error_msg);
......@@ -316,7 +312,8 @@ wrtd_status wrtd_get_error(wrtd_dev *wrtd,
* @param[in] wrtd Device token. Can be NULL to allow calling this function
* even when initialisation has failed.
* @param[in] err_code #wrtd_status error code to convert.
* @param[out] err_message Buffer of at least 256 bytes to store the resulting string.
* @param[out] err_message Buffer of at least #WRTD_ERR_MSG_BUF_SIZE bytes
* to store the resulting string.
* @return #wrtd_status
*/
wrtd_status wrtd_error_message(wrtd_dev *wrtd,
......@@ -336,71 +333,92 @@ wrtd_status wrtd_error_message(wrtd_dev *wrtd,
switch(err_code){
case WRTD_SUCCESS:
snprintf(err_message, 256, "WRTD_SUCCESS");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE, "WRTD_SUCCESS");
break;
case WRTD_ERROR_INVALID_ATTRIBUTE:
snprintf(err_message, 256, "WRTD_ERROR_INVALID_ATTRIBUTE");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_INVALID_ATTRIBUTE");
break;
case WRTD_ERROR_ATTR_NOT_WRITEABLE:
snprintf(err_message, 256, "WRTD_ERROR_ATTR_NOT_WRITEABLE");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_ATTR_NOT_WRITEABLE");
break;
case WRTD_ERROR_ATTR_NOT_READABLE:
snprintf(err_message, 256, "WRTD_ERROR_ATTR_NOT_READABLE");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_ATTR_NOT_READABLE");
break;
case WRTD_ERROR_INVALID_VALUE:
snprintf(err_message, 256, "WRTD_ERROR_INVALID_VALUE");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_INVALID_VALUE");
break;
case WRTD_ERROR_NOT_INITIALIZED:
snprintf(err_message, 256, "WRTD_ERROR_NOT_INITIALIZED");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_NOT_INITIALIZED");
break;
case WRTD_ERROR_UNKNOWN_CHANNEL_NAME:
snprintf(err_message, 256, "WRTD_ERROR_UNKNOWN_CHANNEL_NAME");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_UNKNOWN_CHANNEL_NAME");
break;
case WRTD_ERROR_OUT_OF_MEMORY:
snprintf(err_message, 256, "WRTD_ERROR_OUT_OF_MEMORY");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_OUT_OF_MEMORY");
break;
case WRTD_ERROR_NULL_POINTER:
snprintf(err_message, 256, "WRTD_ERROR_NULL_POINTER");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_NULL_POINTER");
break;
case WRTD_ERROR_UNEXPECTED_RESPONSE:
snprintf(err_message, 256, "WRTD_ERROR_UNEXPECTED_RESPONSE");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_UNEXPECTED_RESPONSE");
break;
case WRTD_ERROR_RESOURCE_UNKNOWN:
snprintf(err_message, 256, "WRTD_ERROR_RESOURCE_UNKNOWN");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_RESOURCE_UNKNOWN");
break;
case WRTD_ERROR_BADLY_FORMED_SELECTOR:
snprintf(err_message, 256, "WRTD_ERROR_BADLY_FORMED_SELECTOR");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_BADLY_FORMED_SELECTOR");
break;
case WRTD_ERROR_ALARM_EXISTS:
snprintf(err_message, 256, "WRTD_ERROR_ALARM_EXISTS");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_ALARM_EXISTS");
break;
case WRTD_ERROR_ALARM_DOES_NOT_EXIST:
snprintf(err_message, 256, "WRTD_ERROR_ALARM_DOES_NOT_EXIST");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_ALARM_DOES_NOT_EXIST");
break;
case WRTD_ERROR_VERSION_MISMATCH:
snprintf(err_message, 256, "WRTD_ERROR_VERSION_MISMATCH");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_VERSION_MISMATCH");
break;
case WRTD_ERROR_INTERNAL:
snprintf(err_message, 256, "WRTD_ERROR_INTERNAL");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_INTERNAL");
break;
case WRTD_ERROR_UNKNOWN_LOG_TYPE:
snprintf(err_message, 256, "WRTD_ERROR_UNKNOWN_LOG_TYPE");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_UNKNOWN_LOG_TYPE");
break;
case WRTD_ERROR_RESOURCE_ACTIVE:
snprintf(err_message, 256, "WRTD_ERROR_RESOURCE_ACTIVE");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_RESOURCE_ACTIVE");
break;
case WRTD_ERROR_ATTR_GLOBAL:
snprintf(err_message, 256, "WRTD_ERROR_ATTR_GLOBAL");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_ATTR_GLOBAL");
break;
case WRTD_ERROR_OUT_OF_RESOURCES:
snprintf(err_message, 256, "WRTD_ERROR_OUT_OF_RESOURCES");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_OUT_OF_RESOURCES");
break;
case WRTD_ERROR_RULE_EXISTS:
snprintf(err_message, 256, "WRTD_ERROR_RULE_EXISTS");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_RULE_EXISTS");
break;
case WRTD_ERROR_RULE_DOES_NOT_EXIST:
snprintf(err_message, 256, "WRTD_ERROR_RULE_DOES_NOT_EXIST");
snprintf(err_message, WRTD_ERR_MSG_BUF_SIZE,
"WRTD_ERROR_RULE_DOES_NOT_EXIST");
break;
default:
......@@ -445,9 +463,8 @@ wrtd_status wrtd_set_attr_bool(wrtd_dev *wrtd,
{
wrtd_status status;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_validate_id(wrtd, rep_cap_id, __func__);
WRTD_RETURN_IF_ERROR(status);
......@@ -499,14 +516,13 @@ wrtd_status wrtd_get_attr_bool(wrtd_dev *wrtd,
{
wrtd_status status;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_validate_id(wrtd, rep_cap_id, __func__);
WRTD_RETURN_IF_ERROR(status);
if(value == NULL){
if (value == NULL) {
return wrtd_return_error
(wrtd, WRTD_ERROR_NULL_POINTER,
"Null pointer passed for function %s, "
......@@ -567,9 +583,8 @@ wrtd_status wrtd_set_attr_int32(wrtd_dev *wrtd,
{
wrtd_status status;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_validate_id(wrtd, rep_cap_id, __func__);
WRTD_RETURN_IF_ERROR(status);
......@@ -631,14 +646,13 @@ wrtd_status wrtd_get_attr_int32(wrtd_dev *wrtd,
{
wrtd_status status;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_validate_id(wrtd, rep_cap_id, __func__);
WRTD_RETURN_IF_ERROR(status);
if(value == NULL){
if (value == NULL) {
return wrtd_return_error
(wrtd, WRTD_ERROR_NULL_POINTER,
"Null pointer passed for function %s, "
......@@ -766,9 +780,8 @@ wrtd_status wrtd_set_attr_string(wrtd_dev *wrtd,
{
wrtd_status status;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_validate_id(wrtd, rep_cap_id, __func__);
WRTD_RETURN_IF_ERROR(status);
......@@ -815,9 +828,8 @@ wrtd_status wrtd_get_attr_string(wrtd_dev *wrtd,
{
wrtd_status status;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_validate_id(wrtd, rep_cap_id, __func__);
WRTD_RETURN_IF_ERROR(status);
......@@ -844,7 +856,7 @@ wrtd_status wrtd_get_attr_string(wrtd_dev *wrtd,
}
/**
* Set an attribute of type `timestamp`.
* Set an attribute of type `timestamp` (#wrtd_tstamp).
*
* Modelled after the IVI-C SetAttribute family of functions.
*
......@@ -852,30 +864,36 @@ wrtd_status wrtd_get_attr_string(wrtd_dev *wrtd,
* @param[in] rep_cap_id ID (string) of concerned repeated capability.
* If it is a global attribute, use #WRTD_GLOBAL_REP_CAP_ID
* @param[in] id ID (#wrtd_attr) of concerned attribute.
* @param[in] value Value to write to the attribute.
* @param[in] value Value (#wrtd_tstamp) to write to the attribute.
* If the `ns` part is greater or equal to 1e9, the `seconds` part will be
* automatically increased and the `ns` part will be reduced accordingly.
* @return #wrtd_status
*/
wrtd_status wrtd_set_attr_tstamp(wrtd_dev *wrtd,
const char *rep_cap_id,
wrtd_attr id,
const wrtd_tstamp *value)
wrtd_tstamp *value)
{
wrtd_status status;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_validate_id(wrtd, rep_cap_id, __func__);
WRTD_RETURN_IF_ERROR(status);
if(value == NULL){
if (value == NULL) {
return wrtd_return_error
(wrtd, WRTD_ERROR_NULL_POINTER,
"Null pointer passed for function %s, "
"parameter value", __func__);
}
while (value->ns >= 1e9) {
value->seconds++;
value->ns -= 1e9;
}
switch(id) {
case WRTD_ATTR_ALARM_TIME:
return wrtd_attr_set_alarm_time
......@@ -913,7 +931,7 @@ wrtd_status wrtd_set_attr_tstamp(wrtd_dev *wrtd,
}
/**
* Get an attribute of type `timestamp`.
* Get an attribute of type `timestamp` (#wrtd_tstamp).
*
* Modelled after the IVI-C GetAttribute family of functions.
*
......@@ -921,7 +939,7 @@ wrtd_status wrtd_set_attr_tstamp(wrtd_dev *wrtd,
* @param[in] rep_cap_id ID (string) of concerned repeated capability.
* If it is a global attribute, use #WRTD_GLOBAL_REP_CAP_ID
* @param[in] id ID (#wrtd_attr) of concerned attribute.
* @param[out] value Retrieved attribute value.
* @param[out] value Retrieved attribute value (#wrtd_tstamp).
* @return #wrtd_status
*/
wrtd_status wrtd_get_attr_tstamp(wrtd_dev *wrtd,
......@@ -931,14 +949,13 @@ wrtd_status wrtd_get_attr_tstamp(wrtd_dev *wrtd,
{
wrtd_status status;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_validate_id(wrtd, rep_cap_id, __func__);
WRTD_RETURN_IF_ERROR(status);
if(value == NULL){
if (value == NULL) {
return wrtd_return_error
(wrtd, WRTD_ERROR_NULL_POINTER,
"Null pointer passed for function %s, "
......@@ -1067,9 +1084,8 @@ wrtd_status wrtd_get_next_event_log_entry(wrtd_dev *wrtd,
struct tm *tm;
time_t t;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
/* Do not retrieve entry from log if buffer_size
is zero. Just report on necessary buffer size.
......@@ -1077,7 +1093,7 @@ wrtd_status wrtd_get_next_event_log_entry(wrtd_dev *wrtd,
if (log_entry_buffer_size == 0)
return WRTD_LOG_ENTRY_SIZE;
if(log_entry == NULL){
if (log_entry == NULL) {
return wrtd_return_error
(wrtd, WRTD_ERROR_NULL_POINTER,
"Null pointer passed for function %s, "
......@@ -1109,7 +1125,7 @@ wrtd_status wrtd_get_next_event_log_entry(wrtd_dev *wrtd,
int ret;
ret = snprintf(sptr, count, "Id:%-16s|Seq:%04d|",
log.event.id, log.event.seq % 10000);
log.event.id.c, log.event.seq % 10000);
if (ret < 0)
return wrtd_return_error(
wrtd, WRTD_ERROR_UNEXPECTED_RESPONSE,
......@@ -1183,7 +1199,7 @@ wrtd_status wrtd_get_next_event_log_entry(wrtd_dev *wrtd,
if (log.reason == WRTD_LOG_GENERATED_ALARM)
ret = snprintf(sptr, count, "GENERATED|ALARM ");
else if ((log.reason >= WRTD_LOG_GENERATED_DEVICE_0) &&
(log.reason <= WRTD_LOG_GENERATED_DEVICE_7) &&
(log.reason <= WRTD_LOG_GENERATED_DEVICE_12) &&
(log.reason % 8 == 0))
ret = snprintf(sptr, count, "GENERATED|DEVICE_%d",
(log.reason - 8) / 8);
......@@ -1261,9 +1277,8 @@ wrtd_status wrtd_clear_event_log_entries(wrtd_dev *wrtd)
{
int ret, i;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
for (i = 0; i < wrtd->nbr_cpus; ++i) {
ret = trtl_hmq_flush(wrtd->trtl, i, WRTD_HMQ);
......@@ -1305,9 +1320,8 @@ wrtd_status wrtd_add_alarm(wrtd_dev *wrtd,
int idx;
struct wrtd_alarm *alarm;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
/* Validate rep_cap_id. */
status = wrtd_validate_id(wrtd, rep_cap_id, __func__);
......@@ -1327,12 +1341,13 @@ wrtd_status wrtd_add_alarm(wrtd_dev *wrtd,
/* Find a free slot, check not already used. */
idx = -1;
for (i = 0; i < wrtd->nbr_alarms; i++) {
if (wrtd_id_eq(wrtd->alarms[i].alarm.event.id, rep_cap_id)) {
if (wrtd_id_str_eq(&wrtd->alarms[i].alarm.event.id,
rep_cap_id)) {
return wrtd_return_error(wrtd, WRTD_ERROR_ALARM_EXISTS,
"%s: The alarm already exists",
__func__);
}
if (idx < 0 && wrtd_id_null(wrtd->alarms[i].alarm.event.id))
if (idx < 0 && wrtd_id_null(&wrtd->alarms[i].alarm.event.id))
idx = i;
}
if (idx == -1)
......@@ -1345,7 +1360,7 @@ wrtd_status wrtd_add_alarm(wrtd_dev *wrtd,
alarm = &wrtd->alarms[idx].alarm;
/* That should be the default, but... */
memset(alarm, 0, sizeof(struct wrtd_alarm));
wrtd_id_copy(alarm->event.id, rep_cap_id);
wrtd_id_build(&alarm->event.id, rep_cap_id);
/* Write-back. */
status = wrtd_write_alarm(wrtd, idx, __func__);
......@@ -1373,16 +1388,15 @@ wrtd_status wrtd_disable_all_alarms(wrtd_dev *wrtd)
struct wrtd_alarm *alarm;
int changed = 0;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_fill_alarms(wrtd, __func__);
WRTD_RETURN_IF_ERROR(status);
for (idx = 0; idx < wrtd->nbr_alarms; idx++) {
alarm = &wrtd->alarms[idx].alarm;
if(alarm->enabled != 0) {
if (alarm->enabled != 0) {
alarm->enabled = 0;
changed = 1;
}
......@@ -1412,9 +1426,8 @@ wrtd_status wrtd_remove_alarm(wrtd_dev *wrtd,
unsigned idx;
struct wrtd_alarm *alarm;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_find_alarm(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
......@@ -1448,9 +1461,8 @@ extern wrtd_status wrtd_remove_all_alarms(wrtd_dev *wrtd)
unsigned idx;
struct wrtd_alarm *alarm;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_fill_alarms(wrtd, __func__);
WRTD_RETURN_IF_ERROR(status);
......@@ -1499,9 +1511,8 @@ wrtd_status wrtd_get_alarm_name(wrtd_dev *wrtd,
unsigned i;
unsigned n;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
/* Load all alarms. */
status = wrtd_fill_alarms(wrtd, __func__);
......@@ -1509,12 +1520,12 @@ wrtd_status wrtd_get_alarm_name(wrtd_dev *wrtd,
/* Search it. */
for (n = 0, i = 0; i < wrtd->nbr_alarms; i++) {
const char *aid = wrtd->alarms[i].alarm.event.id;
const union wrtd_id *aid = &wrtd->alarms[i].alarm.event.id;
if (wrtd_id_null(aid))
continue;
if (n == index) {
status = wrtd_id_copy_buf
(wrtd, name, name_buffer_size, aid, __func__);
(wrtd, name, name_buffer_size, aid->c, __func__);
WRTD_RETURN_IF_ERROR(status);
return WRTD_SUCCESS;
}
......@@ -1552,11 +1563,11 @@ wrtd_status wrtd_add_rule(wrtd_dev *wrtd,
wrtd_status status;
unsigned int i;
int idx;
struct wrtd_rule *rule;
struct wrtd_rule_config *rule;
struct wrtd_rule_stats stats;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
/* 1. Validate rep_cap_id. */
status = wrtd_validate_id(wrtd, rep_cap_id, __func__);
......@@ -1569,13 +1580,13 @@ wrtd_status wrtd_add_rule(wrtd_dev *wrtd,
/* 3. Find a free slot, check not already used. */
idx = -1;
for (i = 0; i < wrtd->nbr_rules; i++) {
if (wrtd_id_eq(wrtd->rules[i].rule.conf.id, rep_cap_id)) {
if (wrtd_id_str_eq(&wrtd->rules[i].conf.id, rep_cap_id)) {
return wrtd_return_error(wrtd, WRTD_ERROR_RULE_EXISTS,
"%s: The rule already exists",
__func__);
}
if (idx < 0
&& wrtd_id_null(wrtd->rules[i].rule.conf.id))
&& wrtd_id_null(&wrtd->rules[i].conf.id))
idx = i;
}
if (idx == -1)
......@@ -1585,14 +1596,19 @@ wrtd_status wrtd_add_rule(wrtd_dev *wrtd,
__func__);
/* 4. Initialize with default values. */
rule = &wrtd->rules[idx].rule;
rule = &wrtd->rules[idx].conf;
/* That should be the default, but... */
memset(rule, 0, sizeof(struct wrtd_rule));
wrtd_id_copy(rule->conf.id, rep_cap_id);
rule->conf.send_late = true;
memset(rule, 0, sizeof(struct wrtd_rule_config));
wrtd_id_build(&rule->id, rep_cap_id);
rule->send_late = true;
/* 5. Write-back. */
status = wrtd_write_rule(wrtd, idx, __func__);
status = wrtd_write_rule_conf(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
/* 6. Clear stats. */
memset(&stats, 0, sizeof(stats));
status = wrtd_write_rule_stats(wrtd, idx, &stats, __func__);
WRTD_RETURN_IF_ERROR(status);
return WRTD_SUCCESS;
......@@ -1617,17 +1633,16 @@ wrtd_status wrtd_disable_all_rules(wrtd_dev *wrtd)
struct wrtd_lib_rule *r;
int changed = 0;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_fill_rules(wrtd, __func__);
WRTD_RETURN_IF_ERROR(status);
for (idx = 0; idx < wrtd->nbr_rules; idx++) {
r = &wrtd->rules[idx];
if (r->rule.conf.enabled != 0) {
r->rule.conf.enabled = 0;
if (r->conf.enabled != 0) {
r->conf.enabled = 0;
changed = 1;
}
}
......@@ -1653,11 +1668,10 @@ wrtd_status wrtd_remove_rule(wrtd_dev *wrtd,
{
wrtd_status status;
unsigned idx;
struct wrtd_rule *rule;
struct wrtd_rule_config *rule;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
......@@ -1666,11 +1680,11 @@ wrtd_status wrtd_remove_rule(wrtd_dev *wrtd,
WRTD_RETURN_IF_ERROR(status);
/* Clear it. */
rule = &wrtd->rules[idx].rule;
memset(rule, 0, sizeof(struct wrtd_rule));
rule = &wrtd->rules[idx].conf;
memset(rule, 0, sizeof(*rule));
/* Write-back. */
status = wrtd_write_rule(wrtd, idx, __func__);
status = wrtd_write_rule_conf(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
return WRTD_SUCCESS;
......@@ -1689,11 +1703,10 @@ wrtd_status wrtd_remove_all_rules(wrtd_dev *wrtd)
{
wrtd_status status;
unsigned idx;
struct wrtd_rule *rule;
struct wrtd_rule_config *rule;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_fill_rules(wrtd, __func__);
WRTD_RETURN_IF_ERROR(status);
......@@ -1704,13 +1717,13 @@ wrtd_status wrtd_remove_all_rules(wrtd_dev *wrtd)
}
for (idx = 0; idx < wrtd->nbr_rules; idx++) {
rule = &wrtd->rules[idx].rule;
rule = &wrtd->rules[idx].conf;
/* Clear it. */
memset(rule, 0, sizeof(struct wrtd_rule));
memset(rule, 0, sizeof(*rule));
/* Write-back. */
status = wrtd_write_rule(wrtd, idx, __func__);
status = wrtd_write_rule_conf(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
}
......@@ -1744,9 +1757,8 @@ wrtd_status wrtd_get_rule_name(wrtd_dev *wrtd,
unsigned i;
unsigned n;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
/* Load all rules. */
status = wrtd_fill_rules(wrtd, __func__);
......@@ -1754,12 +1766,12 @@ wrtd_status wrtd_get_rule_name(wrtd_dev *wrtd,
/* Search it. */
for (n = 0, i = 0; i < wrtd->nbr_rules; i++) {
const char *aid = wrtd->rules[i].rule.conf.id;
const union wrtd_id *aid = &wrtd->rules[i].conf.id;
if (wrtd_id_null(aid))
continue;
if (n == index) {
status = wrtd_id_copy_buf
(wrtd, name, name_buffer_size, aid, __func__);
(wrtd, name, name_buffer_size, aid->c, __func__);
WRTD_RETURN_IF_ERROR(status);
return WRTD_SUCCESS;
}
......@@ -1786,11 +1798,10 @@ wrtd_status wrtd_reset_rule_stats(wrtd_dev *wrtd,
{
wrtd_status status;
unsigned idx;
struct wrtd_rule *rule;
struct wrtd_rule_stats stats;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
status = wrtd_find_rule(wrtd, rep_cap_id, &idx, __func__);
WRTD_RETURN_IF_ERROR(status);
......@@ -1798,16 +1809,11 @@ wrtd_status wrtd_reset_rule_stats(wrtd_dev *wrtd,
status = wrtd_rule_check_disabled(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
rule = &wrtd->rules[idx].rule;
/* Clear stats. */
memset(&rule->stat, 0, sizeof(struct wrtd_rule_stats));
memset(&stats, 0, sizeof(stats));
/* Write-back. */
status = wrtd_write_rule(wrtd, idx, __func__);
WRTD_RETURN_IF_ERROR(status);
return WRTD_SUCCESS;
status = wrtd_write_rule_stats(wrtd, idx, &stats, __func__);
return status;
}
/**
......@@ -1845,9 +1851,8 @@ wrtd_status wrtd_get_fw_name(wrtd_dev *wrtd,
wrtd_status status;
unsigned i;
if(wrtd == NULL){
if (wrtd == NULL)
return WRTD_ERROR_NOT_INITIALIZED;
}
/* Load all roots. */
status = wrtd_fill_roots(wrtd, __func__);
......
......@@ -236,6 +236,9 @@ typedef enum wrtd_attr {
/** Size (in characters, including null termination) of an event log enty. */
#define WRTD_LOG_ENTRY_SIZE 120
/** Size (in characters, including null termination) of minimum error message bugger. */
#define WRTD_ERR_MSG_BUF_SIZE 256
/* ------------------------------------------------------------------- */
/* Function prototypes for the official WRTD API. Documented in wrtd.c */
/* ------------------------------------------------------------------- */
......@@ -302,7 +305,7 @@ wrtd_status wrtd_get_attr_string(wrtd_dev *wrtd,
wrtd_status wrtd_set_attr_tstamp(wrtd_dev *wrtd,
const char *rep_cap_id,
wrtd_attr id,
const wrtd_tstamp *value);
wrtd_tstamp *value);
wrtd_status wrtd_get_attr_tstamp(wrtd_dev *wrtd,
const char *rep_cap_id,
......
#!/usr/bin/env python
from setuptools import setup
from setuptools import setup, find_packages
setup(
name='PyWrtd',
......@@ -15,6 +15,7 @@ setup(
"Documentation": "https://wrtd.readthedocs.io",
"Forum" : "https://forums.ohwr.org/c/wrtd",
},
py_modules=['PyWrtd'],
install_requires=['decorator'],
packages=find_packages(),
license='LGPLv3',
)
-include Makefile.specific
all:
clean:
install:
python setup.py install
.PHONY: all clean install
from setuptools import setup, find_packages
setup(
name="wrtd-tool",
version="1.0",
packages=find_packages(),
description='WRTD Tool',
author="Dimitris Lampridis",
author_email="dimitris.lampridis@cern.ch",
maintainer="Dimitris Lampridis",
maintainer_email="dimitris.lampridis@cern.ch",
url='http://www.ohwr.org/projects/wrtd',
project_urls={
"Documentation": "https://wrtd.readthedocs.io",
"Forum" : "https://forums.ohwr.org/c/wrtd",
},
license='LGPLv3',
entry_points = {
'console_scripts': [
"wrtd-tool = wrtd_tool.wrtd_tool:main"
]
}
)
......@@ -12,7 +12,7 @@ import time
import argparse
import re
from PyWrtd import *
from PyWrtd import PyWrtd
def signal_handler(sig, frame):
sys.exit(0)
......@@ -288,6 +288,35 @@ def cmd_alarm_info(wrtd, args):
print(" - Repeat Count......: {0}".format(
wrtd.get_attr_int32(args.name, wrtd.WRTD_ATTR_ALARM_REPEAT_COUNT)))
def cmd_cli(wrtd, args):
try:
import readline
except ImportError:
readline = None
print("Warning: readline not present")
parser = create_parser(True)
while True:
try:
l = input('wrtd-tool> ')
except EOFError:
print('exiting')
break
l = l.split()
# We don't want to exit in case of error, so continue.
# Ugly until we use python 3.9 and exit_on_error=False
try:
args = parser.parse_args(l)
except SystemExit:
continue
# Do not exit on error.
try:
args.func(wrtd, args)
except OSError as e:
print(e)
def time_interval(string):
m = re.match('\A([0-9]+)([nums]?)\Z', string)
if m == None:
......@@ -306,14 +335,23 @@ def time_interval_help():
return """Default unit is ns, but an 'n','u','m' or 's' can be appended \
to the value to set it explicitly to nano, micro, milli or full seconds"""
def main():
parser = argparse.ArgumentParser(description='WRTD Node configuration tool')
devid_parse = argparse.ArgumentParser(add_help=False)
devid_parse.add_argument('devid', type=lambda x: int(x,0),
metavar='<node_id>',
help='The ID of the WRTD Node (int, can be hex with "0x" prefix)')
def concat(*args):
res = []
for e in args:
if e is not None:
res.append(e)
return res
def create_parser(is_cli):
# Parent parsers for common args.
if not is_cli:
devid_parse = argparse.ArgumentParser(add_help=False)
devid_parse.add_argument('devid', type=lambda x: int(x,0),
metavar='<node_id>',
help='The ID of the WRTD Node (int, can be hex with "0x" prefix)')
else:
# No devid with cli
devid_parse = None
verbose_parse = argparse.ArgumentParser(add_help=False)
verbose_parse.add_argument('-v', '--verbose', action='store_true',
......@@ -327,160 +365,214 @@ def main():
aname_parse.add_argument('name', metavar='<alarm_id>',
help='The ID of the Alarm (string up to 15 characters)')
# The parser (with its subparsers)
parser = argparse.ArgumentParser(
description='WRTD Node configuration tool')
subparsers = parser.add_subparsers(title='Available commands',
dest='command', metavar='<command>',
help='(Use "<command> -h" to get more details)')
subparsers.required = True;
# list-nodes
cmd_parser = subparsers.add_parser('list-nodes',
help='List the IDs of all detected WRTD Nodes',
parents=[verbose_parse])
cmd_parser = subparsers.add_parser(
'list-nodes',
help='List the IDs of all detected WRTD Nodes',
parents=[verbose_parse])
cmd_parser.set_defaults(func=cmd_list_nodes, devid=None)
# sys-info
cmd_parser = subparsers.add_parser('sys-info', help='Show system information',
parents=[devid_parse, verbose_parse])
cmd_parser = subparsers.add_parser(
'sys-info',
help='Show system information',
parents=concat(devid_parse, verbose_parse))
cmd_parser.set_defaults(func=cmd_sys_info)
# sys-time
cmd_parser = subparsers.add_parser('sys-time', help='Show current system time',
parents=[devid_parse])
cmd_parser = subparsers.add_parser(
'sys-time', help='Show current system time',
parents=concat(devid_parse))
cmd_parser.set_defaults(func=cmd_sys_time)
# enable-log
cmd_parser = subparsers.add_parser('enable-log', help='Enable logging',
parents=[devid_parse])
cmd_parser = subparsers.add_parser(
'enable-log', help='Enable logging',
parents=concat(devid_parse))
cmd_parser.set_defaults(func=cmd_set_log, set_log=True)
# disable-log
cmd_parser = subparsers.add_parser('disable-log', help='Disable logging',
parents=[devid_parse])
cmd_parser = subparsers.add_parser(
'disable-log', help='Disable logging',
parents=concat(devid_parse))
cmd_parser.set_defaults(func=cmd_set_log, set_log=False)
# show-log
cmd_parser = subparsers.add_parser('show-log', help='Show log entries',
parents=[devid_parse])
cmd_parser.add_argument('-c', '--count', dest='count', type=int, default=0,
help='Number of entries to read (0 = infinite, the default)')
cmd_parser.add_argument('-e', '--enable', dest='set_log', action='store_true',
help='Enable event logging on the Node if not already enabled')
cmd_parser = subparsers.add_parser(
'show-log', help='Show log entries',
parents=concat(devid_parse))
cmd_parser.add_argument(
'-c', '--count', dest='count', type=int, default=0,
help='Number of entries to read (0 = infinite, the default)')
cmd_parser.add_argument(
'-e', '--enable', dest='set_log', action='store_true',
help='Enable event logging on the Node if not already enabled')
cmd_parser.set_defaults(func=cmd_show_log)
# clear-log
cmd_parser = subparsers.add_parser('clear-log', help='Clear pending log entries',
parents=[devid_parse])
cmd_parser = subparsers.add_parser(
'clear-log', help='Clear pending log entries',
parents=concat(devid_parse))
cmd_parser.set_defaults(func=cmd_clear_log)
# list-rules
cmd_parser = subparsers.add_parser('list-rules', help='List all defined Rules',
parents=[devid_parse, verbose_parse])
cmd_parser = subparsers.add_parser(
'list-rules', help='List all defined Rules',
parents=concat(devid_parse, verbose_parse))
cmd_parser.set_defaults(func=cmd_list_rules)
# add-rule
cmd_parser = subparsers.add_parser('add-rule', help='Define a new Rule',
parents=[devid_parse, rname_parse])
cmd_parser = subparsers.add_parser(
'add-rule', help='Define a new Rule',
parents=concat(devid_parse, rname_parse))
cmd_parser.set_defaults(func=cmd_add_rule)
# set-rule
cmd_parser = subparsers.add_parser('set-rule', help='Configure a Rule',
parents=[devid_parse, rname_parse])
cmd_parser.add_argument('-d', '--delay', type=time_interval, default = 0,
help='Set the delay for this Rule. ' + time_interval_help())
cmd_parser.add_argument('source', help='The source Event ID for this Rule.')
cmd_parser.add_argument('destination', help='The destination Event ID for this Rule.')
cmd_parser = subparsers.add_parser(
'set-rule', help='Configure a Rule',
parents=concat(devid_parse, rname_parse))
cmd_parser.add_argument(
'-d', '--delay', type=time_interval, default = 0,
help='Set the delay for this Rule. ' + time_interval_help())
cmd_parser.add_argument(
'source', help='The source Event ID for this Rule.')
cmd_parser.add_argument(
'destination', help='The destination Event ID for this Rule.')
cmd_parser.set_defaults(func=cmd_set_rule)
# remove-rule
cmd_parser = subparsers.add_parser('remove-rule', help='Delete a Rule',
parents=[devid_parse, rname_parse])
cmd_parser = subparsers.add_parser(
'remove-rule', help='Delete a Rule',
parents=concat(devid_parse, rname_parse))
cmd_parser.set_defaults(func=cmd_remove_rule)
# remove-all-rules
cmd_parser = subparsers.add_parser('remove-all-rules', help='Delete all Rules',
parents=[devid_parse])
cmd_parser = subparsers.add_parser(
'remove-all-rules', help='Delete all Rules',
parents=concat(devid_parse))
cmd_parser.set_defaults(func=cmd_remove_all_rules)
# enable-rule
cmd_parser = subparsers.add_parser('enable-rule', help='Enable a Rule',
parents=[devid_parse, rname_parse])
cmd_parser = subparsers.add_parser(
'enable-rule', help='Enable a Rule',
parents=concat(devid_parse, rname_parse))
cmd_parser.set_defaults(func=cmd_enable_rule)
# disable-rule
cmd_parser = subparsers.add_parser('disable-rule', help='Disable a Rule',
parents=[devid_parse, rname_parse])
cmd_parser = subparsers.add_parser(
'disable-rule', help='Disable a Rule',
parents=concat(devid_parse, rname_parse))
cmd_parser.set_defaults(func=cmd_disable_rule)
# disable-all-rules
cmd_parser = subparsers.add_parser('disable-all-rules', help='Disable all Rules',
parents=[devid_parse])
cmd_parser = subparsers.add_parser(
'disable-all-rules', help='Disable all Rules',
parents=concat(devid_parse))
cmd_parser.set_defaults(func=cmd_disable_all_rules)
# rule-info
cmd_parser = subparsers.add_parser('rule-info', help='Display information about a Rule',
parents=[devid_parse, rname_parse])
cmd_parser = subparsers.add_parser(
'rule-info', help='Display information about a Rule',
parents=concat(devid_parse, rname_parse))
cmd_parser.set_defaults(func=cmd_rule_info)
# reset-rule-stats
cmd_parser = subparsers.add_parser('reset-rule-stats', help='Reset all statistics of a Rule',
parents=[devid_parse, rname_parse])
cmd_parser = subparsers.add_parser(
'reset-rule-stats', help='Reset all statistics of a Rule',
parents=concat(devid_parse, rname_parse))
cmd_parser.set_defaults(func=cmd_reset_rule_stats)
# list-alarms
cmd_parser = subparsers.add_parser('list-alarms', help='List all defined Alarms',
parents=[devid_parse, verbose_parse])
cmd_parser = subparsers.add_parser(
'list-alarms', help='List all defined Alarms',
parents=concat(devid_parse, verbose_parse))
cmd_parser.set_defaults(func=cmd_list_alarms)
# add-alarm
cmd_parser = subparsers.add_parser('add-alarm', help='Define a new Alarm',
parents=[devid_parse, aname_parse])
cmd_parser = subparsers.add_parser(
'add-alarm', help='Define a new Alarm',
parents=concat(devid_parse, aname_parse))
cmd_parser.set_defaults(func=cmd_add_alarm)
# set-alarm
cmd_parser = subparsers.add_parser('set-alarm', help='Configure an Alarm',
parents=[devid_parse, aname_parse])
cmd_parser.add_argument('-d', '--delay', type=time_interval, required = True,
help='Set the delay for this Alarm wrt now. ' + time_interval_help())
cmd_parser.add_argument('-s', '--setup', type=time_interval, default = 0,
help='Set the setup time for this Alarm. ' + time_interval_help())
cmd_parser.add_argument('-p', '--period', type=time_interval, default = 0,
help='Set the period for this Alarm. ' + time_interval_help())
cmd_parser.add_argument('-c', '--count', type=int, default = 0,
help='Set the repeat count for this Alarm')
cmd_parser.add_argument('-e', '--enable', action='store_true',
help='Also enable the Alarm after configuring it.')
cmd_parser = subparsers.add_parser(
'set-alarm', help='Configure an Alarm',
parents=concat(devid_parse, aname_parse))
cmd_parser.add_argument(
'-d', '--delay', type=time_interval, required = True,
help='Set the delay for this Alarm wrt now. ' + time_interval_help())
cmd_parser.add_argument(
'-s', '--setup', type=time_interval, default = 0,
help='Set the setup time for this Alarm. ' + time_interval_help())
cmd_parser.add_argument(
'-p', '--period', type=time_interval, default = 0,
help='Set the period for this Alarm. ' + time_interval_help())
cmd_parser.add_argument(
'-c', '--count', type=int, default = 0,
help='Set the repeat count for this Alarm')
cmd_parser.add_argument(
'-e', '--enable', action='store_true',
help='Also enable the Alarm after configuring it.')
cmd_parser.set_defaults(func=cmd_set_alarm)
# remove-alarm
cmd_parser = subparsers.add_parser('remove-alarm', help='Delete an Alarm',
parents=[devid_parse, aname_parse])
cmd_parser = subparsers.add_parser(
'remove-alarm', help='Delete an Alarm',
parents=concat(devid_parse, aname_parse))
cmd_parser.set_defaults(func=cmd_remove_alarm)
# remove-all-alarms
cmd_parser = subparsers.add_parser('remove-all-alarms', help='Delete all Alarms',
parents=[devid_parse])
cmd_parser = subparsers.add_parser(
'remove-all-alarms', help='Delete all Alarms',
parents=concat(devid_parse))
cmd_parser.set_defaults(func=cmd_remove_all_alarms)
# enable-alarm
cmd_parser = subparsers.add_parser('enable-alarm', help='Enable an Alarm',
parents=[devid_parse, aname_parse])
cmd_parser = subparsers.add_parser(
'enable-alarm', help='Enable an Alarm',
parents=concat(devid_parse, aname_parse))
cmd_parser.set_defaults(func=cmd_enable_alarm)
# disable-alarm
cmd_parser = subparsers.add_parser('disable-alarm', help='Disable an Alarm',
parents=[devid_parse, aname_parse])
cmd_parser = subparsers.add_parser(
'disable-alarm', help='Disable an Alarm',
parents=concat(devid_parse, aname_parse))
cmd_parser.set_defaults(func=cmd_disable_alarm)
# disable-all-alarms
cmd_parser = subparsers.add_parser('disable-all-alarms', help='Disable all Alarms',
parents=[devid_parse])
cmd_parser = subparsers.add_parser(
'disable-all-alarms', help='Disable all Alarms',
parents=concat(devid_parse))
cmd_parser.set_defaults(func=cmd_disable_all_alarms)
# alarm-info
cmd_parser = subparsers.add_parser('alarm-info', help='Display information about an Alarm',
parents=[devid_parse, aname_parse])
cmd_parser = subparsers.add_parser(
'alarm-info', help='Display information about an Alarm',
parents=concat(devid_parse, aname_parse))
cmd_parser.set_defaults(func=cmd_alarm_info)
# cli
if not is_cli:
cmd_parser = subparsers.add_parser(
'cli', help='Command line interface',
parents=concat(devid_parse))
cmd_parser.set_defaults(func=cmd_cli)
return parser
def main():
parser = create_parser(is_cli=False)
args = parser.parse_args()
if (args.devid != None):
......
# WRTD systems are pre programmed, so it is fine to unreset the MockTurtle
# CPUs as soon as we have a running driver
SUBSYSTEM=="mockturtle", KERNEL=="trtl-[0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z]-[0-9][0-9]" ACTION=="add", ATTRS{application_id}=="0x57544e[0-9a-zA-Z][0-9a-zA-Z]", ATTR{reset}=="1", ATTR{reset}:="0"
# Assign wrtd group to mockturtle devices, cpus and hmqs (if the wrtd group
# does not exits, then it will be root)
SUBSYSTEM=="mockturtle", KERNEL=="trtl-[0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z]" ACTION=="add", ATTR{application_id}=="0x57544e[0-9a-zA-Z][0-9a-zA-Z]", GROUP="wrtd"
SUBSYSTEM=="mockturtle", KERNEL=="trtl-[0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z]-[0-9][0-9]" ACTION=="add", ATTRS{application_id}=="0x57544e[0-9a-zA-Z][0-9a-zA-Z]", GROUP="wrtd"
SUBSYSTEM=="mockturtle", KERNEL=="trtl-[0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z]-[0-9][0-9]-[0-9][0-9]" ACTION=="add", ATTRS{application_id}=="0x57544e[0-9a-zA-Z][0-9a-zA-Z]", GROUP="wrtd"
SUBSYSTEM=="mockturtle", KERNEL=="trtl-[0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z]" ACTION=="add", ATTR{application_id}=="0x57544e[0-9a-zA-Z][0-9a-zA-Z]" RUN+="/usr/bin/chown root:wrtd $sys/$devpath/reset_mask"
SUBSYSTEM=="mockturtle", KERNEL=="trtl-[0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z]-[0-9][0-9]" ACTION=="add", ATTRS{application_id}=="0x57544e[0-9a-zA-Z][0-9a-zA-Z]" RUN+="/usr/bin/chown root:wrtd $sys/$devpath/reset"
SUBSYSTEM=="mockturtle", KERNEL=="trtl-[0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z]-[0-9][0-9]-[0-9][0-9]" ACTION=="add", ATTRS{application_id}=="0x57544e[0-9a-zA-Z][0-9a-zA-Z]" RUN+="/usr/bin/chown root:wrtd $sys/$devpath/discard_all"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment