Penghitungan siklus dengan CPU modern (mis. ARM)

14

Dalam banyak aplikasi, CPU yang pelaksanaan instruksinya memiliki hubungan waktu yang diketahui dengan rangsangan input yang diharapkan dapat menangani tugas-tugas yang akan membutuhkan CPU yang jauh lebih cepat jika hubungannya tidak diketahui. Misalnya, dalam proyek yang saya lakukan menggunakan PSOC untuk menghasilkan video, saya menggunakan kode untuk menghasilkan satu byte data video setiap 16 jam CPU. Karena menguji apakah perangkat SPI siap dan bercabang jika IIRC tidak akan mengambil 13 jam, dan memuat dan menyimpan data keluaran akan memakan waktu 11, tidak ada cara untuk menguji kesiapan perangkat antara byte; sebagai gantinya, saya hanya mengatur agar prosesor mengeksekusi kode persis 16 siklus untuk setiap byte setelah yang pertama (saya percaya saya menggunakan beban nyata yang diindeks, beban yang diindeks boneka, dan toko). Tulisan SPI pertama dari setiap baris terjadi sebelum video dimulai, dan untuk setiap penulisan berikutnya ada jendela 16-siklus di mana penulisan dapat terjadi tanpa buffer overrun atau underrun. Loop cabang menghasilkan jendela 13 siklus ketidakpastian, tetapi eksekusi 16 siklus yang dapat diprediksi berarti bahwa ketidakpastian untuk semua byte berikutnya akan cocok dengan jendela 13 siklus yang sama (yang pada gilirannya sesuai dengan jendela 16 siklus ketika penulisan dapat diterima terjadi).

Untuk CPU yang lebih tua, informasi waktu instruksi jelas, tersedia, dan tidak ambigu. Untuk ARM yang lebih baru, informasi waktu tampaknya jauh lebih kabur. Saya mengerti bahwa ketika kode dieksekusi dari flash, perilaku caching dapat membuat hal-hal lebih sulit untuk diprediksi, jadi saya berharap bahwa setiap kode yang dihitung siklus harus dieksekusi dari RAM. Bahkan ketika mengeksekusi kode dari RAM, spesifikasi tampak agak kabur. Apakah penggunaan kode yang dihitung siklus masih merupakan ide yang bagus? Jika demikian, apa teknik terbaik untuk membuatnya bekerja dengan andal? Sejauh mana seseorang dapat dengan aman berasumsi bahwa vendor chip tidak akan secara diam-diam menyelipkan chip "baru yang ditingkatkan" yang mengurangi siklus pelaksanaan instruksi tertentu dalam kasus-kasus tertentu?

Dengan asumsi loop berikut dimulai pada batas kata, bagaimana seseorang menentukan berdasarkan spesifikasi dengan tepat berapa lama (anggap Cortex-M3 dengan memori nol-tunggu-negara; tidak ada hal lain tentang sistem yang penting untuk contoh ini).

myloop:
  mov r0, r0; Instruksi sederhana singkat untuk memungkinkan lebih banyak instruksi untuk dibuat lebih dulu
  mov r0, r0; Instruksi sederhana singkat untuk memungkinkan lebih banyak instruksi untuk dibuat lebih dulu
  mov r0, r0; Instruksi sederhana singkat untuk memungkinkan lebih banyak instruksi untuk dibuat lebih dulu
  mov r0, r0; Instruksi sederhana singkat untuk memungkinkan lebih banyak instruksi untuk dibuat lebih dulu
  mov r0, r0; Instruksi sederhana singkat untuk memungkinkan lebih banyak instruksi untuk dibuat lebih dulu
  mov r0, r0; Instruksi sederhana singkat untuk memungkinkan lebih banyak instruksi untuk dibuat lebih dulu
  menambahkan r2, r1, # 0x12000000; Instruksi 2 kata
  ; Ulangi yang berikut ini, mungkin dengan operan yang berbeda
  ; Akan terus menambahkan nilai sampai terjadi carry
  itcc
  tambahcc r2, r2, # 0x12000000; Instruksi 2 kata, plus "kata" tambahan untuk itcc
  itcc
  tambahcc r2, r2, # 0x12000000; Instruksi 2 kata, plus "kata" tambahan untuk itcc
  itcc
  tambahcc r2, r2, # 0x12000000; Instruksi 2 kata, plus "kata" tambahan untuk itcc
  itcc
  tambahcc r2, r2, # 0x12000000; Instruksi 2 kata, plus "kata" tambahan untuk itcc
; ... dll, dengan instruksi dua kata yang lebih kondisional
  sub r8, r8, # 1
  bpl myloop

Selama pelaksanaan enam instruksi pertama, inti akan memiliki waktu untuk mengambil enam kata, dimana tiga akan dieksekusi, sehingga mungkin ada hingga tiga instruksi yang diambil sebelumnya. Instruksi selanjutnya adalah tiga kata masing-masing, sehingga inti tidak mungkin mengambil instruksi secepat mereka dieksekusi. Saya akan berharap bahwa beberapa instruksi "itu" akan mengambil siklus, tetapi saya tidak tahu bagaimana memprediksi yang mana.

Alangkah baiknya jika ARM dapat menentukan kondisi tertentu di mana waktu instruksi "itu" akan menjadi deterministik (misalnya jika tidak ada status tunggu atau pertentangan kode-bus, dan dua instruksi sebelumnya adalah instruksi register 16-bit, dll.) tapi saya belum melihat spek seperti itu.

Contoh aplikasi

Misalkan seseorang sedang mencoba mendesain papan induk untuk Atari 2600 untuk menghasilkan output video komponen pada 480P. 2600 memiliki clock pixel 3,579MHz, dan clock CPU 1,19MHz (dot clock / 3). Untuk video komponen 480P, setiap baris harus menjadi output dua kali, menyiratkan output clock clock 7,158MHz. Karena chip video Atari (TIA) mengeluarkan salah satu dari 128 warna menggunakan sinyal luma 3-bit plus sinyal fase dengan resolusi sekitar 18ns, akan sulit untuk menentukan warna secara akurat hanya dengan melihat keluarannya. Pendekatan yang lebih baik adalah dengan mencegat penulisan ke register warna, mengamati nilai-nilai yang ditulis, dan memberi makan setiap register dalam nilai luminansi TIA yang sesuai dengan nomor register.

Semua ini dapat dilakukan dengan FPGA, tetapi beberapa perangkat ARM yang cukup cepat dapat memiliki jauh lebih murah daripada FPGA dengan RAM yang cukup untuk menangani buffering yang diperlukan (ya, saya tahu bahwa untuk volume hal seperti itu dapat dihasilkan biayanya bukan t faktor nyata). Namun, mewajibkan ARM untuk menonton sinyal jam yang masuk akan secara signifikan meningkatkan kecepatan CPU yang diperlukan. Hitungan siklus yang dapat diprediksi dapat membuat segalanya lebih bersih.

Pendekatan desain yang relatif sederhana adalah membuat CPLD menonton CPU dan TIA dan menghasilkan sinyal sinkronisasi 13-bit RGB +, dan kemudian ARM DMA mengambil nilai 16-bit dari satu port dan menulisnya ke port lain dengan waktu yang tepat. Ini akan menjadi tantangan desain yang menarik, untuk melihat apakah ARM yang murah dapat melakukan segalanya. DMA bisa menjadi aspek yang berguna dari pendekatan all-in-one jika efeknya pada jumlah siklus CPU dapat diprediksi (terutama jika siklus DMA dapat terjadi dalam siklus ketika bus memori sedang tidak digunakan), tetapi pada beberapa titik dalam proses ARM harus melakukan fungsi lookup table dan bus-watching. Perhatikan bahwa tidak seperti banyak arsitektur video di mana register warna ditulis selama interval pengosongan, Atari 2600 sering menulis ke register warna selama bagian bingkai yang ditampilkan,

Mungkin pendekatan terbaik adalah dengan menggunakan beberapa chip diskrit-logika untuk mengidentifikasi penulisan warna dan memaksa bit-bit register warna ke nilai yang tepat, dan kemudian menggunakan dua saluran DMA untuk sampel bus CPU yang masuk dan data output TIA, dan saluran DMA ketiga untuk menghasilkan data output. CPU kemudian akan bebas untuk memproses semua data dari kedua sumber untuk setiap baris pemindaian, melakukan terjemahan yang diperlukan, dan buffer untuk output. Satu-satunya aspek tugas adaptor yang harus terjadi dalam "waktu nyata" adalah menimpa data yang ditulis ke COLUxx, dan itu bisa diatasi dengan menggunakan dua chip logika umum.

supercat
sumber

Jawaban:

7

Saya memilih DMA. Ini sangat fleksibel di Cortex-M3 dan lebih tinggi - dan Anda dapat melakukan semua jenis hal gila seperti secara otomatis mendapatkan data dari satu tempat dan mengeluarkannya ke tempat lain dengan laju yang ditentukan atau pada beberapa peristiwa tanpa menghabiskan siklus CPU APA PUN. DMA jauh lebih dapat diandalkan.

Tetapi mungkin agak sulit untuk memahami secara detail.

Pilihan lain adalah soft-core pada FPGA dengan implementasi perangkat keras dari hal-hal yang ketat ini.

BarsMonster
sumber
1
Saya suka gagasan DMA. Saya tidak berpikir inti Cortex M3 memiliki DMA, meskipun - itu adalah fungsi dari chip masing-masing produsen, dan mereka semua tampaknya menerapkannya secara berbeda. Satu hal yang saya anggap menjengkelkan dengan setidaknya satu implementasi saya benar-benar bermain dengan (STM32L152), adalah bahwa saya tidak dapat menemukan cara untuk memiliki pin strobo ketika data DMA adalah output. Juga tidak jelas faktor apa yang dapat mempengaruhi ketepatan waktu DMA.
supercat
1
Dalam hal apa pun, sehubungan dengan salah satu aplikasi pertama yang saya renungkan untuk pemukulan siklus yang tepat, saya memposting lebih banyak informasi dalam pertanyaan awal. Saya ingin tahu apa yang Anda pikirkan. Situasi lain di mana saya merenungkan siklus-memukul akan peledakan data tampilan ke LCD berwarna. Data akan buffered dalam RAM menggunakan warna 8-bit, tetapi layar membutuhkan warna 16-bit. Cara tercepat yang saya pikirkan untuk menghasilkan data adalah dengan menggunakan perangkat keras untuk menghasilkan tulisan tulis, sehingga CPU hanya perlu mencatat data. Apakah lebih baik menerjemahkan 8-> 16 bit ke dalam buffer kecil ...
supercat
1
... dan kemudian mengatur DMA untuk mentransfer itu, atau apa yang akan menjadi pendekatan terbaik?
supercat
4

Informasi waktu tersedia, tetapi, seperti yang Anda tunjukkan, kadang-kadang bisa kabur. Ada banyak informasi waktu dalam Bagian 18.2 dan Tabel 18.1 dari Manual Referensi Teknis untuk Cortex-M3, misalnya, ( pdf di sini ), dan kutipan di sini:

kutipan 18.2

yang memberikan daftar kondisi waktu maksimum. Waktu untuk banyak instruksi tergantung pada faktor-faktor eksternal, beberapa di antaranya memang meninggalkan ambiguitas. Saya telah menyoroti setiap ambiguitas yang saya temukan dalam kutipan berikut dari bagian itu:

[1] Cabang mengambil satu siklus untuk instruksi dan kemudian pipa kembali untuk instruksi target. Cabang yang tidak diambil adalah total 1 siklus. Cabang yang diambil dengan segera biasanya 1 siklus pemuatan pipa (total 2 siklus). Cabang yang diambil dengan register operan biasanya 2 siklus pemuatan pipa (total 3 siklus). Reload pipeline lebih lama [Berapa lama lagi?] Ketika bercabang ke instruksi 32-bit yang tidak selaras selain mengakses memori yang lebih lambat. Petunjuk cabang dipancarkan ke bus kode yang memungkinkan sistem lebih lambat [Berapa banyak lebih lambat?] Untuk dimuat sebelumnya. Ini dapat [Apakah ini opsional?] Mengurangi [Berapa banyak?] Penalti target cabang untuk memori lebih lambat, tetapi tidak pernah kurang dari yang ditunjukkan di sini.

[2] Secara umum, instruksi penyimpanan memuat mengambil dua siklus untuk akses pertama dan satu siklus untuk setiap akses tambahan. Toko dengan offset langsung membutuhkan satu siklus.

[3] UMULL / SMULL / UMLAL / SMLAL menggunakan terminasi dini tergantung pada ukuran nilai sumber [Ukuran apa?]. Ini adalah interruptible (ditinggalkan / restart), dengan latensi terburuk dari satu siklus. Versi MLAL mengambil empat hingga tujuh siklus dan versi MULL mengambil tiga hingga lima siklus . Untuk MLAL, versi yang ditandatangani lebih lama satu siklus dari yang tidak ditandatangani.

[4] Instruksi TI dapat dilipat . [Kapan? Lihat komentar.]

[5] Pengaturan waktu DIV tergantung pada dividen dan pembagi . [Masalah yang sama dengan MUL] DIV adalah interruptible (ditinggalkan / restart), dengan latensi terburuk dari satu siklus. Ketika dividen dan pembagi yang sama [Bagaimana serupa?] Dalam ukuran, membagi berakhir dengan cepat. Waktu minimum untuk kasus pembagi lebih besar dari dividen dan pembagi nol. Pembagi nol mengembalikan nol (bukan kesalahan), meskipun perangkap debug tersedia untuk menangkap kasus ini. [Berapa kisaran, yang diberikan untuk MUL?]

[6] Tidur adalah satu siklus untuk instruksi plus sebanyak mungkin siklus tidur. WFE hanya menggunakan satu siklus ketika acara telah berlalu. WFI biasanya lebih dari satu siklus kecuali gangguan terjadi tepat saat memasuki WFI.

[7] ISB membutuhkan satu siklus (bertindak sebagai cabang). DMB dan DSB mengambil satu siklus kecuali data tertunda di buffer tulis atau LSU. Jika interupsi datang selama penghalang, itu ditinggalkan / dimulai kembali.

Untuk semua kasus penggunaan, ini akan lebih kompleks daripada "Instruksi ini adalah satu siklus, instruksi ini adalah dua siklus, ini adalah satu siklus ..." menghitung kemungkinan dalam prosesor yang lebih sederhana, lebih lambat, lebih tua. Untuk beberapa kasus penggunaan, Anda tidak akan menemukan ambiguitas. Jika Anda menemukan ambiguitas, saya sarankan:

  1. Hubungi vendor Anda dan tanyakan kepada mereka berapa waktu instruksi untuk use case Anda.
  2. Tes untuk menentukan perilaku yang ambigu
  3. Tes ulang untuk setiap revisi prosesor dan terutama ketika melalui perubahan vendor.

Persyaratan ini mungkin menjawab pertanyaan Anda, "Tidak, itu bukan ide yang baik, kecuali kesulitan yang dihadapi sepadan dengan biayanya" - tetapi Anda sudah tahu itu.

Kevin Vermeer
sumber
1
Saya akan menganggap yang berikut ini tidak jelas: "Reload pipa lebih panjang ketika bercabang ke instruksi 32-bit yang tidak selaras selain mengakses ke memori yang lebih lambat" tidak mengatakan apakah ia menambahkan satu siklus dengan tepat, dan "Instruksi TI dapat dilipat" tidak dapat menentukan dalam kondisi apa mereka mau atau tidak.
supercat
1
Waktu "IT" akan tampak sangat mengganggu, karena itu adalah instruksi yang akan sering digunakan dalam siklus penghitungan siklus yang ketat, dan saya cukup yakin itu tidak selalu dapat dilipat. Saya akan menebak bahwa jika seseorang selalu cabang ke awal loop sensitif-waktu, memaksa loop untuk memulai pada batas kata, menghindari beban bersyarat atau menyimpan dalam loop, dan orang tidak segera menempatkan instruksi "IT" setelah memuat atau memperbarui toko, pengaturan waktu "IT" akan konsisten, tetapi spesifikasi tidak menjelaskannya.
supercat
1
Dugaan saya adalah bahwa TI mungkin dapat (dengan jujur) mencatat sesuatu seperti, "Dengan tidak adanya status tunggu atau pertentangan kode-bus, TI dapat dilipat jika (1) instruksi sebelumnya adalah instruksi 16-bit yang tidak dapat diakses. memori atau penghitung program, dan (2) instruksi selanjutnya adalah instruksi 16-bit, atau instruksi sebelumnya bukanlah target dari cabang "tidak selaras". Pelipatan TI juga dapat terjadi dalam keadaan lain yang tidak ditentukan. " Spesifikasi semacam itu akan memungkinkan seseorang untuk menulis program dengan waktu instruksi-TI yang dapat diprediksi dengan memastikan kode tersebut diatur seperti yang ditunjukkan.
supercat
1
Wow - saya akui bahwa saya hanya melewati hitungan siklus kasus terburuk yang sederhana, daripada benar-benar bergumul dengan peringatan di bawah meja. Jawaban saya yang diperbarui menyoroti beberapa ambiguitas lainnya.
Kevin Vermeer
1
Ada banyak situasi di mana seseorang tertarik pada jumlah kasus terburuk, dan cukup banyak di mana seseorang tertarik pada jumlah kasus terbaik (misalnya jika port SPI dapat menghasilkan satu byte setiap 16 siklus, menghasilkan setiap byte akan membutuhkan 14 siklus kasus terbaik, dan memeriksa kesiapan akan membutuhkan 5 siklus, memeriksa kesiapan setiap byte akan membatasi kecepatan hingga satu byte setiap 19 siklus kasus terbaik, menulis secara membabi buta dengan dua NOP ditambahkan akan memungkinkan kecepatan satu byte setiap 16 siklus kasus terbaik ). Kasus-kasus di mana waktu yang tepat diperlukan tidak seperti biasa, tetapi mereka dapat muncul.
supercat
3

Salah satu cara untuk mengatasi masalah ini adalah dengan menggunakan perangkat dengan timing deterministik atau yang dapat diprediksi, seperti Parallax Propeller dan chip XMOS:

http://www.parallaxsemiconductor.com/multicoreconcept

http://www.xmos.com/

Penghitungan siklus berfungsi sangat baik dengan Propeller (bahasa assembly harus digunakan), sementara perangkat XMOS memiliki utilitas perangkat lunak yang sangat kuat, XMOS Timing Analyzer, yang bekerja dengan aplikasi yang ditulis dalam bahasa pemrograman XC:

https://www.xmos.com/download/public/XMOS-Timing-Analyzer-Whitepaper%281%29.pdf

Leon Heller
sumber
1
Saya mulai berpikir Leon memiliki saham di XMOS ... ;-)
Federico Russo
1
Saya suka keripik mereka, dan orang-orang yang bekerja di sana. Parallax adalah perusahaan yang baik dengan produk yang bagus juga.
Leon Heller
1
Ya, jangan tersinggung. Itu hanya mengejutkan saya bahwa semua jawaban (kecuali satu) di mana XMOS disebutkan berasal dari Anda. Tidak ada yang salah dengan menjadi antusias tentang sesuatu.
Federico Russo
@Federico, @Leon - Itulah tepatnya yang membuat saya sedikit khawatir tentang XMOS: mengapa hanya ada 1 pengguna di dunia (setidaknya seperti itulah tampilannya)? Jika ini luar biasa, mengapa ini tidak menjadi pembicaraan di kota? Saya tidak pernah mendengar ada yang membicarakannya, lebih jarang menggunakannya.
stevenvh
Coba forum XMOS: xcore.com
Leon Heller
2

Penghitungan siklus menjadi lebih bermasalah saat Anda menjauh dari mikrokontroler tingkat rendah dan menjadi prosesor komputasi tujuan umum. Yang pertama biasanya memiliki waktu instruksi yang ditentukan dengan baik, sebagian karena alasan situs Anda. Itu juga karena arsitektur mereka cukup sederhana, sehingga waktu instruksi tetap dan dapat diketahui.

Contoh yang baik dari ini adalah kebanyakan Microchip PIC. Seri 10, 12, 16, dan 18 memiliki timing instruksi yang sangat terdokumentasi dan dapat diprediksi. Ini bisa menjadi fitur yang berguna dalam jenis aplikasi kontrol kecil yang dimaksudkan oleh chip ini.

Saat Anda keluar dari biaya sangat rendah, dan oleh karena itu perancang dapat menghabiskan lebih banyak area chip untuk mendapatkan kecepatan lebih tinggi dari arsitektur yang lebih eksotis, Anda juga bisa lolos dari kemungkinan yang dapat diprediksi. Lihatlah varian x86 modern sebagai contoh ekstrem dari ini. Ada beberapa level cache, vitualisasi memori, lookahead fetch, pipelining, dan banyak lagi, yang membuat penghitungan siklus instruksi hampir mustahil. Dalam aplikasi ini tidak masalah karena pelanggan tertarik pada kecepatan tinggi, bukan prediksi waktu instruksi.

Anda bahkan dapat melihat efek ini bekerja di model Microchip yang lebih tinggi. Inti 24 bit (seri 24, 30, dan 33) memiliki timing instruksi yang dapat diprediksi secara luas, kecuali untuk beberapa pengecualian ketika ada pertengkaran bus yang didaftarkan. Misalnya, dalam beberapa kasus mesin memasukkan warung ketika instruksi selanjutnya menggunakan register dengan beberapa mode pengalamatan tidak langsung yang nilainya diubah dalam instruksi sebelumnya. Jenis kios ini tidak biasa pada dsPIC, dan sebagian besar waktu Anda dapat mengabaikannya, tetapi ini menunjukkan bagaimana hal-hal ini merayap masuk karena para perancang berusaha memberi Anda prosesor yang lebih cepat dan lebih mampu.

Jadi jawaban dasarnya adalah, itulah bagian dari tradeoff ketika Anda memilih prosesor. Untuk aplikasi kontrol kecil, Anda dapat memilih sesuatu yang kecil, murah, berdaya rendah, dan dengan waktu instruksi yang dapat diprediksi. Ketika Anda menuntut lebih banyak kekuatan pemrosesan, arsitekturnya berubah sehingga Anda harus melepaskan waktu instruksi yang dapat diprediksi. Untungnya, itu bukan masalah karena Anda dapat lebih banyak aplikasi komputasi intensif dan tujuan umum, jadi saya pikir tradeoffs bekerja dengan cukup baik.

Olin Lathrop
sumber
Saya setuju bahwa secara umum aplikasi yang lebih intensif komputasi menjadi kurang sensitif terhadap waktu mikroskopis, tetapi ada beberapa skenario di mana orang mungkin memerlukan sedikit lebih banyak pemrosesan dari pada PIC-18 tetapi juga perlu diprediksi. Saya bertanya-tanya sejauh mana saya harus berusaha untuk mempelajari hal-hal seperti arsitektur PIC 16-bit, atau sejauh mana saya harus mengetahui ARM kemungkinan akan memadai.
supercat
0

Ya, Anda masih bisa melakukannya, bahkan pada ARM. Masalah terbesar dengan itu pada ARM adalah bahwa ARM menjual core bukan chip, dan waktu inti diketahui, tetapi apa yang dibungkus oleh vendor chip bervariasi dari vendor ke vendor dan kadang-kadang dari keluarga chip ke yang lain dalam vendor. Jadi chip tertentu dari vendor tertentu bisa sangat deterministik (jika Anda tidak menggunakan cache misalnya), tetapi menjadi lebih sulit untuk port. Ketika berhadapan dengan 5 jam di sini dan 11 jam di sana menggunakan pengatur waktu bermasalah karena jumlah instruksi yang diperlukan untuk sampel timer dan mencari tahu apakah batas waktu Anda telah kedaluwarsa. Dari suara pengalaman pemrograman Anda sebelumnya, saya berani bertaruh Anda mungkin debug dengan osiloskop seperti yang saya lakukan, sehingga Anda dapat mencoba loop ketat pada chip pada clock rate, melihat spi atau i2c atau bentuk gelombang apa pun, tambahkan atau menghapus nops, ubah berapa kali melalui loop dan pada dasarnya tune. Seperti halnya platform apa pun, tidak menggunakan interupsi sangat membantu sifat deterministik pelaksanaan instruksi.

Tidak, ini tidak sesederhana PIC, tetapi masih cukup bisa dilakukan, terutama jika penundaan / waktu mendekati laju clock prosesor. Sejumlah vendor berbasis ARM memungkinkan Anda untuk melipatgandakan clock rate dan menghilangkan 60MHz dari referensi 8 mhz, jadi jika Anda memerlukan antarmuka 2mhz alih-alih melakukan sesuatu setiap 4 instruksi, Anda dapat meningkatkan clock (jika Anda memiliki anggaran daya) dan kemudian gunakan timer dan beri diri Anda banyak jam untuk melakukan hal-hal lain juga.

old_timer
sumber