Dorothy : the way

Saturday, 21 June 2025
|
Écrit par
Grégory Soutadé

 The way (2025) 

Trois ans après Gifts from the Holy Ghost, Dorothy sort son nouvel album The way. Signe que le groupe prend de l'ampleur, on pourra y trouver une collaboration avec Slash sur le titre Tombstone Town. Le style y est plus rock que sur les précédents opus, avec plus de solos, même s'il y a énormément d'arrangements qui viennent polluer l'ensemble (il faudrait carrément supprimer le synthé). Pourtant, on sent bien que le fond est vraiment intéressant. Il faut dire que le groupe a quasiment changé puisque peu de temps après la sortie de Gifts from the Holy Ghost, les deux guitaristes et le batteur ont été remplacés, de quoi largement influencer la composition musicale. Le seul survivant reste le bassiste, présent depuis le clash avec la formation originelle (2017).

Au hasard de l'écoute, il y a un titre qui nous éclate à la figure : MUD ! Poussé le volume à fond, on ressent toute la puissance de cette chanteuse exceptionnelle, qui se permet un growl de toute beauté !

Pour profiter pleinement de cet album, il faudrait assister à un de leurs concerts afin d'avoir une version plus dépouillée. Malheureusement, malgré de nombreuses dates prévues, il n'y a rien en dehors des États-Unis.

CRC32 optimization for ARM Cortex M4

Sunday, 15 June 2025
|
Écrit par
Grégory Soutadé

At work I played with an ultra low power SoC powered by a single core ARM Cortex M4. To check some data integrity, we have to use CRC32 but there is no hardware peripheral to speed up computation and ARMv6 doesn't have special instruction for this (it starts from Armv8.1). After some researches, I was surprised not to find any optimized implementation on Internet. So, I wrote it by myself and the result is quite impressive : my version is ~50% faster ! Some figures (on ~30KB of data) :

  • -Os compilation : 19.4 milliseconds
  • -02 compilation : 15.2 milliseconds
  • -0s + optimizations : 8.2 milliseconds

Here, we have to consider that Cortex M4 doesn't have Data nor Instruction cache and memory accesses are done on a SRAM. Compilation is done in thumb mode with GCC 9.

Original version is the one from Wang Yaofu licensed under Apache2. It's quite simple and very academic. C primitives doesn't allows to optimize this algorithm so much because CRC has to be processed byte by byte, so we have to do some assembly !

I used multiple optimization tricks :

Use all registers available

The idea is to play with registers from r0 to 10 and not be limited to r0-r5 as commonly used.

Unroll loop

Avoid to break CPU pipeline by doing some checks + jump. Code is bigger and repetitive, but faster. We may write macro to reduce source code, not my choice here.

Do memory burst instead of unitary access

Especially when there is no cache, memory burst accesses are really faster. Here we load 4*32 bits at a time and keep all data into registers. Bytes outside burst window are computed using non optimized version.

Use shifts and rotates within load and eor instructions

ARM instructions allows to shift registers values within load and eor (and some other instructions) without having to do it in a separate line.

Avoid pipeline register lock

When it's possible, we can invert assembly lines to avoid working on the same registers on consecutive instructions (and thus avoid to lock them).

Update condition flags in sub instruction

Use subs variant to update EQ flag and avoid to check it for 0 in a separate instruction.

Do aligned accesses

In the calling function there is some code to inject "s" as a 32 bits aligned pointer (extra bytes processed by standard code).

Here is the optimized function. Whole C file can be found here

/**
 * Optimized version of _update_crc32 for 16 bytes blocks
 */
static void _update_crc32_opt16(const unsigned char *s, unsigned int len)
{
    /* unsigned int i; */

    /* for (i = 0;  i < len;  i++) { */
    /*     crc32val = crc32_tab[(crc32val ^ s[i]) & 0xFF] ^ ((crc32val >> 8) & 0x00FFFFFF); */
    /* } */

    /*
      r0 -> s
      r1 -> len
      r2 -> crc32val
      r3 -> crc32tab
      r4 -> curval[0]
      r5 -> (crc32val ^ s[i]) & 0xFF
      r6 -> crc32_tab[(crc32val ^ s[i]) & 0xFF]
      r7 -> curval[1]
      r8 -> curval[2]
      r9 -> curval[3]
     */
    __asm__ volatile (
        "mov r0, %1\n"
        "mov r1, %2\n"
        "mov r2, %3\n"
        "mov r3, %4\n"

        "push {r7, r8, r9}\n"

        "crc32_opt16_loop:\n"
        "ldm r0!, {r4, r7, r8, r9}\n"

        // curval[0]
        "eor r5, r2, r4\n"
        "uxtb r5, r5\n"
        "ldr r6, [r3, r5, lsl #2]\n"
        "eor r2, r6, r2, lsr #8\n"

        "eor r5, r2, r4, ror #8\n"
        "uxtb r5, r5\n"
        "ldr r6, [r3, r5, lsl #2]\n"
        "eor r2, r6, r2, lsr #8\n"

        "eor r5, r2, r4, ror #16\n"
        "uxtb r5, r5\n"
        "ldr r6, [r3, r5, lsl #2]\n"
        "eor r2, r6, r2, lsr #8\n"

        "eor r5, r2, r4, ror #24\n"
        "uxtb r5, r5\n"
        "ldr r6, [r3, r5, lsl #2]\n"
        "eor r2, r6, r2, lsr #8\n"

        // curval[1]        
        "eor r5, r2, r7\n"
        "uxtb r5, r5\n"
        "ldr r6, [r3, r5, lsl #2]\n"
        "eor r2, r6, r2, lsr #8\n"

        "eor r5, r2, r7, ror #8\n"
        "uxtb r5, r5\n"
        "ldr r6, [r3, r5, lsl #2]\n"
        "eor r2, r6, r2, lsr #8\n"

        "eor r5, r2, r7, ror #16\n"
        "uxtb r5, r5\n"
        "ldr r6, [r3, r5, lsl #2]\n"
        "eor r2, r6, r2, lsr #8\n"

        "eor r5, r2, r7, ror #24\n"
        "uxtb r5, r5\n"
        "ldr r6, [r3, r5, lsl #2]\n"
        "eor r2, r6, r2, lsr #8\n"

        // curval[2]        
        "eor r5, r2, r8\n"
        "uxtb r5, r5\n"
        "ldr r6, [r3, r5, lsl #2]\n"
        "eor r2, r6, r2, lsr #8\n"

        "eor r5, r2, r8, ror #8\n"
        "uxtb r5, r5\n"
        "ldr r6, [r3, r5, lsl #2]\n"
        "eor r2, r6, r2, lsr #8\n"

        "eor r5, r2, r8, ror #16\n"
        "uxtb r5, r5\n"
        "ldr r6, [r3, r5, lsl #2]\n"
        "eor r2, r6, r2, lsr #8\n"

        "eor r5, r2, r8, ror #24\n"
        "uxtb r5, r5\n"
        "ldr r6, [r3, r5, lsl #2]\n"
        "eor r2, r6, r2, lsr #8\n"

        // curval[3]        
        "eor r5, r2, r9\n"
        "uxtb r5, r5\n"
        "ldr r6, [r3, r5, lsl #2]\n"
        "eor r2, r6, r2, lsr #8\n"

        "eor r5, r2, r9, ror #8\n"
        "uxtb r5, r5\n"
        "ldr r6, [r3, r5, lsl #2]\n"
        "eor r2, r6, r2, lsr #8\n"

        "eor r5, r2, r9, ror #16\n"
        "uxtb r5, r5\n"
        "ldr r6, [r3, r5, lsl #2]\n"
        "eor r2, r6, r2, lsr #8\n"

        "eor r5, r2, r9, ror #24\n"
        "uxtb r5, r5\n"
        "ldr r6, [r3, r5, lsl #2]\n"

        // Last two lines inverted
        "subs r1, r1, #16\n"
        "eor r2, r6, r2, lsr #8\n"

        "bne crc32_opt16_loop\n"

        "pop {r7, r8, r9}\n"
        "str r2, %0\n"
        : "=m" (crc32val)
        : "r" (s), "r" (len), "r" (crc32val), "r" (crc32_tab)
          // Missing r7-r9, manually save it
        : "r0", "r1", "r2", "r3", "r4", "r5", "r6"
        );
}

Code has to be compiled with minimum -O1 or -Os option

For comparison, the (quite good) code generated by GCC 12 with -Os, working on a single byte :

 570:   4288            cmp     r0, r1
 572:   d100            bne.n   576 <_update_crc32+0x12>
 574:   bd30            pop     {r4, r5, pc}
 576:   6814            ldr     r4, [r2, #0]
 578:   f810 3b01       ldrb.w  r3, [r0], #1
 57c:   4063            eors    r3, r4
 57e:   b2db            uxtb    r3, r3
 580:   f855 3023       ldr.w   r3, [r5, r3, lsl #2]
 584:   ea83 2314       eor.w   r3, r3, r4, lsr #8
 588:   6013            str     r3, [r2, #0]
 58a:   e7f1            b.n     570 <_update_crc32+0xc>

Not so far from mine, but main weakness is result write at each loop, which is really time consuming.

Cime du Cheiron

Sunday, 01 June 2025
|
Écrit par
Grégory Soutadé

Aujourd'hui, direction la cime du Cheiron. Je l'avais dans un coin de ma tête depuis quelques années sans jamais oser me lancer. Surtout qu'après ma mésaventure d'Escragnolles, je voulais emprunter un chemin plus simple à suivre. Ici, la distance ne semble pas trop longue (~11km), mais le dénivelé y est plus important qu'à l'habitude avec 950m d'ascension verticale, qui va nous mener à 1778m d'altitude. La randonnée est notée comme difficile, principalement à cause du dénivelé je pense. Elle est pourtant assez populaire et l'on croise facilement tout le long du trajet des personnes, des groupes, voire même des trailers, qui font la montée et la descente en courant. Pour plus de simplicité, j'ai choisi l'option de randoxygène avec un départ depuis Gréolières, plus court, mais beaucoup moins alambiqué que les instructions visorando qui empruntent des chemins avec comme seul repère des cairns...

Village de Gréolières

Il ne fallait pas traîner pour en profiter pendant les beaux jours qui restent, car la chaleur sera très vite là (dès juin). En effet, bien qu'il ne fasse que 13°C au point de départ, la température corporelle monte rapidement, d'autant plus que les 2 premiers kilomètres sont vraiment raides. Il faudra donc bien penser à prendre de l'eau, un chapeau, des lunettes de soleil et de la crème solaire, car 80% du chemin se fait à découvert. À ce sujet, il est possible de se recharger en eau dans les fontaines du village !

Village de Gréolières

Le chemin passe à côté du second château (le hameau ayant été séparé et réunifié au fil du temps), offrant un beau panorama dès que l'on prend un peu d'altitude.

La progression verticale est plutôt rapide, alternant chemins plutôt agréables et d'autres avec plus de cailloux.

Au loin, le plateau de Calern avec l'observatoire de la Côte d'Azur.

Passé ces 2 kilomètres plutôt ardus, la pente se fait plus douce. On a même l'impression de toucher rapidement au but une fois arrivé au collet du Barri. Ce n'est en réalité que la première partie ! La suite se déroule dans un bois ombragé avec un sol parfois glissant (surtout après la pluie). Cette partie n'est pas forcément aisée, avec parfois un peu de dénivelé à passer.

Au sortir du bois, la perspective s'ouvre sur un paysage lunaire avec beaucoup de pierres. L'antenne relais au loin est notre véritable objectif ! Attention, à partir de ce point, le chemin est moins visible.

Arrivé au sommet, nous attend un panorama magnifique avec le haut des remontées mécaniques ainsi que les montagnes encore enneigées en arrière plan.

Les nuages chargés d'eau remontent sur la paroi Est, poussés par le vent.

J'ai raté le point de vue sur la mer, préférant rester non loin du point culminant pour me restaurer. Ce n'est que partie remise...

Le retour se fait en sens inverse. Il faudra être vigilant, le sol n'étant pas toujours très stable à cause des pierres.

La faune et la flore locale :

Cascade de Clars

Sunday, 18 May 2025
|
Écrit par
Grégory Soutadé

Bassin de la cascade de Clars

Traditionnellement, les mois d'avril et de mai sont parfaits pour faire des randonnées : beau temps et températures idéales. Mais, entre pluies, travail et préparation des courses, il devient de plus en plus difficile de trouver un créneau pour sortir s'aérer. Juste avant de partir en congés dans l'Aveyron, il y avait bien ce mercredi là, même si le temps allait se gâter en milieu de journée. Les indications données sur visorando étaient compliquées, car la boucle est en réalité une agrégation de plusieurs parcours, pas forcément bien balisés et avec des aller-retour. Le plan était donc assez foireux à la base, et ce n'était que le début...

J'avais repéré le point de départ, situé à l'extérieur d'Escragnolles. Pourtant, une fois rentré dans le village, impossible de prendre la route en question (il faut en réalité prendre l'entrée au niveau du giratoire de la Charbonnière). Difficile de circuler une fois à l'intérieur du village, surtout quand un habitant abandonne sa voiture sur le passage pour aller dire bonjour à ses voisins... Bref, en cherchant un peu je vois quand même un panneau indiquant le point de départ, j'espère qu'il ne sera pas trop loin. Dès les premiers mètres, je sens que mon poignet est plutôt léger. En effet, j'ai oublié ma montre... Rien de dramatique, je continue. Le paysage est sympa, avec une belle luminosité, donc première photo ... En fait non, car, bien que chargé, le bouton d'alimentation s'est enclenché quand j'ai mis l'appareil dans la sacoche quelques jours auparavant. Retour donc à la voiture pour déposer cet objet mort. À ce moment, je savais qu'il ne fallait pas insister et revenir à la maison, il y avait trop de signes négatifs. Je décide pourtant de continuer.

Cascade de Clars

Après analyse, il y a en réalité 2km pour joindre le départ de la randonnée ! Une fois le bon sentier trouvé, le temps commence à tourner. Je décide de faire la randonnée dans le sens inverse en espérant que je pourrais m'orienter plus facilement et me dirige vers la cascade qui est bien indiquée. On y arrive en seulement 20 minutes sans trop de difficultés (trop court pour une rando).

Vallée d'Escragnolles

Éclair de génie (...), au moment d'arriver à la cascade, je me suis souvenu que mon téléphone pourrait faire office d'appareil photo de secours. Je cherche des traces sur la colline d'en face, mais je ne vois pas la suite du chemin. En relisant les instructions, je me rend compte qu'il s'agit d'un aller retour. La bifurcation se trouve un peu en aval. Après un temps de réflexion je décide de faire la rando complète car je ne viens pas souvent dans le coin.

Chemin Chemin

Une fois passé la rivière, on marche principalement à flanc de montagne, ce qui est plutôt agréable. J'arrive à repérer la bifurcation un peu cachée. Sur le chemin qui suit, il est indiqué un mégalithe à 100m. Je ne l'ai jamais vu... Nouveau croisement. Je prends à gauche, on dirait qu'il s'agit de la redescente et décide de poursuivre tout droit.

Champs de thym

Je me retrouve alors dans un champs de thym et peut profiter des effluves à chaque pas, mais je suis loin du chemin. L'endroit est clairement utilisé par les chasseurs, on y voit beaucoup de promontoires. Arrivé près de la falaise, je remonte pour aller au sommet de la montagne. Ce n'est pas évident hors sentier, mais ça se fait. Une fois sur le plateau, la vue est magnifique, je ne regrette pas d'être venu. En plus c'est l'heure du casse-croûte ! (j'avais faim depuis au moins une demi heure).

Panorama

Pour le retour, je suis le chemin principal (une large piste pour les chasseurs). Retour à ce fameux croisement, je prends donc la piste qui semble être celle du retour, mais arrive dans un cul-de-sac. C'est à ce moment que les choses dérapent... Je continue ma descente hors piste en espérant retrouver cette fameuse trace (le chemin a l'air plus court que si je devais revenir sur mes pas). Cette partie est assez découverte. ourtant, malgré les quelques pistes qui semblent tracées, impossible de tomber sur le chemin. J'ai déjà beaucoup descendu et arrive dans la forêt. Dilemme : tout remonter ou continuer ? je continue bonnant malant en repérant de minces traces par-ci par-là. Quelques gouttes tombent du ciel. Heureusement la pluie s'arrête rapidement. Une fois dans la forêt, les repères sont beaucoup moins clairs. Par chance, il y a cette restanque, je ne dois pas être si loin que ça d'une piste, je poursuis en la longeant et ... Je me retrouve presque perdu. C'est dans ce genre de situation qu'il ne faut surtout pas céder à la panique.

Un peu plus bas se trouve le lit d'une rivière asséché. Sur la carte il faut descendre toute la montagne jusqu'à la rivière du bas. Je progresse un peu plus vite sur cette partie car il n'y a pas de végétation. Une fois arrivé tout en bas nouveau dilemme : aller à droite ou à gauche ? C'est dans ce cas que le bout de carte IGN de visorando peut sauver des vies : d'une part, il y a les tracés des rivières, et d'autre part, les courbes de dénivelé permettent de se faire une représentation mentale en 3D et ainsi mieux se repérer dans l'espace. La progression est assez difficile car il y a beaucoup de végétation. De l'autre côté, il semble y avoir le champs aperçu quand j'étais plus en amont. Hélas, impossible de trouver ce fameux "pont en pierre très bien conservé", je traverse donc à un passage plus facile et escalade les quelques murets pour remonter (en m'accrochant au passage dans les ronces). En haut, je tombe sur un champs entouré d'une clôture électrifiée, j'espère qu'il n'y a pas un Patou qui monte la garde...

Finalement je peux remonter la route, avec beaucoup de retard sur l'heure prévue (le départ est le lendemain, je dois préparer les affaires). Il y avait une inauguration du bassin récupérateur d'eau ce jour là et j'ai pu croiser une voiture qui m'a gentiment ramené en stop, ce qui m'a évité les 3 derniers kilomètres de bitume !

Bref, même si je ne m'en sors qu'avec des griffures de ronces, ce fut une grosse galère, comme pressenti dès le départ...

Sentier des Douaniers / du Corbusier

Sunday, 13 April 2025
|
Écrit par
Grégory Soutadé

Le sentier des Douaniers, renommée sentier du Corbusier en hommage au célèbre architecte inhumé à Roquebrune-Cap-Martin, est une promenade familiale qui longe la côte de Roquebrune. Le chemin, goudronné dans son ensemble, est relativement plat, bien qu'entrecoupé régulièrement d'escaliers. D'une distance d'environ 3km (aller), il permet de rejoindre le cap (Martin). Cet aspect accessible fait qu'il est assez emprunté par les touristes et les locaux.

L'idéal est de prendre le train puis de s'arrêter en gare de Roquebrune-Cap-Martin. Le point de départ se situe immédiatement sur la gauche en sortant de la gare. En suivant le chemin des douaniers (côté opposé, sur la droite, direction les plages), il est possible de joindre Monte Carlo (~2 km), mais la promenade semble moins intéressante. Une fois sur le sentier, il n'y a pas vraiment d'issue, il suffit de poursuivre jusqu'à la fin.

Ce dimanche, la météo était au beau fixe sur les Alpes-Maritimes. Pourtant, les nuages sont restés accrochés sur le flanc de la montagne sans se disperser, ce qui rend les photos moins jolies, mais la promenade pas forcément moins agréable. En effet, le sentier est plein sud, goudronné, avec peu d'ombre. Il faudra donc penser à mettre un couvre chef et prendre de l'eau, voire des lunettes de soleil et de la crème solaire, les jours de beau temps.

Tout le long du chemin, il y a des petites criques accessibles, ainsi que plusieurs bancs. Il est donc aisé d'atteindre la mer, même si cette dernière est entourée de rochers plus ou moins saillants. Il faudra donc être vigilant lors des baignades (privilégiez des chaussures aquatiques).

Si l'on a la plupart du temps les yeux rivés sur la mer, on peut apercevoir ça et là les immenses villas en hauteur (encore plus impressionnant quand on regarde sur Google Maps). D'autant que beaucoup d'entre elles datent de la Belle Époque. Notamment ce promontoire (privé) aménagé en front de mer.

Curiosité du parcours, des chèvres ! Elles sont habituées au passage et se collent même au grillage pour capter quelques caresses.

Sur le retour, la baie de Monaco s'offre à nous. Paradis pour personnes fortunées du fait de sa fiscalité avantageuse, et aberration urbaine, dont les immeubles constituent un investissement financier plus qu'un pied à terre, faisant passer Paris pour une ville accessible (le prix au mètre carré y est 5 à 8 fois plus cher). C'était d'ailleurs un week-end du Masters 1000 de Monte-Carlo.

En fin de (mi-)parcours se profile au loin la ville de Menton, frontalière avec l'Italie. Le parking adjacent peut également être le point de départ de la randonnée.

Dernier gif les joies du code Quand je code depuis des heures et que je réalise que je suis sur la mauvaise branche