İkili talimat kod çözücü eğiticisi

Bu eğitimin hedefleri şunlardır:

  • İkili program biçimi açıklama dosyasının yapısını ve söz dizimini öğrenin.
  • İkili program biçimi açıklamasının ISA açıklamasıyla nasıl eşleştiğini öğrenin.
  • RiscV RV32I talimat alt kümesi için ikili açıklamaları yazın.

Genel Bakış

RiscV ikili talimatı kodlaması

İkili talimat kodlaması, görevlerdeki talimatları kodlamanın standart yoludur. çalıştırmayı öğreteceğim. Bu dosyalar, normalde yürütülebilir bir dosyada biçiminde girin. Talimatlar sabit genişlikli veya değişken olabilir dokunun.

Talimatlarda genellikle her biçimi içeren küçük bir kodlama biçimi kullanılır. kodlanan talimatların türü için özelleştirilmiş olması gerekir. Örneğin, register-register talimatlarda, kullanılabilir işlem kodu sayısını en üst düzeye çıkaran bir biçim kullanılabilir. hemen kayıt talimatlarında ise bir işlem yapmadan önce kodlanabilir anlık öğenin boyutunu artırmak için kullanılabilir. Dal ve atlama talimatlarında hemen hemen her zaman dalları desteklemek için hızlı bir şekilde bulmalıdır.

RiscV'mizde kodunu çözmek istediğimiz talimatlar tarafından kullanılan talimat biçimleri şunlardır:

Kayıt talimatları için kullanılan R-Type biçimi:

31..25 24...20 19...15 14..12 11..7 6..0
7 5 5 3 5 7
func7 rs2 rs1 func3 . işlem kodu

Anında kayıt talimatları, yükleme talimatları ve yükleme talimatları için kullanılan I-Type biçimi jalr talimatı, 12 bit anında.

31...20 19...15 14..12 11..7 6..0
12 5 3 5 7
imm12 rs1 func3 . işlem kodu

Hızlı talimatlarla kaydırma için kullanılan, 5 bit'lik özel I-Type biçimi anında:

31..25 24...20 19...15 14..12 11..7 6..0
7 5 5 3 5 7
func7 uimm5 rs1 func3 . işlem kodu

Hızlı ve anında talimatlar için kullanılan U Türü biçimi (lui, auipc), 20 bit anında:

31...12 11..7 6..0
20 5 7
uimm20 . işlem kodu

Koşullu dallar için kullanılan, 12 bit anında kullanılan B Türü biçimi.

31 30..25 24...20 19...15 14..12 11..8 7 6..0
1 6 5 5 3 4 1 7
imm imm rs2 rs1 func3 imm imm işlem kodu

jal talimatı için kullanılan J Türü biçimi, 20 bit anında.

31 30...21 20 19...12 11..7 6..0
1 10 1 8 5 7
imm imm imm imm . işlem kodu

Mağaza talimatları için kullanılan, 12 bit anında kullanılan S-Type biçimi.

31..25 24...20 19...15 14..12 11..7 6..0
7 5 5 3 5 7
imm rs2 rs1 func3 imm işlem kodu

Bu biçimlerden görebileceğiniz gibi, tüm bu talimatlar 32 bit uzunluğunda ve her biçimdeki küçük 7 bit ise işlem kodu alanıdır. Ayrıca, birçok biçim aynı boyuta sahip olsa da bitleri kaynak bazı bölümleri kapsıyor. Göreceğimiz gibi, ikili kod çözücü bunu ifade edebiliyor.

İkili kodlama açıklaması

Talimatın ikili kodlaması, ikili biçimde ifade edilir. (.bin_fmt) açıklama dosyasına kaydedin. Bu şema, talimatlarının tutarlı bir şekilde çalıştırılabilmesini sağlar. Böylece, elde edilir. Oluşturulan kod çözücü, işlem kodunu belirler, işlem gören ve anında görüntülenen alanlara (ISA'nın ihtiyaç duyduğu bilgileri sağlamak için) önceki eğiticide açıklandığı gibi kodlamadan bağımsız kod çözücüye uygundur.

Bu eğiticide, bir alt küme için bir ikili kodlama açıklama dosyası yazacağız RiscV32I talimatlarının büyük bir kısmı, küçük "Hello World" çok önemli. RiscV ISA hakkında daha fazla bilgi için bkz. Risc-V Teknik Özellikleri{.external}.

İlk olarak dosyayı açın: riscv_bin_decoder/riscv32i.bin_fmt

Dosya içeriği birkaç bölüme ayrılmıştır.

Birincisi, decoder tanımıdır.

decoder RiscV32I {
  // The namespace in which code will be generated.
  namespace mpact::sim::codelab;
  // The name (including any namespace qualifiers) of the opcode enum type.
  opcode_enum = "OpcodeEnum";
  // Include files specific to this decoder.
  includes {
    #include "riscv_isa_decoder/solution/riscv32i_decoder.h"
  }
  // Instruction groups for which to generate decode functions.
  RiscVInst32;
};

Kod çözücü tanımımız, RiscV32I kod çözücüümüzün adını ve ek iş çıkarmanızı sağlar. Bunlardan ilki, namespace oluşturulan kodun yerleştirileceği ad alanıdır. İkinci olarak, opcode_enum, işlem kodu numaralandırma türünün nasıl oluşturulduğunu belirtir. oluşturulan kodda ISA kod çözücüsünün referans noktası bulunmalıdır. Üçüncüsü, includes {}, şunlar için oluşturulan kod için gerekli dosyaları içereceğini belirtir: kod çözücüyüm. Örneğimizde bu, ISA kod çözücü tarafından önceki eğiticide bulabilirsiniz. Genel kapsamlı bir includes {} içinde ek dahil etme dosyaları belirtilebilir belirler. Bu, birden fazla kod çözücü tanımlanmışsa ve bunların hepsinin eklemeniz gerekebilir. Dördüncüsünde ise kod çözücünün oluşturulduğu talimatları oluşturan gruplar. Şurada: yalnızca bir tane vardır: RiscVInst32.

Ardından üç biçim tanımı vardır. Bunlar farklı talimatları önceden tanımlanmış talimatlar tarafından kullanılan 32 bitlik talimat kelimesinin biçimleri dosyadır.

// The generic RiscV 32 bit instruction format.
format Inst32Format[32] {
  fields:
    unsigned bits[25];
    unsigned opcode[7];
};

// RiscV 32 bit instruction format used by a number of instructions
// needing a 12 bit immediate, including CSR instructions.
format IType[32] : Inst32Format {
  fields:
    signed imm12[12];
    unsigned rs1[5];
    unsigned func3[3];
    unsigned rd[5];
    unsigned opcode[7];
};

// RiscV instruction format used by fence instructions.
format Fence[32] : Inst32Format {
  fields:
    unsigned fm[4];
    unsigned pred[4];
    unsigned succ[4];
    unsigned rs1[5];
    unsigned func3[3];
    unsigned rd[5];
    unsigned opcode[7];
};

İlki, 32 bit genişliğinde ve 32 bit genişliğe sahip Inst32Format adlı, iki alan: bits (25 bit genişliğinde) ve opcode (7 bit genişliğinde). Her alan unsigned: Çıkarıldığında değer sıfır olarak genişletilir ve C++ tam sayı türüne yerleştirilir. Bit alanlarının genişliklerinin toplamı, biçimin genişliğine eşittir. Bir hata varsa araç düşünülebilir. Bu biçim başka herhangi bir biçimden türetilmediği için üst düzey bir biçim olarak değerlendirilir.

İkincisi ise IType adında, 32 bit genişliğinde bir talimat biçimi tanımlar ve Bu iki biçimi alakalı hale getiriyor.Inst32Format Biçim 5 değerini içerir alanlar: imm12, rs1, func3, rd ve opcode. imm12 alanı signed (Bu, değer şu olduğunda değerin işaretleneceği anlamına gelir: çıkarılıp C++ tam sayı türüne yerleştirilir. Her ikisinde de IType.opcode aynı imzalı/imzasız özelliğe sahiptir ve aynı talimat kelime bitlerine işaret eder Inst32Format.opcode olarak.

Üçüncü biçim, yalnızca fence tarafından kullanılan özel bir biçimdir. Bu, halihazırda belirtilmiş bir talimattır ve elimizde henüz bazı önemli hususlara değineceğiz.

Önemli nokta: Geçerli olduğu sürece, alan adlarını farklı ilgili biçimlerde yeniden kullanın aynı bitleri temsil eder ve aynı imzalı/imzasız özelliğe sahiptir.

riscv32i.bin_fmt içindeki biçim tanımlarından sonra bir talimat grubu gelir belirler. Bir talimat grubundaki tüm talimatlar aynı olmalıdır bit uzunluğunda olmalıdır ve aynı öğeden (dolaylı olarak) türetilen bir biçim üst düzey talimat formatıdır. ISA, ne zaman farklı her uzunluk için farklı bir talimat grubu kullanılır. Ayrıca, Hedef ISA kodu çözme işlemi, Kol ve Küçük Resim gibi bir yürütme moduna bağlıysa her mod için ayrı bir talimat grubu gerekir. İlgili içeriği oluşturmak için kullanılan bin_fmt ayrıştırıcısı, her bir talimat grubu için bir ikili kod çözücü oluşturur.

instruction group RiscV32I[32] "OpcodeEnum" : Inst32Format {
  fence   : Fence  : func3 == 0b000, opcode == 0b000'1111;
  csrs    : IType  : func3 == 0b010, rs1 != 0, opcode == 0b111'0011;
  csrw_nr : IType  : func3 == 0b001, rd == 0,  opcode == 0b111'0011;
  csrs_nw : IType  : func3 == 0b010, rs1 == 0, opcode == 0b111'0011;
};

Talimat grubu, RiscV32I adını, genişlik [32], "OpcodeEnum" kullanılacak işlem kodu numaralandırma türü ve bir temel talimat biçimindedir. opcode numaralandırma türü, ISA konulu eğiticide ele alınan bağımsız talimat kod çözücü biçimi kod çözücü.

Her talimat kodlama açıklaması 3 bölümden oluşur:

  • Talimatta kullanılanla aynı olması gereken işlem kodu adı kod çözücü açıklaması verebilirsiniz.
  • İşletim kodu için kullanılacak talimat biçimi. Bu biçim, son bölümdeki bit alanlarına yapılan referansları karşılamak için kullanılır.
  • Bit alanı kısıtlamalarının virgülle ayrılmış listesi, ==, !=, <, <=, >, işlem kodunun başarılı bir şekilde eşleşmesi için tümünün doğru olması gereken >= talimat kelimesi.

.bin_fmt ayrıştırıcısı, tüm bu bilgileri kullanarak aşağıdaki özelliklere sahip bir kod çözücü oluşturur:

  • Her bit için uygun olan ayıklama işlevlerini (imzalı/imzasız) sağlar her biçimde olması gerekir. Ayıklayıcı işlevleri ad alanlarına yerleştirilir. biçim adının yılan şeklinde büyük harf içeren sürümüne göre adlandırılmıştır. Örneğin, IType biçimine ait ayıklayıcı işlevleri i_type ad alanına yerleştirilmiş. Her ayıklayıcı işlevi inline olarak tanımlanır ve en dar uint_t değerini alır biçimin genişliğini barındıran ve en dar int_t değerini döndüren tür (imzalanmış için), çıkarılan alanı barındıran uint_t (imzasız için) türü dokunun. Örneğin:
inline uint8_t ExtractOpcode(uint32_t value) {
  return value & 0x7f;
}
  • Her bir talimat grubu için bir kod çözme işlevi. Şu tür bir değer döndürür: OpcodeEnum veuint_t talimat grubu biçimindedir.

İlk derlemeyi gerçekleştir

Dizini riscv_bin_decoder olarak değiştirin ve projeyi şu komutu kullanın:

$ cd riscv_bin_decoder
$ bazel build :all

Şimdi dizininizi depo köküyle değiştirin ve bir bakalım. oluşturulan kaynaklarda gösterilir. Bunun için, dizini bazel-out/k8-fastbuild/bin/riscv_bin_decoder (x86 kullandığınız varsayılır) ana makine - diğer ana makineler için k8-Fastbuild, başka bir dize olacaktır).

$ cd ..
$ cd bazel-out/k8-fastbuild/bin/riscv_bin_decoder
  • riscv32i_bin_decoder.h
  • riscv32i_bin_decoder.cc

Oluşturulan başlık dosyası (.h)

riscv32i_bin_decoder.h uygulamasını açın. Dosyanın ilk bölümünde standart ortak metin korumaları, dosyalar ve ad alanı beyanları içermelidir. Ardından internal ad alanında şablonlu bir yardımcı işlev bulunuyor. Bu işlev 64 bit C++ sürümüne sığmayacak kadar uzun biçimlerden bit alanlarını ayıklamak için kullanılır Tam sayı.

#ifndef RISCV32I_BIN_DECODER_H
#define RISCV32I_BIN_DECODER_H

#include <iostream>
#include <cstdint>

#include "third_party/absl/functional/any_invocable.h"


#include "learning/brain/research/mpact/sim/codelab/riscv_isa_decoder/solution/riscv32i_decoder.h"

namespace mpact {
namespace sim {
namespace codelab {


namespace internal {

template <typename T>
static inline T ExtractBits(const uint8_t *data, int data_size,
                            int bit_index, int width) {
  if (width == 0) return 0;

  int byte_pos = bit_index >> 3;
  int end_byte = (bit_index + width - 1) >> 3;
  int start_bit = bit_index & 0x7;

  // If it is only from one byte, extract and return.
  if (byte_pos == end_byte) {
    uint8_t mask = 0xff >> start_bit;
    return (mask & data[byte_pos]) >> (8 - start_bit - width);
  }

  // Extract from the first byte.
  T val = 0;
  val = data[byte_pos++] & 0xff >> start_bit;
  int remainder = width - (8 - start_bit);
  while (remainder >= 8) {
    val = (val << 8) | data[byte_pos++];
    remainder -= 8;
  }

  // Extract any remaining bits.
  if (remainder > 0) {
    val <<= remainder;
    int shift = 8 - remainder;
    uint8_t mask = 0b1111'1111 << shift;
    val |= (data[byte_pos] & mask) >> shift;
  }
  return val;
}

}  // namespace internal

İlk bölümün ardından, her biri için bir tane olmak üzere üç ad alanından oluşan bir grup bulunur. riscv32i.bin_fmt dosyasındaki format beyandan:


namespace fence {

...

}  // namespace fence

namespace i_type {

...

}  // namespace i_type

namespace inst32_format {

...

}  // namespace inst32_format

Bu ad alanlarının her birinde inline bit alanı ayıklama işlevi her bit alanının tanımıdır. Buna ek olarak, temel biçim alt biçimlerden çıkarma fonksiyonlarını kopyalar 1) alan adları yalnızca tek bir alan adında bulunuyor veya 2) alan adının alan adları aynı tür alanına (imzalı/imzasız ve bit konumları) başvuruda bulunuyor bulunabilir. Bu, aynı bit değerleri (en üst düzey biçim ad alanındaki işlevler kullanılarak ayıklanır).

i_type ad alanındaki işlevler aşağıda gösterilmiştir:

namespace i_type {

inline uint8_t ExtractFunc3(uint32_t value) {
  return  (value >> 12) & 0x7;
}

inline int16_t ExtractImm12(uint32_t value) {
  int16_t result = ( (value >> 20) & 0xfff) << 4;
  result = result >> 4;
  return result;
}

inline uint8_t ExtractOpcode(uint32_t value) {
  return value & 0x7f;
}

inline uint8_t ExtractRd(uint32_t value) {
  return  (value >> 7) & 0x1f;
}

inline uint8_t ExtractRs1(uint32_t value) {
  return  (value >> 15) & 0x1f;
}

}  // namespace i_type

Son olarak, talimat için kod çözücü işlevinin işlev bildirimi RiscVInst32 grubu bildirildi. Belgenin değeri olarak 32 bit talimat kelimesini ekler ve OpcodeEnum numaralandırma sınıfı üyesini döndürür veya eşleşme yoksa OpcodeEnum::kNone yazın.

OpcodeEnum DecodeRiscVInst32(uint32_t inst_word);

Oluşturulan Kaynak Dosya (.cc)

Şimdi riscv32i_bin_decoder.cc uygulamasını açın. Dosyanın ilk bölümünde #include ve ad alanı beyanları, ardından kod çözücü işlevi beyanlar:

#include "riscv32i_bin_decoder.h"

namespace mpact {
namespace sim {
namespace codelab {

OpcodeEnum DecodeRiscVInst32None(uint32_t);
OpcodeEnum DecodeRiscVInst32_0(uint32_t inst_word);
OpcodeEnum DecodeRiscVInst32_0_3(uint32_t inst_word);
OpcodeEnum DecodeRiscVInst32_0_3c(uint32_t inst_word);
OpcodeEnum DecodeRiscVInst32_0_5c(uint32_t inst_word);

DecodeRiscVInst32None, boş kod çözme işlemleri (yani OpcodeEnum::kNone sonucu döndürür. Diğer üç fonksiyon kod çözücü oluşturuldu. Genel kod çözücü hiyerarşik bir şekilde çalışır. Bir grup Talimattaki bit sayısı, büyük/küçük harfe duyarlı değil üst düzey talimatlar veya talimat grupları içerir. Bitlerin kesintisiz olmalıdır. Bit sayısı, bitmek üzere gösterilen arama tablosunun ikinci düzey kod çözücü işlevleriyle doldurulur. Bu, daha sonra bölümüne ekleyin:

absl::AnyInvocable<OpcodeEnum(uint32_t)> parse_group_RiscVInst32_0[kParseGroupRiscVInst32_0_Size] = {
    &DecodeRiscVInst32None, &DecodeRiscVInst32None,
    &DecodeRiscVInst32None, &DecodeRiscVInst32_0_3,
    &DecodeRiscVInst32None, &DecodeRiscVInst32None,

    ...

    &DecodeRiscVInst32None, &DecodeRiscVInst32None,
    &DecodeRiscVInst32None, &DecodeRiscVInst32None,
    &DecodeRiscVInst32_0_3c, &DecodeRiscVInst32None,

    ...
};

Son olarak, kod çözücü işlevleri tanımlanır:

OpcodeEnum DecodeRiscVInst32None(uint32_t) {
  return OpcodeEnum::kNone;
}

OpcodeEnum DecodeRiscVInst32_0(uint32_t inst_word) {
  if ((inst_word & 0x4003) != 0x3) return OpcodeEnum::kNone;
  uint32_t index;
  index = (inst_word >> 2) & 0x1f;
  index |= (inst_word >> 7) & 0x60;
  return parse_group_RiscVInst32_0[index](inst_word);
}

OpcodeEnum DecodeRiscVInst32_0_3(uint32_t inst_word) {
  return OpcodeEnum::kFence;
}

OpcodeEnum DecodeRiscVInst32_0_3c(uint32_t inst_word) {
  if ((inst_word & 0xf80) != 0x0) return OpcodeEnum::kNone;
  return OpcodeEnum::kCsrwNr;
}

OpcodeEnum DecodeRiscVInst32_0_5c(uint32_t inst_word) {
  uint32_t rs1_value = (inst_word >> 15) & 0x1f;
  if (rs1_value != 0x0)
    return OpcodeEnum::kCsrs;
  if (rs1_value == 0x0)
    return OpcodeEnum::kCsrsNw;
  return OpcodeEnum::kNone;
}

OpcodeEnum DecodeRiscVInst32(uint32_t inst_word) {
  OpcodeEnum opcode;
  opcode = DecodeRiscVInst32_0(inst_word);
  return opcode;
}

Bu örnekte, yalnızca 4 talimat tanımlanmışsa yalnızca bir tek bir kod çözme düzeyi ve çok seyrek bir arama tablosu bulunur. Talimatlar kod çözücünün yapısı değişir ve kod çözücü tablosu hiyerarşisi artabilir.


Kayıt-kayıt ALU talimatları ekleme

Şimdi riscv32i.bin_fmt dosyasına bazı yeni talimatlar eklemenin zamanı geldi. İlgili içeriği oluşturmak için kullanılan ilk talimat grubu, add, and vb. RiscV32'de bunların tümü R tipi ikili talimatını kullanır biçim:

31..25 24...20 19...15 14..12 11..7 6..0
7 5 5 3 5 7
func7 rs2 rs1 func3 . işlem kodu

Yapmamız gereken ilk şey biçimi eklemektir. Devam edin ve şunu açın: riscv32i.bin_fmt favori düzenleyicinizde. Inst32Format uygulamasından hemen sonra Inst32Format değişkeninden türetilen RType adlı bir biçim ekleyin. Tüm bit alanları RType bölgesinde unsigned. Adları, bit genişliğini ve sırayı (soldan sağa) kullanın aşağıdaki tablodan seçin. İpucuna ihtiyacınız olursa veya tam çözüm burayı tıklayın.

Ardından talimatları eklememiz gerekir. Talimatlar şunlardır:

  • add - tam sayı toplama.
  • and - bit tabanlı ve.
  • or - bit tabanlı veya.
  • sll - sola kaydırma mantıksal.
  • sltu - "Küçüktür" olarak ayarla, imzasız.
  • sub: Tamsayı çıkarma işlemi.
  • xor - bit tabanlı xor.

Kodlamaları şu şekildedir:

31..25 24...20 19...15 14..12 11..7 6..0 işlem kodu adı
000.000 rs2 rs1 000 . 011 0011 add
000.000 rs2 rs1 111 . 011 0011 ve
000.000 rs2 rs1 110 . 011 0011 veya
000.000 rs2 rs1 001 . 011 0011 Sl
000.000 rs2 rs1 011 . 011 0011 Sltu
010 0.000 rs2 rs1 000 . 011 0011 yerine girdi
000.000 rs2 rs1 100 . 011 0011 Xor
func7 func3 işlem kodu

Bu talimat tanımlarını RiscVInst32 talimat grubu. İkili dizeler başında bir 0b öneki (onaltılık sayılar için 0x ile benzer). Ekibiniz ve sizin için ikili basamaklı uzun dizeleri okurken tek tırnak işaretini de ' bir rakam ayırıcısıdır.

Bu talimat tanımlarının her biri üç kısıtlamaya sahip olacaktır. func7, func3 ve opcode. sub hariç tümü için func7 kısıtlaması şöyle olmalıdır:

func7 == 0b000'0000

func3 kısıtlaması, talimatların çoğunda değişiklik gösterir. add ve sub:

func3 == 0b000

opcode kısıtlaması bu talimatların her biri için aynıdır:

opcode == 0b011'0011

Her satırı noktalı virgül ; ile sonlandırmayı unutmayın.

Bitmiş çözüm, burada bulabilirsiniz.

Şimdi projenizi önceki gibi derleyin ve oluşturulan riscv32i_bin_decoder.cc dosyası yükleyin. Ek kod çözücü işlevlerinin yeni talimatların işlenmesi için oluşturuldu. Çoğunlukla Bunlar daha önce oluşturulan raporlara benzer ancak add/sub kod çözme işlemi için kullanılan DecodeRiscVInst32_0_c:

OpcodeEnum DecodeRiscVInst32_0_c(uint32_t inst_word) {
  static constexpr OpcodeEnum opcodes[2] = {
    OpcodeEnum::kAdd,
    OpcodeEnum::kSub,
  };
  if ((inst_word & 0xbe000000) != 0x0) return OpcodeEnum::kNone;
  uint32_t index;
  index = (inst_word >> 30) & 0x1;
  return opcodes[index];
}

Bu fonksiyonda, oluşturulmuş statik bir kod çözme tablosu vardır ve bir arama değeri ayıklanır. Bu işlem, ikinci katmanında yer alabilir, ancak işlem kodu başka karşılaştırma yapılmadan doğrudan bir tabloda bakıldığında, bu satıra işlevini kullanın.


Anlık içeren ALU talimatları ekleme

Ekleyeceğimiz bir sonraki talimat grubu, kayıtlardan biri yerine anında değer katar. Bu üç grup talimatlar (bir sonraki alana göre): I-Type hızlı talimatları hemen 12 bit imzalı, özel I-Type hızlı talimatları ve U Türü için 20 bitlik imzasız bir anlık değer gösterilir. Biçimler aşağıda gösterilmiştir:

I-Type'ın anlık biçimi:

31...20 19...15 14..12 11..7 6..0
12 5 3 5 7
imm12 rs1 func3 . işlem kodu

Özel I-Type hızlı biçimi:

31..25 24...20 19...15 14..12 11..7 6..0
7 5 5 3 5 7
func7 uimm5 rs1 func3 . işlem kodu

U-Type hızlı biçimi:

31...12 11..7 6..0
20 5 7
uimm20 . işlem kodu

I-Type biçimi riscv32i.bin_fmt içinde zaten mevcuttur, dolayısıyla bu biçimi eklemeniz gerekir.

Özel I-Type biçimini, burada tanımladığımız R-Type biçimiyle karşılaştırırsak gördüğünüz gibi, tek farkın rs2 alanları , uimm5 olarak yeniden adlandırıldı. Tamamen yeni bir biçim eklemek yerine, R-Type biçimi. Genişliği artacağı için başka bir alan ekleyemiyoruz ama bir yer paylaşımı ekleyebiliriz. Yer paylaşımı, bitleri haline getirilir ve bu alanın birden çok sonraki tekrarlarını birleştirmek için farklı bir adlandırılmış varlığa dönüştürür. Bunun yan etkisi, oluşturulan kodun artık yer paylaşımı için bir ayıklama işlevi de açıklayacağım. Bu durumda, hem rs2 hem de uimm5 imzalanmadığında alanın kullanıldığını açıkça belirtmek dışında pek fark yaratmaz ele alacağız. R-Type biçimine uimm5 adlı bir yer paylaşımı eklemek için şunu ekleyin:

  overlays:
    unsigned uimm5[5] = rs2;

Eklememiz gereken tek yeni biçim U Türü biçimidir. Ekleme işleminden önce biçimi varsa bu biçimi kullanan iki talimata bakalım: auipc ve lui. Bunların her ikisi de, 20 bitlik anında değeri, kullanmadan önce 12'lik bir tarihe kaydırır veya doğrudan bir kasaya yazarakauipc (lui). Yer paylaşımı kullanarak anında, önceden kaydırılmış sürümünü sağlayabiliriz. Daha küçük bir hesaplama işleminin talimatı yürütmeden öğretime kaydırması çözer. Önce, tabloda belirtilen alanlara göre biçimi ekleyin bölümünü ziyaret edin. Daha sonra, aşağıdaki yer paylaşımını ekleyebiliriz:

  overlays:
    unsigned uimm32[32] = uimm20, 0b0000'0000'0000;

Yer paylaşımı söz dizimi, yalnızca alanları değil, aynı zamanda dizeleri olur. Bu örnekte, 12 tane sıfır ile birleştiririz ve sonuç olarak, sola kaydırırız. 12 tarihine kadar.

Eklememiz gereken I-Type talimatları şunlardır:

  • addi - Hemen ekleyin.
  • andi - Bit tabanlı ve anında.
  • ori - Bit tabanlı veya anında.
  • xori - Bit tabanlı Xor ve anında.

Kodlamaları şu şekildedir:

31...20 19...15 14..12 11..7 6..0 opcode_name
imm12 rs1 000 . 001 0011 Addi
imm12 rs1 111 . 001 0011 Andi
imm12 rs1 110 . 001 0011 Ori
imm12 rs1 100 . 001 0011 sori
func3 işlem kodu

Eklememiz gereken R-Type (özel I-Type) talimatları şunlardır:

  • slli - Hemen sola mantıksal olarak kaydırır.
  • srai - Hemen aritmetiği sağa kaydır.
  • srli - Hemen sağa kaydırır.

Kodlamaları şu şekildedir:

31..25 24...20 19...15 14..12 11..7 6..0 işlem kodu adı
000.000 uimm5 rs1 001 . 001 0011 Slli
010 0.000 uimm5 rs1 101 . 001 0011 Sarai
000.000 uimm5 rs1 101 . 001 0011 srli
func7 func3 işlem kodu

Eklememiz gereken U-Type talimatları şunlardır:

  • auipc - Hemen pc'ye ekle.
  • lui - Hemen üst öğeyi yükle.

Kodlamaları şu şekildedir:

31...12 11..7 6..0 işlem kodu adı
uimm20 . 001 0111 auipc
uimm20 . 011 0111 Lui
işlem kodu

Değişiklikleri yapın ve sonra oluşturun. Oluşturulan çıkışı kontrol edin. Adil önceki gibi çalışmanızı riscv32i.bin_fmt adresine gidin.


Tanımlanması gereken bir sonraki talimat grubu, talimatlar, atlama ve bağlantı talimatı, ve bağlantı ekleme teşekkür ederiz.

Eklediğimiz koşullu dallar, B-Type kodlamasını kullanmaktadır.

31..25 24...20 19...15 14..12 11..7 6..0
7 5 5 3 5 7
imm7 rs2 rs1 func3 imm5 işlem kodu

B-Tipi kodlaması, düzen açısından R-Type kodlamasıyla özdeş olsa da, RiscV dokümanlarıyla uyumlu olması için yeni bir biçim türü kullanmayı tercih etmeniz gerekir. Ancak uygun dal almak için bir yer paylaşımı da R-Type'ın func7 ve rd alanlarını kullanarak yer değiştirme kullanır.

Yukarıda belirtilen alanları içeren bir BType biçiminin eklenmesi gerekir ancak bu zorunlu değildir yeterli olacaktır. Gördüğünüz gibi, hemen iki talimat alanına bölünmüştür. Ayrıca, şube talimatlarında bu durum, gireceğiz. Bunun yerine, her alan daha fazla bölümlendirilir ve bu bölümler farklı bir sırada sıralar. Son olarak, bu değer için bir değer bulunmalıdır.

Anı oluşturmak için kullanılan talimat kelimesinde bit dizisi şu şekildedir: 31, 7, 30..25, 11..8. Bu, aşağıdaki alt alan referanslarına karşılık gelir ve dizin veya aralık, alandaki bitleri belirtir; sağdan sola doğru (yani imm7[6], imm7 öğesinin msb'sini, imm5[0] ise lsb değerini ifade eder imm5.

imm7[6], imm5[0], imm7[5..0], imm5[4..1]

Bu küçük manipülasyonun dal talimatlarının bir parçası haline getirmek için dezavantajları var. İlk olarak, anlamsal fonksiyonun uygulamasını ikili talimat gösterimindeki ayrıntılara yer verir. İkinci olarak, reklamların yardımcı olabilir. Bunun yanıtı, BType biçimine bir yer paylaşımı eklemektir. Örneğin, sonda '0' hesaba katacağım.

  overlays:
    signed b_imm[13] = imm7[6], imm5[0], imm7[5..0], imm5[4..1], 0b0;

Yer paylaşımı imzalandığı için otomatik olarak genişletilir anahtar kelimeden ayıklandığında ne olur?

Jump-and-link (hemen) talimatı J-Type kodlamasını kullanır:

31...12 11..7 6..0
20 5 7
imm20 . işlem kodu

Bu da eklenmesi kolay bir biçimdir, ancak kullanıcı tarafından kullanılan anlık göründüğü kadar kolay değil. Kullanılan bit dizileri 31, 19..12, 20, 30..21 ve son hemen hemen yarım kelime hizalama için bir sola kaydırılır. Çözüm, tablodaki şu biçime sahiptir: (sol kayma için 21 bit):

  overlays:
    signed j_imm[21] = imm20[19, 7..0, 8, 18..9], 0b0;

Gördüğünüz gibi bindirmelerin söz dizimi, bir kullanabilirsiniz. Buna ek olarak, hiçbir alan adı kullanılmazsa sayılar talimat kelimesinin kendisine işaret ettiği için yukarıdakiler de aynı şekilde şu şekilde yazıldı:

    signed j_imm[21] = [31, 19..12, 20, 30..21], 0b0;

Son olarak, atlama ve bağlantı (kaydet) işlevi, öğrendi.

I-Type'ın anlık biçimi:

31...20 19...15 14..12 11..7 6..0
12 5 3 5 7
imm12 rs1 func3 . işlem kodu

Bu kez, biçimde herhangi bir değişiklik yapılması gerekmez.

Eklememiz gereken dal talimatları şunlardır:

  • beq - Eşitse dal.
  • bge - Büyükse veya eşitse dal.
  • bgeu - Büyüktür veya eşittir imzalanmamışsa şube.
  • blt - Küçükse şubelere ayırın.
  • bltu - İmzalanmamışsa şubelerden yararlanın.
  • bne - Eşit değilse dal.

Bunlar şu şekilde kodlanır:

31..25 24...20 19...15 14..12 11..7 6..0 işlem kodu adı
imm7 rs2 rs1 000 imm5 110.0011 beq
imm7 rs2 rs1 101 imm5 110.0011 Bge
imm7 rs2 rs1 111 imm5 110.0011 Bgeu
imm7 rs2 rs1 100 imm5 110.0011 blt
imm7 rs2 rs1 110 imm5 110.0011 bltu
imm7 rs2 rs1 001 imm5 110.0011 Bne
func3 işlem kodu

jal talimatı şu şekilde kodlanır:

31...12 11..7 6..0 işlem kodu adı
imm20 . 110 1111 Jal
işlem kodu

jalr talimatı şu şekilde kodlanır:

31...20 19...15 14..12 11..7 6..0 opcode_name
imm12 rs1 000 . 110 0111 Jalr
func3 işlem kodu

Değişiklikleri yapın ve sonra oluşturun. Oluşturulan çıkışı kontrol edin. Adil önceki gibi çalışmanızı riscv32i.bin_fmt adresine gidin.


Mağaza talimatları ekleyin

Mağaza talimatlarında, B-Tipi ile bire bir aynı olan S-Type kodlaması kullanılır. parçasının bileşenleri hariç olmak üzere, dal talimatları tarafından kullanılan kodlama hemen öğrenebilirsiniz. RiscV ile uyumlu kalmak için SType biçimini eklemeyi tercih ediyoruz belgelerinden faydalanabilirsiniz.

31..25 24...20 19...15 14..12 11..7 6..0
7 5 5 3 5 7
imm7 rs2 rs1 func3 imm5 işlem kodu

SType biçiminde, neyse ki hemen iki yakın alanın ileriye doğru birleştirilmesi için yer paylaşımı spesifikasyonu şu basitçe ifade edilir:

  overlays:
    signed s_imm[12] = imm7, imm5;

Tüm alanları birleştirirken bit aralığı tanımlayıcısına gerek olmadığını unutmayın.

Mağaza talimatları şu şekilde kodlanmıştır:

31..25 24...20 19...15 14..12 11..7 6..0 işlem kodu adı
imm7 rs2 rs1 000 imm5 010 0011 sb
imm7 rs2 rs1 001 imm5 010 0011 sh
imm7 rs2 rs1 010 imm5 010 0011 sw
func3 işlem kodu

Değişiklikleri yapın ve sonra oluşturun. Oluşturulan çıkışı kontrol edin. Adil önceki gibi çalışmanızı riscv32i.bin_fmt adresine gidin.


Yükleme talimatlarını ekleyin

Yükleme talimatlarında I-Type biçimi kullanılır. Orada herhangi bir değişiklik yapılması gerekmez.

Kodlamalar şunlardır:

31...20 19...15 14..12 11..7 6..0 opcode_name
imm12 rs1 000 . 000 0011 lb
imm12 rs1 100 . 000 0011 Lbu
imm12 rs1 001 . 000 0011 h
imm12 rs1 101 . 000 0011 lhu
imm12 rs1 010 . 000 0011 lw
func3 işlem kodu

Değişiklikleri yapın ve sonra oluşturun. Oluşturulan çıkışı kontrol edin. Adil önceki gibi çalışmanızı riscv32i.bin_fmt adresine gidin.

Eğiticiyi sonlandırıyor. Yararlı olduğunu umuyoruz.