forked from M-Labs/artiq
Remove UP support.
The only advantage of UP is to support the Papilio Pro, but that port is also very limited in other ways and the Pipistrello provides a more reasonable platform that also supports AMP. On the other hand, RPCs on UP are difficult to implement with the session.c protocol system (without an operating system or coroutines), along with many other minor difficulties and maintainance issues. Planned features such as watchdogs in the core device are also difficult on UP.
This commit is contained in:
parent
1ca49787b4
commit
938e1c2842
@ -1,9 +1,11 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
ARTIQ_PREFIX=$(python3 -c "import artiq; print(artiq.__path__[0])")
|
ARTIQ_PREFIX=$(python3 -c "import artiq; print(artiq.__path__[0])")
|
||||||
|
|
||||||
# Default is ppro
|
# Default is kc705
|
||||||
BOARD=ppro
|
BOARD=kc705
|
||||||
|
|
||||||
while getopts "bBrht:d:" opt
|
while getopts "bBrht:d:" opt
|
||||||
do
|
do
|
||||||
@ -21,15 +23,12 @@ do
|
|||||||
if [ "$OPTARG" == "kc705" ]
|
if [ "$OPTARG" == "kc705" ]
|
||||||
then
|
then
|
||||||
BOARD=kc705
|
BOARD=kc705
|
||||||
elif [ "$OPTARG" == "ppro" ]
|
|
||||||
then
|
|
||||||
BOARD=ppro
|
|
||||||
elif [ "$OPTARG" == "pipistrello" ]
|
elif [ "$OPTARG" == "pipistrello" ]
|
||||||
then
|
then
|
||||||
BOARD=pipistrello
|
BOARD=pipistrello
|
||||||
else
|
else
|
||||||
echo "Supported targets (-t option) are:"
|
echo "Supported targets (-t option) are:"
|
||||||
echo "kc705, ppro, or pipistrello"
|
echo "kc705 or pipistrello"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
@ -47,12 +46,12 @@ do
|
|||||||
echo ""
|
echo ""
|
||||||
echo "To flash everything, do not use any of the -b|-B|-r option."
|
echo "To flash everything, do not use any of the -b|-B|-r option."
|
||||||
echo ""
|
echo ""
|
||||||
echo "usage: $0 [-b] [-B] [-r] [-h] [-t kc705|ppro|pipistrello] [-d path]"
|
echo "usage: $0 [-b] [-B] [-r] [-h] [-t kc705|pipistrello] [-d path]"
|
||||||
echo "-b Flash bitstream"
|
echo "-b Flash bitstream"
|
||||||
echo "-B Flash BIOS"
|
echo "-B Flash BIOS"
|
||||||
echo "-r Flash ARTIQ runtime"
|
echo "-r Flash ARTIQ runtime"
|
||||||
echo "-h Show this help message"
|
echo "-h Show this help message"
|
||||||
echo "-t Target (kc705, pipistrello, ppro, default is: ppro)"
|
echo "-t Target (kc705, pipistrello, default is: kc705)"
|
||||||
echo "-d Directory containing the binaries to be flashed"
|
echo "-d Directory containing the binaries to be flashed"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
@ -88,27 +87,7 @@ then
|
|||||||
BIN_PREFIX=$BIN_PATH
|
BIN_PREFIX=$BIN_PATH
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$BOARD" == "ppro" ]
|
if [ "$BOARD" == "kc705" ]
|
||||||
then
|
|
||||||
UDEV_RULES=99-ppro.rules
|
|
||||||
BITSTREAM=artiq_ppro-up-papilio_pro.bin
|
|
||||||
CABLE=papilio
|
|
||||||
PROXY=bscan_spi_lx9_papilio.bit
|
|
||||||
BIOS_ADDR=0x60000
|
|
||||||
RUNTIME_ADDR=0x70000
|
|
||||||
if [ -z "$BIN_PREFIX" ]; then BIN_PREFIX=$ARTIQ_PREFIX/binaries/ppro; fi
|
|
||||||
search_for_proxy $PROXY
|
|
||||||
elif [ "$BOARD" == "pipistrello" ]
|
|
||||||
then
|
|
||||||
UDEV_RULES=99-ppro.rules
|
|
||||||
BITSTREAM=artiq_pipistrello-amp-pipistrello.bin
|
|
||||||
CABLE=papilio
|
|
||||||
PROXY=bscan_spi_lx9_csg324.bit
|
|
||||||
BIOS_ADDR=0x170000
|
|
||||||
RUNTIME_ADDR=0x180000
|
|
||||||
if [ -z "$BIN_PREFIX" ]; then BIN_PREFIX=$ARTIQ_PREFIX/binaries/pipistrello; fi
|
|
||||||
search_for_proxy $PROXY
|
|
||||||
elif [ "$BOARD" == "kc705" ]
|
|
||||||
then
|
then
|
||||||
UDEV_RULES=99-kc705.rules
|
UDEV_RULES=99-kc705.rules
|
||||||
BITSTREAM=artiq_kc705-artiqsocbasic-kc705.bit
|
BITSTREAM=artiq_kc705-artiqsocbasic-kc705.bit
|
||||||
@ -118,6 +97,16 @@ then
|
|||||||
RUNTIME_ADDR=0xb00000
|
RUNTIME_ADDR=0xb00000
|
||||||
if [ -z "$BIN_PREFIX" ]; then BIN_PREFIX=$ARTIQ_PREFIX/binaries/kc705; fi
|
if [ -z "$BIN_PREFIX" ]; then BIN_PREFIX=$ARTIQ_PREFIX/binaries/kc705; fi
|
||||||
search_for_proxy $PROXY
|
search_for_proxy $PROXY
|
||||||
|
elif [ "$BOARD" == "pipistrello" ]
|
||||||
|
then
|
||||||
|
UDEV_RULES=99-papilio.rules
|
||||||
|
BITSTREAM=artiq_pipistrello-amp-pipistrello.bin
|
||||||
|
CABLE=papilio
|
||||||
|
PROXY=bscan_spi_lx9_csg324.bit
|
||||||
|
BIOS_ADDR=0x170000
|
||||||
|
RUNTIME_ADDR=0x180000
|
||||||
|
if [ -z "$BIN_PREFIX" ]; then BIN_PREFIX=$ARTIQ_PREFIX/binaries/pipistrello; fi
|
||||||
|
search_for_proxy $PROXY
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if neither of -b|-B|-r have been used
|
# Check if neither of -b|-B|-r have been used
|
||||||
|
@ -6,12 +6,12 @@ KC705
|
|||||||
|
|
||||||
The main target board for the ARTIQ core device is the KC705 development board from Xilinx.
|
The main target board for the ARTIQ core device is the KC705 development board from Xilinx.
|
||||||
|
|
||||||
Papilio Pro
|
Pipistrello
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
The low-cost Papilio Pro FPGA board can be used with some limitations.
|
The low-cost Pipistrello FPGA board can be used as a lower-cost but slower alternative.
|
||||||
|
|
||||||
When plugged to an adapter, the NIST QC1 hardware can be used with a limited number of TTL channels. The TTL lines are mapped to RTIO channels as follows:
|
When plugged to an adapter, the NIST QC1 hardware can be used. The TTL lines are mapped to RTIO channels as follows:
|
||||||
|
|
||||||
+--------------+----------+-----------------+
|
+--------------+----------+-----------------+
|
||||||
| RTIO channel | TTL line | Capability |
|
| RTIO channel | TTL line | Capability |
|
||||||
@ -20,19 +20,13 @@ When plugged to an adapter, the NIST QC1 hardware can be used with a limited num
|
|||||||
+--------------+----------+-----------------+
|
+--------------+----------+-----------------+
|
||||||
| 1 | PMT1 | Input only |
|
| 1 | PMT1 | Input only |
|
||||||
+--------------+----------+-----------------+
|
+--------------+----------+-----------------+
|
||||||
| 2 | TTL0 | Output only |
|
| 2-18 | TTL0-16 | Output only |
|
||||||
+--------------+----------+-----------------+
|
+--------------+----------+-----------------+
|
||||||
| 3 | TTL1 | Output only |
|
| 19-21 | LEDs | Output only |
|
||||||
+--------------+----------+-----------------+
|
+--------------+----------+-----------------+
|
||||||
| 4 | TTL2 | Output only |
|
| 22 | TTL2 | Output only |
|
||||||
+--------------+----------+-----------------+
|
|
||||||
| 5 | TTL3 | Output only |
|
|
||||||
+--------------+----------+-----------------+
|
|
||||||
| 6 | TTL4 | Output only |
|
|
||||||
+--------------+----------+-----------------+
|
|
||||||
| 7 | FUD | DDS driver only |
|
|
||||||
+--------------+----------+-----------------+
|
+--------------+----------+-----------------+
|
||||||
|
|
||||||
The input only limitation on channels 0 and 1 comes from the QC-DAQ adapter. When the adapter is not used (and physically unplugged from the Papilio Pro board), the corresponding pins on the Papilio Pro can be used as outputs. Do not configure these channels as outputs when the adapter is plugged, as this would cause electrical contention.
|
The input only limitation on channels 0 and 1 comes from the QC-DAQ adapter. When the adapter is not used (and physically unplugged from the Pipistrello board), the corresponding pins on the Pipistrello can be used as outputs. Do not configure these channels as outputs when the adapter is plugged, as this would cause electrical contention.
|
||||||
|
|
||||||
The board can accept an external RTIO clock connected to XTRIG.
|
The board can accept an external RTIO clock connected to PMT2.
|
||||||
|
@ -100,7 +100,7 @@ Create a new file ``rtio.py`` containing the following: ::
|
|||||||
delay(2*us)
|
delay(2*us)
|
||||||
|
|
||||||
|
|
||||||
Connect an oscilloscope or logic analyzer to TTL0 (pin C11 on the Papilio Pro) and run ``artiq_run.py led.py``. Notice that the generated signal's period is precisely 4 microseconds, and that it has a duty cycle of precisely 50%. This is not what you would expect if the delay and the pulse were implemented with CPU-controlled GPIO: overhead from the loop management, function calls, etc. would increase the signal's period, and asymmetry in the overhead would cause duty cycle distortion.
|
Connect an oscilloscope or logic analyzer to TTL0 (pin C11 on the Pipistrello) and run ``artiq_run.py led.py``. Notice that the generated signal's period is precisely 4 microseconds, and that it has a duty cycle of precisely 50%. This is not what you would expect if the delay and the pulse were implemented with CPU-controlled GPIO: overhead from the loop management, function calls, etc. would increase the signal's period, and asymmetry in the overhead would cause duty cycle distortion.
|
||||||
|
|
||||||
Instead, inside the core device, output timing is generated by the gateware and the CPU only programs switching commands with certain timestamps that the CPU computes. This guarantees precise timing as long as the CPU can keep generating timestamps that are increasing fast enough. In case it fails to do that (and attempts to program an event with a timestamp in the past), the :class:`artiq.coredevice.runtime_exceptions.RTIOUnderflow` exception is raised. The kernel causing it may catch it (using a regular ``try... except...`` construct), or it will be propagated to the host.
|
Instead, inside the core device, output timing is generated by the gateware and the CPU only programs switching commands with certain timestamps that the CPU computes. This guarantees precise timing as long as the CPU can keep generating timestamps that are increasing fast enough. In case it fails to do that (and attempts to program an event with a timestamp in the past), the :class:`artiq.coredevice.runtime_exceptions.RTIOUnderflow` exception is raised. The kernel causing it may catch it (using a regular ``try... except...`` construct), or it will be propagated to the host.
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ Try the following code and observe the generated pulses on a 2-channel oscillosc
|
|||||||
self.ttl1.pulse(4*us)
|
self.ttl1.pulse(4*us)
|
||||||
delay(4*us)
|
delay(4*us)
|
||||||
|
|
||||||
TTL1 is assigned to the pin C10 of the Papilio Pro. The name of the attributes (``ttl0`` and ``ttl1``) is used to look up hardware in the device database.
|
TTL1 is assigned to the pin C10 of the Pipistrello. The name of the attributes (``ttl0`` and ``ttl1``) is used to look up hardware in the device database.
|
||||||
|
|
||||||
Within a parallel block, some statements can be made sequential again using a ``with sequential`` construct. Observe the pulses generated by this code: ::
|
Within a parallel block, some statements can be made sequential again using a ``with sequential`` construct. Observe the pulses generated by this code: ::
|
||||||
|
|
||||||
|
@ -8,9 +8,9 @@ These steps are required to generate bitstream (``.bit``) files, build the MiSoC
|
|||||||
|
|
||||||
* Install the FPGA vendor tools (e.g. Xilinx ISE and/or Vivado):
|
* Install the FPGA vendor tools (e.g. Xilinx ISE and/or Vivado):
|
||||||
|
|
||||||
* Get Xilinx tools from http://www.xilinx.com/support/download/index.htm. ISE can build bitstreams both for boards using the Spartan-6 (Papilio Pro) and 7-series devices (KC705), while Vivado supports only boards using 7-series devices.
|
* Get Xilinx tools from http://www.xilinx.com/support/download/index.htm. ISE can build bitstreams both for boards using the Spartan-6 (Pipistrello) and 7-series devices (KC705), while Vivado supports only boards using 7-series devices.
|
||||||
|
|
||||||
* The Papilio Pro is supported by Webpack, the KC705 is not.
|
* The Pipistrello is supported by Webpack, the KC705 is not.
|
||||||
|
|
||||||
* During the Xilinx toolchain installation, uncheck ``Install cable drivers`` (they are not required as we use better and open source alternatives).
|
* During the Xilinx toolchain installation, uncheck ``Install cable drivers`` (they are not required as we use better and open source alternatives).
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ These steps are required to generate bitstream (``.bit``) files, build the MiSoC
|
|||||||
$ make -j4
|
$ make -j4
|
||||||
$ sudo make install
|
$ sudo make install
|
||||||
|
|
||||||
* Install JTAG tools needed to program Papilio Pro and KC705:
|
* Install JTAG tools needed to program the Pipistrello and KC705:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@ -69,14 +69,14 @@ These steps are required to generate bitstream (``.bit``) files, build the MiSoC
|
|||||||
|
|
||||||
The purpose of the flash proxy bitstream is to give programming software fast JTAG access to the flash connected to the FPGA.
|
The purpose of the flash proxy bitstream is to give programming software fast JTAG access to the flash connected to the FPGA.
|
||||||
|
|
||||||
* Papilio Pro:
|
* Pipistrello:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
$ cd ~/artiq-dev
|
$ cd ~/artiq-dev
|
||||||
$ git clone https://github.com/GadgetFactory/Papilio-Loader
|
$ wget http://www.phys.ethz.ch/~robertjo/bscan_spi_lx45_csg324.bit
|
||||||
|
|
||||||
Then copy ``~/artiq-dev/Papilio-Loader/xc3sprog/trunk/bscan_spi/bscan_spi_lx9_papilio.bit`` to ``~/.migen``, ``/usr/local/share/migen`` or ``/usr/share/migen``.
|
Then copy ``~/artiq-dev/bscan_spi_lx45_csg324.bit`` to ``~/.migen``, ``/usr/local/share/migen`` or ``/usr/share/migen``.
|
||||||
|
|
||||||
* KC705:
|
* KC705:
|
||||||
|
|
||||||
@ -107,9 +107,9 @@ These steps are required to generate bitstream (``.bit``) files, build the MiSoC
|
|||||||
* Then, build and flash the ARTIQ runtime: ::
|
* Then, build and flash the ARTIQ runtime: ::
|
||||||
|
|
||||||
$ cd ~/artiq-dev/artiq/soc/runtime && make runtime.fbi
|
$ cd ~/artiq-dev/artiq/soc/runtime && make runtime.fbi
|
||||||
$ ~/artiq-dev/artiq/artiq/frontend/artiq_flash.sh -t ppro -d $PWD -r
|
$ ~/artiq-dev/artiq/artiq/frontend/artiq_flash.sh -t pipistrello -d $PWD -r
|
||||||
|
|
||||||
.. note:: The `-t` option specifies the board your are targeting. Available options are `ppro` for Papilio Pro, `kc705` for KC705 and `pipistrello` for Pipistrello.
|
.. note:: The `-t` option specifies the board your are targeting. Available options are ``kc705`` and ``pipistrello``.
|
||||||
|
|
||||||
* Check that the board boots by running a serial terminal program (you may need to press its FPGA reconfiguration button or power-cycle it to load the bitstream that was newly written into the flash): ::
|
* Check that the board boots by running a serial terminal program (you may need to press its FPGA reconfiguration button or power-cycle it to load the bitstream that was newly written into the flash): ::
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ This command installs all the required packages: ::
|
|||||||
|
|
||||||
Note that ARTIQ requires Python 3.4 or above.
|
Note that ARTIQ requires Python 3.4 or above.
|
||||||
|
|
||||||
To set user permissions on the JTAG and serial ports of the Papilio Pro, create a ``/etc/udev/rules.d/30-usb-papilio-pro.rules`` file containing the following: ::
|
To set user permissions on the JTAG and serial ports of the Pipistrello, create a ``/etc/udev/rules.d/30-usb-papilio.rules`` file containing the following: ::
|
||||||
|
|
||||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", GROUP="dialout"
|
SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", GROUP="dialout"
|
||||||
|
|
||||||
|
@ -1,24 +1,7 @@
|
|||||||
include $(MSCDIR)/software/common.mak
|
include $(MSCDIR)/software/common.mak
|
||||||
|
|
||||||
OBJECTS := isr.o flash_storage.o elf_loader.o services.o session.o log.o test_mode.o kloader.o main.o
|
OBJECTS := isr.o flash_storage.o elf_loader.o services.o session.o log.o test_mode.o kloader.o mailbox.o ksupport_data.o main.o
|
||||||
OBJECTS_KSUPPORT := exception_jmp.o exceptions.o rtio.o dds.o
|
OBJECTS_KSUPPORT := ksupport.o exception_jmp.o exceptions.o mailbox.o bridge.o rtio.o dds.o
|
||||||
|
|
||||||
# NOTE: this does not handle dependencies well. Run "make clean"
|
|
||||||
# when switching between UP and AMP.
|
|
||||||
UNIPROCESSOR := $(shell printf "\#include <generated/csr.h>\nCSR_KERNEL_CPU_BASE" | $(CC_normal) $(CFLAGS) -E - | tail -n 1 | grep -c CSR_KERNEL_CPU_BASE)
|
|
||||||
|
|
||||||
ifeq ($(UNIPROCESSOR),0)
|
|
||||||
OBJECTS += mailbox.o ksupport_data.o
|
|
||||||
OBJECTS_KSUPPORT += mailbox.o bridge.o ksupport.o
|
|
||||||
CFLAGS += -DARTIQ_AMP
|
|
||||||
SERVICE_TABLE_INPUT = ksupport.elf
|
|
||||||
else
|
|
||||||
ifeq ($(UNIPROCESSOR),1)
|
|
||||||
OBJECTS += $(OBJECTS_KSUPPORT)
|
|
||||||
else
|
|
||||||
$(error failed to determine UP/AMP build)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
CFLAGS += -Ilwip/src/include -Iliblwip
|
CFLAGS += -Ilwip/src/include -Iliblwip
|
||||||
|
|
||||||
@ -57,8 +40,8 @@ ksupport.elf: $(OBJECTS_KSUPPORT)
|
|||||||
ksupport_data.o: ksupport.bin
|
ksupport_data.o: ksupport.bin
|
||||||
$(LD) -r -b binary -o $@ $<
|
$(LD) -r -b binary -o $@ $<
|
||||||
|
|
||||||
service_table.h: $(SERVICE_TABLE_INPUT) gen_service_table.py
|
service_table.h: ksupport.elf gen_service_table.py
|
||||||
@echo " GEN " $@ && ./gen_service_table.py $(SERVICE_TABLE_INPUT) > $@
|
@echo " GEN " $@ && ./gen_service_table.py ksupport.elf > $@
|
||||||
|
|
||||||
services.c: service_table.h
|
services.c: service_table.h
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from elftools.elf.elffile import ELFFile
|
||||||
|
|
||||||
|
|
||||||
services = [
|
services = [
|
||||||
("syscalls", [
|
("syscalls", [
|
||||||
@ -24,17 +26,7 @@ services = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def print_up():
|
def print_service_table(ksupport_elf_filename):
|
||||||
for name, contents in services:
|
|
||||||
print("static const struct symbol {}[] = {{".format(name))
|
|
||||||
for name, value in contents:
|
|
||||||
print(" {{\"{}\", {}}},".format(name, value))
|
|
||||||
print(" {NULL, NULL}")
|
|
||||||
print("};")
|
|
||||||
|
|
||||||
|
|
||||||
def print_amp(ksupport_elf_filename):
|
|
||||||
from elftools.elf.elffile import ELFFile
|
|
||||||
with open(ksupport_elf_filename, "rb") as f:
|
with open(ksupport_elf_filename, "rb") as f:
|
||||||
elf = ELFFile(f)
|
elf = ELFFile(f)
|
||||||
symtab = elf.get_section_by_name(b".symtab")
|
symtab = elf.get_section_by_name(b".symtab")
|
||||||
@ -50,10 +42,8 @@ def print_amp(ksupport_elf_filename):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if len(sys.argv) == 1:
|
if len(sys.argv) == 2:
|
||||||
print_up()
|
print_service_table(sys.argv[1])
|
||||||
elif len(sys.argv) == 2:
|
|
||||||
print_amp(sys.argv[1])
|
|
||||||
else:
|
else:
|
||||||
print("Incorrect number of command line arguments")
|
print("Incorrect number of command line arguments")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -49,12 +49,10 @@ static int symtab_add(const char *name, void *target)
|
|||||||
|
|
||||||
int kloader_load(void *buffer, int length)
|
int kloader_load(void *buffer, int length)
|
||||||
{
|
{
|
||||||
#ifdef ARTIQ_AMP
|
|
||||||
if(!kernel_cpu_reset_read()) {
|
if(!kernel_cpu_reset_read()) {
|
||||||
log("BUG: attempted to load while kernel CPU running");
|
log("BUG: attempted to load while kernel CPU running");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
symtab_init();
|
symtab_init();
|
||||||
return load_elf(
|
return load_elf(
|
||||||
resolve_service_symbol, symtab_add,
|
resolve_service_symbol, symtab_add,
|
||||||
@ -66,8 +64,6 @@ kernel_function kloader_find(const char *name)
|
|||||||
return find_symbol(symtab, name);
|
return find_symbol(symtab, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ARTIQ_AMP
|
|
||||||
|
|
||||||
extern char _binary_ksupport_bin_start;
|
extern char _binary_ksupport_bin_start;
|
||||||
extern char _binary_ksupport_bin_end;
|
extern char _binary_ksupport_bin_end;
|
||||||
|
|
||||||
@ -107,5 +103,3 @@ void kloader_stop_kernel(void)
|
|||||||
{
|
{
|
||||||
kernel_cpu_reset_write(1);
|
kernel_cpu_reset_write(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -9,11 +9,9 @@ typedef void (*kernel_function)(void);
|
|||||||
int kloader_load(void *buffer, int length);
|
int kloader_load(void *buffer, int length);
|
||||||
kernel_function kloader_find(const char *name);
|
kernel_function kloader_find(const char *name);
|
||||||
|
|
||||||
#ifdef ARTIQ_AMP
|
|
||||||
void kloader_start_bridge(void);
|
void kloader_start_bridge(void);
|
||||||
void kloader_start_idle_kernel(void);
|
void kloader_start_idle_kernel(void);
|
||||||
void kloader_start_user_kernel(kernel_function k);
|
void kloader_start_user_kernel(kernel_function k);
|
||||||
void kloader_stop_kernel(void);
|
void kloader_stop_kernel(void);
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __KLOADER_H */
|
#endif /* __KLOADER_H */
|
||||||
|
@ -3,15 +3,8 @@
|
|||||||
|
|
||||||
#include <generated/csr.h>
|
#include <generated/csr.h>
|
||||||
|
|
||||||
#ifdef ARTIQ_AMP
|
|
||||||
#include "mailbox.h"
|
#include "mailbox.h"
|
||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
#else
|
|
||||||
#include <system.h>
|
|
||||||
#include "exceptions.h"
|
|
||||||
#include "rtio.h"
|
|
||||||
#include "dds.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "kloader.h"
|
#include "kloader.h"
|
||||||
@ -73,18 +66,14 @@ void session_start(void)
|
|||||||
buffer_out_index_data = 0;
|
buffer_out_index_data = 0;
|
||||||
buffer_out_index_mem = 0;
|
buffer_out_index_mem = 0;
|
||||||
memset(&buffer_out[4], 0, 4);
|
memset(&buffer_out[4], 0, 4);
|
||||||
#ifdef ARTIQ_AMP
|
|
||||||
kloader_stop_kernel();
|
kloader_stop_kernel();
|
||||||
#endif
|
|
||||||
user_kernel_state = USER_KERNEL_NONE;
|
user_kernel_state = USER_KERNEL_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_end(void)
|
void session_end(void)
|
||||||
{
|
{
|
||||||
#ifdef ARTIQ_AMP
|
|
||||||
kloader_stop_kernel();
|
kloader_stop_kernel();
|
||||||
kloader_start_idle_kernel();
|
kloader_start_idle_kernel();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* host to device */
|
/* host to device */
|
||||||
@ -204,53 +193,6 @@ static int send_rpc_request(int rpc_num, va_list args)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ARTIQ_AMP
|
|
||||||
static int rpc_reply_eid;
|
|
||||||
static int rpc_reply_retval;
|
|
||||||
|
|
||||||
int rpc(int rpc_num, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
va_start(args, rpc_num);
|
|
||||||
send_rpc_request(rpc_num, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
user_kernel_state = USER_KERNEL_WAIT_RPC;
|
|
||||||
/*while(user_kernel_state == USER_KERNEL_WAIT_RPC)
|
|
||||||
comm_service();*/
|
|
||||||
|
|
||||||
if(rpc_reply_eid != EID_NONE)
|
|
||||||
exception_raise(rpc_reply_eid);
|
|
||||||
return rpc_reply_retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* assumes output buffer is empty when called */
|
|
||||||
static void run_kernel_up(kernel_function k)
|
|
||||||
{
|
|
||||||
void *jb;
|
|
||||||
int eid;
|
|
||||||
long long eparams[3];
|
|
||||||
|
|
||||||
jb = exception_push();
|
|
||||||
if(exception_setjmp(jb)) {
|
|
||||||
eid = exception_getid(eparams);
|
|
||||||
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_EXCEPTION;
|
|
||||||
memcpy(&buffer_out[9], &eid, 4);
|
|
||||||
memcpy(&buffer_out[13], eparams, 3*8);
|
|
||||||
submit_output(9+4+3*8);
|
|
||||||
} else {
|
|
||||||
dds_init();
|
|
||||||
rtio_init();
|
|
||||||
flush_cpu_icache();
|
|
||||||
k();
|
|
||||||
exception_pop(1);
|
|
||||||
buffer_out[8] = REMOTEMSG_TYPE_KERNEL_FINISHED;
|
|
||||||
submit_output(9);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* !ARTIQ_AMP */
|
|
||||||
|
|
||||||
static int process_input(void)
|
static int process_input(void)
|
||||||
{
|
{
|
||||||
switch(buffer_in[8]) {
|
switch(buffer_in[8]) {
|
||||||
@ -321,35 +263,22 @@ static int process_input(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ARTIQ_AMP
|
|
||||||
kloader_start_user_kernel(k);
|
kloader_start_user_kernel(k);
|
||||||
user_kernel_state = USER_KERNEL_RUNNING;
|
user_kernel_state = USER_KERNEL_RUNNING;
|
||||||
#else
|
|
||||||
user_kernel_state = USER_KERNEL_RUNNING;
|
|
||||||
run_kernel_up(k);
|
|
||||||
user_kernel_state = USER_KERNEL_LOADED;
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case REMOTEMSG_TYPE_RPC_REPLY: {
|
case REMOTEMSG_TYPE_RPC_REPLY: {
|
||||||
#ifdef ARTIQ_AMP
|
|
||||||
struct msg_rpc_reply reply;
|
struct msg_rpc_reply reply;
|
||||||
#endif
|
|
||||||
|
|
||||||
if(user_kernel_state != USER_KERNEL_WAIT_RPC) {
|
if(user_kernel_state != USER_KERNEL_WAIT_RPC) {
|
||||||
log("Unsolicited RPC reply");
|
log("Unsolicited RPC reply");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ARTIQ_AMP
|
|
||||||
reply.type = MESSAGE_TYPE_RPC_REPLY;
|
reply.type = MESSAGE_TYPE_RPC_REPLY;
|
||||||
memcpy(&reply.eid, &buffer_in[9], 4);
|
memcpy(&reply.eid, &buffer_in[9], 4);
|
||||||
memcpy(&reply.retval, &buffer_in[13], 4);
|
memcpy(&reply.retval, &buffer_in[13], 4);
|
||||||
mailbox_send_and_wait(&reply);
|
mailbox_send_and_wait(&reply);
|
||||||
#else
|
|
||||||
memcpy(&rpc_reply_eid, &buffer_in[9], 4);
|
|
||||||
memcpy(&rpc_reply_retval, &buffer_in[13], 4);
|
|
||||||
#endif
|
|
||||||
user_kernel_state = USER_KERNEL_RUNNING;
|
user_kernel_state = USER_KERNEL_RUNNING;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -411,7 +340,6 @@ int session_input(void *data, int len)
|
|||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ARTIQ_AMP
|
|
||||||
/* assumes output buffer is empty when called */
|
/* assumes output buffer is empty when called */
|
||||||
static void process_kmsg(struct msg_base *umsg)
|
static void process_kmsg(struct msg_base *umsg)
|
||||||
{
|
{
|
||||||
@ -470,7 +398,6 @@ static void process_kmsg(struct msg_base *umsg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* ARTIQ_AMP */
|
|
||||||
|
|
||||||
void session_poll(void **data, int *len)
|
void session_poll(void **data, int *len)
|
||||||
{
|
{
|
||||||
@ -478,7 +405,6 @@ void session_poll(void **data, int *len)
|
|||||||
|
|
||||||
l = get_out_packet_len();
|
l = get_out_packet_len();
|
||||||
|
|
||||||
#ifdef ARTIQ_AMP
|
|
||||||
/* If the output buffer is available,
|
/* If the output buffer is available,
|
||||||
* check if the kernel CPU has something to transmit.
|
* check if the kernel CPU has something to transmit.
|
||||||
*/
|
*/
|
||||||
@ -492,7 +418,6 @@ void session_poll(void **data, int *len)
|
|||||||
}
|
}
|
||||||
l = get_out_packet_len();
|
l = get_out_packet_len();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
*len = l - buffer_out_index_data;
|
*len = l - buffer_out_index_data;
|
||||||
*data = &buffer_out[buffer_out_index_data];
|
*data = &buffer_out[buffer_out_index_data];
|
||||||
|
@ -7,14 +7,13 @@
|
|||||||
#include <generated/csr.h>
|
#include <generated/csr.h>
|
||||||
#include <console.h>
|
#include <console.h>
|
||||||
|
|
||||||
#include "dds.h"
|
|
||||||
#include "test_mode.h"
|
|
||||||
|
|
||||||
#ifdef ARTIQ_AMP
|
|
||||||
|
|
||||||
#include "kloader.h"
|
#include "kloader.h"
|
||||||
#include "mailbox.h"
|
#include "mailbox.h"
|
||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
|
#include "dds.h"
|
||||||
|
#include "test_mode.h"
|
||||||
|
|
||||||
|
/* bridge access functions */
|
||||||
|
|
||||||
static void amp_bridge_init(void)
|
static void amp_bridge_init(void)
|
||||||
{
|
{
|
||||||
@ -102,48 +101,7 @@ static void p_ddsfud(void)
|
|||||||
mailbox_send_and_wait(&msg);
|
mailbox_send_and_wait(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* ARTIQ_AMP */
|
/* */
|
||||||
|
|
||||||
#include "rtio.h"
|
|
||||||
|
|
||||||
static void p_ttlout(int n, int value)
|
|
||||||
{
|
|
||||||
rtio_init();
|
|
||||||
rtio_set_oe(rtio_get_counter() + 8000, n, 1);
|
|
||||||
rtio_set_o(rtio_get_counter() + 8000, n, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void p_ddssel(int channel)
|
|
||||||
{
|
|
||||||
DDS_WRITE(DDS_GPIO, channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void p_ddsreset(void)
|
|
||||||
{
|
|
||||||
unsigned int g;
|
|
||||||
|
|
||||||
g = DDS_READ(DDS_GPIO);
|
|
||||||
DDS_WRITE(DDS_GPIO, g | (1 << 7));
|
|
||||||
DDS_WRITE(DDS_GPIO, g);
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int p_ddsread(unsigned int address)
|
|
||||||
{
|
|
||||||
return DDS_READ(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void p_ddswrite(unsigned int address, unsigned int data)
|
|
||||||
{
|
|
||||||
DDS_WRITE(address, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void p_ddsfud(void)
|
|
||||||
{
|
|
||||||
rtio_init();
|
|
||||||
rtio_fud(rtio_get_counter() + 8000);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* ARTIQ_AMP */
|
|
||||||
|
|
||||||
static void leds(char *value)
|
static void leds(char *value)
|
||||||
{
|
{
|
||||||
@ -462,9 +420,7 @@ void test_main(void)
|
|||||||
{
|
{
|
||||||
char buffer[64];
|
char buffer[64];
|
||||||
|
|
||||||
#ifdef ARTIQ_AMP
|
|
||||||
amp_bridge_init();
|
amp_bridge_init();
|
||||||
#endif
|
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
putsnonl("\e[1mtest>\e[0m ");
|
putsnonl("\e[1mtest>\e[0m ");
|
||||||
|
@ -94,18 +94,6 @@ set_false_path -from [get_clocks rsys_clk] -to [get_clocks rio_clk]
|
|||||||
set_false_path -from [get_clocks rio_clk] -to [get_clocks rsys_clk]
|
set_false_path -from [get_clocks rio_clk] -to [get_clocks rsys_clk]
|
||||||
""", rsys_clk=self.rtio.cd_rsys.clk, rio_clk=self.rtio.cd_rio.clk)
|
""", rsys_clk=self.rtio.cd_rsys.clk, rio_clk=self.rtio.cd_rio.clk)
|
||||||
|
|
||||||
class UP(_Peripherals):
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
_Peripherals.__init__(self, *args, **kwargs)
|
|
||||||
|
|
||||||
rtio_csrs = self.rtio.get_csrs()
|
|
||||||
self.submodules.rtiowb = wbgen.Bank(rtio_csrs)
|
|
||||||
self.add_wb_slave(mem_decoder(self.mem_map["rtio"]), self.rtiowb.bus)
|
|
||||||
self.add_csr_region("rtio", self.mem_map["rtio"] + 0x80000000, 32, rtio_csrs)
|
|
||||||
|
|
||||||
self.add_wb_slave(mem_decoder(self.mem_map["dds"]), self.dds.bus)
|
|
||||||
self.add_memory_region("dds", self.mem_map["dds"] + 0x80000000, 64*4)
|
|
||||||
|
|
||||||
|
|
||||||
class AMP(_Peripherals):
|
class AMP(_Peripherals):
|
||||||
csr_map = {
|
csr_map = {
|
||||||
|
@ -121,20 +121,6 @@ trce -v 12 -fastpaths -tsi {build_name}.tsi -o {build_name}.twr {build_name}.ncd
|
|||||||
self.comb += dds_pads.fud_n.eq(~fud)
|
self.comb += dds_pads.fud_n.eq(~fud)
|
||||||
|
|
||||||
|
|
||||||
class UP(_Peripherals):
|
|
||||||
def __init__(self, platform, **kwargs):
|
|
||||||
_Peripherals.__init__(self, platform, **kwargs)
|
|
||||||
|
|
||||||
rtio_csrs = self.rtio.get_csrs()
|
|
||||||
self.submodules.rtiowb = wbgen.Bank(rtio_csrs)
|
|
||||||
self.add_wb_slave(mem_decoder(self.mem_map["rtio"]), self.rtiowb.bus)
|
|
||||||
self.add_csr_region("rtio", self.mem_map["rtio"] + 0x80000000, 32,
|
|
||||||
rtio_csrs)
|
|
||||||
|
|
||||||
self.add_wb_slave(mem_decoder(self.mem_map["dds"]), self.dds.bus)
|
|
||||||
self.add_memory_region("dds", self.mem_map["dds"] + 0x80000000, 64*4)
|
|
||||||
|
|
||||||
|
|
||||||
class AMP(_Peripherals):
|
class AMP(_Peripherals):
|
||||||
csr_map = {
|
csr_map = {
|
||||||
"kernel_cpu": 14
|
"kernel_cpu": 14
|
||||||
|
@ -1,131 +0,0 @@
|
|||||||
from migen.fhdl.std import *
|
|
||||||
from migen.bank.description import *
|
|
||||||
from migen.bank import wbgen
|
|
||||||
from mibuild.generic_platform import *
|
|
||||||
|
|
||||||
from misoclib.com import gpio
|
|
||||||
from misoclib.soc import mem_decoder
|
|
||||||
from misoclib.mem.sdram.core.minicon import MiniconSettings
|
|
||||||
from targets.ppro import BaseSoC
|
|
||||||
|
|
||||||
from artiq.gateware import rtio, ad9858, nist_qc1
|
|
||||||
from artiq.gateware.rtio.phy import ttl_simple
|
|
||||||
|
|
||||||
|
|
||||||
class _TestGen(Module):
|
|
||||||
def __init__(self, pad):
|
|
||||||
divc = Signal(15)
|
|
||||||
ce = Signal()
|
|
||||||
self.sync += Cat(divc, ce).eq(divc + 1)
|
|
||||||
|
|
||||||
sr = Signal(8, reset=0b10101000)
|
|
||||||
self.sync += If(ce, sr.eq(Cat(sr[1:], sr[0])))
|
|
||||||
self.comb += pad.eq(sr[0])
|
|
||||||
|
|
||||||
|
|
||||||
class _RTIOMiniCRG(Module, AutoCSR):
|
|
||||||
def __init__(self, platform):
|
|
||||||
self._clock_sel = CSRStorage()
|
|
||||||
self.clock_domains.cd_rtio = ClockDomain()
|
|
||||||
|
|
||||||
# 80MHz -> 125MHz
|
|
||||||
rtio_internal_clk = Signal()
|
|
||||||
self.specials += Instance("DCM_CLKGEN",
|
|
||||||
p_CLKFXDV_DIVIDE=2,
|
|
||||||
p_CLKFX_DIVIDE=16, p_CLKFX_MD_MAX=1.6, p_CLKFX_MULTIPLY=25,
|
|
||||||
p_CLKIN_PERIOD=12.5, p_SPREAD_SPECTRUM="NONE",
|
|
||||||
p_STARTUP_WAIT="FALSE",
|
|
||||||
|
|
||||||
i_CLKIN=ClockSignal(), o_CLKFX=rtio_internal_clk,
|
|
||||||
i_FREEZEDCM=0, i_RST=ResetSignal())
|
|
||||||
|
|
||||||
rtio_external_clk = platform.request("xtrig")
|
|
||||||
platform.add_period_constraint(rtio_external_clk, 8.0)
|
|
||||||
self.specials += Instance("BUFGMUX",
|
|
||||||
i_I0=rtio_internal_clk,
|
|
||||||
i_I1=rtio_external_clk,
|
|
||||||
i_S=self._clock_sel.storage,
|
|
||||||
o_O=self.cd_rtio.clk)
|
|
||||||
|
|
||||||
platform.add_platform_command("""
|
|
||||||
NET "{int_clk}" TNM_NET = "GRPint_clk";
|
|
||||||
NET "{ext_clk}" TNM_NET = "GRPext_clk";
|
|
||||||
NET "sys_clk" TNM_NET = "GRPsys_clk";
|
|
||||||
TIMESPEC "TSfix_ise1" = FROM "GRPint_clk" TO "GRPsys_clk" TIG;
|
|
||||||
TIMESPEC "TSfix_ise2" = FROM "GRPsys_clk" TO "GRPint_clk" TIG;
|
|
||||||
TIMESPEC "TSfix_ise3" = FROM "GRPext_clk" TO "GRPsys_clk" TIG;
|
|
||||||
TIMESPEC "TSfix_ise4" = FROM "GRPsys_clk" TO "GRPext_clk" TIG;
|
|
||||||
TIMESPEC "TSfix_ise5" = FROM "GRPext_clk" TO "GRPint_clk" TIG;
|
|
||||||
TIMESPEC "TSfix_ise6" = FROM "GRPint_clk" TO "GRPext_clk" TIG;
|
|
||||||
""", int_clk=rtio_internal_clk, ext_clk=rtio_external_clk)
|
|
||||||
|
|
||||||
|
|
||||||
class UP(BaseSoC):
|
|
||||||
csr_map = {
|
|
||||||
"rtio": None, # mapped on Wishbone instead
|
|
||||||
"rtiocrg": 13
|
|
||||||
}
|
|
||||||
csr_map.update(BaseSoC.csr_map)
|
|
||||||
mem_map = {
|
|
||||||
"rtio": 0x20000000, # (shadow @0xa0000000)
|
|
||||||
"dds": 0x50000000, # (shadow @0xd0000000)
|
|
||||||
}
|
|
||||||
mem_map.update(BaseSoC.mem_map)
|
|
||||||
|
|
||||||
def __init__(self, platform, cpu_type="or1k",
|
|
||||||
with_test_gen=False, **kwargs):
|
|
||||||
BaseSoC.__init__(self, platform,
|
|
||||||
cpu_type=cpu_type,
|
|
||||||
sdram_controller_settings=MiniconSettings(),
|
|
||||||
**kwargs)
|
|
||||||
platform.add_extension(nist_qc1.papilio_adapter_io)
|
|
||||||
|
|
||||||
self.submodules.leds = gpio.GPIOOut(Cat(
|
|
||||||
platform.request("user_led", 0),
|
|
||||||
platform.request("ext_led", 0)))
|
|
||||||
|
|
||||||
self.comb += [
|
|
||||||
platform.request("ttl_l_tx_en").eq(1),
|
|
||||||
platform.request("ttl_h_tx_en").eq(1)
|
|
||||||
]
|
|
||||||
|
|
||||||
# RTIO channels
|
|
||||||
rtio_channels = []
|
|
||||||
for i in range(2):
|
|
||||||
phy = ttl_simple.Inout(platform.request("pmt", i))
|
|
||||||
self.submodules += phy
|
|
||||||
rtio_channels.append(rtio.Channel(phy.rtlink))
|
|
||||||
for i in range(5):
|
|
||||||
phy = ttl_simple.Output(platform.request("ttl", i))
|
|
||||||
self.submodules += phy
|
|
||||||
rtio_channels.append(rtio.Channel(phy.rtlink))
|
|
||||||
|
|
||||||
fud = Signal()
|
|
||||||
self.add_constant("RTIO_FUD_CHANNEL", len(rtio_channels))
|
|
||||||
phy = ttl_simple.Output(fud)
|
|
||||||
self.submodules += phy
|
|
||||||
rtio_channels.append(rtio.Channel(phy.rtlink))
|
|
||||||
|
|
||||||
# RTIO core
|
|
||||||
self.submodules.rtiocrg = _RTIOMiniCRG(platform)
|
|
||||||
self.submodules.rtio = rtio.RTIO(rtio_channels,
|
|
||||||
clk_freq=125000000,
|
|
||||||
counter_width=32)
|
|
||||||
|
|
||||||
rtio_csrs = self.rtio.get_csrs()
|
|
||||||
self.submodules.rtiowb = wbgen.Bank(rtio_csrs)
|
|
||||||
self.add_wb_slave(mem_decoder(self.mem_map["rtio"]), self.rtiowb.bus)
|
|
||||||
self.add_csr_region("rtio", self.mem_map["rtio"] + 0x80000000,
|
|
||||||
32, rtio_csrs)
|
|
||||||
|
|
||||||
if with_test_gen:
|
|
||||||
self.submodules.test_gen = _TestGen(platform.request("ttl", 8))
|
|
||||||
|
|
||||||
dds_pads = platform.request("dds")
|
|
||||||
self.submodules.dds = ad9858.AD9858(dds_pads)
|
|
||||||
self.add_wb_slave(mem_decoder(self.mem_map["dds"]), self.dds.bus)
|
|
||||||
self.add_memory_region("dds", self.mem_map["dds"] + 0x80000000, 64*4)
|
|
||||||
self.comb += dds_pads.fud_n.eq(~fud)
|
|
||||||
|
|
||||||
|
|
||||||
default_subtarget = UP
|
|
Loading…
Reference in New Issue
Block a user