Commit 7533c4d0 authored by Federico Vaga's avatar Federico Vaga

Merge remote-tracking branch 'origin/proposed_master' into develop

parents 0c081bed 7cb88275
......@@ -28,3 +28,9 @@
[submodule "dependencies/gn4124-core"]
path = dependencies/gn4124-core
url = https://ohwr.org/project/gn4124-core.git
[submodule "dependencies/spec"]
path = dependencies/spec
url = https://ohwr.org/project/spec.git
[submodule "dependencies/svec"]
path = dependencies/svec
url = https://ohwr.org/project/svec.git
Subproject commit bb5b8f75e6f85335b43fef320375404686a74008
Subproject commit 1a1293900e6334bc41251ee84d0ae7d19980e584
Subproject commit 1e0e561f4902940a0b3ec85bdc863ac92cc650da
Subproject commit ce4ef303e38b0119c5c62a5634f8426ddc69b068
Subproject commit 28cd756047ce9f85cf7c134367c7439f1189114d
Subproject commit 284373b7ea1db559dd323634dd34a8dba1811c12
Subproject commit 72adf76dab9a6fc33fbff7c86d786c31e175a46a
Subproject commit 91d5eface7608d306991d2c1aa4e6f5210e9305c
Subproject commit b07df87ad36d963beb7d7596b3dffa4221d6bd58
Subproject commit add8319c68770cd2dac9c10842aad8487aeb1717
Subproject commit 1b48d76430920f62e871ce0e46bc61731f04d9b1
Subproject commit 3da89c5c700260ce0d7296438d463d789c44161d
Subproject commit 1204aeca29ec3c72b6fa615976f000c664c7d152
Subproject commit 366ca4dbe1777f5bc98341d2878070a6c6fa350f
......@@ -104,6 +104,9 @@ as information regarding any discarded :ref:`event`, along with the reason for d
The Event Log has a limited storage buffer. Newer entries will overwrite older, unread ones.
For an explanation of the fields of an Event Log entry, please refer to the documentation of the
:cpp:func:`wrtd_get_next_event_log_entry` function.
.. _local_channel:
Local Channel
......
......@@ -11,8 +11,3 @@ Installation
Permissions
===========
.. _node_id:
Node Identification
===================
......@@ -98,15 +98,27 @@ The initialisation API provides the functions to initiate/close a connection to
well as to reset it.
:cpp:func:`wrtd_init` is the first function that should be called by any program, in order to obtain
the "device token" to be used in all subsequent function calls. See also :ref:`node_id` on how to
figure out the ``resource_name`` of a :ref:`node`.
the "device token" to be used in all subsequent function calls.
Conversely, :cpp:func:`wrtd_close` should be called before exiting the program. No further WRTD
library functions can be used after that.
In order to identify the :ref:`node` to connect to, it is necessary to provide the ID of that
:ref:`node`. This ID is simply an integer that uniquely identifies a Node within a given host
system. Functions :cpp:func:`wrtd_get_node_count` and :cpp:func:`wrtd_get_node_id` can help you
figure out the ID of each :ref:`node`.
.. important::
The Node ID is not sequential, nor does it start counting from zero (or one). It might well be
that you only have one Node in a given host, and that it has an ID different than 1. Always
retrieve therefore the Node ID with :cpp:func:`wrtd_get_node_id`.
.. doxygenfunction:: wrtd_init
.. doxygenfunction:: wrtd_close
.. doxygenfunction:: wrtd_reset
.. doxygenfunction:: wrtd_get_node_count
.. doxygenfunction:: wrtd_get_node_id
.. code-block:: c
:caption: Opening and closing a connection to a Node.
......@@ -115,8 +127,17 @@ library functions can be used after that.
int main(void) {
wrtd_dev *wrtd;
wrtd_status status;
uint32_t node_count;
uint32_t node_id;
status = wrtd_init("MT01", false, NULL, &wrtd);
/* Not really used in this example */
status = wrtd_get_node_count(&node_count);
/* Get the ID of the first Node */
status= wrtd_get_node_id(1, &node_id);
/* Access the first Node */
status = wrtd_init(node_id, false, NULL, &wrtd);
/* This will erase all defined rules and alarms
from the Node, so it might not be what you want
......
......@@ -16,61 +16,51 @@ The wrapper is provided as a Python package with a single class that encapsulate
All the provided class methods have exactly the same names (and function) as their C counterparts,
without the "wrtd\_" prefix.
To start using it, simply import the PyWrtd package and instantiate a :py:class:`PyWrtd` object,
passing to it the :ref:`identifier of the Node<node_id>` you wish to access.
If the identifier is wrong or if the user does not have the correct permissions to access it, WRTD
will return :cpp:enumerator:`WRTD_ERROR_RESOURCE_UNKNOWN`.
.. code-block:: python
.. hint::
>>> from PyWrtd import PyWrtd
>>> wrtd = PyWrtd("bad id")
Error 0xbffa0060: WRTD_ERROR_RESOURCE_UNKNOWN
>>> wrtd = PyWrtd("MT01")
>>> wrtd
<PyWrtd.PyWrtd object at 0x7fa9aeeaee48>
Compared to the :ref:`clib`, the Python wrapper lacks the :cpp:func:`wrtd_init`,
:cpp:func:`wrtd_close`, :cpp:func:`wrtd_get_error` and :cpp:func:`wrtd_error_message` functions,
because the Python wrapper performs these tasks (initialisation and error handling) internally.
.. hint::
The provided :ref:`tools <tools>` are built on top of this Python wrapper, so they also serve as
a good example of how to use the wrapper.
Error Handling API
------------------
.. automethod:: PyWrtd.get_error
.. code-block:: python
>>> wrtd.get_error()
(0, 'WRTD_SUCCESS ')
.. automethod:: PyWrtd.error_message
.. code-block:: python
>>> wrtd.error_message(PyWrtd.WRTD_SUCCESS)
'WRTD_SUCCESS'
.. _pyapi_init:
Initialisation API
------------------
Compared to the :ref:`clib` :ref:`api_init`, the Python version lacks the :cpp:func:`wrtd_init` and
:cpp:func:`wrtd_close` functions, because the Python wrapper performs these tasks internally.
To start using it, simply import the PyWrtd package and instantiate a :py:class:`PyWrtd` object,
passing to it the ID of the Node you wish to access.
In order to retrieve the ID of the :ref:`node`, the :py:class:`PyWrtd` class provides the static
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
access it, WRTD will return :cpp:enumerator:`WRTD_ERROR_RESOURCE_UNKNOWN`.
.. automethod:: PyWrtd.reset
.. code-block:: python
>>> from PyWrtd import PyWrtd
>>> wrtd = PyWrtd(11)
OSError: [Errno -1074134944] WRTD_ERROR_RESOURCE_UNKNOWN
>>> PyWrtd.get_node_id(3)
OSError: [Errno -1074134944] WRTD_ERROR_RESOURCE_UNKNOWN
>>> PyWrtd.get_node_count()
2
>>> PyWrtd.get_node_id(1)
10
>>> wrtd = PyWrtd(10)
>>> wrtd
<PyWrtd.PyWrtd object at 0x7fa9aeeaee48>
>>> wrtd.reset()
>>> wrtd.add_rule('rule1')
>>> # Query number of declared rules
>>> wrtd.get_attr_int32(PyWrtd.WRTD_GLOBAL_REP_CAP_ID, PyWrtd.WRTD_ATTR_RULE_COUNT)
1
>>> # After reset, 'rule1' should be gone
>>> wrtd.reset()
>>> wrtd.get_attr_int32(PyWrtd.WRTD_GLOBAL_REP_CAP_ID, PyWrtd.WRTD_ATTR_RULE_COUNT)
0
.. automethod:: PyWrtd.get_node_count
.. automethod:: PyWrtd.get_node_id
.. automethod:: PyWrtd.reset
.. _pyapi_attr:
......
......@@ -5,46 +5,43 @@ Tools
.. module:: PyWrtd
WRTD provides two comand-line, Python based tools for accessing a :ref:`node`. One
(:ref:`wrtd_config`) is used to add/remove/configure :ref:`Rules <rule>` and :ref:`Alarms <alarm>`,
and to display information about the :ref:`node` while the other (:ref:`wrtd_logging`) is used for
reading entries from the :ref:`event_log`.
WRTD provides a comand-line, Python based tool (:ref:`wrtd_tool`) for accessing a :ref:`node`.
Both tools have a built-in help system that can be accessed by passing the ``--help`` (or ``-h``)
option to the tool.
.. hint::
Both tools take an obligatory ``-D`` option to specify the :ref:`node` to access. For more details,
please refer to :ref:`node_id`. You also need to run them with the proper :ref:`permissions`.
Please make sure that you run the tool wih the proper :ref:`permissions <permissions>`.
For details on how to install these tools (and their dependencies), please refer to
For details on how to install the tool (and their dependencies), please refer to
:numref:`installation`.
.. _wrtd_config:
.. _wrtd_tool:
wrtd-config
-----------
wrtd-tool
---------
``wrtd-config`` is a command-line tool that implements several different operations on a
``wrtd-tool`` is a command-line tool that implements several different operations on a
:ref:`node`. It supports most of the functionality provided by the :ref:`pywrap`.
A list of the available commands can be retrieved by passing the ``-h`` option to the tool:
.. code-block:: console
> wrtd-config -h
usage: wrtd-config [-h] -D DEV <command> ...
> wrtd-tool -h
usage: wrtd-tool [-h] <command> ...
WRTD node configuration tool
WRTD Node configuration tool
optional arguments:
-h, --help show this help message and exit
-D DEV, --dev-id DEV MockTurtle device ID (integer) to open
Available commands:
<command> (Use "<command> -h" to get more details)
list-nodes List the IDs of all detected WRTD Nodes
sys-info Show system information
sys-time Show current system time
set-log Enable/Disable logging
enable-log Enable logging
disable-log Disable logging
show-log Show log entries
clear-log Clear pending log entries
list-rules List all defined Rules
add-rule Define a new Rule
......@@ -71,12 +68,14 @@ and passing the ``-h`` option after the command:
.. code-block:: console
> wrtd-config set-alarm -h
usage: wrtd-config set-alarm [-h] -d DELAY [-s SETUP] [-p PERIOD]
[-c COUNT] [-e] name
> wrtd-tool set-alarm -h
usage: wrtd-tool set-alarm [-h] -d DELAY [-s SETUP] [-p PERIOD]
[-c COUNT] [-e] <node_id> <alarm_id>
positional arguments:
name The name of the Alarm to configure
<node_id> The ID of the WRTD Node (int, can be hex with "0x"
prefix)
<alarm_id> The ID of the Alarm (string up to 15 characters)
optional arguments:
-h, --help show this help message and exit
......@@ -100,36 +99,58 @@ and passing the ``-h`` option after the command:
-e, --enable Also enable the Alarm after configuring it.
If a command returns an :ref:`Error Code <api_error_codes>`, the underlying :ref:`pywrap` will raise
an OSError exception and will provide all the available details coming from
:py:meth:`PyWrtd.get_error`:
an OSError exception and will provide all the available details:
.. code-block:: console
> wrtd-config -D 1 remove-alarm alarm5
OSError: [Errno -1074122744] Error 0xbffa3008: WRTD_ERROR_ALARM_DOES_NOT_EXIST wrtd_remove_alarm/wrtd_find_alarm: The specified alarm has not been defined
> wrtd-tool remove-alarm 1 alarm5
OSError: [Errno -1074122744] WRTD_ERROR_ALARM_DOES_NOT_EXIST
wrtd_remove_alarm/wrtd_find_alarm: The specified alarm has not been defined
.. _wrtd_logging:
wrtd-logging
------------
wrtd-logging is a simple command-line tool that monitors the :ref:`event_log` of a :ref:`node`.
A list of the available options can be retrieved by passing the ``-h`` option to the tool:
Here's an example on how to configure a :ref:`rule` and check the :ref:`event_log` for :ref:`Events
<event>`:
.. code-block:: console
> wrtd-logging -h
usage: wrtd-logging [-h] -D DEV [-c COUNT]
WRTD node log monitoring tool
optional arguments:
-h, --help show this help message and exit
-D DEV, --dev-id DEV MockTurtle device ID (integer) to open
-c COUNT, --count COUNT
Number of entries to read (0 = infinite)
-e, --enable Enable event logging on the Node if not already
enabled.
Log entries are printed using the format presented in :cpp:func:`wrtd_get_next_event_log_entry`.
> wrtd-tool list-nodes
-> WRTD Node detected with ID: 10
> wrtd-tool list-rules 10
0 Rules defined.
> wrtd-tool add-rule 10 rule0
> wrtd-tool set-rule 10 rule0 LC-I1 NET0
> wrtd-tool list-rules 10 -v
1 Rule defined:
+ rule0
+ Configuration
- Name..............: rule0
- Source............: LC-I1
- Destination.......: NET0
- Enabled...........: False
- Send Late.........: True
- Repeat Count......: 0
- Delay.............: 0.000ns
- Holdoff...........: 0.000ns
- Resync Period.....: 0.000ns
- Resync Factor.....: 0
+ Statistics
- RX Events.........: 0
- Last RX...........: Never
- TX Events.........: 0
- Last TX...........: Never
- Latency (min).....: 0.000ns
- Latency (avg).....: 0.000ns
- Latency (max).....: 0.000ns
- Missed (late).....: 0
- Missed (holdoff)..: 0
- Missed (no sync)..: 0
- Missed (overflow).: 0
- Last Missed.......: Never
> wrtd-tool enable-rule 10 rule0
> wrtd-tool enable-log 10
> wrtd-tool show-log 10 -c 6
Id:LC-I1 |Seq:0000|...|...|GENERATED|DEVICE_0
Id:NET0 |Seq:0016|...|...|NETWORK |TX
Id:LC-I1 |Seq:0000|...|...|GENERATED|DEVICE_0
Id:NET0 |Seq:0017|...|...|TX
Id:LC-I1 |Seq:0000|...|...|GENERATED|DEVICE_0
Id:NET0 |Seq:0018|...|...|TX
# HDLMake 'develop' branch required.
#
# Due to bugs in release v3.0 of hdlmake it is necessary to use the "develop"
# branch of hdlmake, commit db4e1ab.
board = "spec"
target = "xilinx"
action = "synthesis"
......@@ -14,21 +9,14 @@ syn_top = "wrtd_ref_spec150t_adc"
syn_project = "wrtd_ref_spec150t_adc.xise"
syn_tool = "ise"
fetchto = "../../../dependencies"
ctrls = ["bank3_64b_32b"]
syn_pre_project_cmd = "make -C ../../../software/firmware"
syn_post_project_cmd = (
"$(TCL_INTERPRETER) " + \
fetchto + "/general-cores/tools/sdb_desc_gen.tcl " + \
syn_tool + " $(PROJECT_FILE);" \
"$(TCL_INTERPRETER) syn_extra_steps.tcl $(PROJECT_FILE)"
)
# Allow the user to override fetchto using:
# hdlmake -p "fetchto='xxx'"
if locals().get('fetchto', None) is None:
fetchto = "../../../dependencies"
files = [
"wrtd_ref_spec150t_adc.ucf",
"buildinfo_pkg.vhd",
]
modules = {
......@@ -36,3 +24,17 @@ modules = {
"../../top/wrtd_ref_spec150t_adc",
],
}
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)"
spec_base_ucf = ['wr', 'ddr3', 'onewire', 'spi']
ctrls = ["bank3_64b_32b"]
# HDLMake 'develop' branch required.
#
# Due to bugs in release v3.0 of hdlmake it is necessary to use the "develop"
# branch of hdlmake, commit db4e1ab.
board = "svec"
target = "xilinx"
action = "synthesis"
......@@ -14,19 +9,14 @@ syn_top = "wrtd_ref_svec_tdc_fd"
syn_project = "wrtd_ref_svec_tdc_fd.xise"
syn_tool = "ise"
fetchto = "../../../dependencies"
syn_pre_project_cmd = "make -C ../../../software/firmware"
syn_post_project_cmd = (
"$(TCL_INTERPRETER) " + \
fetchto + "/general-cores/tools/sdb_desc_gen.tcl " + \
syn_tool + " $(PROJECT_FILE);" \
"$(TCL_INTERPRETER) syn_extra_steps.tcl $(PROJECT_FILE)"
)
# Allow the user to override fetchto using:
# hdlmake -p "fetchto='xxx'"
if locals().get('fetchto', None) is None:
fetchto = "../../../dependencies"
files = [
"wrtd_ref_svec_tdc_fd.ucf",
"buildinfo_pkg.vhd",
]
modules = {
......@@ -34,3 +24,17 @@ modules = {
"../../top/wrtd_ref_svec_tdc_fd",
],
}
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_template_ucf = ['wr', 'led', 'gpio']
ctrls = ["bank4_64b_32b", "bank5_64b_32b"]
......@@ -4,3 +4,4 @@ Makefile
modelsim.ini
transcript*
*.wlf
buildinfo_pkg.vhd
board = "spec"
sim_tool = "modelsim"
top_module = "main"
sim_top = "main"
action = "simulation"
target = "xilinx"
syn_device = "xc6slx150t"
vcom_opt = "-93 -mixedsvvh"
fetchto = "../../../dependencies"
# Allow the user to override fetchto using:
# hdlmake -p "fetchto='xxx'"
if locals().get('fetchto', None) is None:
fetchto = "../../../dependencies"
sim_pre_cmd = "EXTRA2_CFLAGS='-DSIMULATION' make -C ../../../software/firmware"
ctrls = ["bank3_64b_32b"]
include_dirs = [
"../include",
fetchto + "/gn4124-core/hdl/gn4124core/sim/gn4124_bfm",
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",
......@@ -23,7 +24,7 @@ include_dirs = [
files = [
"main.sv",
"dut_env.sv",
"synthesis_descriptor.vhd",
"buildinfo_pkg.vhd",
]
modules = {
......@@ -31,3 +32,11 @@ modules = {
"../../top/wrtd_ref_spec150t_adc",
],
}
ctrls = ["bank3_64b_32b"]
# Do not fail during hdlmake fetch
try:
exec(open(fetchto + "/general-cores/tools/gen_buildinfo.py").read())
except:
pass
......@@ -30,7 +30,6 @@
module dut_env
(
IGN4124PCIMaster i_gn4124,
output[2:0] acq_fsm_state,
output sfp_txp_o, sfp_txn_o,
input sfp_rxp_i, sfp_rxn_i,
input ext_trigger_i
......@@ -87,15 +86,15 @@ module dut_env
.clk_125m_pllref_n_i (~clk_125m_pll),
.clk_125m_gtp_n_i (clk_125m_gtp),
.clk_125m_gtp_p_i (~clk_125m_gtp),
.pll25dac_sync_n_o (),
.pll20dac_sync_n_o (),
.pll25dac_cs_n_o (),
.pll20dac_cs_n_o (),
.plldac_din_o (),
.plldac_sclk_o (),
.led_sfp_red_o (),
.led_sfp_green_o (),
.led_act_o (),
.led_link_o (),
.aux_leds_o (),
.pcbrev_i (4'b0),
.carrier_onewire_b (),
.onewire_b (),
.sfp_txp_o (sfp_txp_o),
.sfp_txn_o (sfp_txn_o),
.sfp_rxp_i (sfp_rxp_i),
......@@ -135,24 +134,24 @@ module dut_env
.gn_tx_error_i (i_gn4124.tx_error),
.gn_vc_rdy_i (i_gn4124.vc_rdy),
.gn_gpio_b (),
.ddr0_a_o (ddr_a),
.ddr0_ba_o (ddr_ba),
.ddr0_cas_n_o (ddr_cas_n),
.ddr0_ck_n_o (ddr_ck_n),
.ddr0_ck_p_o (ddr_ck_p),
.ddr0_cke_o (ddr_cke),
.ddr0_dq_b (ddr_dq),
.ddr0_ldm_o (ddr_dm[0]),
.ddr0_ldqs_n_b (ddr_dqs_n[0]),
.ddr0_ldqs_p_b (ddr_dqs_p[0]),
.ddr0_odt_o (ddr_odt),
.ddr0_ras_n_o (ddr_ras_n),
.ddr0_reset_n_o (ddr_reset_n),
.ddr0_rzq_b (ddr_rzq),
.ddr0_udm_o (ddr_dm[1]),
.ddr0_udqs_n_b (ddr_dqs_n[1]),
.ddr0_udqs_p_b (ddr_dqs_p[1]),
.ddr0_we_n_o (ddr_we_n),
.ddr_a_o (ddr_a),
.ddr_ba_o (ddr_ba),
.ddr_cas_n_o (ddr_cas_n),
.ddr_ck_n_o (ddr_ck_n),
.ddr_ck_p_o (ddr_ck_p),
.ddr_cke_o (ddr_cke),
.ddr_dq_b (ddr_dq),
.ddr_ldm_o (ddr_dm[0]),
.ddr_ldqs_n_b (ddr_dqs_n[0]),
.ddr_ldqs_p_b (ddr_dqs_p[0]),
.ddr_odt_o (ddr_odt),
.ddr_ras_n_o (ddr_ras_n),
.ddr_reset_n_o (ddr_reset_n),
.ddr_rzq_b (ddr_rzq),
.ddr_udm_o (ddr_dm[1]),
.ddr_udqs_n_b (ddr_dqs_n[1]),
.ddr_udqs_p_b (ddr_dqs_p[1]),
.ddr_we_n_o (ddr_we_n),
.fmc0_adc_ext_trigger_p_i (ext_trigger_i),
.fmc0_adc_ext_trigger_n_i (~ext_trigger_i),
.fmc0_adc_dco_p_i (clk_400m_adc),
......@@ -187,8 +186,6 @@ module dut_env
.fmc0_sda_b ()
);
assign acq_fsm_state = DUT.cmp0_fmc_adc_mezzanine.cmp_fmc_adc_100Ms_core.acq_fsm_state;
//---------------------------------------------------------------------------
// DDR memory model
//---------------------------------------------------------------------------
......@@ -291,16 +288,16 @@ module dut_env
initial begin
// Skip WR SoftPLL lock
force DUT.cmp_xwrc_board_spec.cmp_board_common.cmp_xwr_core.
force DUT.inst_spec_template.gen_wr.cmp_xwrc_board_spec.cmp_board_common.cmp_xwr_core.
WRPC.U_SOFTPLL.U_Wrapped_Softpll.out_locked_o = 3'b111;
// Silence Xilinx unisim DSP48A1 warnings about invalid OPMODE
force DUT.cmp_xwrc_board_spec.cmp_board_common.cmp_xwr_core.
force DUT.inst_spec_template.gen_wr.cmp_xwrc_board_spec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D1.OPMODE_dly = 0;
force DUT.cmp_xwrc_board_spec.cmp_board_common.cmp_xwr_core.
force DUT.inst_spec_template.gen_wr.cmp_xwrc_board_spec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D2.OPMODE_dly = 0;
force DUT.cmp_xwrc_board_spec.cmp_board_common.cmp_xwr_core.
force DUT.inst_spec_template.gen_wr.cmp_xwrc_board_spec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D3.OPMODE_dly = 0;
end // initial begin
......
......@@ -28,9 +28,11 @@
`include "wrtd_driver.svh"
`include "fmc_adc_100Ms_csr.v"
`include "fmc_adc_alt_trigout.v"
`define DMA_BASE 'h00c0
`define VIC_BASE 'h0100
`define ADC_CSR_BASE 'h5000
`define ADC_EIC_BASE 'h5500
module main;
......@@ -38,10 +40,9 @@ module main;
IGN4124PCIMaster hostB ();
reg duta_ext_trig, dutb_ext_trig;
wire[2:0] duta_acq_state, dutb_acq_state;
dut_env DUTA (hostA, duta_acq_state, a2b_txp, a2b_txn, a2b_rxp, a2b_rxn, duta_ext_trig);
dut_env DUTB (hostB, dutb_acq_state, a2b_rxp, a2b_rxn, a2b_txp, a2b_txn, dutb_ext_trig);
dut_env DUTA (hostA, a2b_txp, a2b_txn, a2b_rxp, a2b_rxn, duta_ext_trig);
dut_env DUTB (hostB, a2b_rxp, a2b_rxn, a2b_txp, a2b_txn, dutb_ext_trig);
IMockTurtleIRQ MtIrqMonitorA (`MT_ATTACH_IRQ(DUTA.DUT.cmp_mock_turtle));
IMockTurtleIRQ MtIrqMonitorB (`MT_ATTACH_IRQ(DUTB.DUT.cmp_mock_turtle));
......@@ -52,6 +53,8 @@ module main;
const uint64_t MT_BASE = 'h0002_0000;
int sim_end = 0;
initial begin
uint64_t val, expected;
......@@ -72,21 +75,27 @@ module main;
devA.set_rule ( "rule0", "LC-I5", "NET0", 0 );
devA.enable_rule ( "rule0" );
// Configure the EIC for an interrupt on ACQ_END
accA.write(`ADC_EIC_BASE + 'h4, 'h2);
// Configure the VIC
accA.write(`VIC_BASE + 'h8, 'h7f);
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_GAIN, 'h8000);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH2_GAIN, 'h8000);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH3_GAIN, 'h8000);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH4_GAIN, 'h8000);
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);
val = (1'b1 << `FMC_ADC_100MS_CSR_TRIG_EN_EXT_OFFSET);
val |= (1'b1 << `FMC_ADC_100MS_CSR_TRIG_EN_FWD_EXT_OFFSET);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_TRIG_EN, val);
expected = 'h39;
......@@ -95,7 +104,6 @@ module main;
$fatal (1, "ADC status error (got 0x%8x, expected 0x%8x).", val, expected);
$display ("[DUT:A] <%t> ADC configured and armed", $realtime);
wait (duta_acq_state == 1);
end
begin
......@@ -107,29 +115,32 @@ module main;
devB.set_rule ( "rule0", "NET0", "LC-O1", 50000 );
devB.enable_rule ( "rule0" );
// Configure the EIC for an interrupt on ACQ_END
accB.write(`ADC_EIC_BASE + 'h4, 'h2);
// Configure the VIC
accB.write(`VIC_BASE + 'h8, 'h7f);
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_GAIN, 'h8000);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH2_GAIN, 'h8000);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH3_GAIN, 'h8000);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH4_GAIN, 'h8000);
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);
val = (1'b1 << `FMC_ADC_100MS_CSR_TRIG_EN_ALT_TIME_OFFSET);
accB.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_TRIG_EN, val);
expected = 'h39;
accB.read(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_STA, val);
if (val != expected)
$fatal (1, "ADC status error (got 0x%8x, expected 0x%8x).", val, expected);
$display ("[DUT:B] <%t> ADC configured and armed", $realtime);
wait (dutb_acq_state == 1);
end
join
......@@ -147,59 +158,68 @@ module main;
fork
begin
wait (duta_acq_state == 1);
wait (DUTA.DUT.cmp0_fmc_adc_mezzanine.acq_end_irq_o == 1);
$display("[DUT:A] <%t> END ACQ 1", $realtime);
accA.write(`ADC_EIC_BASE + 'hc, 'h2);
accA.write(`VIC_BASE + 'h1c, 'h0);
accA.read(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_TRIG_POS, val);
$display("[DUT:A] <%t> TRIG POSITION %.8x", $realtime, val);
// DMA transfer
accA.write('h2008, val); // dma start addr
accA.write(`DMA_BASE + 'h08, val); // dma start addr
accA.write('h200C, 'h00001000); // host addr
accA.write('h2010, 'h00000000);
accA.write(`DMA_BASE + 'h0C, 'h00001000); // host addr
accA.write(`DMA_BASE + 'h10, 'h00000000);
accA.write('h2014, 'h00000100); // len << 2
accA.write(`DMA_BASE + 'h14, 'h00000100); // len << 2
accA.write('h2018, 'h00000000); // next
accA.write('h201C, 'h00000000);
accA.write(`DMA_BASE + 'h18, 'h00000000); // next
accA.write(`DMA_BASE + 'h1C, 'h00000000);
accA.write('h2020, 'h00000000); // attrib: pcie -> host
accA.write(`DMA_BASE + 'h20, 'h00000000); // attrib: pcie -> host
accA.write('h2000, 'h00000001); // xfer start
accA.write(`DMA_BASE + 'h00, 'h00000001); // xfer start
wait (DUTA.DUT.dma_irq[0] == 1);
wait (DUTA.DUT.inst_spec_template.irqs[2] == 1);
$display("[DUT:A] <%t> END DMA 1", $realtime);
accA.write(`DMA_BASE + 'h04, 'h04); // clear DMA IRQ
accA.write(`VIC_BASE + 'h1c, 'h0);
end
begin
wait (dutb_acq_state == 1);
wait (DUTB.DUT.cmp0_fmc_adc_mezzanine.acq_end_irq_o == 1);
$display("[DUT:B] <%t> END ACQ 1", $realtime);
accB.write(`ADC_EIC_BASE + 'hc, 'h2);
accB.write(`VIC_BASE + 'h1c, 'h0);
accB.read(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_TRIG_POS, val);
$display("[DUT:B] <%t> TRIG POSITION %.8x", $realtime, val);
// DMA transfer
accB.write('h2008, val); // dma start addr
accB.write(`DMA_BASE + 'h08, val); // dma start addr
accB.write('h200C, 'h00001000); // host addr
accB.write('h2010, 'h00000000);
accB.write(`DMA_BASE + 'h0C, 'h00001000); // host addr
accB.write(`DMA_BASE + 'h10, 'h00000000);
accB.write('h2014, 'h00000100); // len << 2
accB.write(`DMA_BASE + 'h14, 'h00000100); // len << 2
accB.write('h2018, 'h00000000); // next
accB.write('h201C, 'h00000000);
accB.write(`DMA_BASE + 'h18, 'h00000000); // next
accB.write(`DMA_BASE + 'h1C, 'h00000000);
accB.write('h2020, 'h00000000); // attrib: pcie -> host
accB.write(`DMA_BASE + 'h20, 'h00000000); // attrib: pcie -> host
accB.write('h2000, 'h00000001); // xfer start
accB.write(`DMA_BASE + 'h00, 'h00000001); // xfer start
wait (DUTB.DUT.dma_irq[0] == 1);
wait (DUTB.DUT.inst_spec_template.irqs[2] == 1);
$display("[DUT:B] <%t> END DMA 1", $realtime);
accB.write(`DMA_BASE + 'h04, 'h04); // clear DMA IRQ
accB.write(`VIC_BASE + 'h1c, 'h0);
end
join
sim_end = 1;
end
......@@ -219,7 +239,7 @@ module main;
$display("-------------------");
$display();
#5000us;
wait (sim_end == 1);
$display();
$display("Simulation PASSED");
......
--------------------------------------------------------------------------------
-- SDB meta information for wrtd_ref_spec150t_adc.xise.
--
-- This file was automatically generated by ../../../dependencies/general-cores/tools/sdb_desc_gen.tcl on:
-- Wednesday, January 30 2019
--
-- ../../../dependencies/general-cores/tools/sdb_desc_gen.tcl is part of OHWR general-cores:
-- https://www.ohwr.org/projects/general-cores/wiki
--
-- For more information on SDB meta information, see also:
-- https://www.ohwr.org/projects/sdb/wiki
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.wishbone_pkg.all;
package synthesis_descriptor is
constant c_sdb_synthesis_info : t_sdb_synthesis := (
syn_module_name => "wrtd_ref_spec150",
syn_commit_id => "eaa378a35717954407166b2e80e34c2*",
syn_tool_name => "ISE ",
syn_tool_version => x"00000147",
syn_date => x"20190130",
syn_username => "Dimitris Lampri");
constant c_sdb_repo_url : t_sdb_repo_url := (
repo_url => "git@ohwr-gitlab.cern.ch:project/wrtd.git ");
end package synthesis_descriptor;
......@@ -3,3 +3,4 @@ Makefile
modelsim.ini
transcript*
*.wlf
buildinfo_pkg.vhd
......@@ -6,7 +6,10 @@ target = "xilinx"
syn_device = "xc6slx150t"
vcom_opt = "-93 -mixedsvvh"
fetchto="../../../dependencies"
# Allow the user to override fetchto using:
# hdlmake -p "fetchto='xxx'"
if locals().get('fetchto', None) is None:
fetchto = "../../../dependencies"
sim_pre_cmd = "EXTRA2_CFLAGS='-DSIMULATION' make -C ../../../software/firmware"
......@@ -14,12 +17,13 @@ include_dirs = [
"../include",
fetchto + "/general-cores/sim/",
fetchto + "/mock-turtle/hdl/testbench/include/",
fetchto + "/vme64x-core/hdl/sim/vme64x_bfm/",
]
files = [
"main.sv",
"dut_env.sv",
"synthesis_descriptor.vhd",
"buildinfo_pkg.vhd",
]
modules = {
......@@ -27,3 +31,13 @@ modules = {
"../../top/wrtd_ref_svec_tdc_fd",
],
}
ctrls = ["bank4_64b_32b", "bank5_64b_32b"]
svec_template_ucf = []
# Do not fail during hdlmake fetch
try:
exec(open(fetchto + "/general-cores/tools/gen_buildinfo.py").read())
except:
pass
......@@ -25,7 +25,8 @@
`timescale 1ns/1ps
`include "vhd_wishbone_master.svh"
`include "vme64x_bfm.svh"
`include "svec_vme_buffers.svh"
module simple_tdc_driver
(
......@@ -211,7 +212,7 @@ endmodule // simple_fdelay_mon
module dut_env
(
IVHDWishboneMaster host,
IVME64X VME,
output clk_sys, rst_sys_n,
sfp_txp_o, sfp_txn_o,
input sfp_rxp_i, sfp_rxn_i
......@@ -247,24 +248,47 @@ module dut_env
// The DUT
//---------------------------------------------------------------------------
`DECLARE_VME_BUFFERS(VME.slave);
bit [4:0] slot_id = 8;
wrtd_ref_svec_tdc_fd #
(
.g_SIMULATION (1),
.g_SIM_BYPASS_VME (1),
.g_WRPC_INITF ("../../../dependencies/wr-cores/bin/wrpc/wrc_phy8_sim.bram")
)
DUT
(
.rst_n_i (1'b1),
.vme_sysreset_n_i (1'b1),
.vme_sysreset_n_i (VME_RST_n),
.vme_as_n_i (VME_AS_n),
.vme_write_n_i (VME_WRITE_n),
.vme_am_i (VME_AM),
.vme_ds_n_i (VME_DS_n),
.vme_gap_i (^slot_id),
.vme_ga_i (~slot_id),
.vme_berr_o (VME_BERR),
.vme_dtack_n_o (VME_DTACK_n),
.vme_retry_n_o (VME_RETRY_n),
.vme_retry_oe_o (VME_RETRY_OE),
.vme_lword_n_b (VME_LWORD_n),
.vme_addr_b (VME_ADDR),
.vme_data_b (VME_DATA),
.vme_irq_o (VME_IRQ_n),
.vme_iack_n_i (VME_IACK_n),
.vme_iackin_n_i (VME_IACKIN_n),
.vme_iackout_n_o (VME_IACKOUT_n),
.vme_dtack_oe_o (VME_DTACK_OE),
.vme_data_dir_o (VME_DATA_DIR),
.vme_data_oe_n_o (VME_DATA_OE_N),
.vme_addr_dir_o (VME_ADDR_DIR),
.vme_addr_oe_n_o (VME_ADDR_OE_N),
.clk_125m_pllref_p_i (clk_125m_pll),
.clk_125m_pllref_n_i (~clk_125m_pll),
.clk_125m_gtp_p_i (clk_125m_gtp),
.clk_125m_gtp_n_i (~clk_125m_gtp),
.clk_20m_vcxo_i (clk_20m_vcxo),
.sim_wb_i (host.out),
.sim_wb_o (host.in),
.carrier_onewire_b (),
.onewire_b (),
.sfp_txp_o (sfp_txp_o),
.sfp_txn_o (sfp_txn_o),
.sfp_rxp_i (sfp_rxp_i),
......@@ -363,7 +387,7 @@ module dut_env
initial begin
// No pulse before: WR (300us) + TDC setup.
automatic time start = 480us;
automatic time start = 850us;
push_pulse(0, start + 10us);
push_pulse(1, start + 30us);
......@@ -376,16 +400,16 @@ module dut_env
initial begin
// Skip WR SoftPLL lock
force DUT.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
force DUT.inst_svec_template.gen_wr.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.U_SOFTPLL.U_Wrapped_Softpll.out_locked_o = 3'b111;
// Silence Xilinx unisim DSP48A1 warnings about invalid OPMODE
force DUT.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
force DUT.inst_svec_template.gen_wr.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D1.OPMODE_dly = 0;
force DUT.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
force DUT.inst_svec_template.gen_wr.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D2.OPMODE_dly = 0;
force DUT.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
force DUT.inst_svec_template.gen_wr.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D3.OPMODE_dly = 0;
end // initial begin
......
......@@ -24,10 +24,13 @@
`timescale 1ns/1ps
`include "vme64x_bfm.svh"
`include "wrtd_driver.svh"
`include "vhd_wishbone_master.svh"
`define TDC_DIRECT_BASE 'h18000
`define VME_OFFSET 'h8000_0000
`define TDC_DIRECT_BASE `VME_OFFSET + 'h0001_8000
`define MT_BASE `VME_OFFSET + 'h0002_0000
module main;
......@@ -35,9 +38,9 @@ module main;
wire sfp_txp, sfp_txn, sfp_rxp, sfp_rxn;
IVHDWishboneMaster host (clk_sys, rst_sys_n);
IVME64X VME(rst_sys_n);
dut_env DUT (host, clk_sys, rst_sys_n, sfp_txp, sfp_txn, sfp_rxp, sfp_rxn);
dut_env DUT (VME, clk_sys, rst_sys_n, sfp_txp, sfp_txn, sfp_rxp, sfp_rxn);
IMockTurtleIRQ MtIrqMonitor (`MT_ATTACH_IRQ(DUT.DUT.cmp_mock_turtle));
......@@ -46,18 +49,35 @@ module main;
WrtdDrv dev;
const uint64_t MT_BASE = 'h0002_0000;
initial begin
CBusAccessor acc;
CBusAccessor_VME64x acc;
initial begin
acc = new(VME.tb);
$timeformat (-6, 3, "us", 10);
#10us;
acc = host.get_accessor();
acc.set_default_xfer_size(4);
dev = new (acc, MT_BASE, MtIrqMonitor, "DUT");
#5us;
/* map func0 to 0x80000000, A32 */
acc.write('h7ff63, 'h80, A32|CR_CSR|D08Byte3);
acc.write('h7ff67, 0, CR_CSR|A32|D08Byte3);
acc.write('h7ff6b, 0, CR_CSR|A32|D08Byte3);
acc.write('h7ff6f, 36, CR_CSR|A32|D08Byte3);
acc.write('h7ff33, 1, CR_CSR|A32|D08Byte3);
acc.write('h7fffb, 'h10, CR_CSR|A32|D08Byte3); /* enable module (BIT_SET = 0x10) */
acc.set_default_modifiers(A32 | D32 | SINGLE);
/* Hack around CBusAccessor to make it work like CBusAccessor_VME64x. This is needed
because WrtdDev expects a CBusAccesor and will not respect the m_default_modifiers value
of CBusAccessor_VME64x when performing reads/writes. */
acc.set_default_xfer_size(A32 | D32 | SINGLE);
acc.write(`TDC_DIRECT_BASE + 'h4, 'h40);
#5us;
dev = new (acc, `MT_BASE, MtIrqMonitor, "DUT");
dev.init();
dev.add_rule ( "rule0" );
......@@ -86,8 +106,19 @@ module main;
// Set dead-time
acc.write(`TDC_DIRECT_BASE + 'h4, 'h40);
#5us;
// Enable channels
acc.write(`TDC_DIRECT_BASE + 'h0, 'h1f);
// Force start_fpga from TDC to make sure that the FSM has been started
force DUT.DUT.U_TDC_Core.cmp_tdc_mezz.cmp_tdc_core.start_from_fpga = 'b1;
#100ns;
release DUT.DUT.U_TDC_Core.cmp_tdc_mezz.cmp_tdc_core.start_from_fpga;
dev.mdisplay("Configuration complete, ready to accept pulses...");
end
initial begin
......
--------------------------------------------------------------------------------
-- SDB meta information for svec_list_tdc_fd.xise.
--
-- This file was automatically generated by ../../../ip_cores/general-cores/tools/sdb_desc_gen.tcl on:
-- Friday, July 20 2018
--
-- ../../../ip_cores/general-cores/tools/sdb_desc_gen.tcl is part of OHWR general-cores:
-- https://www.ohwr.org/projects/general-cores/wiki
--
-- For more information on SDB meta information, see also:
-- https://www.ohwr.org/projects/sdb/wiki
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.wishbone_pkg.all;
package synthesis_descriptor is
constant c_sdb_synthesis_info : t_sdb_synthesis := (
syn_module_name => "svec_list_tdc_fd",
syn_commit_id => "4a68a12eede44d878435d25c3c7eaaf4",
syn_tool_name => "ISE ",
syn_tool_version => x"00000147",
syn_date => x"20180720",
syn_username => "Dimitris Lampri");
constant c_sdb_repo_url : t_sdb_repo_url := (
repo_url => "ssh://git@gitlab.cern.ch:7999/coht/wr-trigger-distribution.git ");
end package synthesis_descriptor;
files = [
"wrtd_ref_spec150t_adc.vhd",
"carrier_csr_wbgen2_pkg.vhd",
"carrier_csr.vhd",
"dma_eic.vhd",
]
fetchto = "../../../dependencies"
......@@ -15,6 +12,7 @@ modules = {
"https://ohwr.org/project/mock-turtle.git",
"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",
],
}
---------------------------------------------------------------------------------------
-- Title : Wishbone slave core for Carrier control and status registers
---------------------------------------------------------------------------------------
-- File : ../carrier_csr.vhd
-- Author : auto-generated by wbgen2 from carrier_csr.wb
-- Created : Wed Jan 30 13:16:24 2019
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE carrier_csr.wb
-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
---------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.carrier_csr_wbgen2_pkg.all;
entity carrier_csr is
port (
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
wb_adr_i : in std_logic_vector(1 downto 0);
wb_dat_i : in std_logic_vector(31 downto 0);
wb_dat_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
wb_err_o : out std_logic;
wb_rty_o : out std_logic;
wb_stall_o : out std_logic;
regs_i : in t_carrier_csr_in_registers;
regs_o : out t_carrier_csr_out_registers
);
end carrier_csr;
architecture syn of carrier_csr is
signal carrier_csr_ctrl_led_green_int : std_logic ;
signal carrier_csr_ctrl_led_red_int : std_logic ;
signal carrier_csr_ctrl_dac_clr_n_int : std_logic ;
signal carrier_csr_rst_fmc0_int : std_logic ;
signal ack_sreg : std_logic_vector(9 downto 0);
signal rddata_reg : std_logic_vector(31 downto 0);
signal wrdata_reg : std_logic_vector(31 downto 0);
signal bwsel_reg : std_logic_vector(3 downto 0);
signal rwaddr_reg : std_logic_vector(1 downto 0);
signal ack_in_progress : std_logic ;
signal wr_int : std_logic ;
signal rd_int : std_logic ;
signal allones : std_logic_vector(31 downto 0);
signal allzeros : std_logic_vector(31 downto 0);
begin
-- Some internal signals assignments
wrdata_reg <= wb_dat_i;
--
-- Main register bank access process.
process (clk_sys_i, rst_n_i)
begin
if (rst_n_i = '0') then
ack_sreg <= "0000000000";
ack_in_progress <= '0';
rddata_reg <= "00000000000000000000000000000000";
carrier_csr_ctrl_led_green_int <= '0';
carrier_csr_ctrl_led_red_int <= '0';
carrier_csr_ctrl_dac_clr_n_int <= '0';
carrier_csr_rst_fmc0_int <= '0';
elsif rising_edge(clk_sys_i) then
-- advance the ACK generator shift register
ack_sreg(8 downto 0) <= ack_sreg(9 downto 1);
ack_sreg(9) <= '0';
if (ack_in_progress = '1') then
if (ack_sreg(0) = '1') then
ack_in_progress <= '0';
else
end if;
else
if ((wb_cyc_i = '1') and (wb_stb_i = '1')) then
case rwaddr_reg(1 downto 0) is
when "00" =>
if (wb_we_i = '1') then
end if;
rddata_reg(3 downto 0) <= regs_i.carrier_pcb_rev_i;
rddata_reg(15 downto 4) <= regs_i.carrier_reserved_i;
rddata_reg(31 downto 16) <= regs_i.carrier_type_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "01" =>
if (wb_we_i = '1') then
end if;
rddata_reg(0) <= regs_i.stat_fmc_pres_i;
rddata_reg(1) <= regs_i.stat_p2l_pll_lck_i;
rddata_reg(2) <= regs_i.stat_sys_pll_lck_i;
rddata_reg(3) <= regs_i.stat_ddr3_cal_done_i;
rddata_reg(4) <= 'X';
rddata_reg(5) <= 'X';
rddata_reg(6) <= 'X';
rddata_reg(7) <= 'X';
rddata_reg(8) <= 'X';
rddata_reg(9) <= 'X';
rddata_reg(10) <= 'X';
rddata_reg(11) <= 'X';
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "10" =>
if (wb_we_i = '1') then
carrier_csr_ctrl_led_green_int <= wrdata_reg(0);
carrier_csr_ctrl_led_red_int <= wrdata_reg(1);
carrier_csr_ctrl_dac_clr_n_int <= wrdata_reg(2);
end if;
rddata_reg(0) <= carrier_csr_ctrl_led_green_int;
rddata_reg(1) <= carrier_csr_ctrl_led_red_int;
rddata_reg(2) <= carrier_csr_ctrl_dac_clr_n_int;
rddata_reg(3) <= 'X';
rddata_reg(4) <= 'X';
rddata_reg(5) <= 'X';
rddata_reg(6) <= 'X';
rddata_reg(7) <= 'X';
rddata_reg(8) <= 'X';
rddata_reg(9) <= 'X';
rddata_reg(10) <= 'X';
rddata_reg(11) <= 'X';
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "11" =>
if (wb_we_i = '1') then
carrier_csr_rst_fmc0_int <= wrdata_reg(0);
end if;
rddata_reg(0) <= carrier_csr_rst_fmc0_int;
rddata_reg(1) <= 'X';
rddata_reg(2) <= 'X';
rddata_reg(3) <= 'X';
rddata_reg(4) <= 'X';
rddata_reg(5) <= 'X';
rddata_reg(6) <= 'X';
rddata_reg(7) <= 'X';
rddata_reg(8) <= 'X';
rddata_reg(9) <= 'X';
rddata_reg(10) <= 'X';
rddata_reg(11) <= 'X';
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when others =>
-- prevent the slave from hanging the bus on invalid address
ack_in_progress <= '1';
ack_sreg(0) <= '1';
end case;
end if;
end if;
end if;
end process;
-- Drive the data output bus
wb_dat_o <= rddata_reg;
-- PCB revision
-- Reserved register
-- Carrier type
-- FMC presence
-- GN4142 core P2L PLL status
-- System clock PLL status
-- DDR3 calibration status
-- Green LED
regs_o.ctrl_led_green_o <= carrier_csr_ctrl_led_green_int;
-- Red LED
regs_o.ctrl_led_red_o <= carrier_csr_ctrl_led_red_int;
-- DAC clear
regs_o.ctrl_dac_clr_n_o <= carrier_csr_ctrl_dac_clr_n_int;
-- State of the reset line
regs_o.rst_fmc0_o <= carrier_csr_rst_fmc0_int;
rwaddr_reg <= wb_adr_i;
wb_stall_o <= (not ack_sreg(0)) and (wb_stb_i and wb_cyc_i);
wb_err_o <= '0';
wb_rty_o <= '0';
-- ACK signal generation. Just pass the LSB of ACK counter.
wb_ack_o <= ack_sreg(0);
end syn;
---------------------------------------------------------------------------------------
-- Title : Wishbone slave core for Carrier control and status registers
---------------------------------------------------------------------------------------
-- File : ../carrier_csr_wbgen2_pkg.vhd
-- Author : auto-generated by wbgen2 from carrier_csr.wb
-- Created : Wed Jan 30 13:16:24 2019
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE carrier_csr.wb
-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
---------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package carrier_csr_wbgen2_pkg is
-- Input registers (user design -> WB slave)
type t_carrier_csr_in_registers is record
carrier_pcb_rev_i : std_logic_vector(3 downto 0);
carrier_reserved_i : std_logic_vector(11 downto 0);
carrier_type_i : std_logic_vector(15 downto 0);
stat_fmc_pres_i : std_logic;
stat_p2l_pll_lck_i : std_logic;
stat_sys_pll_lck_i : std_logic;
stat_ddr3_cal_done_i : std_logic;
end record;
constant c_carrier_csr_in_registers_init_value: t_carrier_csr_in_registers := (
carrier_pcb_rev_i => (others => '0'),
carrier_reserved_i => (others => '0'),
carrier_type_i => (others => '0'),
stat_fmc_pres_i => '0',
stat_p2l_pll_lck_i => '0',
stat_sys_pll_lck_i => '0',
stat_ddr3_cal_done_i => '0'
);
-- Output registers (WB slave -> user design)
type t_carrier_csr_out_registers is record
ctrl_led_green_o : std_logic;
ctrl_led_red_o : std_logic;
ctrl_dac_clr_n_o : std_logic;
rst_fmc0_o : std_logic;
end record;
constant c_carrier_csr_out_registers_init_value: t_carrier_csr_out_registers := (
ctrl_led_green_o => '0',
ctrl_led_red_o => '0',
ctrl_dac_clr_n_o => '0',
rst_fmc0_o => '0'
);
function "or" (left, right: t_carrier_csr_in_registers) return t_carrier_csr_in_registers;
function f_x_to_zero (x:std_logic) return std_logic;
function f_x_to_zero (x:std_logic_vector) return std_logic_vector;
end package;
package body carrier_csr_wbgen2_pkg is
function f_x_to_zero (x:std_logic) return std_logic is
begin
if x = '1' then
return '1';
else
return '0';
end if;
end function;
function f_x_to_zero (x:std_logic_vector) return std_logic_vector is
variable tmp: std_logic_vector(x'length-1 downto 0);
begin
for i in 0 to x'length-1 loop
if(x(i) = '1') then
tmp(i):= '1';
else
tmp(i):= '0';
end if;
end loop;
return tmp;
end function;
function "or" (left, right: t_carrier_csr_in_registers) return t_carrier_csr_in_registers is
variable tmp: t_carrier_csr_in_registers;
begin
tmp.carrier_pcb_rev_i := f_x_to_zero(left.carrier_pcb_rev_i) or f_x_to_zero(right.carrier_pcb_rev_i);
tmp.carrier_reserved_i := f_x_to_zero(left.carrier_reserved_i) or f_x_to_zero(right.carrier_reserved_i);
tmp.carrier_type_i := f_x_to_zero(left.carrier_type_i) or f_x_to_zero(right.carrier_type_i);
tmp.stat_fmc_pres_i := f_x_to_zero(left.stat_fmc_pres_i) or f_x_to_zero(right.stat_fmc_pres_i);
tmp.stat_p2l_pll_lck_i := f_x_to_zero(left.stat_p2l_pll_lck_i) or f_x_to_zero(right.stat_p2l_pll_lck_i);
tmp.stat_sys_pll_lck_i := f_x_to_zero(left.stat_sys_pll_lck_i) or f_x_to_zero(right.stat_sys_pll_lck_i);
tmp.stat_ddr3_cal_done_i := f_x_to_zero(left.stat_ddr3_cal_done_i) or f_x_to_zero(right.stat_ddr3_cal_done_i);
return tmp;
end function;
end package body;
This diff is collapsed.
WBGEN2 = $(shell which wbgen2)
RTL = ..
all: carrier_csr dma_eic
carrier_csr:
$(WBGEN2) -l vhdl -H record -V $(RTL)/$@.vhd -p $(RTL)/$@_wbgen2_pkg.vhd $@.wb
dma_eic:
$(WBGEN2) -l vhdl -V $(RTL)/$@.vhd $@.wb
peripheral {
name = "Carrier control and status registers";
description = "Wishbone slave for control and status registers related to the FMC carrier";
hdl_entity = "carrier_csr";
prefix = "carrier_csr";
reg {
name = "Carrier type and PCB version";
prefix = "carrier";
field {
name = "PCB revision";
description = "Binary coded PCB layout revision.";
prefix = "pcb_rev";
type = SLV;
size = 4;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "Reserved register";
description = "Ignore on read, write with 0's.";
prefix = "reserved";
type = SLV;
size = 12;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "Carrier type";
description = "Carrier type identifier\n1 = SPEC\n2 = SVEC\n3 = VFC\n4 = SPEXI";
prefix = "type";
type = SLV;
size = 16;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Status";
prefix = "stat";
field {
name = "FMC presence";
description = "0: FMC slot is populated\n1: FMC slot is not populated.";
prefix = "fmc_pres";
type = BIT;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "GN4142 core P2L PLL status";
description = "0: not locked\n1: locked.";
prefix = "p2l_pll_lck";
type = BIT;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "System clock PLL status";
description = "0: not locked\n1: locked.";
prefix = "sys_pll_lck";
type = BIT;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "DDR3 calibration status";
description = "0: not done\n1: done.";
prefix = "ddr3_cal_done";
type = BIT;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Control";
prefix = "ctrl";
field {
name = "Green LED";
description = "Manual control of the front panel green LED (unused in the fmc-adc application)";
prefix = "led_green";
type = BIT;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Red LED";
description = "Manual control of the front panel red LED (unused in the fmc-adc application)";
prefix = "led_red";
type = BIT;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "DAC clear";
description = "Active low clear signal for VCXO DACs";
prefix = "dac_clr_n";
type = BIT;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "Reset Register";
prefix = "rst";
description = "Controls software reset of the mezzanine including the ddr interface and the time-tagging core.";
field {
name = "State of the reset line";
description = "write 0: Normal FMC operation\
write 1: FMC is held in reset";
type = BIT;
size = 1;
prefix = "fmc0";
access_bus = WRITE;
access_dev = READ;
};
};
};
peripheral {
name = "GN4124 DMA enhanced interrupt controller";
description = "Enhanced interrrupt controller for GN4124 DMA.";
hdl_entity = "dma_eic";
prefix = "dma_eic";
irq {
name = "DMA done interrupt";
description = "DMA done interrupt line (rising edge sensitive).";
prefix = "dma_done";
trigger = EDGE_RISING;
};
irq {
name = "DMA error interrupt";
description = "DMA error interrupt line (rising edge sensitive).";
prefix = "dma_error";
trigger = EDGE_RISING;
};
};
......@@ -6,6 +6,7 @@ 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",
......@@ -13,5 +14,6 @@ modules = {
"https://ohwr.org/project/mock-turtle.git",
"https://ohwr.org/project/fmc-tdc-1ns-5cha-gw.git",
"https://ohwr.org/project/fmc-delay-1ns-8cha.git",
"https://ohwr.org/project/ddr3-sp6-core.git",
],
}
......@@ -10,7 +10,7 @@ REPO_PARENT ?= $(CURDIR)/..
# on Mock Turtle.
WRTD_DEP_TRTL ?= $(CURDIR)/../dependencies/mock-turtle
DIRS = $(WRTD_DEP_TRTL)/software lib firmware
DIRS = $(WRTD_DEP_TRTL)/software drivers lib firmware
all clean: $(DIRS)
......
......@@ -15,4 +15,4 @@ obj-m := wrtd-ref-spec150t-adc.o
obj-m += wrtd-ref-svec-tdc-fd.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
\ No newline at end of file
wrtd-ref-svec-tdc-fd-objs := wrtd-ref-svec-tdc-fd-core.o
......@@ -10,7 +10,7 @@ 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)/hdl/rtl/wb_gen
EXTRA_CFLAGS += -I$(WRTD_DEP_FMC_ADC)/software/include/hw
all:
......
......@@ -30,7 +30,7 @@ static inline uint32_t adcin_readl(const struct wrtd_adcin_dev *dev, uint32_t re
static inline int adcin_wr_link_up(struct wrtd_adcin_dev *adcin)
{
return adcin_readl(adcin, ALT_TRIGOUT_STATUS) & ALT_TRIGOUT_WR_LINK;
return adcin_readl(adcin, AUX_TRIGOUT_STATUS) & AUX_TRIGOUT_WR_LINK;
}
static inline int adcin_wr_time_locked(struct wrtd_adcin_dev *adcin)
......@@ -45,7 +45,7 @@ static void adcin_wr_enable_lock(struct wrtd_adcin_dev *dev, int enable)
static inline int adcin_wr_time_ready(struct wrtd_adcin_dev *adcin)
{
return adcin_readl(adcin, ALT_TRIGOUT_STATUS) & ALT_TRIGOUT_WR_VALID;
return adcin_readl(adcin, AUX_TRIGOUT_STATUS) & AUX_TRIGOUT_WR_VALID;
}
static inline int adcin_wr_sync_timeout(void)
......@@ -62,28 +62,28 @@ static inline int adcin_wr_sync_timeout(void)
*/
static void adcin_input(struct wrtd_adcin_dev *adcin)
{
uint32_t status = adcin_readl(adcin, ALT_TRIGOUT_STATUS);
uint32_t status = adcin_readl(adcin, AUX_TRIGOUT_STATUS);
uint32_t mask;
struct wrtd_event ev;
int i;
/* Poll the FIFO and read the timestamp */
if(!(status & ALT_TRIGOUT_TS_PRESENT))
if(!(status & AUX_TRIGOUT_TS_PRESENT))
return;
mask = adcin_readl(adcin, ALT_TRIGOUT_TS_MASK_SEC + 0);
ev.ts.seconds = adcin_readl(adcin, ALT_TRIGOUT_TS_MASK_SEC + 4);
ev.ts.ns = adcin_readl(adcin, ALT_TRIGOUT_TS_CYCLES) * 8;
mask = adcin_readl(adcin, AUX_TRIGOUT_TS_MASK_SEC + 0);
ev.ts.seconds = adcin_readl(adcin, AUX_TRIGOUT_TS_MASK_SEC + 4);
ev.ts.ns = adcin_readl(adcin, AUX_TRIGOUT_TS_CYCLES) * 8;
ev.ts.frac = 0;
for (i = 0; i < ADCIN_NUM_CHANNELS; i++) {
/* The last channel is the ext trigger with a different mask */
if ( i == ADCIN_NUM_CHANNELS - 1 ) {
if (!(mask & (ALT_TRIGOUT_EXT_MASK >> 32)))
if (!(mask & (AUX_TRIGOUT_EXT_MASK >> 32)))
continue;
}
else if (!(mask & ((ALT_TRIGOUT_CH1_MASK >> 32) << i)))
else if (!(mask & ((AUX_TRIGOUT_CH1_MASK >> 32) << i)))
continue;
memset(ev.id, 0, WRTD_ID_LEN);
......
......@@ -14,7 +14,7 @@
#include "mockturtle-rt.h"
#include <mockturtle-framework.h>
#include "wrtd-common.h"
#include "fmc_adc_alt_trigin.h"
#include "fmc_adc_aux_trigin.h"
#define OUT_QUEUE_MAXTIME 10
#define OUT_QUEUE_PREFIX adcout_
......@@ -91,7 +91,7 @@ static void adcout_drop_trigger(struct wrtd_adcout_dev *dev,
adcout_out_queue_pop(q);
/* Disarm the ADC output */
adcout_writel(dev, 0, ALT_TRIGIN_CTRL);
adcout_writel(dev, 0, AUX_TRIGIN_CTRL);
wrtd_log(WRTD_LOG_MSG_EV_DISCARDED, reason, NULL, ev, now);
}
......@@ -105,7 +105,7 @@ static void adcout_output (struct wrtd_adcout_dev *dev)
{
struct adcout_out_queue *q = &dev->queue;
struct wrtd_event *ev = adcout_out_queue_front(q);
uint32_t ctrl = adcout_readl(dev, ALT_TRIGIN_CTRL);
uint32_t ctrl = adcout_readl(dev, AUX_TRIGIN_CTRL);
struct wrtd_tstamp ts;
/* Check if the output has triggered */
......@@ -117,7 +117,7 @@ static void adcout_output (struct wrtd_adcout_dev *dev)
return;
}
#endif
if (ctrl & ALT_TRIGIN_CTRL_ENABLE) {
if (ctrl & AUX_TRIGIN_CTRL_ENABLE) {
/* Armed but still waiting for trigger */
struct wrtd_tstamp now;
ts_now(&now);
......@@ -147,10 +147,10 @@ static void adcout_output (struct wrtd_adcout_dev *dev)
}
/* Program the output start time */
adcout_writel(dev, 0, ALT_TRIGIN_SECONDS + 0);
adcout_writel(dev, ev->ts.seconds, ALT_TRIGIN_SECONDS + 4);
adcout_writel(dev, ev->ts.ns / 8, ALT_TRIGIN_CYCLES);
adcout_writel(dev, ALT_TRIGIN_CTRL_ENABLE, ALT_TRIGIN_CTRL);
adcout_writel(dev, 0, AUX_TRIGIN_SECONDS + 0);
adcout_writel(dev, ev->ts.seconds, AUX_TRIGIN_SECONDS + 4);
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);
......
......@@ -9,7 +9,7 @@
#include "mockturtle-rt.h"
#include <mockturtle-framework.h>
#include "wrtd-common.h"
#include "fmc_adc_alt_trigout.h"
#include "fmc_adc_aux_trigout.h"
#define NBR_CPUS 1
#define CPU_IDX 0
......
......@@ -20,17 +20,112 @@
* @{
*/
/**
* Retrieve the number of detected WRTD Nodes.
*
* @param[out] count number of detected WRTD Nodes
* @return #wrtd_status
*/
wrtd_status wrtd_get_node_count(uint32_t *count)
{
int i;
uint32_t dev_count = 0;
struct trtl_dev *trtl;
const struct trtl_config_rom *cfgrom;
char **dev_list = trtl_list();
if (!dev_list)
return WRTD_ERROR_INTERNAL;
for (i = 0; dev_list[i]; i++) {
trtl = trtl_open(dev_list[i]);
if (trtl == NULL) {
trtl_list_free(dev_list);
return WRTD_ERROR_RESOURCE_UNKNOWN;
}
cfgrom = trtl_config_get(trtl);
/* WRTD = 0x57525444 */
if (cfgrom->app_id == 0x57525444)
dev_count++;
trtl_close(trtl);
}
trtl_list_free(dev_list);
*count = dev_count;
return WRTD_SUCCESS;
}
/**
* Retrieve the ID of a WRTD Node.
*
* Before calling this function, you should probably call #wrtd_get_node_count to know the
* number of Nodes.
*
* @param[in] index The index of the Node ("1" for the first Node, etc.)
* @param[out] node_id The retrieved ID of the Node
* @return #wrtd_status
*/
wrtd_status wrtd_get_node_id(uint32_t index, uint32_t *node_id)
{
int i;
uint32_t dev_count = 0;
struct trtl_dev *trtl;
const struct trtl_config_rom *cfgrom;
char **dev_list = trtl_list();
if (!dev_list)
return WRTD_ERROR_INTERNAL;
*node_id = 0;
for (i = 0; dev_list[i]; i++) {
trtl = trtl_open(dev_list[i]);
if (trtl == NULL) {
trtl_list_free(dev_list);
return WRTD_ERROR_RESOURCE_UNKNOWN;
}
cfgrom = trtl_config_get(trtl);
/* WRTD = 0x57525444 */
if (cfgrom->app_id == 0x57525444)
dev_count++;
if (dev_count == index) {
char *eptr;
/* expecting string in the form of "trtl-xxxx, where
xxxx is a hex integer */
*node_id = strtoul(dev_list[i]+5, &eptr, 16);
if (*eptr != 0) {
trtl_list_free(dev_list);
trtl_close(trtl);
return WRTD_ERROR_INTERNAL;
}
}
trtl_close(trtl);
}
trtl_list_free(dev_list);
if (*node_id == 0)
return WRTD_ERROR_RESOURCE_UNKNOWN;
return WRTD_SUCCESS;
}
/**
* Initialize the WRTD Node and obtain the WRTD device token.
*
* @param[in] resource_name Underlying MockTurtle device ID in
* the form of **MTxxx** or **trtl-xxxx**.
* @param[in] node_id WRTD Node ID
* @param[in] reset Reserved for future use.
* @param[in] options_str Reserved for future use.
* @param[out] wrtd Pointer to WRTD device token.
* @return #wrtd_status
*/
wrtd_status wrtd_init(const char *resource_name,
wrtd_status wrtd_init(uint32_t node_id,
bool reset,
const char *options_str,
wrtd_dev **wrtd)
......@@ -41,35 +136,12 @@ wrtd_status wrtd_init(const char *resource_name,
struct wrtd_config_msg msg;
wrtd_status status;
static int initialized;
/* In case of error... */
*wrtd = NULL;
/* Initialize (only once).*/
if (!initialized) {
initialized = 1;
trtl_init();
}
trtl = trtl_open_by_id(node_id);
/* Resource is MTxxx where xxx is the mock-turtle device id. */
if (resource_name[0] == 'M' && resource_name[1] == 'T') {
unsigned long dev_id;
char *eptr;
dev_id = strtoul(resource_name + 2, &eptr, 0);
if (*eptr != 0) {
/* Invalid characters. */
return WRTD_ERROR_RESOURCE_UNKNOWN;
}
trtl = trtl_open_by_id(dev_id);
}
else if (strncmp(resource_name, "trtl-", 5) == 0) {
trtl = trtl_open(resource_name);
}
else {
return WRTD_ERROR_RESOURCE_UNKNOWN;
}
if (trtl == NULL)
if (trtl == NULL)
return WRTD_ERROR_RESOURCE_UNKNOWN;
wrtd_dev *res;
......@@ -666,7 +738,7 @@ wrtd_status wrtd_get_attr_int32(wrtd_dev *wrtd,
return wrtd_attr_get_stat_rule_missed_holdoff
(wrtd, rep_cap_id, value);
case WRTD_ATTR_STAT_RULE_MISSED_NOSYNC:
return wrtd_attr_get_stat_rule_missed_holdoff
return wrtd_attr_get_stat_rule_missed_nosync
(wrtd, rep_cap_id, value);
case WRTD_ATTR_STAT_RULE_MISSED_OVERFLOW:
return wrtd_attr_get_stat_rule_missed_overflow
......
......@@ -242,7 +242,11 @@ typedef enum wrtd_attr {
/* Initialisation */
wrtd_status wrtd_init(const char *resource_name,
wrtd_status wrtd_get_node_count(uint32_t *count);
wrtd_status wrtd_get_node_id(uint32_t index, uint32_t *node_id);
wrtd_status wrtd_init(uint32_t node_id,
bool reset,
const char *options_str,
wrtd_dev **wrtd);
......
This diff is collapsed.
wrtd-boot
wrtd-in-config
wrtd-out-config
wrtd-logging
wrtd-config
"""
@file wrtd-logging.py
@copyright: Copyright (c) 2019 CERN (home.cern)
SPDX-License-Identifier: LGPL-3.0-or-later
"""
import sys
import signal
import argparse
from PyWrtd import *
def signal_handler(sig, frame):
sys.exit(0)
def print_logging(wrtd, count):
n_read = 0
while ((count == 0) or (n_read < count)):
log_entry = wrtd.get_next_event_log_entry()
if len(log_entry):
print(log_entry)
n_read += 1
def main():
signal.signal(signal.SIGINT, signal_handler)
parser = argparse.ArgumentParser(description='WRTD node log monitoring tool')
parser.add_argument('-D', '--dev-id', dest='dev', required=True, type=int,
help='MockTurtle device ID (integer) to open')
parser.add_argument('-c', '--count', dest='count', type=int, default=0,
help='Number of entries to read (0 = infinite)')
parser.add_argument('-e', '--enable', action='store_true',
help='Enable event logging on the Node if not already enabled.')
args = parser.parse_args()
dev = 'MT' + str(args.dev)
wrtd = PyWrtd(dev)
if (args.enable):
wrtd.set_attr_bool(PyWrtd.WRTD_GLOBAL_REP_CAP_ID,
PyWrtd.WRTD_ATTR_EVENT_LOG_ENABLED,
True)
print_logging(wrtd, args.count)
if __name__ == "__main__":
main()
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