Birçok uygulamada, komut yürütmesi beklenen giriş uyaranlarıyla bilinen bir zamanlama ilişkisi olan bir CPU, ilişki bilinmiyorsa çok daha hızlı bir CPU gerektiren görevleri işleyebilir. Örneğin, video oluşturmak için PSOC kullandığım bir projede, her 16 CPU saatinde bir bayt video verisi çıkışı için kod kullandım. SPI cihazının hazır olup olmadığının test edilmesi ve eğer değilse IIRC'nin 13 saat alacağı ve çıkış verisine yük ve depolamanın 11 alacağı test edildiğinden, cihazı baytlar arasında hazır olup olmadığını test etmenin bir yolu yoktu; Bunun yerine, işlemcinin ilkinden sonra her bayt için 16 döngünün kodunu tam olarak yürütmesini sağladım (gerçek bir dizinlenmiş yük, bir sahte dizin yükü ve bir mağaza kullandığımı düşünüyorum). Her satırın ilk SPI yazımı videonun başlamasından önce oldu, ve sonraki her yazma işlemi için, yazma işleminin arabellek aşımı veya az çalışması olmadan meydana gelebileceği 16-döngü bir pencere vardı. Dallanma döngüsü bir 13 döngü belirsizlik penceresi üretti, ancak öngörülebilir 16 döngü yürütme, sonraki tüm baytlar için belirsizliğin aynı 13 döngü penceresine uyacağı anlamına geliyordu (bu da yazmanın kabul edilebilir olduğu 16 döngü penceresine sığacak) ) meydana gelir.
Daha eski CPU'lar için, talimat zamanlama bilgileri açık, kullanılabilir ve açıktı. Daha yeni ARM'ler için, zamanlama bilgisi çok daha belirsiz görünüyor. Kod flash yürütülürken, önbellekleme davranışı tahmin etmek çok daha zor hale anlayabiliyorum, bu yüzden herhangi bir döngü sayılan kod RAM yürütülmelidir beklenebilir. RAM'den kod çalıştırırken bile, özellikler biraz belirsiz görünüyor. Çevrim sayımlı kod kullanımı hala iyi bir fikir midir? Öyleyse, güvenilir bir şekilde çalışması için en iyi teknikler nelerdir? Bir çip satıcısının, belirli durumlarda belirli talimatların yürütülmesini devre dışı bırakan bir "yeni geliştirilmiş" çipte sessizce kaymayacağını ne kadar güvenli bir şekilde varsayabiliriz?
Aşağıdaki döngünün bir kelime sınırında başladığı varsayılarak, spesifikasyonlara göre ne kadar süreceği kesin olarak nasıl belirlenir (Cortex-M3'ü sıfır bekleme durum hafızası ile varsayalım; sistem hakkında başka hiçbir şey bu örnek için önemli olmamalıdır).
myloop: mov r0, r0; Daha fazla talimatın önceden getirilmesine izin vermek için kısa basit talimatlar mov r0, r0; Daha fazla talimatın önceden getirilmesine izin vermek için kısa basit talimatlar mov r0, r0; Daha fazla talimatın önceden getirilmesine izin vermek için kısa basit talimatlar mov r0, r0; Daha fazla talimatın önceden getirilmesine izin vermek için kısa basit talimatlar mov r0, r0; Daha fazla talimatın önceden getirilmesine izin vermek için kısa basit talimatlar mov r0, r0; Daha fazla talimatın önceden getirilmesine izin vermek için kısa basit talimatlar r2, r1, # 0x12000000 ekler; 2 kelimelik talimat ; Muhtemelen farklı işlenenlerle aşağıdakileri tekrarlayın ; Bir taşıma gerçekleşene kadar değer eklemeye devam edecek ITCC addscc r2, r2, # 0x12000000; 2 kelimelik talimatlar, artı itcc için ekstra "kelime" ITCC addscc r2, r2, # 0x12000000; 2 kelimelik talimatlar, artı itcc için ekstra "kelime" ITCC addscc r2, r2, # 0x12000000; 2 kelimelik talimatlar, artı itcc için ekstra "kelime" ITCC addscc r2, r2, # 0x12000000; 2 kelimelik talimatlar, artı itcc için ekstra "kelime" ; ... vb, daha koşullu iki kelimelik talimatlarla alt r8, r8, # 1 bpl myloop
İlk altı talimatın yürütülmesi sırasında, çekirdeğin üç kelimeyi yürütecek altı kelimeyi getirecek zamanı olacaktır, bu nedenle önceden getirilmiş üç taneye kadar olabilir. Sonraki talimatların her biri üç kelimeden oluşur, bu nedenle çekirdeğin talimatları yürütülmekte olduğu kadar hızlı getirmesi mümkün olmaz. Bazı "bu" talimatların bir döngü alacağını umuyorum, ama hangilerini tahmin edeceğimi bilmiyorum.
ARM'nin "it" talimat zamanlamasının belirleyici olacağı belirli koşulları belirleyebilmesi iyi olurdu (örneğin, bekleme durumları veya kod-veri yolu çekişmesi yoksa ve önceki iki talimat 16 bit kayıt talimatları vb. İse) ama böyle bir özellik görmedim.
Örnek uygulama
Birinin 480P'de komponent video çıkışı oluşturmak için Atari 2600 için bir anakart tasarlamaya çalıştığını varsayalım. 2600, 3.579MHz piksel saatine ve 1.19MHz CPU saatine (nokta saati / 3) sahiptir. 480P komponent video için, her bir hattın 7.158MHz nokta saat çıkışı anlamına gelen iki çıkışı olmalıdır. Atari'nin video yongası (TIA), 3 bit luma sinyali artı yaklaşık 18ns çözünürlüğe sahip bir faz sinyali kullanarak 128 renkten birini çıkardığı için, yalnızca çıktılara bakarak rengi doğru bir şekilde belirlemek zor olacaktır. Daha iyi bir yaklaşım, renk kayıtlarına yazma işlemlerini durdurmak, yazılan değerleri gözlemlemek ve her kaydı, kayıt numarasına karşılık gelen TIA parlaklık değerlerinde beslemek olacaktır.
Tüm bunlar bir FPGA ile yapılabilir, ancak bazı oldukça hızlı ARM cihazları, gerekli tamponlamayı işlemek için yeterli RAM'e sahip bir FPGA'dan çok daha ucuza sahip olabilir (evet, bu tür bir şeyin üretilebileceğini biliyorum. t gerçek bir faktör). Ancak, ARM'nin gelen saat sinyalini izlemesini istemek, gerekli CPU hızını önemli ölçüde artıracaktır. Öngörülebilir döngü sayıları işleri daha temiz hale getirebilir.
Nispeten basit bir tasarım yaklaşımı, bir CPLD'nin CPU ve TIA'yı izlemesi ve 13 bit RGB + senkronizasyon sinyali üretmesi ve daha sonra ARM DMA'nın bir porttan 16 bit değerleri alması ve bunları uygun zamanlamayla yazmasıdır. Bununla birlikte, ucuz bir ARM'nin her şeyi yapıp yapamayacağını görmek ilginç bir tasarım zorluğu olurdu. CPU döngüsü sayıları üzerindeki etkileri tahmin edilebilirse (özellikle bellek veri yolu başka bir şekilde boşta olduğunda döngülerde DMA döngüleri meydana gelebiliyorsa), ancak sürecin bir noktasında DMA, hepsi bir arada bir yaklaşımın yararlı bir yönü olabilir. ARM masa araması ve otobüs izleme işlevlerini yerine getirmek zorundaydı. Karartma aralıkları sırasında renk kayıtlarının yazıldığı birçok video mimarisinin aksine, Atari 2600'ün bir karenin görüntülenen bir bölümü sırasında sık sık renk kayıtlarına yazdığını,
Belki de en iyi yaklaşım, renk yazmalarını tanımlamak ve renk kayıtlarının alt bitlerini uygun değerlere zorlamak için birkaç ayrık mantık yongaları kullanmak ve daha sonra gelen CPU veri yolu ve TIA çıkış verilerini örneklemek için iki DMA kanalı kullanmak ve çıkış verilerini oluşturmak için üçüncü bir DMA kanalı. CPU daha sonra her tarama hattı için her iki kaynaktan gelen tüm verileri işlemek, gerekli çeviriyi yapmak ve çıktı için arabelleğe almakta serbesttir. Bağdaştırıcının görevlerinin "gerçek zamanlı" olarak gerçekleşmesi gereken tek yönü, COLUxx'a yazılan verilerin geçersiz kılınmasıdır ve bu iki ortak mantık yongalarının kullanılmasıyla halledilebilir.