OSCPU / ysyx

一生一芯的信息发布和内容网站
123 stars 8 forks source link

difftest访存踩坑分享 #10

Open ColsonZhang opened 3 years ago

ColsonZhang commented 3 years ago

错误描述

我在对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 commented 3 years ago

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

ColsonZhang commented 3 years ago

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

谢谢!!! 我之前没有注意到,在这里给大家指个路。 点击右方链接有verilog版本的访存代码-> https://github.com/OSCPU/ysyx/issues/9#issuecomment-891889850

lsyic commented 3 years ago

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

ColsonZhang commented 3 years ago

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

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

lsyic commented 3 years ago

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

了解了!十分感谢! 麻烦发我一下吧!liusyic@gmail.com 多谢!

ColsonZhang commented 3 years ago

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

了解了!十分感谢! 麻烦发我一下吧!liusyic@gmail.com 多谢!

已发送,准备分享一下汇编的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 commented 3 years ago

收到 十分感谢!

chenxi1018 commented 3 years ago

老哥你在文章中说的

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

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

ColsonZhang commented 3 years ago

老哥你在文章中说的

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

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

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