Coprocesseur pour le traitement parall` ele de donn´ ees
22 janvier 2020
Documents fournis : projet Vivado synth´etis´e et exemple de module noyau
Nous nous int´eressons `a l’“acc´el´eration” de calculs par l’ajout de co-processeurs reconfigurables dans le FPGA `a cˆot´e du processeur ARM ´equipant le Zynq. Une des approches qui a permis l’acc´el´eration des traitements est l’architecture SIMD (Single Instruction Multiple Data) utilis´ee par de nombreux fondeurs, incluant les jeux d’instructions MMX puis SSE (Streaming SIMD Extensions) chez Intel, NEON chez ARM ou cartes graphiques, en particulier nVidia. Dans ces architectures, une mˆeme instruction est appliqu´ee `a plusieurs donn´ees simultan´ement renseign´ees dans les registres ad´equats, ´evitant les multiples s´equences d’appels des instructions (opcodes) selon le cyclefetch-decode-executedes architectures SISD (Single Instruction on Single Data).
Nous nous proposons d’aborder le probl`eme de l’addition selon le sch´ema de traitement ci-dessous :
DDR
FIXED_IO
adder_substracter_reel
adder_substracter_real_v1_0 data1_in data2_in
data_out axi_to_dac_0
axi_to_dac_v1_0 s00_axi
dataA_out dataB_out ref_clk_i
ref_rst_i s00_axi_aclk s00_axi_reset
dataReal_to_ram_0
dataReal_to_ram_v1_0 s00_axi data1_in s00_axi_aclk s00_axi_reset expanderReal_retire_bit
expanderReal_v1_0 data_in data_out processing_system7_0
ZYNQ7 Processing System DDR FIXED_IO SPI_0 USBIND_0 M_AXI_GP0 TTC0_WAVE0_OUT TTC0_WAVE1_OUT TTC0_WAVE2_OUT M_AXI_GP0_ACLK
IRQ_F2P[0:0]
FCLK_CLK0 FCLK_RESET0_N
ps7_0_axi_periph
AXI Interconnect S00_AXI
M00_AXI M01_AXI M02_AXI ACLK
ARESETN S00_ACLK S00_ARESETN M00_ACLK M00_ARESETN M01_ACLK M01_ARESETN M02_ACLK M02_ARESETN rst_ps7_0_125M
Processor System Reset slowest_sync_clk ext_reset_in aux_reset_in mb_debug_sys_rst dcm_locked
mb_reset bus_struct_reset[0:0]
peripheral_reset[0:0]
interconnect_aresetn[0:0]
peripheral_aresetn[0:0]
dans lequel le processeur fournit deux mots de 32 bits au FPGA qui se charge de les sommer et de renvoyer le r´esultat.
1. Sachant que les deux mots de 32 bits sont transmis au bloc axi to dacpar des registres situ´es
`
a l’adresse de base +4 et +8, et que le r´esultat du traitement est transmis au bloc data to ram en ´ecrivant `a son adresse de base+0 pour lire le contenu `a l’adresse de base+8, d´emontrer votre capacit´e, en faisant appel aux commandes du shell, `a additionner 6 et 9.
2. Afin de profiter du parall´elisme de l’approche SIMD, construire les arguments de la somme afin d’obtenir la somme des nombres de 3 `a 6 avec les nombres de 42 `a 45, toujours depuis le shell, afin d’effectuer en une seule operation toutes les sommes.
3 4 5 6
+
42 43 44 45
=?
3. Afin d’abstraire les interfaces et d’´eviter d’acc´eder aux ressources par leurs emplacements en m´emoire, un pilote doit permettre les mˆemes fonctionnalit´es. En partant de l’exemple de module fourni, d´emontrer l’´echange entre le module noyau Linux et le FPGA : on constatera le bon fonctionnement en affichant le r´esultat pardmesg.
4. Plutˆot que n´ecessiter de recompiler le module pour chaque nouvelle op´eration, nous d´esirons exposer une interface `a l’utilisateur de fa¸con `a ce que deux ´ecritures successives dans cette interface se traduisent par le stockage des arguments dans le FPGA, tandis que la lecture de cette interface permette l’obtention du r´esultat. D´emontrer le bon fonctionnement d’un tel pilote.
5. Afin de profiter du parall´elisme de l’approche SIMD, modifier le pilote pour accepter 4 paires d’octets successifs qui seront les arguments de la somme, et fournir `a l’utilisateur les 4 r´esultats individuels de la somme. On pourra pour ce faire par exemple lire 4 fois sur l’interface de commu- nication entre le noyau et l’espace utilisateur pour obtenir les 4 r´esultats. D´emontrer la somme des nombres de 42 `a 45 avec les nombres de 3 `a 6.
6. L’additionneur peut se configurer comme soustracteur. Modifier la chaˆıne de traitement ex´ecut´ee dans le FPGA pour pouvoir choisir, depuis le processeur, de soit fournir la somme, soit la diff´erence des arguments. On pourra profiter du commutateur switchReal fourni par OscimpDigital pour s´electionner le signal rout´e, avec la s´election de la voie (0 ou 1) en ´ecrivant dans le registre d’adresse de base+4. D´emontrer le bon fonctionnement en appelant le bloc de traitement depuis le shell pour cette fois effectuer la soustraction entre les arguments de la question pr´ec´edente.
7. Modifier le pilote pour configurer le FPGA pour effectuer l’une ou l’autre fonction. Quel appel syst`eme accessible depuis le pseudo-fichier dans/dev permet une telle configuration ? On pourra consulter dansoscimpDigital/linux driverle piloteswitch core
1
R´eponses
1. la s´equence de commandes devmem 0x43c10004 32 6 devmem 0x43c10008 32 9 devmem 0x43c00000 32 0 devmem 0x43c00008 16 fournit la r´eponse0x000F 2. la s´equence de commandes
devmem 0x43c10004 32 0x2a2b2c2d devmem 0x43c10008 32 0x03040506 devmem 0x43c00000 32 0
devmem 0x43c00008 32 fournit la r´eponse0x2D2F3133 qui est bien 45, 47, 49 et 51.
3.1 #include <linux/module.h> /* Needed by all modules */
2 #include <linux/kernel.h> /* Needed for KERN_INFO */
3 #include <linux/init.h> /* Needed for the macros */
4 #include <linux/ioport.h> // request_mem 5 #include <linux/io.h> // ioremap 6 #include <linux/fs.h> // fops 7 #include <linux/miscdevice.h>
8
9 #define IO_BASE1 0x43c00000 10 #define IO_BASE2 0x43c10000 11 #define mio 0
12
13 int hello_start(void);
14 void hello_end(void);
15
16 int hello_start()
17 {static void __iomem *ram,*dac;
18 if (request_mem_region(IO_BASE1,8,"GPIO test")==NULL) 19 printk(KERN_ALERT "mem1 request failed");
20 ram = (void __iomem*)ioremap(IO_BASE1, 8);
21 if (request_mem_region(IO_BASE2,8,"GPIO test")==NULL) 22 printk(KERN_ALERT "mem2 request failed");
23 dac = (void __iomem*)ioremap(IO_BASE2, 8);
24 writel(4,dac+4);
25 writel(2,dac+8);
26 writel(1,ram+0);
27 printk(KERN_INFO "res:%d\n",readl(ram+8));
28 return 0;
29 } 30
31 void hello_end()
32 {printk(KERN_INFO "Goodbye\n");
33 release_mem_region(IO_BASE1, 8);
34 release_mem_region(IO_BASE2, 8);
35 } 36
37 module_init(hello_start);
38 module_exit(hello_end);
4. copy from useret copy to userdans les fonctions de read et write 5. d´ecalages en entr´ee et masques en sortie
6.
DDR FIXED_IO adder_substracter_reel
adder_substracter_real_v1_0 data1_in data2_in data_out
adder_substracter_reel1
adder_substracter_real_v1_0 data1_in data2_in data_out axi_to_dac_0
axi_to_dac_v1_0 s00_axi
dataA_out dataB_out ref_clk_i ref_rst_i s00_axi_aclk s00_axi_reset
dataReal_to_ram_0
dataReal_to_ram_v1_0 s00_axi data1_in s00_axi_aclk s00_axi_reset dupplReal_1_to_2_0
dupplReal_1_to_2_v1_0 data1_out data_in
data2_out
dupplReal_1_to_2_1
dupplReal_1_to_2_v1_0 data1_out data_in
data2_out
expanderReal_retire_bit
expanderReal_v1_0 data_in data_out
processing_system7_0
ZYNQ7 Processing System DDR FIXED_IO SPI_0 USBIND_0 M_AXI_GP0 TTC0_WAVE0_OUT TTC0_WAVE1_OUT TTC0_WAVE2_OUT M_AXI_GP0_ACLK
IRQ_F2P[0:0]
FCLK_CLK0 FCLK_RESET0_N
ps7_0_axi_periph
AXI Interconnect S00_AXI
M00_AXI M01_AXI M02_AXI ACLK ARESETN S00_ACLK S00_ARESETN M00_ACLK M00_ARESETN M01_ACLK M01_ARESETN M02_ACLK M02_ARESETN rst_ps7_0_125M
Processor System Reset slowest_sync_clk ext_reset_in aux_reset_in mb_debug_sys_rst dcm_locked
mb_reset bus_struct_reset[0:0]
peripheral_reset[0:0]
interconnect_aresetn[0:0]
peripheral_aresetn[0:0]
switchReal_0
switchReal_v1_0 s00_axi data1_in
data2_in data_out
s00_axi_aclk s00_axi_reset
2
Le switch est configur´e vers la voie 1 du soustracteur devmem 0x43c20004 32 1 # soustraction devmem 0x43c10004 32 9
devmem 0x43c10008 32 6
devmem 0x43c00000 32 0 # transfer devmem 0x43c00008 16 # read result 0x0003
tandis que configurer le switch vers la voie 0 connect´ee `a l’additionneur devmem 0x43c20004 32 0 # addition
devmem 0x43c10004 32 9 devmem 0x43c10008 32 6
devmem 0x43c00000 32 0 # transfer devmem 0x43c00008 16 # read result 0x000F
7. ioctl()
3