die blöden Bits wieder...uint16_t zu 4-bit parallel out



  • @SeppJ

    Danke Dir schon einmal für die Antwort!

    Die muss ich jetzt auch erst einmal 5x lesen, da ich blutiger Anfänger bin.

    Kling plausibel auch wenn mir ein klein wenig Code dabei sehr geholfen hätte.

    Mein Gedankengang war folgender:

    • 2 uint64_t variablen erstellen (16x4bits)
    • beide variablen anpassen (1x für A und 1x für B )
    • beide variablen OR

    müsste ja die korrekten bytes liefern, oder?

    -vom Ergebnis des OR mit einer Maske (0xFFFF000000000000) die ersten Bits für den buffer holen...usw


  • Mod

    @wob sagte in die blöden Bits wieder...:

    Das Aufspreizen ginge z.B. mit _pdep_u32 (bzw. dem u64-Gegenstück) Intrinsics. (aber nur, wenn ich dich richtig verstanden habe).

    Klingt von der Beschreibung her richtig. Was mich eher wundert: Da gibt es ein Intrinsic für? Kann mir jemand erklären, wofür das gut ist? Die Operation klingt so exotisch. Was ist denn da die Anwendung, für die es sich lohnt, so etwas in einen Prozessor einzubauen?


  • Mod

    @Hamstaaa sagte in die blöden Bits wieder...:

    Kling plausibel auch wenn mir ein klein wenig Code dabei sehr geholfen hätte

    Später oder morgen, falls sich nicht jemand anderes findet. Jetzt gerade habe ich nicht die Zeit, das auszuprogrammieren.



  • @SeppJ

    Okay Sepp ich versuche das mit der Funktion mal selbst. Auch wenn ich nicht glaube dass das was wird😅

    Einwände / Änderungsvorschläge sind gern gesehen

    void Funktion(uint16_t A,  uint16_t B){
    
    uint32_t buffer[3] = 0;
    
        for (int i=0; i <3; i++){           // Quadrant
    
    
        }
    
    
    
    buffer[0] = (0x6117 << 16) | 0x1111;         
    buffer[1] = ;
    buffer[2] = ;
    
    }
    

    für mehr fehlt mir die Erfahrung 🤮

    @SeppJ sagte in die blöden Bits wieder...uint16_t zu 4-bit parallel out:

    Grundlegender Algorithmus (Alle Angaben mit 0 als Anfang der Zählung, und ganz rechts steht das 0. Bit):

    • Für N von 0 bis 3 (Das sind unsere Quadranten):

      • Zielwert auf 0001000100010001 setzen (Das 0xx1-Muster kommt von den pin1 und pin4. Die Werte dazwischen habe ich willkürlich 0 gesetzt, wir überschreiben sie sowieso im nächsten Schritt)

      • Für B von 0 bis 3 (Damit adressieren wir die Bits):

        • Bit 1+4*B des Zielwerts auf den Wert des B+4*N'ten Bits von Wert A setzen

        • Bit 2+4*B des Zielwerts auf den Wert des B+4*N'ten Bits von Wert B setzen

      • Der Zielwert ist nun das Resultat für Quadrant N (z.B. 7577 für N=0). Dieses merkt man sich oder fügt es gleich an passender Stelle in den buffer ein. Ungetestet. So wie ich mich kenne, ist da bestimmt irgendwo ein Bit um eine Position daneben.

    Eventuell kann ja ein erfahrener User helfen und auf die Schnelle etwas schreiben 🙂



  • @SeppJ sagte in die blöden Bits wieder...uint16_t zu 4-bit parallel out:

    Später oder morgen, falls sich nicht jemand anderes findet. Jetzt gerade habe ich nicht die Zeit, das auszuprogrammieren.

    Ja lieber Sepp, bitte erbarme Dich 🙂



  • Bin zwar nicht @SeppJ , aber hier meine Lösung:

    #include  <immintrin.h>
    #include <cstdint>
    
    int main() {
        const uint64_t mask = 0b1000100010001000100010001000100010001000100010001000100010001;
        
        uint16_t pin4 = 0xFFFF;
        uint16_t pin3 = 123;
        uint16_t pin2 = 0xFFFF;
        uint16_t pin1 = 0;
    
        auto result = 
            _pdep_u64(pin1, mask << 3) |
            _pdep_u64(pin2, mask << 2) |
            _pdep_u64(pin3, mask << 1) |
            _pdep_u64(pin4, mask);
        return result - 0x5555555557777577;
    }
    

    Wie du hier siehst, wird 0 zurückgegeben. Also funktioniert der Code hier so, wie er soll 🙂 Geht so für >= Haswell, also Intel i-Prozessoren ab 4. Generation. Sonst muss man es von Hand machen - dazu kannst du einfach den Code von Intel nehmen: https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_pdep_u64&expand=4152


  • Mod

    @Hamstaaa sagte in die blöden Bits wieder...uint16_t zu 4-bit parallel out:

    @SeppJ sagte in die blöden Bits wieder...uint16_t zu 4-bit parallel out:

    Später oder morgen, falls sich nicht jemand anderes findet. Jetzt gerade habe ich nicht die Zeit, das auszuprogrammieren.

    Ja lieber Sepp, bitte erbarme Dich 🙂

    Morgen. Aber ich bin ein bisschen enttäuscht, denn was ich da beschrieb kann man fast Wort für Wort nach C++ übersetzen. Wenn du keine einfachen Abläufe nachprogrammieren kannst, dann ist Bitmanipulation zu dieser Zeit noch nichts für dich. Oder verstehst du auch nur eine Zeile von dem was wob geschrieben hat? Wenn du Code nur abschreibst, ohne ihn zu verstehen, lernst du nichts.



  • @wob

    Vielen Dank für den Code.

    Vielleicht hätte ich noch erwähnen sollen, dass der Code auf einem ESP32 läuft. 😅

    _pdep_u64 kann ich also leider nicht nutzen ☹

    @SeppJ

    Ja, mit dem Code von Wob kann ich ein bisschen was anfangen.

    nur leider kenne ich die Funktion _pdep_u64 nicht.

    stehe echt auf dem Schlauch. Vielleicht fehlt mir auch die Übung.



  • Schreib das pdep doch 1:1 von der Intel-Beschreibung ab:

    (ungetestet)

    uint64_t my_pdep_u64(uint64_t a, uint64_t mask) {
        auto tmp = a;
        uint64_t dst = 0;
        int m = 0;
        int k = 0;
        const uint64_t one = 1;
        while (m < 64) {
            if (mask & (one << m)) {
                dst |= uint64_t((tmp & (one << k)) != 0) << m;
                k = k + 1;
            }
            m = m + 1;
        }
        return dst;
    }
    


  • @wob

    cool danke Wob!

    jetzt liefert deine vorherige Funktion bei mir auch das Richtige Ergebnis. 🤗

    jetzt werde ich versuchen das 'result' an die Richtige stelle im Buffer zu bringen.

    Vielen Dank schon mal an alle.

    Ihr seid Super hilfsbereit!!


Anmelden zum Antworten