FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://sites.google.com/site/fpgadevelopindex/

自作RISC-Vシミュレータを拡張してシステムレジスタを実装する(途中2)

とりあえずCSRのビットフィールドを定義した。

github.com

$sysreg_table[37] = Array[0x243,    'HRW',       'hbadaddr'  , Array[Array[31, 0, 'hbadaddr' , 'RW']]]   # temporary implementation
$sysreg_table[38] = Array[0xA01,    'HRW',       'stimew'    , Array[Array[31, 0, 'stimew'   , 'RW']]]   # temporary implementation
$sysreg_table[39] = Array[0xA81,    'HRW',       'stimehw'   , Array[Array[31, 0, 'stimehw'  , 'RW']]]   # temporary implementation
# Machine-Level CSR
$sysreg_table[40] = Array[0xF00,    'MRO',       'mcpuid'   , Array[Array[31,30, 'Base', 'R'], Array[25, 0, 'Extensions', 'R']]]
$sysreg_table[41] = Array[0xF01,    'MRO',       'mimpid'   , Array[Array[31,16, 'Implementation', 'R'], Array[15, 0, 'Source', 'R']]]
$sysreg_table[42] = Array[0xF10,    'MRO',       'mhartid'  , Array[Array[31, 0, 'Hart_ID', 'R']]]
$sysreg_table[43] = Array[0x300,    'MRW',       'mstatus'  , Array[Array[31,31, 'SD', 'RW'], Array[21,17, 'VM', 'RW'], Array[16,16, 'MPRV', 'RW'], Array[15,14, 'XS', 'RW'], Array[13,12, 'FS', 'RW'],
                                                                    Array[11,10, 'PRV3', 'RW'], Array[ 9, 9, 'IE3', 'RW'],
                                                                    Array[ 8, 7, 'PRV2', 'RW'], Array[ 6, 6, 'IE2', 'RW'],
                                                                    Array[ 5, 4, 'PRV1', 'RW'], Array[ 3, 3, 'IE1', 'RW'],
                                                                    Array[ 2, 1, 'PRV' , 'RW'], Array[ 0, 0, 'IE' , 'RW']]]
$sysreg_table[44] = Array[0x301,    'MRW',       'mtvec'    , Array[Array[31, 2, 'Trap_Vector_Base_Address', 'RW']]]
$sysreg_table[45] = Array[0x302,    'MRW',       'mtdeleg'  , Array[Array[31,16, 'Interrupts', 'RW'], Array[15, 0, 'Synchronous_Exception', 'RW']]]
$sysreg_table[46] = Array[0x304,    'MRW',       'mie'      , Array[Array[ 7, 7, 'MTIP', 'RW'], Array[ 6, 6, 'HTIP', 'RW'], Array[ 5, 5, 'STIP', 'RW'],
                                                                    Array[ 3, 3, 'MSIP', 'RW'], Array[ 2, 2, 'HSIP', 'RW'], Array[ 1, 1, 'SSIP', 'RW']]]

RISC-VのCSRにビットフィールドを上記のように定義し、実際の構造体を定義し、読み書きの関数を自動的に生成できるよにする。

下記のような構造体が自動的に生成される。

struct sysreg_mhartid {
    uint32_t Hart_ID;
};


union sysreg_mstatus {
    struct {
        uint32_t IE : 1;
        uint32_t PRV : 2;
        uint32_t IE1 : 1;
        uint32_t PRV1 : 2;
        uint32_t IE2 : 1;
        uint32_t PRV2 : 2;
        uint32_t IE3 : 1;
        uint32_t PRV3 : 2;
        uint32_t FS : 2;
        uint32_t XS : 2;
        uint32_t MPRV : 1;
        uint32_t VM : 5;
        uint32_t dummy_0 : 9;
        uint32_t SD : 1;
    } bit_mstatus;
    uint32_t mstatus;
};


union sysreg_mtvec {
    struct {
        uint32_t dummy_0 : 2;
        uint32_t Trap_Vector_Base_Address : 30;
    } bit_mtvec;
    uint32_t mtvec;
};
#ifndef __SYSREG_FUNC_H__
#define __SYSREG_FUNC_H__


#include <stdint.h>
uint32_t Read_FFLAGS ();
uint32_t Read_FRM ();
uint32_t Read_FSCR ();
uint32_t Read_CYCLE ();
uint32_t Read_TIME ();
uint32_t Read_INSTRET ();
uint32_t Read_CYCLEH ();
uint32_t Read_TIMEH ();
uint32_t Read_INSTRETH ();
uint32_t Read_SSTATUS ();
uint32_t Read_STVEC ();
uint32_t Read_SIE ();
uint32_t Read_STIMECMP ();
uint32_t Read_STIME ();
uint32_t Read_STIMEH ();
uint32_t Read_SSCRATCH ();
uint32_t Read_SEPC ();
uint32_t Read_SCAUSE ();
uint32_t Read_SBADADDR ();
uint32_t Read_SIP ();
uint32_t Read_SPTBR ();
uint32_t Read_SASID ();
uint32_t Read_CYCLEW ();
uint32_t Read_TIMEW ();

CSR読み書きのための関数のテンプレートを自動的に生成する。中身はある程度は自動的に生成できるけれど、CSRに書き込んだり読み込んだりすると別の動作が発生するような記述をするために、とりあえず手書きで実装するようにする。

とりあえずMachine-Level CSRのビットフィールドの定義はできたので、あとは中身の実装だー。