Bu eğitimin hedefleri şunlardır:
- Talimatların MPACT-Sim simülatöründe nasıl gösterildiğini öğrenin.
- ISA açıklama dosyasının yapısını ve söz dizimini öğrenin.
- RiscV RV32I talimat alt kümesi için ISA açıklamalarını yazın
Genel Bakış
MPACT-Sim'de hedef talimatların kodu çözülür ve dahili bir ve anlamsal açıdan daha erişilebilir hale getirmek için yürütmek için daha hızlı çalışır. Bu talimat örnekleri bir talimatta önbelleğe alınır Böylece, sıklıkla yürütülen talimatların çalıştırılma sayısını azaltmak için yürütüldü.
Ders dersi
Başlamadan önce, talimatların nasıl hazırlandığına ve
temsil edilir. Instruction
sınıfı şurada tanımlanmıştır:
mpact-sim/mpact/sim/generic/instruction.h.
Talimat sınıfı örneği, şunları yapmak için gereken tüm bilgileri içerir: yürütülürken talimatı simüle eder, örneğin:
- Talimat adresi, simüle edilmiş talimat boyutu, ör. .text olarak boyut.
- Talimat işlem kodu.
- Koşullar işlenen arayüz işaretçisi (varsa).
- Kaynak işlenen arayüz işaretçilerinin vektörü.
- Hedef işlenen arayüz işaretçilerinin vektörü.
- Anlamsal işlev çağrılabilir.
- Mimari durum nesnesinin işaretçisi.
- Bağlam nesnesinin işaretçisi.
- İşaretçiyi alt öğe ve sonraki Talimat örneklerine yönlendirir.
- Ayırma dizesi.
Bu örnekler genellikle bir talimatlar (örnek) önbelleğinde depolanır ve yeniden çalıştırıldığında yeniden kullanılır. Böylece, performans artar yardımcı olabilir.
Bağlam nesnesi işaretçisi dışında tüm veriler, talimatı kod çözücüyü oluşturur. Bunun için çünkü eğitimde bu unsurların ayrıntılarını bilmek gerekmez, çünkü yardımcı olur. Bunun yerine bunların nasıl kullanıldıklarını anlamak için yeterli olacaktır.
Anlamsal işlev çağrılabilir; C++ işlevi/yöntem/işlev nesnesidir
(lambdas dahil) içeren bir JavaScript kodu içerir. Örneğin,
add
talimatı için her bir kaynak işlenenini yükler,
işlem görür ve sonucu tek bir hedef işlenenine yazar. Konu
anlamsal işlevler, anlamsal işlev eğiticisinde ayrıntılı olarak ele alınmıştır.
Talimat işlenenleri
Talimat sınıfı, üç tür işlenen arayüzü işaretleyiciler içerir: değer, kaynak ve hedef. Bu arayüzler, anlamsal işlevlerin temel talimatın gerçek türünden bağımsız olarak yazılmalıdır işlenen. Örneğin, kayıtların ve anındaların değerlerine erişim aynı arayüzden geçiriliyor. Bu, aynı işlemi yapan talimatların da işlem ancak farklı işlenenlerde (ör. kayıtlar ve taklitler) uygulanmış olabilir.
Temel alınan öğeleri destekleyen ISA'lar için yüklem işlenen arayüzü talimatı yürütme (diğer ISA'lar için boştur), bir verilen talimat koşulun boole değerine göre yürütülmelidir.
// The predicte operand interface is intended primarily as the interface to
// read the value of instruction predicates. It is separated from source
// predicates to avoid mixing it in with the source operands needed for modeling
// the instruction semantics.
class PredicateOperandInterface {
public:
virtual bool Value() = 0;
// Return a string representation of the operand suitable for display in
// disassembly.
virtual std::string AsString() const = 0;
virtual ~PredicateOperandInterface() = default;
};
Kaynak işlenen arayüzü, talimat anlamsal işlevinin temel işlenene bakılmaksızın, talimat işlenenlerinden gelen değerler türü. Arayüz yöntemleri hem skaler hem de vektör değerli işlenenleri destekler.
// The source operand interface provides an interface to access input values
// to instructions in a way that is agnostic about the underlying implementation
// of those values (eg., register, fifo, immediate, predicate, etc).
class SourceOperandInterface {
public:
// Methods for accessing the nth value element.
virtual bool AsBool(int index) = 0;
virtual int8_t AsInt8(int index) = 0;
virtual uint8_t AsUint8(int index) = 0;
virtual int16_t AsInt16(int index) = 0;
virtual uint16_t AsUint16(int) = 0;
virtual int32_t AsInt32(int index) = 0;
virtual uint32_t AsUint32(int index) = 0;
virtual int64_t AsInt64(int index) = 0;
virtual uint64_t AsUint64(int index) = 0;
// Return a pointer to the object instance that implements the state in
// question (or nullptr) if no such object "makes sense". This is used if
// the object requires additional manipulation - such as a fifo that needs
// to be pop'ed. If no such manipulation is required, nullptr should be
// returned.
virtual std::any GetObject() const = 0;
// Return the shape of the operand (the number of elements in each dimension).
// For instance {1} indicates a scalar quantity, whereas {128} indicates an
// 128 element vector quantity.
virtual std::vector<int> shape() const = 0;
// Return a string representation of the operand suitable for display in
// disassembly.
virtual std::string AsString() const = 0;
virtual ~SourceOperandInterface() = default;
};
Hedef işlenen arayüzü, ayırma ve işleme yöntemleri sunar.
DataBuffer
örnek (kayıt değerlerini depolamak için kullanılan dahili veri türü). CEVAP
hedef işlemde de bir gecikme vardır. Bu gecikme
talimat tarafından ayrılan veri arabelleği örneği gösterilene kadar beklenecek döngülerin sayısı
anlamsal işlev, hedef kaydın değerini güncellemek için kullanılır. Örneğin,
add
talimatının gecikme süresi 1, mpy
talimatının gecikme süresi ise 1 olabilir.
4 olabilir. Bu konu
konulu videomuzu izleyin.
// The destination operand interface is used by instruction semantic functions
// to get a writable DataBuffer associated with a piece of simulated state to
// which the new value can be written, and then used to update the value of
// the piece of state with a given latency.
class DestinationOperandInterface {
public:
virtual ~DestinationOperandInterface() = default;
// Allocates a data buffer with ownership, latency and delay line set up.
virtual DataBuffer *AllocateDataBuffer() = 0;
// Takes an existing data buffer, and initializes it for the destination
// as if AllocateDataBuffer had been called.
virtual void InitializeDataBuffer(DataBuffer *db) = 0;
// Allocates and initializes data buffer as if AllocateDataBuffer had been
// called, but also copies in the value from the current value of the
// destination.
virtual DataBuffer *CopyDataBuffer() = 0;
// Returns the latency associated with the destination operand.
virtual int latency() const = 0;
// Return a pointer to the object instance that implmements the state in
// question (or nullptr if no such object "makes sense").
virtual std::any GetObject() const = 0;
// Returns the order of the destination operand (size in each dimension).
virtual std::vector<int> shape() const = 0;
// Return a string representation of the operand suitable for display in
// disassembly.
virtual std::string AsString() const = 0;
};
ISA açıklaması
Bir işlemcinin ISA (Talimat Seti Mimarisi) soyut modeli tanımlar yazılımın donanımla etkileşime girmesini sağlar. Projeyi tanımlayan kayıtlarına ve diğer makineye ait yapılandırmanın ve davranışları (anlamsal) üzerine çalışır. Amaçları: ISA, talimatların gerçek kodlamasını içermez. Bunlar ayrı olarak ele alınır.
İşleyen ISA, soyut, kodlamadan bağımsız bir düzeyde ayarlanmış olmasını sağlar. Açıklama dosyası kullanılabilir talimat grubunu sıralar. Her talimat için adının, işlenenlerinin sayısı ile adlarını ve fonksiyonlarının özelliğini uygulayan bir C++ işlevine/çağrılanabilir öğesine bağlama. Ayrıca, Bir ayırma biçimlendirme dizesi ve talimatın donanım kaynağı adları. Birincisi, ikinci bir boyut oluşturmak için hata ayıklama, izleme veya etkileşimli kullanım talimatının temsili. İlgili içeriği oluşturmak için kullanılan ikincisi, simülasyonda daha fazla döngü doğruluğu oluşturmak için kullanılabilir.
ISA açıklama dosyası, isa-parser tarafından talimat kod çözücüyü devreye sokmaktır. Bu kod çözücü, talimat nesnelerinin alanları dolduruluyor. Belirli değerler, örneğin hedef tescil numarası, biçime özel talimattan alınır. kod çözücü. Bu tür kod çözücülerden biri, ikili kod çözücüdür. Bu kod çözücü, bir sonraki eğiticiye göz atın.
Bu eğitimde, basit ve skaler bir veri için ISA açıklama dosyasının nasıl yazılacağı bahsedeceğim. RiscV RV32I talimatının göstermeli ve diğer eğiticilerle birlikte özel geliştirmeler için "Hello World" simülasyonu çok önemli. RiscV ISA hakkında daha fazla bilgi için bkz. Risc-V Özellikleri.
İlk olarak dosyayı açın:
riscv_isa_decoder/riscv32i.isa
.
Dosyanın içeriği birden çok bölüme ayrılır. Birincisi, ISA beyan:
isa RiscV32I {
namespace mpact::sim::codelab;
slots { riscv32; }
}
Bu, RiscV32I
öğesinin ISA adı olduğunu ve kod oluşturucunun
RiscV32IEncodingBase
adında bir sınıf oluşturup
oluşturulan kod çözücü, işlem kodu ve işlenen bilgilerini almak için kullanılır. Kişinin adı
bu sınıf, ISA adının Pascal büyük/küçük harfe dönüştürülerek oluşturulur, ardından
EncodingBase
ile birleştiriliyor. slots { riscv32; }
beyanı
RiscV32I'de yalnızca tek bir talimat yuvası riscv32
olduğunu belirtir
ISA (VLIW talimatındaki birden çok yuvanın aksine) ve yalnızca
geçerli talimatlar, riscv32
içinde yürütülecek şekilde tanımlanmış olan talimatlardır.
// First disasm fragment is 15 char wide and left justified.
disasm widths = {-15};
Bu, herhangi bir parçalamanın ilk sökme parçasının, spesifikasyon (aşağıda daha fazla bilgi verilmiştir), 15 karakter içinde iki yana yaslı olarak bırakılacaktır çok önemlidir. Sonraki parçalar bu alana, girin.
Bunun altında üç alan bildirimi bulunur: riscv32i
, zicsr
ve riscv32
.
Yukarıdaki isa
tanımına göre, yalnızca riscv32
için tanımlanan talimatlar
alanı RiscV32I
SDK'sının bir parçası olacaktır. Diğer iki zaman aralığı ne için?
Slotlar, talimatları ayrı gruplar halinde hesaba katmak için kullanılabilir. Bu gruplar daha sonra
bir araya getirilir. : riscv32i, zicsr
notasyonuna dikkat edin
(riscv32
alan bildirimi) Bu, riscv32
alanının devraldığını belirtir
zicsr
ve riscv32i
alanlarında tanımlanan tüm talimatlar. RiscV 32 bit ISA
RV32I adlı bir temel ISA'dan oluşur. Buna, bir dizi isteğe bağlı uzantı
eklenir. Slot mekanizması, bu uzantılardaki talimatların
tanımlamaları için ayrı ayrı belirtildiğinde
ve gerektiği şekilde birleştirildiğinde
önemli bir rol oynar. Bu durumda, RiscV 'I' ve grup tanımlı
"zicsr" içindekilerden ayrı olarak grubu. Ek gruplar tanımlanabilir
'M' için (çarpma/böl), 'F' (tek duyarlıklı kayan nokta), 'D'
(çift duyarlıklı kayan nokta), 'C' (kompakt 16 bit talimatlar) vb. gibi
gereken nihai RiscV ISA için gereken
// The RiscV 'I' instructions.
slot riscv32i {
...
}
// RiscV32 CSR manipulation instructions.
slot zicsr {
...
}
// The final instruction set combines riscv32i and zicsr.
slot riscv32 : riscv32i, zicsr {
...
}
zicsr
ve riscv32
alan tanımlarının değiştirilmesi gerekmez. Ancak
Bu eğiticide odak noktası, riscv32i
yuvaya yerleştirilmiştir. Bu alanda halihazırda tanımlanmış olan öğelere daha yakından bakalım:
// The RiscV 'I' instructions.
slot riscv32i {
// Include file that contains the declarations of the semantic functions for
// the 'I' instructions.
includes {
#include "learning/brain/research/mpact/sim/codelab/riscv_semantic_functions/solution/rv32i_instructions.h"
}
// These are all 32 bit instructions, so set default size to 4.
default size = 4;
// Model these with 0 latency to avoid buffering the result. Since RiscV
// instructions have sequential semantics this is fine.
default latency = 0;
// The opcodes.
opcodes {
fence{: imm12 : },
semfunc: "&RV32IFence"c
disasm: "fence";
ebreak{},
semfunc: "&RV32IEbreak",
disasm: "ebreak";
}
}
İlk olarak, oluşturulması gereken başlık dosyalarının listelendiği bir includes {}
Bu alana referans verildiğinde, oluşturulan koda doğrudan veya
dolaylı olarak bildirmeliyiz. Dahil et dosyaları global olarak da listelenebilir
kapsamlı bir includes {}
bölümüdür. Bu durumda her zaman dahil edilirler. Bu
her alana aynı "include" (ekleme) dosyasının eklenmesi gerekiyorsa yararlı olur.
belirler.
default size
ve default latency
beyanları,
aksi belirtildiğinde, bir talimatın boyutu 4 ve bir talimatın gecikmesinin
hedef işlem gören yazma 0 döngüdür. Talimatın büyüklüğüne dikkat edin
büyük bir değer, rastgele değeri hesaplamak için program sayacının
simüle edilmiş senaryoda yürütülecek bir sonraki sıralı talimatın
işlemci. Bu boyut, bayt cinsinden boyutla aynı olabilir veya olmayabilir.
yürütülebilir giriş dosyasında talimat temsili.
Alan tanımının merkezinde işlem kodu bölümü bulunur. Gördüğünüz gibi yalnızca iki
fence
ve ebreak
işlem kodları (talimatlar) şu ana kadar
riscv32i
. fence
işlem kodu, ad (fence
) ve
işlem gören spesifikasyonu ({: imm12 : }
) ve ardından isteğe bağlı sökme
biçimi ("fence"
) ve anlamsal olarak bağlanacak çağrılabilir
işlevine ("&RV32IFence"
) gidin.
Talimat işlenenleri, her bileşenle üçlü olarak belirtilir.
noktalı virgülle ayrılmış, predicate ':' kaynak işlenen listesi ':'
hedef işlenen listesi. Kaynak ve hedef işlenen listeleri virgülle ayrılmıştır.
işlem görelerin adlarını içeren ayrılmış bir listedir. Gördüğünüz gibi, bu talimat veri işlemenin
fence
talimatı, koşul işleneni içermiyor, yalnızca tek bir kaynak içeriyor
işlem gören adı imm12
ve hedef işleneni yok. RiscV RV32I alt kümesi
koşullu yürütmeyi desteklemediğinden koşul işleneni her zaman boş olur
inceleyebilirsiniz.
Anlamsal fonksiyon, C++
işlevini veya çağrılmasını sağlayabilirsiniz. İmzalama
anlamsal işlev/çağrılanabilir: void(Instruction *)
.
Sökme spesifikasyonu, virgülle ayrılmış bir dize listesinden oluşur.
Genellikle biri işlem kodu, diğeri de işlem kodu için olmak üzere yalnızca iki dize kullanılır.
işlenenler. Biçimlendirildiğinde (Talimat'ta AsString()
çağrısı kullanılarak) her bir
dize, disasm widths
uyarınca bir alan içinde biçimlendirilir
yukarıda açıklanan özelliklere tabidir.
Aşağıdaki alıştırmalar, riscv32i.isa
dosyasına talimat eklemenize yardımcı olur
"Hello World" ifadesini taklit etmek için yeterlidir çok önemli. Acelesi olanlar için,
çözüm önerileri
riscv32i.isa
ve
rv32i_instructions.h olmalıdır.
İlk Derlemeyi Gerçekleştir
Dizini riscv_isa_decoder
olarak değiştirmediyseniz bu işlemi şimdi yapın. Sonra
Bu derleme başarılı olacaktır.
$ cd riscv_isa_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_isa_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_isa_decoder
Bu dizinde diğer dosyaların yanı sıra şunlar yer alır: oluşturulan C++ dosyaları:
riscv32i_decoder.h
riscv32i_decoder.cc
riscv32i_enums.h
riscv32i_enums.cc
Tarayıcıda tıklayarak riscv32i_enums.h
öğesine bakalım. Şunları yapmalısınız:
aşağıdaki gibi bir ifadeyi içerdiğini görürsünüz:
#ifndef RISCV32I_ENUMS_H
#define RISCV32I_ENUMS_H
namespace mpact {
namespace sim {
namespace codelab {
enum class SlotEnum {
kNone = 0,
kRiscv32,
};
enum class PredOpEnum {
kNone = 0,
kPastMaxValue = 1,
};
enum class SourceOpEnum {
kNone = 0,
kCsr = 1,
kImm12 = 2,
kRs1 = 3,
kPastMaxValue = 4,
};
enum class DestOpEnum {
kNone = 0,
kCsr = 1,
kRd = 2,
kPastMaxValue = 3,
};
enum class OpcodeEnum {
kNone = 0,
kCsrs = 1,
kCsrsNw = 2,
kCsrwNr = 3,
kEbreak = 4,
kFence = 5,
kPastMaxValue = 6
};
constexpr char kNoneName[] = "none";
constexpr char kCsrsName[] = "Csrs";
constexpr char kCsrsNwName[] = "CsrsNw";
constexpr char kCsrwNrName[] = "CsrwNr";
constexpr char kEbreakName[] = "Ebreak";
constexpr char kFenceName[] = "Fence";
extern const char *kOpcodeNames[static_cast<int>(
OpcodeEnum::kPastMaxValue)];
enum class SimpleResourceEnum {
kNone = 0,
kPastMaxValue = 1
};
enum class ComplexResourceEnum {
kNone = 0,
kPastMaxValue = 1
};
enum class AttributeEnum {
kPastMaxValue = 0
};
} // namespace codelab
} // namespace sim
} // namespace mpact
#endif // RISCV32I_ENUMS_H
Gördüğünüz gibi,
riscv32i.isa
dosyası, numaralandırma türlerinden birinde tanımlanmış. Ayrıca
işlem kodlarının tüm adlarını depolayan bir OpcodeNames
dizisi vardır (
(riscv32i_enums.cc
içinde tanımlanmıştır). Diğer dosyalar, oluşturulan kod çözücüyü içerir.
Bu konu başka bir eğitimde daha ayrıntılı şekilde ele alınacaktır.
Bazel Derleme Kuralı
Bazel'deki ISA kod çözücü hedefi,
mpact/sim/decoder/mpact_sim_isa.bzl
üzerinden yüklenen mpact_isa_decoder
mpact-sim
deposunda. Bu eğitim için
riscv_isa_decoder/BUILD
:
mpact_isa_decoder(
name = "riscv32i_isa",
src = "riscv32i.isa",
includes = [],
isa_name = "RiscV32I",
deps = [
"//riscv_semantic_functions:riscv32i",
],
)
Bu kural, C++ kodunu oluşturmak için ISA ayrıştırıcı aracını ve oluşturucuyu çağırır,
daha sonra, oluşturulan dosyayı diğer kuralların bağımlı olabileceği bir kitaplıkta derler.
//riscv_isa_decoder:riscv32i_isa
etiketi. includes
bölümü kullanılır
kullanın..isa
İlgili içeriği oluşturmak için kullanılan
isa_name
, hangi belirli isa'yı belirtmek için kullanılır (birden fazla ISA ise zorunludur)
kod çözücünün oluşturulacağı kaynak dosyada belirtilir.
Kayıt-Kayıt ALU Talimatları Ekleme
Şimdi riscv32i.isa
dosyasına bazı yeni talimatlar eklemenin zamanı geldi. İlk
Talimat grubu, add
,
and
vb. RiscV32'de bunların tümü R tipi ikili talimat biçimini kullanır:
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 |
Biçimden bağımsız kod çözücü oluşturmak için .isa
dosyası kullanılsa da
girişlere yön vermek için ikili program biçimini ve düzenini göz önünde bulundurmak açısından yararlıdır. Siz
Gördüğünüz gibi, veri feed'ini dolduran kod çözücüyle ilgili
talimat nesneleri: rs2
, rs1
ve rd
. Bu noktada
aynı şekilde kodlanan tam sayı kayıtları (bit dizileri) için bu adlar
tüm talimatlarda aynı talimat alanlarında göstermektir.
Ekleyeceğimiz 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.
Bu talimatların her biri,opcodes
riscv32i
alan tanımı. Hatırlayacağınız üzere, adları, işlem kodlarını, kodları,
ve anlamsal işlevi hakkında daha fazla bilgi sahibi olmanızı sağlar. İsim kolay,
yukarıdaki işlem kodu adlarını kullanalım. Ayrıca, hepsi aynı işlenenleri kullandığından
işlenen spesifikasyonu için { : rs1, rs2 : rd}
kullanabiliriz. Bunun anlamı,
rs1 tarafından belirtilen kayıt kaynağı işleneninin kaynakta dizini 0 olur
talimat nesnesindeki işlem gören vektörü, belirtilen kayıt kaynağı işleneni
rs2'ye göre dizin 1'e ve kayıt hedef işleneni rd
hedef işlenen vektördeki tek öğe olacaktır (endeks 0'da).
Sırada, anlamsal fonksiyon spesifikasyonu var. Bu, anahtar kelime
semfunc
ve atama için kullanılabilecek bir çağrılabilen C++ dizesi
std::function
olarak değiştirdik. Bu eğiticide, fonksiyonları kullanacağız;
dizesi "&MyFunctionName"
olacak.
fence
talimatı; bunlar "&RV32IAdd"
, "&RV32IAnd"
vb. olmalıdır.
Sonuncusu da sökme spesifikasyonu. Bu anahtar kelime disasm
anahtar kelimesiyle başlar ve
ardından,
talimatı dize olarak yazdırılmalıdır. Ekranın önünde %
işareti kullanarak
işlem gören adı, dize gösterimini kullanan bir dize değişikliğini gösterir
işleyeceğiz. add
talimatı için bu değer şu şekilde olacaktır: disasm: "add", "%rd,
%rs1,%rs2"
. Bu, add
talimatına ait girişin
örneğin:
add{ : rs1, rs2 : rd},
semfunc: "&RV32IAdd",
disasm: "add", "%rd, %rs1, %rs2";
Devam edin ve riscv32i.isa
dosyasını düzenleyin ve tüm bu talimatları
.isa
açıklama. Yardıma ihtiyacınız olursa (veya çalışmanızı kontrol etmek isterseniz)
açıklama dosyası
burada bulabilirsiniz.
Talimatlar riscv32i.isa
dosyasına eklendikten sonra gerekli olacaktır
oluşturulan yeni anlamsal işlevlerin her biri için
şu konumda bulunan rv32i_instructions.h
dosyasına referansta bulunulmuştur:
`../semantic_functions/. Yardıma ihtiyacınız olursa (veya çalışmalarınızı kontrol etmek isterseniz)
yanıt
burada bulabilirsiniz.
Bu işlemleri tamamladıktan sonra riscv_isa_decoder
uygulamasına geri dönün.
dizini oluşturun ve yeniden oluşturun. Oluşturulan kaynak dosyaları inceleyebilirsiniz.
Anında 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 |
Gördüğünüz gibi, rs1
ve rd
işlenenleri
ve tamsayı kayıtları temsil etmek için kullanılır. Dolayısıyla bu adlar
elde edilir. Anlık değer alanlarının uzunluğu ve konumu farklıdır ve
imm12
imzası varken iki (uimm5
ve uimm20
) imzasız. Her biri
bunlar kendi adlarını kullanır.
Dolayısıyla, I-Type talimatlarının işlenenleri { : rs1, imm12 :rd
}
olmalıdır. Özel I-Type talimatları için { : rs1, uimm5 : rd}
olmalıdır.
U Tipi talimat işleneni spesifikasyonu { : uimm20 : rd }
olmalıdır.
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.
Eklememiz gereken ö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.
Eklememiz gereken U-Type talimatları şunlardır:
auipc
- Hemen pc'ye ekle.lui
- Hemen üst öğeyi yükle.
İşletim kodları için kullanılacak adlar, talimat adlarından doğal bir şekilde gelir
(hepsi benzersiz olduğundan yenilerini bulmaya gerek yok). Mesele,
semantik fonksiyonları belirterek talimat nesnelerinin
temel işlenenden bağımsız olan kaynak işlenenlerine arayüzler
türü. Bu, aynı işleme sahip ancak aynı işlemi gerçekleştirecek talimatlar için
işlem gören türlerinde farklılık gösterebilir, aynı anlamsal işlevi paylaşabilir. Örneğin,
addi
talimatı, aşağıdaki durumlarda add
talimatıyla aynı işlemi gerçekleştirir:
biri işlenen türü yok sayılır, böylece aynı anlamsal işlevi kullanabilir
"&RV32IAdd"
spesifikasyonu. Benzer şekilde andi
, ori
, xori
ve slli
için de geçerlidir.
Diğer talimatlarda yeni anlamsal işlevler kullanılmaktadır, ancak bunlar adlandırılmalı
işleme göre değil, işlenenlere göre değişir. Dolayısıyla srai
için "&RV32ISra"
kullanın. İlgili içeriği oluşturmak için kullanılan
auipc
ve lui
U Tipi talimatlarının kayıtlı eşdeğerleri olmadığından sorun yok
"&RV32IAuipc"
ve "&RV32ILui"
kullanmak için.
Sökme dizeleri önceki alıştırmadakilere çok benzer, ancak
beklediğiniz gibi, %rs2
referansları %imm12
, %uimm5
ve
veya %uimm20
(hangisi uygunsa)
Devam edin ve değişiklikleri yapın ve geliştirin. Oluşturulan çıkışı kontrol edin. Tıpkı daha önceden çalışmanızı riscv32i.isa ve rv32i_instructions.h olmalıdır.
Dal Ekleme ve Jump-And-Link Talimatları
Eklememiz gereken dal ve atlama ve bağlantı talimatlarında bir hedef kullanılır
yalnızca talimatın kendisinde ima edilen işlem göre, yani sonraki pc'de
değer. Bu aşamada, bunu şu ada sahip uygun bir işlenen olarak ele alacağız:
next_pc
Sonraki bir eğiticide ayrıntılı olarak açıklanacaktır.
Şube Talimatları
Eklediğimiz dallar B-Type kodlamasını kullanıyor.
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 |
Farklı doğrudan alanlar, 12 bit imzalı bir hemen olacak şekilde birleştirilir.
değer. Biçim gerçekten alakalı olmadığından buna "hemen" adını veriyoruz.
bimm12
, 12 bit dal için anında kullanılır. Parçalanma,
kod çözücüyü oluşturma hakkında bir sonraki eğiticiye göz atın. Tüm
şube talimatları, rs1 ve rs2 tarafından belirtilen tam sayı kayıtlarını karşılaştırır.
koşul doğruysa hemen değer mevcut pc değerine
yürütülecek bir sonraki talimatın adresini üretir.
bu nedenle dal talimatları { : rs1, rs2, bimm12 : next_pc }
olmalıdır.
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.
Bu işlem kodu adlarının tümü benzersiz olduğundan .isa
içinde yeniden kullanılabilir
dokunun. Elbette yeni anlamsal işlev adları da eklenmelidir (ör.
"&RV32IBeq"
vb.
Söküm spesifikasyonu şimdi biraz daha karmaşık.
Talimat, hedefi aslında parçası olmadan hesaplamak için kullanılır
sayısı kadar satır öğesidir. Ancak bu, söz konusu Google Hesabı'nda saklanan bilgilerin bir
talimat nesnesidir. Dolayısıyla bu kullanılabilir. Çözüm, sisteme
ifade söz dizimini kullanmanız gerekir. "%" yerine ardından
işlem adını almak için %(ifade: yazdırma biçimi) yazabilirsiniz. Yalnızca çok basit
desteklenir ancak adres artı ofseti bunlardan biri. @
geçerli talimat adresi için kullanılan simge. Yazdırma biçimi şuna benzer:
C stilinde yazdırma biçimleri, ancak başında %
yer almaz. için ayırma biçimi
ve beq
talimatı şu şekilde olur:
disasm: "beq", "%rs1, %rs2, %(@+bimm12:08x)"
Atla ve Bağlantı Oluştur Talimatları
Yalnızca iki atlama ve bağlantı talimatı eklenmesi gerekir: jal
(atlama ve bağlantı) ve
jalr
(dolaylı atlama ve bağlantı).
jal
talimatı, J-Type kodlamasını kullanır:
31 | 30...21 | 20 | 19...12 | 11..7 | 6..0 |
---|---|---|---|---|---|
1 | 10 | 1 | 8 | 5 | 7 |
imm | imm | imm | imm | . | işlem kodu |
Dal talimatlarında olduğu gibi 20 bit'lik anlık dosya da
birden çok alana sahip olacağı için bu alanı jimm20
olarak adlandıracağız. Parçalanma önemli değil
şu anda ancak önümüzdeki
kod çözücüyü oluşturma hakkında eğitici videomuzu izleyin. İşlenen
spesifikasyon { : jimm20 : next_pc, rd }
olur. İki platform olduğuna dikkat edin
üçüncü taraf işlem sağlayıcılarına, sonraki pc değerine ve
teşekkür ederiz.
Yukarıdaki dal talimatlarına benzer şekilde, ayırma biçimi şu şekilde olur:
disasm: "jal", "%rd, %(@+jimm20:08x)"
Dolaylı atlama ve bağlantı, hemen 12 bit ile I-Type biçimini kullanır. Google
,
Hedef talimat adresini üretmek için rs1
. Bağlantı kaydı
rd
tarafından belirtilen tam sayı kaydı.
31...20 | 19...15 | 14..12 | 11..7 | 6..0 |
---|---|---|---|---|
12 | 5 | 3 | 5 | 7 |
imm12 | rs1 | func3 | . | işlem kodu |
Kalıbı görmüşseniz, işlem gören spesifikasyonunun
jalr
için { : rs1, imm12 : next_pc, rd }
değeri ve sökme işlemi
spesifikasyon:
disasm: "jalr", "%rd, %rs1, %imm12"
Değişiklikleri yapın ve sonra oluşturun. Oluşturulan çıkışı kontrol edin. Adil önceki gibi çalışmanızı riscv32i.isa ve rv32i_instructions.h olmalıdır.
Mağaza Talimatları Ekleyin
Mağazanın talimatları çok basit. Tümü S-Type biçimini kullanır:
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 |
Gördüğünüz gibi, bu başka bir parçalı 12 bit'e ilişkin başka bir örnektir.
simm12
olarak adlandıralım. Mağaza talimatlarının tümünde tam sayı değeri saklanır
eklenerek elde edilen etkili adrese rs2 tarafından belirtilen kayıt
rs1 tarafından gösterilen tam sayı kaydının değeri
12 bit'i hemen tıklayın. İşlem gören biçimi, şunun için { : rs1, simm12, rs2 }
olmalıdır:
mağazadaki talimatları uygulayın.
Uygulanması gereken mağaza talimatları şunlardır:
sb
- Depolama baytı.sh
- Yarım kelime depolayın.sw
- Mağaza kelimesi.
sb
için sökme teknik özellikleri beklediğiniz gibidir:
disasm: "sb", "%rs2, %simm12(%rs1)"
Anlamsal fonksiyon spesifikasyonları da şu şekildedir: "&RV32ISb"
,
vb.
Değişiklikleri yapın ve sonra oluşturun. Oluşturulan çıkışı kontrol edin. Adil önceki gibi çalışmanızı riscv32i.isa ve rv32i_instructions.h olmalıdır.
Yükleme Talimatları Ekleyin
Yükleme talimatları, simülatörü kullanın. Yük gecikmesinin yüksek olduğu durumları modelleyebilmek için belirsiz, yükleme talimatları iki ayrı eyleme bölünür: 1) etkili adres hesaplaması ile bellek erişimi ve 2) sonuç geri yazma. simülatörü kullanarak bu işlem, yüklemenin anlamsal işlemini ikiye ana talimat ve alt talimat olabilir. Dahası, işlem görenleri belirttiğimizde, bunları hem ana hem de child talimatıdır. Bu, işlenen spesifikasyonunu bir üçlülerin listesi. Söz dizimi şöyledir:
{(predicate : sources : destinations),
(predicate : sources : destinations), ... }
Yükleme talimatlarının tümü, önceki videolarda olduğu gibi I-Type biçimini talimatlar:
31...20 | 19...15 | 14..12 | 11..7 | 6..0 |
---|---|---|---|---|
12 | 5 | 3 | 5 | 7 |
imm12 | rs1 | func3 | . | işlem kodu |
İşlem gören spesifikasyonu, adresi hesaplamak için gerekli işlenenleri böler.
ve yük verileri için kayıt hedefinden bellek erişimini başlatın:
{( : rs1, imm12 : ), ( : : rd) }
Anlamsal işlem iki talimata bölündüğünden, anlamsal fonksiyonlar
iki çağrılabilir. lw
(kelime yükle) için bu değer şu şekildedir:
yazılmış:
semfunc: "&RV32ILw", "&RV32ILwChild"
Söküm spesifikasyonu daha gelenekseldir.
ele alacağız. lw
için bu değer:
disasm: "lw", "%rd, %imm12(%rs1)"
Uygulanması gereken yükleme talimatları şunlardır:
lb
- Bayt yükleme.lbu
- Yükleme baytı imzasız.lh
- Yarım kelime yükle.lhu
- Yarım kelime imzasız yükle.lw
- Kelime yükle.
Değişiklikleri yapın ve sonra oluşturun. Oluşturulan çıkışı kontrol edin. Adil önceki gibi çalışmanızı riscv32i.isa ve rv32i_instructions.h olmalıdır.
Bu noktaya ulaştığınız için teşekkür ederiz. Umarız bu bilgiler işinize yaramıştır.