Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

difftest访存踩坑分享 #10

Open
ColsonZhang opened this issue Aug 4, 2021 · 9 comments
Open

difftest访存踩坑分享 #10

ColsonZhang opened this issue Aug 4, 2021 · 9 comments
Labels
#Chisel Chisel 相关问题 #Difftest Difftest 相关问题

Comments

@ColsonZhang
Copy link

ColsonZhang commented Aug 4, 2021

错误描述

我在对lw和sw指令进行测试,按照学长提供的测试代码自己写了一段汇编并翻译成2进制进行测试。
$MP0RK)HPD 56TZZM27G$G
LYQPQO8B 4GOE6JXA UKUZY
我在ram.cpp里面加入了printf信号打印出存储器,看到写入和读出的数据是正确的。
{P%)B{59% HCKU8@U)C$ARV
但是difftest报错显示,这个读出的数据和理想的寄存器数据不同?
3WYNG1(KF5P5JI5_VB(6)1N
通过分析可以发现理想的寄存器状态是0x0000000400000003,而读出的数据是0x0000000000000003。该pc对应的指令ld,即读取64位数据。那么基本可以判断是在对存储器进行读写时出现的问题。

访存分析

大小端模式

RISCV的数据均为小端模式,即高位数据存储在存储器的大地址,低位数据存储在存储器的小地址。以下图为例,最高位字节是0x0A,最低位字节是0x0D。
1628043702(1)

Difftest的读出写入函数

打开difftest/src/test/csrc/common/ram.cpp文件,找到ram_write_helper和ram_inst_helper函数。在这里,我添加了两行printf(已注释)来打印写入或者读出数据,来辅助调试。

extern "C" uint64_t ram_inst_helper(uint8_t en, uint64_t rIdx) {
  if (!ram)
    return 0;
  if (en && rIdx >= EMU_RAM_SIZE / sizeof(uint64_t)) {
    rIdx %= EMU_RAM_SIZE / sizeof(uint64_t);
  }
  pthread_mutex_lock(&ram_mutex);
  uint64_t rdata = (en) ? ram[rIdx] : 0;
  pthread_mutex_unlock(&ram_mutex);
  // printf("Read\t rIdx: 0x%lx \t rdata: 0x%lx \n", rIdx, rdata );
  return rdata;
}

extern "C" void ram_write_helper(uint64_t wIdx, uint64_t wdata, uint64_t wmask, uint8_t wen) {
  if (wen && ram) {
    if (wIdx >= EMU_RAM_SIZE / sizeof(uint64_t)) {
      printf("ERROR: ram wIdx = 0x%lx out of bound!\n", wIdx);
      assert(wIdx < EMU_RAM_SIZE / sizeof(uint64_t));
    }
    pthread_mutex_lock(&ram_mutex);
    ram[wIdx] = (ram[wIdx] & ~wmask) | (wdata & wmask);
    pthread_mutex_unlock(&ram_mutex);
    // printf("Write\t wIdx: 0x%lx \t wdata: 0x%lx \t wmask: 0x%lx \n", wIdx, wdata, wmask);
  }
}

分析代码可以发现,代码的读写都是以uint64_t进行的!!!所以在写入过程加入了一个64位的写入掩码wmask!!!
即,该存储器是按照64位的存储空间设置的,所以对应的rtl代码要做出相同的适配。
由于项目给出的例子中没有涉及到回写部分的操作,所以在这里我也是纠结了很久才修正了bug。

RTL访存代码(chisel)

我使用的是chisel,给出我的访存部分的代码;对于verilog选手,我也会给出chisel生成的verilog代码。

chisel代码——difftest接口

大体上和chisel接入difftest经验贴的接入部分一致。需要特别注意的是( rvcore.io.mem_r_addr - "h80000000".U(64.W) ) >> 3.U这里计算出来的地址要右移3位。主要原因在于存储器的每个存储地址对应的存储空间是64位的!!!最低的3位的地址是该存储地址内存储空间的索引。
假设低4位的地址为the_addr[3:0],存储器存储的64位数据为the_data[63:0]
那么对于lw来说,the_addr[2]就决定读取the_data的高32位the_data[63:32]还是低32位the_data[31:0]
同样对于lh来说,the_addr[2:1]就决定读取the_data的高16位the_data[63:48]或者是中间的the_data[47:32]the_data[31:16]还是低16位the_data[15:0]
同样对于lb来说,the_addr[2:0]就决定读取the_data的哪8位数据。
对于写入,也是相同的情况。
1628044439(1)

chisel代码——访存阶段(Mem_Stage)

代码写的比较烂,没有进行优化。核心的思想就是,写入或者读出时,按照读写指令的类型和具体的地址,对数据进行移位,配合读写掩码得到正确的结果。

package oscpu

import chisel3._
import chisel3.util._
import chisel3.experimental._

class Mem_Stage extends Module {
    val io = IO(new Bundle{
        val inst_type       = Input(UInt( 5.W))
        val rd_data         = Input(UInt(64.W))
        val save_data       = Input(UInt(64.W))
        val mem_r_data      = Input(UInt(64.W))

        val mem_ext         = Input(UInt(1.W))
        val mem_sel         = Input(UInt(2.W))

        val mem_r_ena       = Output(UInt( 1.W))
        val mem_r_addr      = Output(UInt(64.W))

        val mem_w_ena       = Output(UInt( 1.W))
        val mem_w_addr      = Output(UInt(64.W))
        val mem_w_data      = Output(UInt(64.W))
        val mem_w_mask      = Output(UInt(64.W))

        val rd_w_data       = Output(UInt(64.W))
    })


    val the_mask            = Wire(UInt(64.W))
    val the_data_mask       = Wire(UInt(64.W))  // should be removed
    val the_data_ext        = Wire(UInt(64.W))

    when(reset.asBool) {
        io.mem_r_ena    := 0.U
        io.mem_r_addr   := 0.U
        io.mem_w_ena    := 0.U
        io.mem_w_addr   := 0.U
        io.mem_w_data   := 0.U
        io.mem_w_mask   := 0.U
        io.rd_w_data    := 0.U
        the_mask        := 0.U
        the_data_mask   := 0.U 
        the_data_ext    := 0.U 
    }.otherwise{

        // THE MASK
        // 64-bits
        when     ( io.mem_sel === 3.U ) { 
            the_mask := Cat( VecInit(Seq.fill(64)( 1.U )).asUInt )
        }
        // 32-bits
        .elsewhen( io.mem_sel === 2.U ) { 
            when(io.rd_data(2).asBool){
                the_mask := Cat( VecInit(Seq.fill(32)( 1.U )).asUInt, VecInit(Seq.fill(32)( 0.U )).asUInt ) 
            }.otherwise{
                the_mask := Cat( VecInit(Seq.fill(32)( 0.U )).asUInt, VecInit(Seq.fill(32)( 1.U )).asUInt ) 
            }
        }
        // 16-bits
        .elsewhen( io.mem_sel === 1.U ) { 

            when(io.rd_data(2,1) === 1.U){
                the_mask := Cat( VecInit(Seq.fill(32)( 0.U )).asUInt, VecInit(Seq.fill(16)( 1.U )).asUInt, VecInit(Seq.fill(16)( 0.U )).asUInt ) 
            }  
            .elsewhen(io.rd_data(2,1) === 2.U){
                the_mask := Cat( VecInit(Seq.fill(16)( 0.U )).asUInt, VecInit(Seq.fill(16)( 1.U )).asUInt, VecInit(Seq.fill(32)( 0.U )).asUInt ) 
            }  
            .elsewhen(io.rd_data(2,1) === 3.U){
                the_mask := Cat( VecInit(Seq.fill(16)( 1.U )).asUInt, VecInit(Seq.fill(48)( 0.U )).asUInt ) 
            }    
            .otherwise{
                the_mask := Cat( VecInit(Seq.fill(48)( 0.U )).asUInt, VecInit(Seq.fill(16)( 1.U )).asUInt ) 
            }
        }
        // 8-bits
        .otherwise {
            when(io.rd_data(2,0) === 1.U){
                the_mask := Cat( VecInit(Seq.fill(48)( 0.U )).asUInt, VecInit(Seq.fill( 8)( 1.U )).asUInt, VecInit(Seq.fill( 8)( 0.U )).asUInt  ) 
            }  
            .elsewhen(io.rd_data(2,0) === 2.U){
                the_mask := Cat( VecInit(Seq.fill(40)( 0.U )).asUInt, VecInit(Seq.fill( 8)( 1.U )).asUInt, VecInit(Seq.fill( 16)( 0.U )).asUInt  ) 
            }  
            .elsewhen(io.rd_data(2,0) === 3.U){
                the_mask := Cat( VecInit(Seq.fill(32)( 0.U )).asUInt, VecInit(Seq.fill( 8)( 1.U )).asUInt, VecInit(Seq.fill(24)( 0.U )).asUInt  ) 
            }  
            .elsewhen(io.rd_data(2,0) === 4.U){
                the_mask := Cat( VecInit(Seq.fill(24)( 0.U )).asUInt, VecInit(Seq.fill( 8)( 1.U )).asUInt, VecInit(Seq.fill(32)( 0.U )).asUInt  ) 
            }  
            .elsewhen(io.rd_data(2,0) === 5.U){
                the_mask := Cat( VecInit(Seq.fill(16)( 0.U )).asUInt, VecInit(Seq.fill( 8)( 1.U )).asUInt, VecInit(Seq.fill(40)( 0.U )).asUInt  ) 
            }  
            .elsewhen(io.rd_data(2,0) === 6.U){
                the_mask := Cat( VecInit(Seq.fill( 8)( 0.U )).asUInt, VecInit(Seq.fill( 8)( 1.U )).asUInt, VecInit(Seq.fill(48)( 0.U )).asUInt  ) 
            }  
            .elsewhen(io.rd_data(2,0) === 7.U){
                the_mask := Cat( VecInit(Seq.fill( 8)( 1.U )).asUInt, VecInit(Seq.fill(56)( 0.U )).asUInt ) 
            }  
            .otherwise{
                 the_mask := Cat( VecInit(Seq.fill(56)( 0.U )).asUInt, VecInit(Seq.fill( 8)( 1.U )).asUInt  ) 
            }

        }    



        // load
        when( io.inst_type(1) === 1.U ){
            io.mem_r_ena    := 1.U
            io.mem_r_addr   := io.rd_data
            the_data_mask   := io.mem_r_data & the_mask

            // 64-bits
            when     ( io.mem_sel === 3.U ) { 
                the_data_ext    := the_data_mask
                io.rd_w_data    := the_data_ext
            }
            // 32-bits
            .elsewhen( io.mem_sel === 2.U ) {
                when(io.rd_data(2).asBool){
                    the_data_ext    := the_data_mask >> 32.U
                }.otherwise{
                    the_data_ext    := the_data_mask
                }

                when( io.mem_ext.asBool )   { io.rd_w_data := Cat( VecInit(Seq.fill(32)( the_data_ext(31) )).asUInt,   the_data_ext(31,0) ) }
                .otherwise                  { io.rd_w_data := Cat( VecInit(Seq.fill(32)( 0.U )).asUInt,            the_data_ext(31,0) ) }
            }
            // 16-bits
            .elsewhen( io.mem_sel === 1.U ) {

                when(io.rd_data(2,1) === 1.U){
                    the_data_ext    := the_data_mask >> 16.U
                }  
                .elsewhen(io.rd_data(2,1) === 2.U){
                    the_data_ext    := the_data_mask >> 32.U
                }  
                .elsewhen(io.rd_data(2,1) === 3.U){
                    the_data_ext    := the_data_mask >> 48.U
                }  
                .otherwise{
                    the_data_ext    := the_data_mask
                }

                when( io.mem_ext.asBool )   { io.rd_w_data := Cat( VecInit(Seq.fill(48)( the_data_ext(15) )).asUInt,   the_data_ext(15,0) ) }
                .otherwise                  { io.rd_w_data := Cat( VecInit(Seq.fill(48)( 0.U )).asUInt,            the_data_ext(15,0) ) }
            }
            // 8-bits
            .otherwise                      {
                when(io.rd_data(2,0) === 1.U){
                    the_data_ext    := the_data_mask >> 8.U
                }  
                .elsewhen(io.rd_data(2,0) === 2.U){
                    the_data_ext    := the_data_mask >> 16.U
                }  
                .elsewhen(io.rd_data(2,0) === 3.U){
                    the_data_ext    := the_data_mask >> 24.U
                }  
                .elsewhen(io.rd_data(2,0) === 4.U){
                    the_data_ext    := the_data_mask >> 32.U
                }  
                .elsewhen(io.rd_data(2,0) === 5.U){
                    the_data_ext    := the_data_mask >> 40.U
                }  
                .elsewhen(io.rd_data(2,0) === 6.U){
                    the_data_ext    := the_data_mask >> 48.U
                }  
                .elsewhen(io.rd_data(2,0) === 7.U){
                    the_data_ext    := the_data_mask >> 56.U
                }  
                .otherwise{
                    the_data_ext    := the_data_mask
                }

                when( io.mem_ext.asBool )   { io.rd_w_data := Cat( VecInit(Seq.fill(56)( the_data_ext(7) )).asUInt,    the_data_ext(7,0) ) }
                .otherwise                  { io.rd_w_data := Cat( VecInit(Seq.fill(56)( 0.U )).asUInt,            the_data_ext(7,0) ) }
            }

        }.otherwise{
            io.mem_r_ena    := 0.U
            io.mem_r_addr   := 0.U
            io.rd_w_data    := io.rd_data
            the_data_mask   := 0.U 
            the_data_ext    := 0.U 
        }
        


        // save
        when( io.inst_type(0) === 1.U ){
            io.mem_w_ena    := 1.U
            io.mem_w_addr   := io.rd_data
            io.mem_w_mask   := the_mask

            // 64-bits
            when     ( io.mem_sel === 3.U ) { 
                io.mem_w_data   := io.save_data
            }
            // 32-bits
            .elsewhen( io.mem_sel === 2.U ) {
                when(io.rd_data(2).asBool){
                    io.mem_w_data   := io.save_data << 32.U
                }.otherwise{
                    io.mem_w_data   := io.save_data
                }

            }
            // 16-bits
            .elsewhen( io.mem_sel === 1.U ) {

                when(io.rd_data(2,1) === 1.U){
                    io.mem_w_data   := io.save_data << 16.U
                }  
                .elsewhen(io.rd_data(2,1) === 2.U){
                    io.mem_w_data   := io.save_data << 32.U
                }  
                .elsewhen(io.rd_data(2,1) === 3.U){
                    io.mem_w_data   := io.save_data << 48.U
                }  
                .otherwise{
                    io.mem_w_data   := io.save_data
                }
            }
            // 8-bits
            .otherwise {
                when(io.rd_data(2,0) === 1.U){
                    io.mem_w_data   := io.save_data << 8.U
                }  
                .elsewhen(io.rd_data(2,0) === 2.U){
                    io.mem_w_data   := io.save_data << 16.U
                }  
                .elsewhen(io.rd_data(2,0) === 3.U){
                    io.mem_w_data   := io.save_data << 24.U
                }  
                .elsewhen(io.rd_data(2,0) === 4.U){
                    io.mem_w_data   := io.save_data << 32.U
                }  
                .elsewhen(io.rd_data(2,0) === 5.U){
                    io.mem_w_data   := io.save_data << 40.U
                }  
                .elsewhen(io.rd_data(2,0) === 6.U){
                    io.mem_w_data   := io.save_data << 48.U
                }  
                .elsewhen(io.rd_data(2,0) === 7.U){
                    io.mem_w_data   := io.save_data << 56.U
                }  
                .otherwise{
                    io.mem_w_data   := io.save_data
                }
            }
        }.otherwise{
            io.mem_w_ena    := 0.U
            io.mem_w_addr   := 0.U
            io.mem_w_data   := 0.U
            io.mem_w_mask   := 0.U
        }
    }
}

verilog代码——访存

chisel自动生成的代码,可读性比较差

module Mem_Stage(
  input         clock,
  input         reset,
  input  [4:0]  io_inst_type,
  input  [63:0] io_rd_data,
  input  [63:0] io_save_data,
  input  [63:0] io_mem_r_data,
  input         io_mem_ext,
  input  [1:0]  io_mem_sel,
  output        io_mem_r_ena,
  output [63:0] io_mem_r_addr,
  output        io_mem_w_ena,
  output [63:0] io_mem_w_addr,
  output [63:0] io_mem_w_data,
  output [63:0] io_mem_w_mask,
  output [63:0] io_rd_w_data
);
  wire  _T_1 = io_mem_sel == 2'h3; // @[Mem_Stage.scala 48:31]
  wire  _T_2 = io_mem_sel == 2'h2; // @[Mem_Stage.scala 52:31]
  wire [63:0] _GEN_0 = io_rd_data[2] ? 64'hffffffff00000000 : 64'hffffffff; // @[Mem_Stage.scala 53:39 Mem_Stage.scala 54:26 Mem_Stage.scala 56:26]
  wire  _T_5 = io_mem_sel == 2'h1; // @[Mem_Stage.scala 60:31]
  wire  _T_7 = io_rd_data[2:1] == 2'h1; // @[Mem_Stage.scala 62:34]
  wire  _T_9 = io_rd_data[2:1] == 2'h2; // @[Mem_Stage.scala 65:39]
  wire  _T_11 = io_rd_data[2:1] == 2'h3; // @[Mem_Stage.scala 68:39]
  wire [63:0] _GEN_1 = io_rd_data[2:1] == 2'h3 ? 64'hffff000000000000 : 64'hffff; // @[Mem_Stage.scala 68:47 Mem_Stage.scala 69:26 Mem_Stage.scala 72:26]
  wire [63:0] _GEN_2 = io_rd_data[2:1] == 2'h2 ? 64'hffff00000000 : _GEN_1; // @[Mem_Stage.scala 65:47 Mem_Stage.scala 66:26]
  wire [63:0] _GEN_3 = io_rd_data[2:1] == 2'h1 ? 64'hffff0000 : _GEN_2; // @[Mem_Stage.scala 62:42 Mem_Stage.scala 63:26]
  wire  _T_13 = io_rd_data[2:0] == 3'h1; // @[Mem_Stage.scala 77:34]
  wire  _T_15 = io_rd_data[2:0] == 3'h2; // @[Mem_Stage.scala 80:39]
  wire  _T_17 = io_rd_data[2:0] == 3'h3; // @[Mem_Stage.scala 83:39]
  wire  _T_19 = io_rd_data[2:0] == 3'h4; // @[Mem_Stage.scala 86:39]
  wire  _T_21 = io_rd_data[2:0] == 3'h5; // @[Mem_Stage.scala 89:39]
  wire  _T_23 = io_rd_data[2:0] == 3'h6; // @[Mem_Stage.scala 92:39]
  wire  _T_25 = io_rd_data[2:0] == 3'h7; // @[Mem_Stage.scala 95:39]
  wire [63:0] _GEN_4 = io_rd_data[2:0] == 3'h7 ? 64'hff00000000000000 : 64'hff; // @[Mem_Stage.scala 95:47 Mem_Stage.scala 96:26 Mem_Stage.scala 99:27]
  wire [63:0] _GEN_5 = io_rd_data[2:0] == 3'h6 ? 64'hff000000000000 : _GEN_4; // @[Mem_Stage.scala 92:47 Mem_Stage.scala 93:26]
  wire [63:0] _GEN_6 = io_rd_data[2:0] == 3'h5 ? 64'hff0000000000 : _GEN_5; // @[Mem_Stage.scala 89:47 Mem_Stage.scala 90:26]
  wire [63:0] _GEN_7 = io_rd_data[2:0] == 3'h4 ? 64'hff00000000 : _GEN_6; // @[Mem_Stage.scala 86:47 Mem_Stage.scala 87:26]
  wire [63:0] _GEN_8 = io_rd_data[2:0] == 3'h3 ? 64'hff000000 : _GEN_7; // @[Mem_Stage.scala 83:47 Mem_Stage.scala 84:26]
  wire [63:0] _GEN_9 = io_rd_data[2:0] == 3'h2 ? 64'hff0000 : _GEN_8; // @[Mem_Stage.scala 80:47 Mem_Stage.scala 81:26]
  wire [63:0] _GEN_10 = io_rd_data[2:0] == 3'h1 ? 64'hff00 : _GEN_9; // @[Mem_Stage.scala 77:42 Mem_Stage.scala 78:26]
  wire [63:0] _GEN_11 = io_mem_sel == 2'h1 ? _GEN_3 : _GEN_10; // @[Mem_Stage.scala 60:41]
  wire [63:0] _GEN_12 = io_mem_sel == 2'h2 ? _GEN_0 : _GEN_11; // @[Mem_Stage.scala 52:41]
  wire [63:0] _GEN_13 = io_mem_sel == 2'h3 ? 64'hffffffffffffffff : _GEN_12; // @[Mem_Stage.scala 48:41 Mem_Stage.scala 49:22]
  wire [63:0] the_mask = reset ? 64'h0 : _GEN_13; // @[Mem_Stage.scala 33:24 Mem_Stage.scala 41:25]
  wire [63:0] _the_data_mask_T = io_mem_r_data & the_mask; // @[Mem_Stage.scala 110:46]
  wire [63:0] _GEN_36 = io_inst_type[1] ? _the_data_mask_T : 64'h0; // @[Mem_Stage.scala 107:40 Mem_Stage.scala 110:29 Mem_Stage.scala 182:29]
  wire [63:0] the_data_mask = reset ? 64'h0 : _GEN_36; // @[Mem_Stage.scala 33:24 Mem_Stage.scala 42:25]
  wire [63:0] _the_data_ext_T = {{32'd0}, the_data_mask[63:32]}; // @[Mem_Stage.scala 120:54]
  wire [63:0] _GEN_14 = io_rd_data[2] ? _the_data_ext_T : the_data_mask; // @[Mem_Stage.scala 119:43 Mem_Stage.scala 120:37 Mem_Stage.scala 122:37]
  wire [63:0] _the_data_ext_T_1 = {{16'd0}, the_data_mask[63:16]}; // @[Mem_Stage.scala 132:54]
  wire [63:0] _the_data_ext_T_3 = {{48'd0}, the_data_mask[63:48]}; // @[Mem_Stage.scala 138:54]
  wire [63:0] _GEN_16 = _T_11 ? _the_data_ext_T_3 : the_data_mask; // @[Mem_Stage.scala 137:51 Mem_Stage.scala 138:37 Mem_Stage.scala 141:37]
  wire [63:0] _GEN_17 = _T_9 ? _the_data_ext_T : _GEN_16; // @[Mem_Stage.scala 134:51 Mem_Stage.scala 135:37]
  wire [63:0] _GEN_18 = _T_7 ? _the_data_ext_T_1 : _GEN_17; // @[Mem_Stage.scala 131:46 Mem_Stage.scala 132:37]
  wire [63:0] _the_data_ext_T_4 = {{8'd0}, the_data_mask[63:8]}; // @[Mem_Stage.scala 150:54]
  wire [63:0] _the_data_ext_T_6 = {{24'd0}, the_data_mask[63:24]}; // @[Mem_Stage.scala 156:54]
  wire [63:0] _the_data_ext_T_8 = {{40'd0}, the_data_mask[63:40]}; // @[Mem_Stage.scala 162:54]
  wire [63:0] _the_data_ext_T_10 = {{56'd0}, the_data_mask[63:56]}; // @[Mem_Stage.scala 168:54]
  wire [63:0] _GEN_20 = _T_25 ? _the_data_ext_T_10 : the_data_mask; // @[Mem_Stage.scala 167:51 Mem_Stage.scala 168:37 Mem_Stage.scala 171:37]
  wire [63:0] _GEN_21 = _T_23 ? _the_data_ext_T_3 : _GEN_20; // @[Mem_Stage.scala 164:51 Mem_Stage.scala 165:37]
  wire [63:0] _GEN_22 = _T_21 ? _the_data_ext_T_8 : _GEN_21; // @[Mem_Stage.scala 161:51 Mem_Stage.scala 162:37]
  wire [63:0] _GEN_23 = _T_19 ? _the_data_ext_T : _GEN_22; // @[Mem_Stage.scala 158:51 Mem_Stage.scala 159:37]
  wire [63:0] _GEN_24 = _T_17 ? _the_data_ext_T_6 : _GEN_23; // @[Mem_Stage.scala 155:51 Mem_Stage.scala 156:37]
  wire [63:0] _GEN_25 = _T_15 ? _the_data_ext_T_1 : _GEN_24; // @[Mem_Stage.scala 152:51 Mem_Stage.scala 153:37]
  wire [63:0] _GEN_26 = _T_13 ? _the_data_ext_T_4 : _GEN_25; // @[Mem_Stage.scala 149:46 Mem_Stage.scala 150:37]
  wire [63:0] _GEN_28 = _T_5 ? _GEN_18 : _GEN_26; // @[Mem_Stage.scala 129:45]
  wire [63:0] _GEN_30 = _T_2 ? _GEN_14 : _GEN_28; // @[Mem_Stage.scala 118:45]
  wire [63:0] _GEN_32 = _T_1 ? the_data_mask : _GEN_30; // @[Mem_Stage.scala 113:45 Mem_Stage.scala 114:33]
  wire [63:0] _GEN_37 = io_inst_type[1] ? _GEN_32 : 64'h0; // @[Mem_Stage.scala 107:40 Mem_Stage.scala 183:29]
  wire [63:0] the_data_ext = reset ? 64'h0 : _GEN_37; // @[Mem_Stage.scala 33:24 Mem_Stage.scala 43:25]
  wire [7:0] io_rd_w_data_lo_lo = {the_data_ext[31],the_data_ext[31],the_data_ext[31],the_data_ext[31],the_data_ext[31],
    the_data_ext[31],the_data_ext[31],the_data_ext[31]}; // @[Mem_Stage.scala 125:110]
  wire [15:0] io_rd_w_data_lo = {the_data_ext[31],the_data_ext[31],the_data_ext[31],the_data_ext[31],the_data_ext[31],
    the_data_ext[31],the_data_ext[31],the_data_ext[31],io_rd_w_data_lo_lo}; // @[Mem_Stage.scala 125:110]
  wire [31:0] io_rd_w_data_hi_1 = {the_data_ext[31],the_data_ext[31],the_data_ext[31],the_data_ext[31],the_data_ext[31],
    the_data_ext[31],the_data_ext[31],the_data_ext[31],io_rd_w_data_lo_lo,io_rd_w_data_lo}; // @[Mem_Stage.scala 125:110]
  wire [31:0] io_rd_w_data_lo_1 = the_data_ext[31:0]; // @[Mem_Stage.scala 125:132]
  wire [63:0] _io_rd_w_data_T_32 = {io_rd_w_data_hi_1,io_rd_w_data_lo_1}; // @[Cat.scala 30:58]
  wire [63:0] _io_rd_w_data_T_33 = {32'h0,io_rd_w_data_lo_1}; // @[Cat.scala 30:58]
  wire [63:0] _GEN_15 = io_mem_ext ? _io_rd_w_data_T_32 : _io_rd_w_data_T_33; // @[Mem_Stage.scala 125:45 Mem_Stage.scala 125:60 Mem_Stage.scala 126:60]
  wire [5:0] io_rd_w_data_lo_lo_lo_2 = {the_data_ext[15],the_data_ext[15],the_data_ext[15],the_data_ext[15],the_data_ext
    [15],the_data_ext[15]}; // @[Mem_Stage.scala 144:110]
  wire [11:0] io_rd_w_data_lo_lo_2 = {the_data_ext[15],the_data_ext[15],the_data_ext[15],the_data_ext[15],the_data_ext[
    15],the_data_ext[15],io_rd_w_data_lo_lo_lo_2}; // @[Mem_Stage.scala 144:110]
  wire [23:0] io_rd_w_data_lo_4 = {the_data_ext[15],the_data_ext[15],the_data_ext[15],the_data_ext[15],the_data_ext[15],
    the_data_ext[15],io_rd_w_data_lo_lo_lo_2,io_rd_w_data_lo_lo_2}; // @[Mem_Stage.scala 144:110]
  wire [15:0] io_rd_w_data_lo_5 = the_data_ext[15:0]; // @[Mem_Stage.scala 144:132]
  wire [63:0] _io_rd_w_data_T_82 = {the_data_ext[15],the_data_ext[15],the_data_ext[15],the_data_ext[15],the_data_ext[15]
    ,the_data_ext[15],io_rd_w_data_lo_lo_lo_2,io_rd_w_data_lo_lo_2,io_rd_w_data_lo_4,io_rd_w_data_lo_5}; // @[Cat.scala 30:58]
  wire [63:0] _io_rd_w_data_T_83 = {48'h0,io_rd_w_data_lo_5}; // @[Cat.scala 30:58]
  wire [63:0] _GEN_19 = io_mem_ext ? _io_rd_w_data_T_82 : _io_rd_w_data_T_83; // @[Mem_Stage.scala 144:45 Mem_Stage.scala 144:60 Mem_Stage.scala 145:60]
  wire [6:0] io_rd_w_data_lo_lo_lo_4 = {the_data_ext[7],the_data_ext[7],the_data_ext[7],the_data_ext[7],the_data_ext[7],
    the_data_ext[7],the_data_ext[7]}; // @[Mem_Stage.scala 174:109]
  wire [13:0] io_rd_w_data_lo_lo_4 = {the_data_ext[7],the_data_ext[7],the_data_ext[7],the_data_ext[7],the_data_ext[7],
    the_data_ext[7],the_data_ext[7],io_rd_w_data_lo_lo_lo_4}; // @[Mem_Stage.scala 174:109]
  wire [27:0] io_rd_w_data_lo_8 = {the_data_ext[7],the_data_ext[7],the_data_ext[7],the_data_ext[7],the_data_ext[7],
    the_data_ext[7],the_data_ext[7],io_rd_w_data_lo_lo_lo_4,io_rd_w_data_lo_lo_4}; // @[Mem_Stage.scala 174:109]
  wire [55:0] io_rd_w_data_hi_9 = {the_data_ext[7],the_data_ext[7],the_data_ext[7],the_data_ext[7],the_data_ext[7],
    the_data_ext[7],the_data_ext[7],io_rd_w_data_lo_lo_lo_4,io_rd_w_data_lo_lo_4,io_rd_w_data_lo_8}; // @[Mem_Stage.scala 174:109]
  wire [7:0] io_rd_w_data_lo_9 = the_data_ext[7:0]; // @[Mem_Stage.scala 174:132]
  wire [63:0] _io_rd_w_data_T_140 = {io_rd_w_data_hi_9,io_rd_w_data_lo_9}; // @[Cat.scala 30:58]
  wire [63:0] _io_rd_w_data_T_141 = {56'h0,io_rd_w_data_lo_9}; // @[Cat.scala 30:58]
  wire [63:0] _GEN_27 = io_mem_ext ? _io_rd_w_data_T_140 : _io_rd_w_data_T_141; // @[Mem_Stage.scala 174:45 Mem_Stage.scala 174:60 Mem_Stage.scala 175:60]
  wire [63:0] _GEN_29 = _T_5 ? _GEN_19 : _GEN_27; // @[Mem_Stage.scala 129:45]
  wire [63:0] _GEN_31 = _T_2 ? _GEN_15 : _GEN_29; // @[Mem_Stage.scala 118:45]
  wire [63:0] _GEN_33 = _T_1 ? the_data_ext : _GEN_31; // @[Mem_Stage.scala 113:45 Mem_Stage.scala 115:33]
  wire [63:0] _GEN_35 = io_inst_type[1] ? io_rd_data : 64'h0; // @[Mem_Stage.scala 107:40 Mem_Stage.scala 109:29 Mem_Stage.scala 180:29]
  wire [63:0] _GEN_38 = io_inst_type[1] ? _GEN_33 : io_rd_data; // @[Mem_Stage.scala 107:40 Mem_Stage.scala 181:29]
  wire [95:0] _GEN_78 = {io_save_data, 32'h0}; // @[Mem_Stage.scala 201:53]
  wire [126:0] _io_mem_w_data_T = {{31'd0}, _GEN_78}; // @[Mem_Stage.scala 201:53]
  wire [126:0] _GEN_39 = io_rd_data[2] ? _io_mem_w_data_T : {{63'd0}, io_save_data}; // @[Mem_Stage.scala 200:43 Mem_Stage.scala 201:37 Mem_Stage.scala 203:37]
  wire [79:0] _GEN_79 = {io_save_data, 16'h0}; // @[Mem_Stage.scala 211:53]
  wire [94:0] _io_mem_w_data_T_1 = {{15'd0}, _GEN_79}; // @[Mem_Stage.scala 211:53]
  wire [111:0] _GEN_81 = {io_save_data, 48'h0}; // @[Mem_Stage.scala 217:53]
  wire [126:0] _io_mem_w_data_T_3 = {{15'd0}, _GEN_81}; // @[Mem_Stage.scala 217:53]
  wire [126:0] _GEN_40 = _T_11 ? _io_mem_w_data_T_3 : {{63'd0}, io_save_data}; // @[Mem_Stage.scala 216:51 Mem_Stage.scala 217:37 Mem_Stage.scala 220:37]
  wire [126:0] _GEN_41 = _T_9 ? _io_mem_w_data_T : _GEN_40; // @[Mem_Stage.scala 213:51 Mem_Stage.scala 214:37]
  wire [126:0] _GEN_42 = _T_7 ? {{32'd0}, _io_mem_w_data_T_1} : _GEN_41; // @[Mem_Stage.scala 210:46 Mem_Stage.scala 211:37]
  wire [71:0] _GEN_82 = {io_save_data, 8'h0}; // @[Mem_Stage.scala 226:53]
  wire [78:0] _io_mem_w_data_T_4 = {{7'd0}, _GEN_82}; // @[Mem_Stage.scala 226:53]
  wire [87:0] _GEN_84 = {io_save_data, 24'h0}; // @[Mem_Stage.scala 232:53]
  wire [94:0] _io_mem_w_data_T_6 = {{7'd0}, _GEN_84}; // @[Mem_Stage.scala 232:53]
  wire [103:0] _GEN_86 = {io_save_data, 40'h0}; // @[Mem_Stage.scala 238:53]
  wire [126:0] _io_mem_w_data_T_8 = {{23'd0}, _GEN_86}; // @[Mem_Stage.scala 238:53]
  wire [119:0] _GEN_88 = {io_save_data, 56'h0}; // @[Mem_Stage.scala 244:53]
  wire [126:0] _io_mem_w_data_T_10 = {{7'd0}, _GEN_88}; // @[Mem_Stage.scala 244:53]
  wire [126:0] _GEN_43 = _T_25 ? _io_mem_w_data_T_10 : {{63'd0}, io_save_data}; // @[Mem_Stage.scala 243:51 Mem_Stage.scala 244:37 Mem_Stage.scala 247:37]
  wire [126:0] _GEN_44 = _T_23 ? _io_mem_w_data_T_3 : _GEN_43; // @[Mem_Stage.scala 240:51 Mem_Stage.scala 241:37]
  wire [126:0] _GEN_45 = _T_21 ? _io_mem_w_data_T_8 : _GEN_44; // @[Mem_Stage.scala 237:51 Mem_Stage.scala 238:37]
  wire [126:0] _GEN_46 = _T_19 ? _io_mem_w_data_T : _GEN_45; // @[Mem_Stage.scala 234:51 Mem_Stage.scala 235:37]
  wire [126:0] _GEN_47 = _T_17 ? {{32'd0}, _io_mem_w_data_T_6} : _GEN_46; // @[Mem_Stage.scala 231:51 Mem_Stage.scala 232:37]
  wire [126:0] _GEN_48 = _T_15 ? {{32'd0}, _io_mem_w_data_T_1} : _GEN_47; // @[Mem_Stage.scala 228:51 Mem_Stage.scala 229:37]
  wire [126:0] _GEN_49 = _T_13 ? {{48'd0}, _io_mem_w_data_T_4} : _GEN_48; // @[Mem_Stage.scala 225:46 Mem_Stage.scala 226:37]
  wire [126:0] _GEN_50 = _T_5 ? _GEN_42 : _GEN_49; // @[Mem_Stage.scala 208:45]
  wire [126:0] _GEN_51 = _T_2 ? _GEN_39 : _GEN_50; // @[Mem_Stage.scala 199:45]
  wire [126:0] _GEN_52 = _T_1 ? {{63'd0}, io_save_data} : _GEN_51; // @[Mem_Stage.scala 195:45 Mem_Stage.scala 196:33]
  wire [63:0] _GEN_54 = io_inst_type[0] ? io_rd_data : 64'h0; // @[Mem_Stage.scala 189:40 Mem_Stage.scala 191:29 Mem_Stage.scala 252:29]
  wire [63:0] _GEN_55 = io_inst_type[0] ? the_mask : 64'h0; // @[Mem_Stage.scala 189:40 Mem_Stage.scala 192:29 Mem_Stage.scala 254:29]
  wire [126:0] _GEN_56 = io_inst_type[0] ? _GEN_52 : 127'h0; // @[Mem_Stage.scala 189:40 Mem_Stage.scala 253:29]
  wire [126:0] _GEN_61 = reset ? 127'h0 : _GEN_56; // @[Mem_Stage.scala 33:24 Mem_Stage.scala 38:25]
  assign io_mem_r_ena = reset ? 1'h0 : io_inst_type[1]; // @[Mem_Stage.scala 33:24 Mem_Stage.scala 34:25]
  assign io_mem_r_addr = reset ? 64'h0 : _GEN_35; // @[Mem_Stage.scala 33:24 Mem_Stage.scala 35:25]
  assign io_mem_w_ena = reset ? 1'h0 : io_inst_type[0]; // @[Mem_Stage.scala 33:24 Mem_Stage.scala 36:25]
  assign io_mem_w_addr = reset ? 64'h0 : _GEN_54; // @[Mem_Stage.scala 33:24 Mem_Stage.scala 37:25]
  assign io_mem_w_data = _GEN_61[63:0];
  assign io_mem_w_mask = reset ? 64'h0 : _GEN_55; // @[Mem_Stage.scala 33:24 Mem_Stage.scala 39:25]
  assign io_rd_w_data = reset ? 64'h0 : _GEN_38; // @[Mem_Stage.scala 33:24 Mem_Stage.scala 40:25]
endmodule
@YouTheFreedom1999
Copy link

issue9里有我写的verilog代码,应该跟你是差不多的意思

@ColsonZhang
Copy link
Author

ColsonZhang commented Aug 4, 2021

issue9里有我写的verilog代码,应该跟你是差不多的意思

谢谢!!!
我之前没有注意到,在这里给大家指个路。
点击右方链接有verilog版本的访存代码-> #9 (comment)

@lsyic
Copy link

lsyic commented Aug 11, 2021

请问是重新写了ram.v吗?我看默认的ramhelper只能提交一个读取数据的地址,为什么你的程序既可以提交指令的地址又能提交读取内存的地址呢?
image
还有请问测试访存的.bin文件能共享一下吗?
多谢!!!

@ColsonZhang
Copy link
Author

ColsonZhang commented Aug 11, 2021

请问是重新写了ram.v吗?我看默认的ramhelper只能提交一个读取数据的地址,为什么你的程序既可以提交指令的地址又能提交读取内存的地址呢?
image
还有请问测试访存的.bin文件能共享一下吗?
多谢!!!

这里我重写了双端口的ram,如下图所示。
image
测试访存的bin文件cpu-test里面有一个load-store.c,也可以进行访存的测试。如果实在需要这个.bin可以留个邮箱。

@lsyic
Copy link

lsyic commented Aug 11, 2021

这里我重写了双端口的ram,如下图所示。

了解了!十分感谢!
麻烦发我一下吧![email protected] 多谢!

@ColsonZhang
Copy link
Author

ColsonZhang commented Aug 11, 2021

这里我重写了双端口的ram,如下图所示。

了解了!十分感谢!
麻烦发我一下吧![email protected] 多谢!

已发送,准备分享一下汇编的8进制txt转机器可读取的二进制文件的python小工具。如果有需要对汇编文件进行修改,可以用该程序转换为2进制文件。

import string
import os
import sys
import getopt

def read_file(filename):
    with open(filename, 'r') as f:
        lines = f.readlines()
    return lines

def extract_num(lines, mode='hex', reverse=False):
    if mode in ('hex','Hex','HEX'):
        str_width = 2
        int_widht = 16
    elif mode in ('bin','Bin','BIN'):
        str_width = 8
        int_widht = 2
    else:
        return False
    
    context = ""
    for line in lines:
        if ':' in line:
            line = line[ line.index(':')+1 : ]  # ignore the inst-addr

        if '#' in line:
            line = line[: line.index('#') ]     # ignore the inst-note

        context = context + line
    context = context.replace(' ', '').replace('_', '').replace('\n', '').replace('\t', '')

    list_nums = []
    len_byte = int(len(context)/str_width) #计算字节的个数
    for i in range(0, len_byte):      #循环将解析出来的字节填充到list中
        chs = context[str_width*i : str_width*i + str_width]
        num = int(chs, int_widht)
        list_nums.append(num)        
    
    if(reverse):
        list_nums = order_reverse(list_nums)

    data_bys = bytes(list_nums)
    return data_bys, list_nums

def export_bin(filename, data_bys):
    with open(filename, "wb") as f:
        f.write(data_bys)

def export_txt(filename, data_export ):
    with open(filename, "w") as f:
        f.write(data_export)

def binary_str_gen(list_nums):
    c = ""
    for count, i in enumerate(list_nums):
        temp = "{:0>8b}".format(i)
        c = c + temp
        if (count+1) % 4 == 0:
            c = c + "\n"
        else:
            c = c + "_"
    return c

def order_reverse(list_nums):
    new_list = []
    the_len = int(len(list_nums)/4)
    for i in range(the_len):
        for j in range(3,-1,-1):
            new_list.append( list_nums[4*i+j] )
    print("reverse the list")
    return new_list

def judege_bool(the_str):
    if the_str in ("True","true","TRUE","T","t"):
        return True
    else:
        return False

def arg_handler():
    # default-values
    inputfile   = "./czcpu/test.txt"
    outputfile  = "./czcpu/test.bin"
    mode        = "hex"
    export      = "False"
    reverse     = "False"

    try:
        argv = sys.argv[1:]
        opts, args = getopt.getopt(argv,"hi:o:m:e:r:",["ifile=","ofile=","mode=","export=","reverse="])
        # print(argv)
        # print(opts)
    except getopt.GetoptError:
        print('BinGen.py -i <inputfile> -o <outputfile>')
        sys.exit(2)
    for opt, arg in opts:
        if opt in ("-h", "--help"):
            print('BinGen.py -i <inputfile> -o <outputfile> -m <mode>(hex or bin) -e -r')
            print('-i input-file-path\n-o output-file-path\n-m input-data-mode(hex or bin)\n-e export?\n-r reverse the list?')
            sys.exit()
        elif opt in ("-i", "--ifile"):
            inputfile = arg
        elif opt in ("-o", "--ofile"):
            outputfile = arg
        elif opt in ("-m", "--mode"):
            mode = arg
        elif opt in ("-e", "--export"):
            export = arg
        elif opt in ("-r", "--reverse"):
            reverse = arg

    return inputfile, outputfile, mode, export, reverse
    

if __name__== '__main__':
    # get the args
    inputfile, outputfile, mode, export, reverse = arg_handler()
    # print(inputfile, outputfile, mode, export, reverse)

    export = judege_bool(export)
    reverse = judege_bool(reverse)

    if os.path.exists(inputfile) == False:
        print("The input-file does not exist !!!")
        sys.exit(2)
    
    lines =  read_file(inputfile)
    data_bys, list_nums = extract_num(lines, mode=mode, reverse=reverse)
    # print(data_bys)

    if export :
        data_export =  binary_str_gen(list_nums)
        export_txt(outputfile, data_export)
        print("Extracting the bin from the hex is done !")
    else:
        export_bin(outputfile, data_bys)
        print("Exporting the bin-file is done !")

标准格式的txt文件如下。

00: 0010029b # addiw t0,zero,1 
04: 01f29293 # slli t0,t0,0x1f 
08: 00100213 # li tp,1 
0c: 0042a423 # sw tp,8(t0) 
10: 00120213 # addi tp,tp,1 # 0x1 
14: 0042a623 # sw tp,12(t0) 
18: 00120213 # addi tp,tp,1 # 0x1 
1c: 0042a823 # sw tp,16(t0) 
20: 00120213 # addi tp,tp,1 # 0x1 
24: 0042aa23 # sw tp,20(t0) 
28: 0082a303 # lw t1,8(t0) 
2c: 00c2a383 # lw t2,12(t0) 
30: 0102a403 # lw s0,16(t0) 
34: 0142a483 # lw s1,20(t0) 
35: 0000006b # shut down

@lsyic
Copy link

lsyic commented Aug 11, 2021

收到 十分感谢!

@chenxi1018
Copy link

老哥你在文章中说的

“通过分析可以发现理想的寄存器状态是0x0000000400000003,而读出的数据是0x0000000000000003。该pc对应的指令ld,即读取64位数据。那么基本可以判断是在对存储器进行读写时出现的问题。”

有查到是什么原因吗,我用ram_read_helper打印出来的访存数据,和bin文件里对应地址的数据不一样。0x0000000e00000006,读成了0x0000000000000006。

@ColsonZhang
Copy link
Author

老哥你在文章中说的

“通过分析可以发现理想的寄存器状态是0x0000000400000003,而读出的数据是0x0000000000000003。该pc对应的指令ld,即读取64位数据。那么基本可以判断是在对存储器进行读写时出现的问题。”

有查到是什么原因吗,我用ram_read_helper打印出来的访存数据,和bin文件里对应地址的数据不一样。0x0000000e00000006,读成了0x0000000000000006。

你好,这个应该是因为你在读写的时候没有添加掩码,可以参考上面我写的chisel代码或者我标注的另一个issue中的verilog代码。

@zhangyx1998 zhangyx1998 added #Chisel Chisel 相关问题 #Difftest Difftest 相关问题 labels Sep 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
#Chisel Chisel 相关问题 #Difftest Difftest 相关问题
Projects
None yet
Development

No branches or pull requests

5 participants