- AVX-512'nin vpternlogd komutu, üç girdinin herhangi bir bit düzeyindeki Boolean mantığını 8 bitlik bir immediate değerle seçip tek seferde çalıştıran bir SIMD komutudur
- Kilit nokta, karmaşık mantık ifadelerini ezberlemek değil;
#imm8 değerini üç girdi A/B/C'nin 8 olası durumu için bir lookup table olarak görmektir
- 1985 tarihli Amiga blitter da üç bitmap kaynağı ve 8 bitlik bir minterm ile aynı şekilde mantıksal birleşimleri belirliyordu; masked sprite için sıkça
0xE2 kullanılıyordu
- Sonuç sütunundaki 8 biti aşağıdan yukarı okuyunca immediate değer elde edildiği için, “üç girdiden tam olarak ikisi 1” gibi bir koşul bile doğrudan
0x68 olarak oluşturulabilir
- Intel belgelerindeki vpternlogd örneği ile Amiga demoscene'de yaygın olan
0xE2 kesişiyor; modern SIMD komutları ile retro grafik donanımı aynı tasarım sezgisini paylaşıyor
AVX-512'nin vpternlogd komutu
- vpternlogd, AVX-512 ISA tasarım tanıtım materyallerinde dikkat çeken bir bit düzeyinde üçlü mantık komutudur
- Üç girdi A, B ve C alır ve herhangi bir Boolean mantığını tek komutta ifade edebilir
- Örnek:
(NOT A) OR ((NOT B) XOR (C AND A))
- Girdiler 512 bitlik register olabilir; bu da karmaşık mantığın 512 bitin tamamına aynı anda uygulanmasını sağlar
foo_and_a_or_not_b gibi özel amaçlı komutları sürekli eklemek yerine, tek bir esnek komut ve 8 bitlik immediate ile çok sayıda mantık işlemi yapılır
VPTERNLOGD r0, r1, r3, #imm8
#imm8, hangi bit mantığı fonksiyonunun uygulanacağını belirler
- Pek çok doküman immediate değerin yalnızca “belirli bir ikili fonksiyonu belirlediğini” söyler; bu yüzden gerçek hesaplama yöntemini sezgisel olarak kavramak zordur
Amiga blitter ve minterm
- 1980'lerin bilgisayarlarında grafik işleme için custom chip kullanmak yaygındı
- Commodore Amiga 500'ün blitter birimi, bitmap grafikleri bir konumdan başka bir konuma taşırken mantıksal işlemler uyguluyordu
- En fazla üç bitmap kaynağını ele alıyor ve bunlar arasındaki mantıksal işlem 8 bitlik bir değer olan minterm ile belirtiliyordu
- Üç kaynak ve 8 bitlik bir değerle mantıksal birleşimi seçmesi bakımından vpternlogd ile aynı yapıya sahiptir
- Pek çok Amiga programcısı minterm hesaplamasını doğrudan anlamaktan ziyade sık kullanılan değerleri yeniden kullanıyordu
- Buffer temizlemek için
0x00
- Masked sprite çizmek için
0xE2
- 1989 tarihli “Amiga Hardware Reference Manual”, minterm hesabını kafa karıştırıcı sembollerle anlattığı için o dönemki demo geliştiricilerine pek yardımcı olmuyordu
8 bitlik değeri lookup table olarak hesaplamak
#imm8 ya da minterm, mantık operatörlerinin bir birleşimi olarak değil, 8 öğeli bir lookup table olarak görülebilir
- Üç girdi A, B ve C'nin her biri 0 ya da 1 olduğundan olası birleşim sayısı 8'dir
- İstenen sonucu doğrudan dördüncü sütuna yazmak yeterlidir
| A |
B |
C |
İstenen sonuç |
| 0 |
0 |
0 |
? |
| 0 |
0 |
1 |
? |
| 0 |
1 |
0 |
? |
| 0 |
1 |
1 |
? |
| 1 |
0 |
0 |
? |
| 1 |
0 |
1 |
? |
| 1 |
1 |
0 |
? |
| 1 |
1 |
1 |
? |
- Örneğin üç girdiden yalnızca tam iki tanesi 1 olduğunda sonucu 1 yapmak istiyorsanız, dördüncü sütunu bu koşula göre doldurursunuz
- Ortaya çıkan sonuç sütununun 8 biti aşağıdan yukarı okununca
01101000, yani 0x68 elde edilir
- Dolayısıyla
0x68 fonksiyonu, üç girdiden tam iki tanesi 1 olduğunda sonucu 1 yapar
- Aynı yöntemle üç kaynak arasındaki herhangi bir mantık fonksiyonu için gerekli
#imm8 değeri elde edilebilir
Masked sprite için 0xE2
- Amiga'da çok yaygın minterm değerlerinden biri
0xE2'dir
- Bu değer, masked 2D sprite render ederken sıkça kullanılır
- A: sprite bitmap
- B: sprite mask
- C: background
- Koşul, basit program mantığıyla ifade edilebilir
- Maske pikseli B ayarlıysa sonuç sprite A olur
- Maske pikseli B ayarlı değilse sonuç background C olur
| A |
B |
C |
İstenen sonuç |
| 0 |
0 |
0 |
0 |
| 0 |
0 |
1 |
1 |
| 0 |
1 |
0 |
0 |
| 0 |
1 |
1 |
0 |
| 1 |
0 |
0 |
0 |
| 1 |
0 |
1 |
1 |
| 1 |
1 |
0 |
1 |
| 1 |
1 |
1 |
1 |
- Sonuç sütunu aşağıdan yukarı okununca
11100010, yani 0xE2 elde edilir
0xE2, Amiga demoscene kültüründe çok yaygın bir minterm değeridir
Intel belgeleriyle tesadüfi bağlantı
1 yorum
Hacker News görüşleri
Hesaplamak istediğiniz ifadeden immediate değeri elde etmenin basit bir yolu var. Örneğin
(NOT A) OR ((NOT B) XOR (C AND A))hesaplamak istiyorsanız,~_MM_TERNLOG_A | (~_MM_TERNLOG_B ^ (_MM_TERNLOG_C & _MM_TERNLOG_A))şeklinde yazabilirsinizBu, kelimenin tam anlamıyla hesaplamak istediğiniz ifadedir ve gcc ile clang'ın intrinsic header'larında tanımlı
_MM_TERNLOG_A/B/Csabitlerinden immediate olarak değerlendirilir:typedef enum { _MM_TERNLOG_A = 0xF0, _MM_TERNLOG_B = 0xCC, _MM_TERNLOG_C = 0xAA } _MM_TERNLOG_ENUM;MSVC'de ise bunu kendiniz tanımlayabilirsiniz
A = 0b11110000,B = 0b11001100,C = 0b10101010Başlığı görünce önce bu komutun düzgün çalışmadığı anlamına geldiğini sanmıştım. Asıl yazı ise sadece nasıl çalıştığını anlatıyor
Ergenlik yıllarımda donanım kılavuzundaki o sayfaya “CRAP!” yazmadım ama anlamaya çalışmak için gerçekten çok uzun süre baktım
Sonunda neredeyse herkes gibi Bobs ve basit kopyalama için BLTCON0'ı bulup kullandım ve o kısmı görmezden geldim
Yine de birkaç yıl sonra üniversitede hesaplamalı mantık dersinden A+ aldım; belki de o travmanın biraz faydası olmuştur
Başlık hakkında konuşmak gerekirse, “ternary logic” normalde üç doğruluk değerine sahip mantık anlamına gelir. Ama bu yazı, üç giriş alan tüm ikili mantık kapılarını işleyen bir derleyici komutunu ele alıyor
ternlog, intrinsic'in adı daternarylogic, yani biraz talihsiz olsa da başlık uygunAyrıca
bitwisezaten bir ölçüde bunu “üç değerli mantık”tan ayırıyor veternary, üç giriş anlamında da oldukça sık kullanılıyor.a ? b : cde yaygın olarak ternary operator diye anılıyor; üstelikternlogbu üçlü işleci taklit edebiliyor ve yazı da tam olarak bundan bahsediyorternaryyerinetrinarydüşünmüşsünüzdürC++, JavaScript ve Python açısından
(a < b) ? 5 : 2biçimindeki ternary expression en yaygın kullanım gibi görünüyor. https://www.programiz.com/cpp-programming/ternary-operatorHer durumda hangi varsayımı yaparsanız yapın çok da önemli değil. Sözcüklerin ve ifadelerin birden fazla anlamı olur;
ternaryde üç parçalı anlamına geldiği için burada da uyuyorternaryo anlamda değilC'de
+iki girdi aldığı için binary operator'dür,?:ise üç girdi aldığı için ternary operator'dür. C'de tek örneği olduğu için genelde “the ternary operator” denir, yoksa özünde özel bir yanı yokturvpternlogd, üç girdi alan tüm bit düzeyindeki ternary operator'ları gerçekleştirirWindows'taki
BitBltişlevine benziyor olabilir mi diye düşündüm. En azından Windows 3.1 zamanından beri var gibiydi veopparametresiyle kaynak, hedef ve maskenin nasıl birleştirileceği belirleniyorduGirdilerden bağımsız olarak siyah üreten
BLACKNESS, kaynağı hedefe kopyalayanCOPYgibi kod adları olduğunu hatırlıyorum.BLACKNESSveWHITENESSkulağa bir şekilde şiirsel geliyorduPetzold'da okuduğumu hatırladığım kadarıyla bu yazılımla uygulanıyordu, ama çağrı sırasında opcode işlevin içinde özel assembly'ye çevrildiği için Windows işletim sistemindeki nadir self-modifying code örneklerinden biriydi
BitBltbaşlangıçta ikili işlemleri ters Polonya gösterimiyle saklayan karmaşık 16 bitlik “operation code”lar kullanıyorduSonra Amiga'daki gibi aynı bilgiyi 1 bayta sığdıran bir “operation index” eklendi; bu daha kısa ve daha zarif. Günümüzde her raster operation code hem operation index'i hem de operation code'u içerdiğinden kodlama yinelenmiş durumda. https://devblogs.microsoft.com/oldnewthing/20180528-00/?p=98...
FPGA'nın rastgele mantık fonksiyonlarını lookup table olarak gerçekleştirme biçimine benziyor
Ancak FPGA'lar ya da bu yazıdaki komut gibi özel amaçlı durumlar dışında bu genelde tercih edilmez. Yüksek hızlı register'lar ve statik RAM bazen mantıkla yapılır, ama kapılar yerine doğrudan transistörlerle yapmak daha yaygındır
74181arithmetic logic unit de bunu yapıyorhttps://www.sandpile.org sitesine gidip 3 baytlık opcode sayfasında https://www.sandpile.org/x86/opc_3.htm
VPTERNLOGöğesini ararsanız, Intel'in geçmişte planlamış gibi göründüğü bayt/word masking varyantı AVX512BITALG2'yi de görebilirsinizAyrıca
Iboperandındaki 256 olası durumun tamamını içeren üçlü mantık tablosu sayfasına da bağlanıyor: https://www.sandpile.org/x86/ternlog.htmDokümantasyon örneğinde
E2fonksiyonunun seçilmesinin nedeni, bunun üç girişli Boolean fonksiyonları arasında neredeyse en temel ve standart mux olması olabilir:BiseA, değilseCBu evrensel bir fonksiyondur; seçmek için ille de Amiga hayranı olmak gerekmez. Tabii gerçekten hayran olmuş da olabilirler
Bit düzeyindeki işlemlerin bir tamsayı içinde kodlandığı başka bir örnek de Win32'nin GDI ROP code'larıdır: https://learn.microsoft.com/en-us/windows/win32/gdi/ternary-...
Resmî bir Amiga donanım kılavuzum yoktu; onun yerine “Mapping the Amiga” kitabına bakıyordum. Aynı şeyleri biraz daha uzun anlatarak açıklıyordu
O sırada hangi minterm'leri kullandığımı hatırlamıyorum ama bu kitaba bakarak shadebobs, bobs ve XOR 3D çizgi çizimi gibi şeyleri bir şekilde yaptığımı sanıyorum
Mapping the Amiga'daki ilgili sayfa: https://archive.org/details/1993-thomson-randy-rhett-anderso...