Description
To implement #995, DSLX procs need to use RAM blocks, each with size in range 8 - 128 KBytes.
When running bytecode interpreter-based tests that make use of RAM blocks (using xls_dslx_test
Bazel rule with compare: none
) I've noticed that the progression of the test is extremely slow - it literally executes 1 or 2 iterations of next()
of my test_proc per second. In addition to that, after running the test for ~180 seconds my PC runs out of RAM and the interpreter is killed by Linux kernel OOM. I've confirmed that the RAM consumption comes from interpreter_main
executable of XLS, I have 32G RAM + 32G swap and the interpreter consumes around 55G at the moment when it is killed.
@proppy @cdleary Do you perhaps have some idea why this may be happening and whether there is some workaround? Currently it's a blocker as it prevents us from testing code that uses RAMs.
I can reproduce the behavior using following minimalistic test_proc. It fills 64KByte RAM with zero bytes starting from address 0 and incrementing it by 1 till the full RAM is filled. It writes one byte each 10 iterations of next()
.
import xls.examples.ram as ram
type RamWriteReq = ram::WriteReq;
type RamWriteResp = ram::WriteResp;
type RamReadReq = ram::ReadReq;
type RamReadResp = ram::ReadResp;
#[test_proc]
proc tst_ram {
o_term: chan<bool> out;
o_write_req: chan<ram::WriteReq<16, 8, 8>> out;
i_write_resp: chan<ram::WriteResp> in;
o_read_req: chan<ram::ReadReq<16, 8>> out;
i_read_resp: chan<ram::ReadResp<8>> in;
init {(u32:0, u16:0)}
config(o_term: chan<bool> out) {
let (o_write_req, i_write_req) = chan<ram::WriteReq<16, 8, 8>>;
let (o_write_resp, i_write_resp) = chan<ram::WriteResp>;
let (o_read_req, i_read_req) = chan<ram::ReadReq<16, 8>>;
let (o_read_resp, i_read_resp) = chan<ram::ReadResp<8>>;
spawn ram::RamModel<u32:8, {u32:1<<u32:16}, u32:1>
(i_read_req, o_read_resp, i_write_req, o_write_resp);
(
o_term,
o_write_req, i_write_resp,
o_read_req, i_read_resp
)
}
next (tok: token, state: (u32, u16)) {
let (delay, addr) = state;
let do_write = delay == u32:0;
if do_write {
trace_fmt!("writing addr:{}", addr);
} else {()};
let tok = send_if(tok, o_write_req, do_write, ram::WriteWordReq<u32:8>(addr, u8:0));
let (tok, _) = recv_if(tok, i_write_resp, do_write, RamWriteResp{});
let addr = if do_write {
addr + u16:1
} else {
addr
};
let delay = if do_write {
u32:9
} else {
delay - u32:1
};
send_if(tok, o_term, addr == u16:0, true);
(delay, addr)
}
}
Metadata
Metadata
Assignees
Labels
Type
Projects
Status