Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Industrial programming >> VHDL

Cara membuat Daftar Tertaut di VHDL

Daftar tertaut adalah struktur data dinamis. Daftar tertaut dapat digunakan ketika jumlah total elemen tidak diketahui sebelumnya. Itu tumbuh dan menyusut dalam memori, relatif terhadap jumlah item yang dikandungnya.

Daftar tertaut paling mudah diimplementasikan menggunakan kelas dalam bahasa pemrograman berorientasi objek. VHDL memiliki beberapa fitur berorientasi objek yang dapat digunakan untuk mengabstraksikan kompleksitas implementasi dari pengguna.

Pada artikel ini kita akan menggunakan tipe akses, catatan, dan tipe yang dilindungi untuk mengimplementasikan daftar tertaut di VHDL. Kami akan membuat paket VHDL baru di mana kami akan menulis semua kode daftar tertaut kami.

Paket

Hal pertama yang akan kita lakukan adalah mendeklarasikan sebuah paket yang akan berisi kode kita. Paket VHDL adalah kumpulan tipe, objek, atau subprogram yang dapat diimpor ke file VHDL lain. Sebagian besar modul VHDL mengimpor paket std_logic_1164 dari perpustakaan IEEE. Kami membuat paket kami sendiri, sangat mirip.

Isi file DataStructures.vhd baru kami:

package DataStructures is
   -- Public declarations go here
end package DataStructures;
 
package body DataStructures is
   -- Private declarations and implementations go here
end package body DataStructures;

Meskipun paket hanya akan berisi implementasi daftar tertaut, kami akan membuktikannya di masa mendatang dengan menamakannya DataStructures. Orang dapat dengan mudah membayangkan bahwa seseorang ingin menambahkan struktur data lain seperti pohon atau peta hash ke dalamnya nanti.

Paket terdiri dari dua bagian; wilayah deklaratif, dan badan. Wilayah deklaratif adalah tempat Anda meletakkan segala sesuatu yang seharusnya terlihat oleh pengguna paket. Tubuh dilindungi secara pribadi, dan tidak dapat diakses dari luar.

Jenis yang dilindungi

Jenis yang dilindungi adalah konstruksi seperti kelas di VHDL. Mereka dapat berisi subprogram, deklarasi tipe, dan variabel. Jenis yang dilindungi terdiri dari deklarasi publik dan badan pribadi. Kami akan menambahkan deklarasi ke deklarasi paket, dan badan ke badan paket.

File DataStructures.vhd kami setelah menambahkan jenis yang dilindungi:

package DataStructures is

   type LinkedList is protected

      -- Prototypes of subprograms
      procedure Push(constant Data : in integer);
      impure function Pop return integer;
      impure function IsEmpty return boolean;

   end protected;

end package DataStructures;

package body DataStructures is

   type LinkedList is protected body
   end protected body;

end package body DataStructures;

Kami menamai tipe yang dilindungi LinkedList karena akan berisi semua yang terkait dengan daftar tertaut. Jika kita menambahkan jenis struktur data lain ke paket, itu berarti jenis lain yang dilindungi.

Dalam wilayah deklaratif dari tipe yang dilindungi, kami telah mendeklarasikan tiga subprogram. Belum ada implementasinya, nanti kita bahas. Agar subprogram terlihat di luar tipe yang dilindungi, mereka harus dideklarasikan di sini.

Tiga subprogram adalah metode daftar tertaut standar:Push, Pop, dan IsEmpty. Push menambahkan elemen baru ke awal daftar. Pop menghapus elemen dari akhir daftar. IsEmpty adalah fungsi utilitas yang mengembalikan true jika daftarnya kosong.

Rekam

Catatan adalah tipe komposit yang mungkin berisi beberapa tipe anggota. Ini bekerja seperti struct dalam bahasa pemrograman C. Ketika sinyal atau variabel dibuat dari tipe record, anggota data dapat direferensikan dengan menggunakan "." notasi. Misalnya MyItem.Data .

Deklarasi rekaman kami di dalam badan tipe yang dilindungi:

   type LinkedList is protected body

      type Item is record
         Data : integer;
         NextItem : Ptr;
      end record;

   end protected body;

Kami telah mendeklarasikan tipe record di badan tipe yang dilindungi. Wilayah deklaratif dari tipe yang dilindungi tidak dapat berisi deklarasi tipe atau sinyal lain, jadi kita harus mendeklarasikannya di badan tipe yang dilindungi.

Itu bukan masalah bagi kami karena Item adalah tipe yang digunakan secara internal. Tidak perlu terlihat dari luar. Pengguna daftar tertaut harus mengaksesnya hanya melalui tiga subprogram yang dideklarasikan secara publik.

Catatan kami berisi dua anggota data; Data dan Item Berikutnya. Sedangkan Data bertipe integer , NextItem adalah, untuk saat ini, tipe Ptr misterius.

Jenis akses

Jenis akses adalah pointer VHDL. Dengan menggunakannya, kita dapat membuat objek secara dinamis selama run-time. Kami akan mendeklarasikan tipe akses baru bernama Ptr yang akan menunjuk ke objek yang dibuat secara dinamis dari tipe Item.

Badan paket dengan jenis akses baru ditambahkan:

package body DataStructures is

   type LinkedList is protected body

      -- Declaration of incomplete Item type
      type Item;

      -- Declaration of pointer type to the Item type
      type Ptr is access Item;

      -- Full declaration of the Item type
      type Item is record
         Data : integer;
         NextItem : Ptr; -- Pointer to the next Item
      end record;

      -- Root of the linked list
      variable Root : Ptr;

end package body DataStructures;

Sebuah node daftar tertaut harus berisi referensi ke node berikutnya dalam daftar. Kami telah menerapkan ini dalam catatan Item dengan anggota NextItem. Ini adalah tipe Ptr, yang pada gilirannya merupakan penunjuk kembali ke tipe Item. Untuk menghindari masalah ayam/telur ini, pertama-tama kami mendeklarasikan Item sebagai tipe yang tidak lengkap. Kemudian, kami mendeklarasikan tipe Ptr sebagai penunjuk ke tipe yang tidak lengkap. Terakhir, kita tentukan deklarasi lengkap dari tipe Item.

Hal terakhir yang kami lakukan adalah mendeklarasikan variabel baru bernama Root dengan tipe Ptr. Ini akan menjadi akar dari daftar tertaut. Jika daftar kosong, nilai Root akan menjadi null . Jika tidak, itu akan menunjuk ke item pertama dalam daftar.

Metode daftar tertaut

Sekarang saatnya untuk mengimplementasikan subprogram yang kami deklarasikan di wilayah deklaratif dari tipe yang dilindungi. Itu adalah prosedur Push, dan dua fungsi tidak murni:Pop dan IsEmpty.

Kami akan menempatkan implementasi subprogram di dalam tubuh tipe yang dilindungi.

Tekan

Push adalah satu-satunya subprogram yang merupakan prosedur. Fungsi dalam VHDL memerlukan nilai kembalian yang tidak dapat dihilangkan. Untuk menghindari penggunaan nilai pengembalian dummy, prosedur lebih disukai.

Prosedur Push:

procedure Push(Data : in integer) is
   variable NewItem : Ptr;
   variable Node : Ptr;
begin
   -- Dynamically allocate a new item
   NewItem := new Item;
   NewItem.Data := Data;

   -- If the list is empty, this becomes the root node
   if Root = null then
      Root := NewItem;

   else
      -- Start searching from the root node
      Node := Root;

      -- Find the last node
      while Node.NextItem /= null loop
         Node := Node.NextItem;
      end loop;

      -- Append the new item at the end of the list
      Node.NextItem := NewItem;
   end if;
end;

Hal pertama yang terjadi adalah objek baru bertipe Item dialokasikan secara dinamis. Ini dilakukan dengan menggunakan new kata kunci. Setiap kali new kata kunci digunakan, memori dinamis digunakan oleh simulator.

Sisa kode hanyalah algoritma daftar tertaut standar. Item baru ditambahkan ke akhir daftar, atau menjadi item Root jika daftar kosong. Baca daftar tertaut di Wikipedia jika Anda membutuhkan lebih banyak latar belakang.

Pop

Pop menghapus elemen tertua dari daftar dan mengembalikannya ke pemanggil. Jika kita hanya menghapus referensi ke elemen yang muncul dan mengembalikannya, akan ada kehilangan memori di simulator. Setelah panggilan fungsi selesai, referensi ke objek yang dibuat secara dinamis akan hilang selamanya.

Tidak ada pengumpulan sampah di VHDL sebelum VHDL-2017 (juga disebut sebagai VHDL-2018 atau VHDL-2019). Dan VHDL-2017 tidak didukung oleh sebagian besar simulator. Oleh karena itu, kita harus memanggil deallocate sebelum kembali dari fungsinya.

deallocate operator membebaskan memori yang digunakan oleh objek yang dialokasikan secara dinamis. Untuk setiap panggilan ke new , harus ada panggilan ke deallocate sebelum referensi ke objek dihapus.

Fungsi Pop:

impure function Pop return integer is
   variable Node : Ptr;
   variable RetVal : integer;
begin
   Node := Root;
   Root := Root.NextItem;

   -- Copy and free the dynamic object before returning
   RetVal := Node.Data;
   deallocate(Node);

   return RetVal;
end;

Setelah kita memanggil deallocate , kita tidak dapat mereferensikan data yang ditunjuk oleh variabel Node. Ini telah digratiskan oleh simulator. Solusinya adalah menyalin data ke variabel lokal sebelum membebaskan, lalu mengembalikan nilai variabel.

IsEmpty

Memeriksa apakah daftar kosong atau tidak dapat dilakukan dengan memeriksa apakah simpul akar menunjuk ke sesuatu selain nol:

impure function IsEmpty return boolean is
begin
   return Root = null;
end;

Testbench

Untuk menjalankan kode kita, kita perlu membuat testbench. Sebenarnya, linked list hanya bisa digunakan di testbenches. Jenis akses tidak dapat disintesis, tetapi sangat berguna untuk tujuan verifikasi.

Menggunakan paket perpustakaan

Di testbench, pertama-tama kita mengimpor work Perpustakaan. Ini adalah pustaka default di VHDL, dan di sinilah paket DataStructures kami berada. Setelah itu, kita bisa mengimport tipe protected LinkedList seperti ini:

library work;
use work.DataStructures.LinkedList;

Variabel bersama

Variabel bersama adalah variabel yang dapat diakses oleh beberapa proses. Tidak seperti variabel reguler yang hanya dapat dideklarasikan dalam satu proses, variabel bersama dapat dideklarasikan di wilayah deklaratif arsitektur. Dengan demikian, mereka memiliki cakupan yang sama dengan sinyal.

Kita harus menggunakan variabel bersama karena tidak mungkin untuk mendeklarasikan sinyal tipe yang dilindungi. Jika kami mencoba, ModelSim akan mengeluh:(vcom-1464) Deklarasi ilegal dari sinyal “List” dari tipe work.DataStructures.LinkedList (tipe adalah tipe yang dilindungi).

Kami mendeklarasikan variabel bersama dari tipe LinkedList di wilayah deklaratif dari testbench:

architecture sim of LinkedListTb is

   shared variable List : LinkedList;

begin

Kode terakhir untuk testbench

Untuk menguji tiga fungsi utilitas kami, kami membuat proses baru. Dalam prosesnya, kami menambahkan For-loop yang mendorong lima bilangan bulat ke daftar tertaut. Terakhir, kami mengosongkan daftar tertaut dalam loop Sementara yang berjalan hingga fungsi IsEmpty kami mengembalikan true :

library work;
use work.DataStructures.LinkedList;

entity LinkedListTb is
end entity;

architecture sim of LinkedListTb is

   shared variable List : LinkedList;

begin

   process is
   begin

      for i in 1 to 5 loop
         report "Pushing " & integer'image(i);
         List.Push(i);
      end loop;

      while not List.IsEmpty loop
         report "Popping " & integer'image(List.Pop);
      end loop;

      wait;
   end process;

end architecture;

Kode terakhir untuk paket DataStructures

Setelah menulis semua kode yang sebelumnya kita bicarakan di artikel ini, paket DataStructures akan terlihat seperti ini:

package DataStructures is
   type LinkedList is protected

      procedure Push(constant Data : in integer);
      impure function Pop return integer;
      impure function IsEmpty return boolean;

   end protected;
end package DataStructures;

package body DataStructures is

   type LinkedList is protected body

      type Item;
      type Ptr is access Item;
      type Item is record
         Data : integer;
         NextItem : Ptr;
      end record;

      variable Root : Ptr;

      procedure Push(Data : in integer) is
         variable NewItem : Ptr;
         variable Node : Ptr;
      begin
         NewItem := new Item;
         NewItem.Data := Data;

         if Root = null then
            Root := NewItem;

         else
            Node := Root;

            while Node.NextItem /= null loop
               Node := Node.NextItem;
            end loop;

            Node.NextItem := NewItem;
         end if;
      end;

      impure function Pop return integer is
         variable Node : Ptr;
         variable RetVal : integer;
      begin
         Node := Root;
         Root := Root.NextItem;

         RetVal := Node.Data;
         deallocate(Node);

         return RetVal;
      end;

      impure function IsEmpty return boolean is
      begin
         return Root = null;
      end;

   end protected body;

end package body DataStructures;

Hasilnya

Output ke konsol simulator saat kita menekan tombol run di ModelSim:

VSIM 10> run
# ** Note: Pushing 1
#    Time: 0 ns  Iteration: 0  Instance: /linkedlisttb
# ** Note: Pushing 2
#    Time: 0 ns  Iteration: 0  Instance: /linkedlisttb
# ** Note: Pushing 3
#    Time: 0 ns  Iteration: 0  Instance: /linkedlisttb
# ** Note: Pushing 4
#    Time: 0 ns  Iteration: 0  Instance: /linkedlisttb
# ** Note: Pushing 5
#    Time: 0 ns  Iteration: 0  Instance: /linkedlisttb
# ** Note: Popping 1
#    Time: 0 ns  Iteration: 0  Instance: /linkedlisttb
# ** Note: Popping 2
#    Time: 0 ns  Iteration: 0  Instance: /linkedlisttb
# ** Note: Popping 3
#    Time: 0 ns  Iteration: 0  Instance: /linkedlisttb
# ** Note: Popping 4
#    Time: 0 ns  Iteration: 0  Instance: /linkedlisttb
# ** Note: Popping 5
#    Time: 0 ns  Iteration: 0  Instance: /linkedlisttb

Seperti yang dapat kita lihat dari hasil cetak, lima bilangan bulat didorong ke daftar tertaut. Kemudian, while-loop di testbench mengeluarkannya dari daftar sesuai urutan penyisipannya.


VHDL

  1. Cara membuat daftar string di VHDL
  2. Cara membuat testbench berbasis Tcl untuk modul kunci kode VHDL
  3. Bagaimana menghentikan simulasi di testbench VHDL
  4. Cara membuat pengontrol PWM di VHDL
  5. Cara menghasilkan angka acak di VHDL
  6. Cara membuat penyangga cincin FIFO di VHDL
  7. Cara membuat testbench pemeriksaan mandiri
  8. Cara menggunakan Prosedur dalam Proses di VHDL
  9. Cara menggunakan Fungsi Tidak Murni di VHDL
  10. Cara menggunakan Fungsi di VHDL