Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
XiangShan
提交
bc1445fc
X
XiangShan
项目概览
OpenXiangShan
/
XiangShan
11 个月 前同步成功
通知
1183
Star
3914
Fork
526
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
X
XiangShan
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
bc1445fc
编写于
1月 05, 2021
作者:
Y
Yinan Xu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
ram,axi4: move axi things out of ram.cpp and fix some bugs
上级
ae850398
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
441 addition
and
256 deletion
+441
-256
src/test/csrc/axi4.cpp
src/test/csrc/axi4.cpp
+109
-0
src/test/csrc/axi4.h
src/test/csrc/axi4.h
+214
-0
src/test/csrc/emu.cpp
src/test/csrc/emu.cpp
+11
-6
src/test/csrc/ram.cpp
src/test/csrc/ram.cpp
+104
-67
src/test/csrc/ram.h
src/test/csrc/ram.h
+3
-183
未找到文件。
src/test/csrc/axi4.cpp
0 → 100644
浏览文件 @
bc1445fc
#include <cassert>
#include <cstdio>
#include <cstring>
#include "axi4.h"
// ar channel: (1) read raddr; (2) try to accept the address; (3) check raddr fire
bool
axi_get_raddr
(
const
axi_channel
&
axi
,
axi_addr_t
&
addr
)
{
if
(
axi
.
ar
.
valid
)
{
addr
=
axi
.
ar
.
addr
;
return
true
;
}
return
false
;
}
void
axi_accept_raddr
(
axi_channel
&
axi
)
{
axi
.
ar
.
ready
=
1
;
}
bool
axi_check_raddr_fire
(
const
axi_channel
&
axi
)
{
if
(
axi
.
ar
.
valid
&&
axi
.
ar
.
ready
)
{
#ifdef DEBUG_LOG_AXI4
printf
(
"axi ar channel fired addr = 0x%lx, id = %d
\n
"
,
axi
.
ar
.
addr
,
axi
.
ar
.
id
);
#endif
return
true
;
}
return
false
;
}
// r channel: (1) put rdata; (2) check rdata fire
void
axi_put_rdata
(
axi_channel
&
axi
,
void
*
src
,
size_t
n
,
bool
last
,
uint8_t
id
)
{
memcpy
(
axi
.
r
.
data
,
src
,
n
);
axi
.
r
.
valid
=
1
;
axi
.
r
.
last
=
(
last
)
?
1
:
0
;
axi
.
r
.
id
=
id
;
}
bool
axi_check_rdata_fire
(
const
axi_channel
&
axi
)
{
if
(
axi
.
r
.
ready
&&
axi
.
r
.
valid
)
{
#ifdef DEBUG_LOG_AXI4
printf
(
"axi r channel fired data = %lx, id = %d
\n
"
,
axi
.
r
.
data
[
0
],
axi
.
r
.
id
);
#endif
return
true
;
}
return
false
;
}
// aw channel: (1) read waddr; (2) try to accept the address; (3) check waddr fire
bool
axi_get_waddr
(
const
axi_channel
&
axi
,
axi_addr_t
&
addr
)
{
if
(
axi
.
aw
.
valid
)
{
addr
=
axi
.
aw
.
addr
;
return
true
;
}
return
false
;
}
void
axi_accept_waddr
(
axi_channel
&
axi
)
{
axi
.
aw
.
ready
=
1
;
}
bool
axi_check_waddr_fire
(
const
axi_channel
&
axi
)
{
if
(
axi
.
aw
.
valid
&&
axi
.
aw
.
ready
)
{
assert
(
axi
.
aw
.
burst
==
1
||
(
axi
.
aw
.
burst
==
2
&&
((
axi
.
aw
.
addr
&
0x3f
)
==
0
)));
#ifdef DEBUG_LOG_AXI4
printf
(
"axi aw channel fired
\n
"
);
#endif
return
true
;
}
return
false
;
}
// w channel: (1) accept wdata; (2) get wdata; (3) check wdata fire
void
axi_accept_wdata
(
axi_channel
&
axi
)
{
axi
.
w
.
ready
=
1
;
}
bool
axi_check_wdata_fire
(
const
axi_channel
&
axi
)
{
if
(
axi
.
w
.
valid
&&
axi
.
w
.
ready
)
{
#ifdef DEBUG_LOG_AXI4
printf
(
"axi w channel fired
\n
"
);
#endif
return
true
;
}
return
false
;
}
void
axi_get_wdata
(
const
axi_channel
&
axi
,
void
*
dest
,
size_t
n
)
{
memcpy
(
dest
,
axi
.
w
.
data
,
n
);
}
// b channel: (1) put response; (2) check response fire
void
axi_put_wack
(
axi_channel
&
axi
,
uint8_t
id
)
{
axi
.
b
.
valid
=
1
;
axi
.
b
.
id
=
id
;
}
bool
axi_check_wack_fire
(
const
axi_channel
&
axi
)
{
if
(
axi
.
b
.
valid
&&
axi
.
b
.
ready
)
{
#ifdef DEBUG_LOG_AXI4
printf
(
"axi b channel fired
\n
"
);
#endif
return
true
;
}
return
false
;
}
src/test/csrc/axi4.h
0 → 100644
浏览文件 @
bc1445fc
#ifndef __AXI4_H
#define __AXI4_h
#include <stdint.h>
// #define DEBUG_LOG_AXI4
// 4*64 bits
#define AXI_DATA_WIDTH_64 4
typedef
uint64_t
axi_addr_t
;
typedef
uint64_t
axi_data_t
[
AXI_DATA_WIDTH_64
];
#define axi_copy_data(dest, src) \
memcpy(dest, src, sizeof(uint64_t)*AXI_DATA_WIDTH_64);
struct
axi_aw_channel
{
uint8_t
ready
;
uint8_t
valid
;
axi_addr_t
addr
;
uint8_t
prot
;
uint8_t
id
;
uint8_t
user
;
uint8_t
len
;
uint8_t
size
;
uint8_t
burst
;
uint8_t
lock
;
uint8_t
cache
;
uint8_t
qos
;
};
struct
axi_w_channel
{
uint8_t
ready
;
uint8_t
valid
;
axi_data_t
data
;
uint8_t
strb
;
uint8_t
last
;
};
struct
axi_b_channel
{
uint8_t
ready
;
uint8_t
valid
;
uint8_t
resp
;
uint8_t
id
;
uint8_t
user
;
};
struct
axi_ar_channel
{
uint8_t
ready
;
uint8_t
valid
;
axi_addr_t
addr
;
uint8_t
prot
;
uint8_t
id
;
uint8_t
user
;
uint8_t
len
;
uint8_t
size
;
uint8_t
burst
;
uint8_t
lock
;
uint8_t
cache
;
uint8_t
qos
;
};
struct
axi_r_channel
{
uint8_t
ready
;
uint8_t
valid
;
uint8_t
resp
;
axi_data_t
data
;
uint8_t
last
;
uint8_t
id
;
uint8_t
user
;
};
struct
axi_channel
{
struct
axi_aw_channel
aw
;
struct
axi_w_channel
w
;
struct
axi_b_channel
b
;
struct
axi_ar_channel
ar
;
struct
axi_r_channel
r
;
};
// dut helper for AXI
// NOTE: change this when migrating between different hardware designs
#define DUT_AXI(name) auto_axi_mem_out_##name
#define axi_aw_copy_from_dut_ptr(dut_ptr, aw) \
do { \
aw.ready = dut_ptr->DUT_AXI(aw_ready); \
aw.valid = dut_ptr->DUT_AXI(aw_valid); \
aw.addr = dut_ptr->DUT_AXI(aw_bits_addr); \
aw.prot = dut_ptr->DUT_AXI(aw_bits_prot); \
aw.id = dut_ptr->DUT_AXI(aw_bits_id); \
aw.len = dut_ptr->DUT_AXI(aw_bits_len); \
aw.size = dut_ptr->DUT_AXI(aw_bits_size); \
aw.burst = dut_ptr->DUT_AXI(aw_bits_burst); \
aw.lock = dut_ptr->DUT_AXI(aw_bits_lock); \
aw.cache = dut_ptr->DUT_AXI(aw_bits_cache); \
aw.qos = dut_ptr->DUT_AXI(aw_bits_qos); \
} while (0);
#define axi_aw_set_dut_ptr(dut_ptr, aw) \
do { \
dut_ptr->DUT_AXI(aw_ready) = aw.ready; \
} while (0);
#define axi_w_copy_from_dut_ptr(dut_ptr, w) \
do { \
w.ready = dut_ptr->DUT_AXI(w_ready); \
w.valid = dut_ptr->DUT_AXI(w_valid); \
axi_copy_data(w.data, dut_ptr->DUT_AXI(w_bits_data)) \
w.strb = dut_ptr->DUT_AXI(w_bits_strb); \
w.last = dut_ptr->DUT_AXI(w_bits_last); \
} while (0);
#define axi_w_set_dut_ptr(dut_ptr, w) \
do { \
dut_ptr->DUT_AXI(w_ready) = w.ready; \
} while (0);
#define axi_b_copy_from_dut_ptr(dut_ptr, b) \
do { \
b.ready = dut_ptr->DUT_AXI(b_ready); \
b.valid = dut_ptr->DUT_AXI(b_valid); \
b.resp = dut_ptr->DUT_AXI(b_bits_resp); \
b.id = dut_ptr->DUT_AXI(b_bits_id); \
} while (0);
#define axi_b_set_dut_ptr(dut_ptr, b) \
do { \
dut_ptr->DUT_AXI(b_valid) = b.valid; \
dut_ptr->DUT_AXI(b_bits_resp) = b.resp; \
dut_ptr->DUT_AXI(b_bits_id) = b.id; \
} while (0);
#define axi_ar_copy_from_dut_ptr(dut_ptr, ar) \
do { \
ar.ready = dut_ptr->DUT_AXI(ar_ready); \
ar.valid = dut_ptr->DUT_AXI(ar_valid); \
ar.addr = dut_ptr->DUT_AXI(ar_bits_addr); \
ar.prot = dut_ptr->DUT_AXI(ar_bits_prot); \
ar.id = dut_ptr->DUT_AXI(ar_bits_id); \
ar.len = dut_ptr->DUT_AXI(ar_bits_len); \
ar.size = dut_ptr->DUT_AXI(ar_bits_size); \
ar.burst = dut_ptr->DUT_AXI(ar_bits_burst); \
ar.lock = dut_ptr->DUT_AXI(ar_bits_lock); \
ar.cache = dut_ptr->DUT_AXI(ar_bits_cache); \
ar.qos = dut_ptr->DUT_AXI(ar_bits_qos); \
} while (0);
#define axi_ar_set_dut_ptr(dut_ptr, ar) \
do { \
dut_ptr->DUT_AXI(ar_ready) = ar.ready; \
} while (0);
#define axi_r_copy_from_dut_ptr(dut_ptr, r) \
do { \
r.ready = dut_ptr->DUT_AXI(r_ready); \
r.valid = dut_ptr->DUT_AXI(r_valid); \
r.resp = dut_ptr->DUT_AXI(r_bits_resp); \
axi_copy_data(r.data, dut_ptr->DUT_AXI(r_bits_data)) \
r.last = dut_ptr->DUT_AXI(r_bits_last); \
r.id = dut_ptr->DUT_AXI(r_bits_id); \
} while (0);
#define axi_r_set_dut_ptr(dut_ptr, r) \
do { \
dut_ptr->DUT_AXI(r_valid) = r.valid; \
dut_ptr->DUT_AXI(r_bits_resp) = r.resp; \
axi_copy_data(dut_ptr->DUT_AXI(r_bits_data), r.data) \
dut_ptr->DUT_AXI(r_bits_last) = r.last; \
dut_ptr->DUT_AXI(r_bits_id) = r.id; \
} while (0);
#define axi_copy_from_dut_ptr(dut_ptr, axi) \
do { \
axi_aw_copy_from_dut_ptr(dut_ptr, axi.aw) \
axi_w_copy_from_dut_ptr(dut_ptr, axi.w) \
axi_b_copy_from_dut_ptr(dut_ptr, axi.b) \
axi_ar_copy_from_dut_ptr(dut_ptr, axi.ar) \
axi_r_copy_from_dut_ptr(dut_ptr, axi.r) \
} while (0);
#define axi_set_dut_ptr(dut_ptr, axi) \
do { \
axi_aw_set_dut_ptr(dut_ptr, axi.aw) \
axi_w_set_dut_ptr(dut_ptr, axi.w) \
axi_b_set_dut_ptr(dut_ptr, axi.b) \
axi_ar_set_dut_ptr(dut_ptr, axi.ar) \
axi_r_set_dut_ptr(dut_ptr, axi.r) \
} while (0);
// ar channel: (1) read raddr; (2) try to accept the address; (3) check raddr fire
bool
axi_get_raddr
(
const
axi_channel
&
axi
,
axi_addr_t
&
addr
);
void
axi_accept_raddr
(
axi_channel
&
axi
);
bool
axi_check_raddr_fire
(
const
axi_channel
&
axi
);
// r channel: (1) put rdata; (2) check rdata fire
void
axi_put_rdata
(
axi_channel
&
axi
,
void
*
src
,
size_t
n
,
bool
last
,
uint8_t
id
);
bool
axi_check_rdata_fire
(
const
axi_channel
&
axi
);
// aw channel: (1) read waddr; (2) try to accept the address; (3) check waddr fire
bool
axi_get_waddr
(
const
axi_channel
&
axi
,
axi_addr_t
&
addr
);
void
axi_accept_waddr
(
axi_channel
&
axi
);
bool
axi_check_waddr_fire
(
const
axi_channel
&
axi
);
// w channel: (1) accept wdata; (2) get wdata; (3) check wdata fire
void
axi_accept_wdata
(
axi_channel
&
axi
);
void
axi_get_wdata
(
const
axi_channel
&
axi
,
void
*
dest
,
size_t
n
);
bool
axi_check_wdata_fire
(
const
axi_channel
&
axi
);
// b channel: (1) put response; (2) check response fire
void
axi_put_wack
(
axi_channel
&
axi
,
uint8_t
id
);
bool
axi_check_wack_fire
(
const
axi_channel
&
axi
);
#endif
src/test/csrc/emu.cpp
浏览文件 @
bc1445fc
...
@@ -204,22 +204,27 @@ inline void Emulator::reset_ncycles(size_t cycles) {
...
@@ -204,22 +204,27 @@ inline void Emulator::reset_ncycles(size_t cycles) {
inline
void
Emulator
::
single_cycle
()
{
inline
void
Emulator
::
single_cycle
()
{
dut_ptr
->
clock
=
0
;
dut_ptr
->
clock
=
0
;
dut_ptr
->
eval
();
#ifdef WITH_DRAMSIM3
#ifdef WITH_DRAMSIM3
axi_channel
axi
;
axi_channel
axi
;
axi_copy_from_dut_ptr
(
dut_ptr
,
axi
);
axi_copy_from_dut_ptr
(
dut_ptr
,
axi
);
axi
.
aw
.
addr
-=
0x80000000UL
;
axi
.
aw
.
addr
-=
0x80000000UL
;
axi
.
ar
.
addr
-=
0x80000000UL
;
axi
.
ar
.
addr
-=
0x80000000UL
;
dramsim3_helper
(
axi
);
dramsim3_helper_rising
(
axi
);
axi
.
aw
.
addr
+=
0x80000000UL
;
axi
.
ar
.
addr
+=
0x80000000UL
;
axi_set_dut_ptr
(
dut_ptr
,
axi
);
#endif
#endif
dut_ptr
->
eval
();
dut_ptr
->
clock
=
1
;
dut_ptr
->
clock
=
1
;
dut_ptr
->
eval
();
dut_ptr
->
eval
();
#ifdef WITH_DRAMSIM3
axi_copy_from_dut_ptr
(
dut_ptr
,
axi
);
axi
.
aw
.
addr
-=
0x80000000UL
;
axi
.
ar
.
addr
-=
0x80000000UL
;
dramsim3_helper_falling
(
axi
);
axi_set_dut_ptr
(
dut_ptr
,
axi
);
#endif
#if VM_TRACE == 1
#if VM_TRACE == 1
if
(
enable_waveform
)
{
if
(
enable_waveform
)
{
uint64_t
cycle
=
dut_ptr
->
io_trap_cycleCnt
;
uint64_t
cycle
=
dut_ptr
->
io_trap_cycleCnt
;
...
...
src/test/csrc/ram.cpp
浏览文件 @
bc1445fc
...
@@ -154,7 +154,8 @@ void init_ram(const char *img) {
...
@@ -154,7 +154,8 @@ void init_ram(const char *img) {
#error DRAMSIM3_CONFIG or DRAMSIM3_OUTDIR is not defined
#error DRAMSIM3_CONFIG or DRAMSIM3_OUTDIR is not defined
#endif
#endif
assert
(
dram
==
NULL
);
assert
(
dram
==
NULL
);
dram
=
new
CoDRAMsim3
(
DRAMSIM3_CONFIG
,
DRAMSIM3_OUTDIR
);
// dram = new CoDRAMsim3(DRAMSIM3_CONFIG, DRAMSIM3_OUTDIR);
dram
=
new
SimpleCoDRAMsim3
(
90
);
#endif
#endif
pthread_mutex_init
(
&
ram_mutex
,
0
);
pthread_mutex_init
(
&
ram_mutex
,
0
);
...
@@ -258,6 +259,7 @@ CoDRAMRequest *dramsim3_request(const axi_channel &axi, bool is_write) {
...
@@ -258,6 +259,7 @@ CoDRAMRequest *dramsim3_request(const axi_channel &axi, bool is_write) {
// WRITE
// WRITE
if
(
is_write
)
{
if
(
is_write
)
{
meta
->
len
=
axi
.
aw
.
len
+
1
;
meta
->
len
=
axi
.
aw
.
len
+
1
;
meta
->
size
=
1
<<
axi
.
aw
.
size
;
meta
->
offset
=
0
;
meta
->
offset
=
0
;
meta
->
id
=
axi
.
aw
.
id
;
meta
->
id
=
axi
.
aw
.
id
;
}
}
...
@@ -271,34 +273,26 @@ CoDRAMRequest *dramsim3_request(const axi_channel &axi, bool is_write) {
...
@@ -271,34 +273,26 @@ CoDRAMRequest *dramsim3_request(const axi_channel &axi, bool is_write) {
return
req
;
return
req
;
}
}
void
dramsim3_helper
(
axi_channel
&
axi
)
{
static
CoDRAMResponse
*
wait_resp_r
=
NULL
;
static
CoDRAMResponse
*
wait_resp_b
=
NULL
;
static
CoDRAMRequest
*
wait_req_w
=
NULL
;
// currently only accept one in-flight read + one in-flight write
static
uint64_t
raddr
,
roffset
=
0
,
rlen
;
static
uint64_t
waddr
,
woffset
=
0
,
wlen
;
void
dramsim3_helper_rising
(
const
axi_channel
&
axi
)
{
// ticks DRAMsim3 according to CPU_FREQ:DRAM_FREQ
// ticks DRAMsim3 according to CPU_FREQ:DRAM_FREQ
dram
->
tick
();
dram
->
tick
();
static
CoDRAMResponse
*
wait_resp_r
=
NULL
;
// read data fire: check the last read request
static
CoDRAMResponse
*
wait_resp_b
=
NULL
;
if
(
axi_check_rdata_fire
(
axi
))
{
static
CoDRAMRequest
*
wait_req_w
=
NULL
;
if
(
wait_resp_r
==
NULL
)
{
// currently only accept one in-flight read + one in-flight write
printf
(
"ERROR: There's no in-flight read request.
\n
"
);
static
uint64_t
raddr
,
roffset
=
0
,
rlen
;
assert
(
wait_resp_r
!=
NULL
);
static
uint64_t
waddr
,
woffset
=
0
,
wlen
;
}
// default branch to avoid wrong handshake
axi
.
aw
.
ready
=
0
;
axi
.
w
.
ready
=
1
;
axi
.
b
.
valid
=
0
;
axi
.
ar
.
ready
=
0
;
// axi.r.valid = 0;
// AXI read
// first, check rdata in the last cycle
if
(
axi
.
r
.
ready
&&
axi
.
r
.
valid
)
{
// printf("axi r channel fired data = %lx\n", axi.r.data[0]);
dramsim3_meta
*
meta
=
static_cast
<
dramsim3_meta
*>
(
wait_resp_r
->
req
->
meta
);
dramsim3_meta
*
meta
=
static_cast
<
dramsim3_meta
*>
(
wait_resp_r
->
req
->
meta
);
meta
->
offset
++
;
meta
->
offset
++
;
axi
.
r
.
valid
=
0
;
// check whether the last rdata response has finished
}
if
(
wait_resp_r
)
{
dramsim3_meta
*
meta
=
static_cast
<
dramsim3_meta
*>
(
wait_resp_r
->
req
->
meta
);
if
(
meta
->
offset
==
meta
->
len
)
{
if
(
meta
->
offset
==
meta
->
len
)
{
delete
meta
;
delete
meta
;
delete
wait_resp_r
->
req
;
delete
wait_resp_r
->
req
;
...
@@ -306,68 +300,111 @@ void dramsim3_helper(axi_channel &axi) {
...
@@ -306,68 +300,111 @@ void dramsim3_helper(axi_channel &axi) {
wait_resp_r
=
NULL
;
wait_resp_r
=
NULL
;
}
}
}
}
// second, check whether we response data in this cycle
if
(
!
wait_resp_r
)
// read address fire: accept a new request
wait_resp_r
=
dram
->
check_read_response
();
if
(
axi_check_raddr_fire
(
axi
))
{
if
(
wait_resp_r
)
{
dramsim3_meta
*
meta
=
static_cast
<
dramsim3_meta
*>
(
wait_resp_r
->
req
->
meta
);
// axi.r.data = meta->data[meta->offset];
// printf("meta->size %d offset %d\n", meta->size, meta->offset*meta->size/sizeof(uint64_t));
memcpy
(
axi
.
r
.
data
,
meta
->
data
+
meta
->
offset
*
meta
->
size
/
sizeof
(
uint64_t
),
meta
->
size
);
axi
.
r
.
valid
=
1
;
axi
.
r
.
last
=
(
meta
->
offset
==
meta
->
len
-
1
)
?
1
:
0
;
axi
.
r
.
id
=
meta
->
id
;
}
// third, check ar for next request's address
// put ar in the last since it should be at least one-cycle latency
if
(
axi
.
ar
.
valid
&&
dram
->
will_accept
(
axi
.
ar
.
addr
,
false
))
{
// printf("axi ar channel fired %lx\n", axi.ar.addr);
dram
->
add_request
(
dramsim3_request
(
axi
,
false
));
dram
->
add_request
(
dramsim3_request
(
axi
,
false
));
axi
.
ar
.
ready
=
1
;
}
}
// AXI write
// the last write transaction is acknowledged
// first, check wdata in the last cycle
if
(
axi_check_wack_fire
(
axi
))
{
// aw channel
if
(
wait_resp_b
==
NULL
)
{
if
(
axi
.
aw
.
valid
&&
dram
->
will_accept
(
axi
.
aw
.
addr
,
true
))
{
printf
(
"ERROR: write response fire for nothing in-flight.
\n
"
);
assert
(
wait_req_w
==
NULL
);
// the last request has not finished
assert
(
wait_resp_b
!=
NULL
);
}
// flush data to memory
uint64_t
waddr
=
wait_resp_b
->
req
->
address
%
EMU_RAM_SIZE
;
dramsim3_meta
*
meta
=
static_cast
<
dramsim3_meta
*>
(
wait_resp_b
->
req
->
meta
);
void
*
start_addr
=
ram
+
(
waddr
/
sizeof
(
uint64_t
));
memcpy
(
start_addr
,
meta
->
data
,
meta
->
len
*
meta
->
size
);
for
(
int
i
=
0
;
i
<
meta
->
len
;
i
++
)
{
// uint64_t address = wait_resp_b->req->address % EMU_RAM_SIZE;
// ram[address / sizeof(uint64_t) + i] = meta->data[i];
// printf("flush write to memory[0x%ld] = 0x%lx\n", address)
}
delete
meta
;
delete
wait_resp_b
->
req
;
delete
wait_resp_b
;
wait_resp_b
=
NULL
;
}
// write address fire: accept a new write request
if
(
axi_check_waddr_fire
(
axi
))
{
if
(
wait_req_w
!=
NULL
)
{
printf
(
"ERROR: The last write request has not finished.
\n
"
);
assert
(
wait_req_w
==
NULL
);
}
wait_req_w
=
dramsim3_request
(
axi
,
true
);
wait_req_w
=
dramsim3_request
(
axi
,
true
);
axi
.
aw
.
ready
=
1
;
// printf("accept a new write request to addr = 0x%lx, len = %d\n", axi.aw.addr, axi.aw.len);
// printf("axi aw channel fired %lx\n", axi.aw.addr);
assert
(
axi
.
aw
.
burst
==
1
||
(
axi
.
aw
.
burst
==
2
&&
((
axi
.
aw
.
addr
&
0x3f
)
==
0
)));
}
}
// w channel: ack write data
// write data fire: for the last write transaction
if
(
axi
.
w
.
valid
&&
axi
.
w
.
ready
)
{
if
(
axi_check_wdata_fire
(
axi
))
{
// printf("axi w channel fired\n");
if
(
wait_req_w
==
NULL
)
{
assert
(
wait_req_w
);
printf
(
"ERROR: wdata fire for nothing in-flight.
\n
"
);
assert
(
wait_req_w
!=
NULL
);
}
dramsim3_meta
*
meta
=
static_cast
<
dramsim3_meta
*>
(
wait_req_w
->
meta
);
dramsim3_meta
*
meta
=
static_cast
<
dramsim3_meta
*>
(
wait_req_w
->
meta
);
// meta->data[meta->offset] = axi.w.data;
void
*
data_start
=
meta
->
data
+
meta
->
offset
*
meta
->
size
/
sizeof
(
uint64_t
);
axi_get_wdata
(
axi
,
data_start
,
meta
->
size
);
meta
->
offset
++
;
meta
->
offset
++
;
// if this is the last beat
if
(
meta
->
offset
==
meta
->
len
)
{
if
(
meta
->
offset
==
meta
->
len
)
{
assert
(
dram
->
will_accept
(
wait_req_w
->
address
,
true
));
assert
(
dram
->
will_accept
(
wait_req_w
->
address
,
true
));
dram
->
add_request
(
wait_req_w
);
dram
->
add_request
(
wait_req_w
);
wait_req_w
=
NULL
;
wait_req_w
=
NULL
;
}
}
// printf("accept a new write data\n");
}
}
}
void
dramsim3_helper_falling
(
axi_channel
&
axi
)
{
// default branch to avoid wrong handshake
axi
.
aw
.
ready
=
0
;
axi
.
w
.
ready
=
0
;
axi
.
b
.
valid
=
0
;
axi
.
ar
.
ready
=
0
;
axi
.
r
.
valid
=
0
;
// b channel: ack write
// RDATA: if finished, we try the next rdata response
if
(
!
wait_resp_r
)
wait_resp_r
=
dram
->
check_read_response
();
// if there's some data response, put it onto axi bus
if
(
wait_resp_r
)
{
dramsim3_meta
*
meta
=
static_cast
<
dramsim3_meta
*>
(
wait_resp_r
->
req
->
meta
);
// printf("meta->size %d offset %d\n", meta->size, meta->offset*meta->size/sizeof(uint64_t));
void
*
data_start
=
meta
->
data
+
meta
->
offset
*
meta
->
size
/
sizeof
(
uint64_t
);
axi_put_rdata
(
axi
,
data_start
,
meta
->
size
,
meta
->
offset
==
meta
->
len
-
1
,
meta
->
id
);
}
// RADDR: check whether the read request can be accepted
axi_addr_t
raddr
;
if
(
axi_get_raddr
(
axi
,
raddr
)
&&
dram
->
will_accept
(
raddr
,
false
))
{
axi_accept_raddr
(
axi
);
// printf("try to accept read request to 0x%lx\n", raddr);
}
// WREQ: check whether the write request can be accepted
// Note: block the next write here to simplify logic
axi_addr_t
waddr
;
if
(
wait_req_w
==
NULL
&&
axi_get_waddr
(
axi
,
waddr
)
&&
dram
->
will_accept
(
waddr
,
false
))
{
axi_accept_waddr
(
axi
);
axi_accept_wdata
(
axi
);
// printf("try to accept write request to 0x%lx\n", waddr);
}
// WDATA: check whether the write data can be accepted
if
(
wait_req_w
!=
NULL
)
{
axi_accept_wdata
(
axi
);
}
// WRESP: if finished, we try the next write response
if
(
!
wait_resp_b
)
if
(
!
wait_resp_b
)
wait_resp_b
=
dram
->
check_write_response
();
wait_resp_b
=
dram
->
check_write_response
();
// if there's some write response, put it onto axi bus
if
(
wait_resp_b
)
{
if
(
wait_resp_b
)
{
dramsim3_meta
*
meta
=
static_cast
<
dramsim3_meta
*>
(
wait_resp_b
->
req
->
meta
);
dramsim3_meta
*
meta
=
static_cast
<
dramsim3_meta
*>
(
wait_resp_b
->
req
->
meta
);
axi
.
b
.
valid
=
1
;
axi_put_wack
(
axi
,
meta
->
id
);
axi
.
b
.
id
=
meta
->
id
;
// assert(axi.b.ready == 1);
for
(
int
i
=
0
;
i
<
meta
->
len
;
i
++
)
{
uint64_t
address
=
wait_resp_b
->
req
->
address
%
EMU_RAM_SIZE
;
ram
[
address
/
sizeof
(
uint64_t
)
+
i
]
=
meta
->
data
[
i
];
}
// printf("axi b channel fired\n");
delete
meta
;
delete
wait_resp_b
->
req
;
delete
wait_resp_b
;
wait_resp_b
=
NULL
;
}
}
}
}
...
...
src/test/csrc/ram.h
浏览文件 @
bc1445fc
...
@@ -12,191 +12,11 @@ void* get_ram_start();
...
@@ -12,191 +12,11 @@ void* get_ram_start();
long
get_ram_size
();
long
get_ram_size
();
#ifdef WITH_DRAMSIM3
#ifdef WITH_DRAMSIM3
// 4*64 bits
#include "axi4.h"
#define AXI_DATA_WIDTH_64 4
typedef
uint64_t
axi_addr_t
;
typedef
uint64_t
axi_data_t
[
AXI_DATA_WIDTH_64
];
#define axi_copy_data(dest, src) \
memcpy(dest, src, sizeof(uint64_t)*AXI_DATA_WIDTH_64);
struct
axi_aw_channel
{
uint8_t
ready
;
uint8_t
valid
;
axi_addr_t
addr
;
uint8_t
prot
;
uint8_t
id
;
uint8_t
user
;
uint8_t
len
;
uint8_t
size
;
uint8_t
burst
;
uint8_t
lock
;
uint8_t
cache
;
uint8_t
qos
;
};
struct
axi_w_channel
{
uint8_t
ready
;
uint8_t
valid
;
axi_data_t
data
;
uint8_t
strb
;
uint8_t
last
;
};
struct
axi_b_channel
{
uint8_t
ready
;
uint8_t
valid
;
uint8_t
resp
;
uint8_t
id
;
uint8_t
user
;
};
struct
axi_ar_channel
{
uint8_t
ready
;
uint8_t
valid
;
axi_addr_t
addr
;
uint8_t
prot
;
uint8_t
id
;
uint8_t
user
;
uint8_t
len
;
uint8_t
size
;
uint8_t
burst
;
uint8_t
lock
;
uint8_t
cache
;
uint8_t
qos
;
};
struct
axi_r_channel
{
uint8_t
ready
;
uint8_t
valid
;
uint8_t
resp
;
axi_data_t
data
;
uint8_t
last
;
uint8_t
id
;
uint8_t
user
;
};
struct
axi_channel
{
struct
axi_aw_channel
aw
;
struct
axi_w_channel
w
;
struct
axi_b_channel
b
;
struct
axi_ar_channel
ar
;
struct
axi_r_channel
r
;
};
// dut helper for AXI
// NOTE: change this when migrating between different hardware designs
#define DUT_AXI(name) auto_axi_mem_out_##name
#define axi_aw_copy_from_dut_ptr(dut_ptr, aw) \
do { \
aw.ready = dut_ptr->DUT_AXI(aw_ready); \
aw.valid = dut_ptr->DUT_AXI(aw_valid); \
aw.addr = dut_ptr->DUT_AXI(aw_bits_addr); \
aw.prot = dut_ptr->DUT_AXI(aw_bits_prot); \
aw.id = dut_ptr->DUT_AXI(aw_bits_id); \
aw.len = dut_ptr->DUT_AXI(aw_bits_len); \
aw.size = dut_ptr->DUT_AXI(aw_bits_size); \
aw.burst = dut_ptr->DUT_AXI(aw_bits_burst); \
aw.lock = dut_ptr->DUT_AXI(aw_bits_lock); \
aw.cache = dut_ptr->DUT_AXI(aw_bits_cache); \
aw.qos = dut_ptr->DUT_AXI(aw_bits_qos); \
} while (0);
#define axi_aw_set_dut_ptr(dut_ptr, aw) \
do { \
dut_ptr->DUT_AXI(aw_ready) = aw.ready; \
} while (0);
#define axi_w_copy_from_dut_ptr(dut_ptr, w) \
do { \
w.ready = dut_ptr->DUT_AXI(w_ready); \
w.valid = dut_ptr->DUT_AXI(w_valid); \
axi_copy_data(w.data, dut_ptr->DUT_AXI(w_bits_data)) \
w.strb = dut_ptr->DUT_AXI(w_bits_strb); \
w.last = dut_ptr->DUT_AXI(w_bits_last); \
} while (0);
#define axi_w_set_dut_ptr(dut_ptr, w) \
do { \
dut_ptr->DUT_AXI(w_ready) = w.ready; \
} while (0);
#define axi_b_copy_from_dut_ptr(dut_ptr, b) \
do { \
b.ready = dut_ptr->DUT_AXI(b_valid); \
b.valid = dut_ptr->DUT_AXI(b_valid); \
b.resp = dut_ptr->DUT_AXI(b_bits_resp); \
b.id = dut_ptr->DUT_AXI(b_bits_id); \
} while (0);
#define axi_b_set_dut_ptr(dut_ptr, b) \
do { \
dut_ptr->DUT_AXI(b_valid) = b.valid; \
dut_ptr->DUT_AXI(b_bits_resp) = b.resp; \
dut_ptr->DUT_AXI(b_bits_id) = b.id; \
} while (0);
#define axi_ar_copy_from_dut_ptr(dut_ptr, ar) \
do { \
ar.ready = dut_ptr->DUT_AXI(ar_ready); \
ar.valid = dut_ptr->DUT_AXI(ar_valid); \
ar.addr = dut_ptr->DUT_AXI(ar_bits_addr); \
ar.prot = dut_ptr->DUT_AXI(ar_bits_prot); \
ar.id = dut_ptr->DUT_AXI(ar_bits_id); \
ar.len = dut_ptr->DUT_AXI(ar_bits_len); \
ar.size = dut_ptr->DUT_AXI(ar_bits_size); \
ar.burst = dut_ptr->DUT_AXI(ar_bits_burst); \
ar.lock = dut_ptr->DUT_AXI(ar_bits_lock); \
ar.cache = dut_ptr->DUT_AXI(ar_bits_cache); \
ar.qos = dut_ptr->DUT_AXI(ar_bits_qos); \
} while (0);
#define axi_ar_set_dut_ptr(dut_ptr, ar) \
do { \
dut_ptr->DUT_AXI(ar_ready) = ar.ready; \
} while (0);
#define axi_r_copy_from_dut_ptr(dut_ptr, r) \
do { \
r.ready = dut_ptr->DUT_AXI(r_ready); \
r.valid = dut_ptr->DUT_AXI(r_valid); \
r.resp = dut_ptr->DUT_AXI(r_bits_resp); \
axi_copy_data(r.data, dut_ptr->DUT_AXI(r_bits_data)) \
r.last = dut_ptr->DUT_AXI(r_bits_last); \
r.id = dut_ptr->DUT_AXI(r_bits_id); \
} while (0);
#define axi_r_set_dut_ptr(dut_ptr, r) \
do { \
dut_ptr->DUT_AXI(r_valid) = r.valid; \
dut_ptr->DUT_AXI(r_bits_resp) = r.resp; \
axi_copy_data(dut_ptr->DUT_AXI(r_bits_data), r.data) \
dut_ptr->DUT_AXI(r_bits_last) = r.last; \
dut_ptr->DUT_AXI(r_bits_id) = r.id; \
} while (0);
#define axi_copy_from_dut_ptr(dut_ptr, axi) \
do { \
axi_aw_copy_from_dut_ptr(dut_ptr, axi.aw) \
axi_w_copy_from_dut_ptr(dut_ptr, axi.w) \
axi_b_copy_from_dut_ptr(dut_ptr, axi.b) \
axi_ar_copy_from_dut_ptr(dut_ptr, axi.ar) \
axi_r_copy_from_dut_ptr(dut_ptr, axi.r) \
} while (0);
#define axi_set_dut_ptr(dut_ptr, axi) \
do { \
axi_aw_set_dut_ptr(dut_ptr, axi.aw) \
axi_w_set_dut_ptr(dut_ptr, axi.w) \
axi_b_set_dut_ptr(dut_ptr, axi.b) \
axi_ar_set_dut_ptr(dut_ptr, axi.ar) \
axi_r_set_dut_ptr(dut_ptr, axi.r) \
} while (0);
void
dramsim3_finish
();
void
dramsim3_finish
();
void
dramsim3_helper
(
struct
axi_channel
&
axi
);
void
dramsim3_helper_rising
(
const
struct
axi_channel
&
axi
);
void
dramsim3_helper_falling
(
struct
axi_channel
&
axi
);
#endif
#endif
#endif
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录