Simulator compatibility updates
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption(
|
||||
"--sim-tool",
|
||||
choices=["questa", "xilinx", "stub", "skip", "auto"],
|
||||
choices=["questa", "xsim", "stub", "skip", "auto"],
|
||||
default="auto",
|
||||
help="""
|
||||
Select the simulator to use.
|
||||
@@ -12,6 +12,29 @@ def pytest_addoption(parser):
|
||||
"""
|
||||
)
|
||||
|
||||
parser.addoption(
|
||||
"--gui",
|
||||
default=False,
|
||||
action="store_true",
|
||||
help=""",
|
||||
Launch sim tool in GUI mode
|
||||
|
||||
Only use this option when running a single test
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
parser.addoption(
|
||||
"--rerun",
|
||||
default=False,
|
||||
action="store_true",
|
||||
help=""",
|
||||
Re-run simulation in-place without re-exporting regblock
|
||||
|
||||
Useful if hand-editing a testcase interactively.
|
||||
"""
|
||||
)
|
||||
|
||||
parser.addoption(
|
||||
"--synth-tool",
|
||||
choices=["vivado", "skip", "auto"],
|
||||
|
||||
@@ -49,6 +49,13 @@ class BaseTestCase(unittest.TestCase):
|
||||
def _load_request(self, request):
|
||||
self.request = request
|
||||
|
||||
@property
|
||||
def rerun(self) -> bool:
|
||||
"""
|
||||
Re-run wothout deleting and re-generating prior output directory.
|
||||
"""
|
||||
return self.request.config.getoption("--rerun")
|
||||
|
||||
def get_testcase_dir(self) -> str:
|
||||
class_dir = os.path.dirname(inspect.getfile(self.__class__))
|
||||
return class_dir
|
||||
@@ -114,6 +121,9 @@ class BaseTestCase(unittest.TestCase):
|
||||
)
|
||||
|
||||
def setUp(self) -> None:
|
||||
if self.rerun:
|
||||
return
|
||||
|
||||
# Create fresh build dir
|
||||
run_dir = self.get_run_dir()
|
||||
if os.path.exists(run_dir):
|
||||
|
||||
@@ -95,59 +95,129 @@ interface axi4lite_intf_driver #(
|
||||
@cb;
|
||||
end
|
||||
|
||||
semaphore txn_aw_mutex = new(1);
|
||||
semaphore txn_w_mutex = new(1);
|
||||
semaphore txn_b_mutex = new(1);
|
||||
semaphore txn_ar_mutex = new(1);
|
||||
semaphore txn_r_mutex = new(1);
|
||||
//--------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
logic [1:0] bresp;
|
||||
} write_response_t;
|
||||
|
||||
task automatic write(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] data, logic [DATA_WIDTH/8-1:0] strb = '1);
|
||||
bit w_before_aw;
|
||||
w_before_aw = $urandom_range(1,0);
|
||||
class write_request_t;
|
||||
mailbox #(write_response_t) response_mbx;
|
||||
logic [ADDR_WIDTH-1:0] addr;
|
||||
logic [DATA_WIDTH-1:0] data;
|
||||
logic [DATA_WIDTH/8-1:0] strb;
|
||||
function new();
|
||||
this.response_mbx = new();
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
fork
|
||||
begin
|
||||
txn_aw_mutex.get();
|
||||
mailbox #(write_request_t) aw_mbx = new();
|
||||
mailbox #(write_request_t) w_mbx = new();
|
||||
write_request_t write_queue[$];
|
||||
|
||||
// Issue AW transfers
|
||||
initial forever begin
|
||||
write_request_t req;
|
||||
aw_mbx.get(req);
|
||||
##0;
|
||||
if(w_before_aw) repeat($urandom_range(2,0)) @cb;
|
||||
repeat($urandom_range(2,0)) @cb;
|
||||
cb.AWVALID <= '1;
|
||||
cb.AWADDR <= addr;
|
||||
cb.AWADDR <= req.addr;
|
||||
cb.AWPROT <= '0;
|
||||
@(cb);
|
||||
while(cb.AWREADY !== 1'b1) @(cb);
|
||||
cb.AWVALID <= '0;
|
||||
txn_aw_mutex.put();
|
||||
end
|
||||
|
||||
begin
|
||||
txn_w_mutex.get();
|
||||
// Issue W transfers
|
||||
initial forever begin
|
||||
write_request_t req;
|
||||
w_mbx.get(req);
|
||||
##0;
|
||||
if(!w_before_aw) repeat($urandom_range(2,0)) @cb;
|
||||
repeat($urandom_range(2,0)) @cb;
|
||||
cb.WVALID <= '1;
|
||||
cb.WDATA <= data;
|
||||
cb.WSTRB <= strb;
|
||||
cb.WDATA <= req.data;
|
||||
cb.WSTRB <= req.strb;
|
||||
@(cb);
|
||||
while(cb.WREADY !== 1'b1) @(cb);
|
||||
cb.WVALID <= '0;
|
||||
cb.WSTRB <= '0;
|
||||
txn_w_mutex.put();
|
||||
end
|
||||
|
||||
begin
|
||||
txn_b_mutex.get();
|
||||
// Listen for R responses
|
||||
initial forever begin
|
||||
@cb;
|
||||
while(!(cb.BREADY === 1'b1 && cb.BVALID === 1'b1)) @(cb);
|
||||
assert(!$isunknown(cb.BRESP)) else $error("Read from 0x%0x returned X's on BRESP", addr);
|
||||
txn_b_mutex.put();
|
||||
while(rst || !(cb.BREADY === 1'b1 && cb.BVALID === 1'b1)) @cb;
|
||||
if(write_queue.size() != 0) begin
|
||||
// Can match this response with an existing request.
|
||||
// Send response to requestor
|
||||
write_request_t req;
|
||||
write_response_t resp;
|
||||
req = write_queue.pop_front();
|
||||
resp.bresp = cb.BRESP;
|
||||
req.response_mbx.put(resp);
|
||||
end else begin
|
||||
$error("Got unmatched write response");
|
||||
end
|
||||
join
|
||||
end
|
||||
|
||||
task automatic write(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] data, logic [DATA_WIDTH/8-1:0] strb = '1);
|
||||
write_request_t req;
|
||||
write_response_t resp;
|
||||
|
||||
req = new();
|
||||
req.addr = addr;
|
||||
req.data = data;
|
||||
req.strb = strb;
|
||||
|
||||
aw_mbx.put(req);
|
||||
w_mbx.put(req);
|
||||
write_queue.push_back(req);
|
||||
|
||||
// Wait for response
|
||||
req.response_mbx.get(resp);
|
||||
assert(!$isunknown(resp.bresp)) else $error("Read from 0x%0x returned X's on BRESP", addr);
|
||||
endtask
|
||||
|
||||
task automatic read(logic [ADDR_WIDTH-1:0] addr, output logic [DATA_WIDTH-1:0] data);
|
||||
//--------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
logic [DATA_WIDTH-1: 0] rdata;
|
||||
logic [1:0] rresp;
|
||||
} read_response_t;
|
||||
|
||||
class read_request_t;
|
||||
mailbox #(read_response_t) response_mbx;
|
||||
function new();
|
||||
this.response_mbx = new();
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
semaphore txn_ar_mutex = new(1);
|
||||
read_request_t read_queue[$];
|
||||
|
||||
// Listen for R responses
|
||||
initial forever begin
|
||||
@cb;
|
||||
while(rst || !(cb.RREADY === 1'b1 && cb.RVALID === 1'b1)) @cb;
|
||||
if(read_queue.size() != 0) begin
|
||||
// Can match this response with an existing request.
|
||||
// Send response to requestor
|
||||
read_request_t req;
|
||||
read_response_t resp;
|
||||
req = read_queue.pop_front();
|
||||
resp.rdata = cb.RDATA;
|
||||
resp.rresp = cb.RRESP;
|
||||
req.response_mbx.put(resp);
|
||||
end else begin
|
||||
$error("Got unmatched read response");
|
||||
end
|
||||
end
|
||||
|
||||
task automatic read(logic [ADDR_WIDTH-1:0] addr, output logic [DATA_WIDTH-1:0] data);
|
||||
read_request_t req;
|
||||
read_response_t resp;
|
||||
|
||||
fork
|
||||
begin
|
||||
txn_ar_mutex.get();
|
||||
// Issue read request
|
||||
##0;
|
||||
cb.ARVALID <= '1;
|
||||
cb.ARADDR <= addr;
|
||||
@@ -155,19 +225,18 @@ interface axi4lite_intf_driver #(
|
||||
@(cb);
|
||||
while(cb.ARREADY !== 1'b1) @(cb);
|
||||
cb.ARVALID <= '0;
|
||||
txn_ar_mutex.put();
|
||||
end
|
||||
|
||||
begin
|
||||
txn_r_mutex.get();
|
||||
@cb;
|
||||
while(!(cb.RREADY === 1'b1 && cb.RVALID === 1'b1)) @(cb);
|
||||
assert(!$isunknown(cb.RDATA)) else $error("Read from 0x%0x returned X's on RDATA", addr);
|
||||
assert(!$isunknown(cb.RRESP)) else $error("Read from 0x%0x returned X's on RRESP", addr);
|
||||
data = cb.RDATA;
|
||||
txn_r_mutex.put();
|
||||
end
|
||||
join
|
||||
// Push new request into queue
|
||||
req = new();
|
||||
read_queue.push_back(req);
|
||||
txn_ar_mutex.put();
|
||||
|
||||
// Wait for response
|
||||
req.response_mbx.get(resp);
|
||||
|
||||
assert(!$isunknown(resp.rdata)) else $error("Read from 0x%0x returned X's on RDATA", addr);
|
||||
assert(!$isunknown(resp.rresp)) else $error("Read from 0x%0x returned X's on RRESP", addr);
|
||||
data = resp.rdata;
|
||||
endtask
|
||||
|
||||
task automatic assert_read(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] expected_data, logic [DATA_WIDTH-1:0] mask = '1);
|
||||
@@ -177,6 +246,7 @@ interface axi4lite_intf_driver #(
|
||||
assert(data == expected_data) else $error("Read from 0x%x returned 0x%x. Expected 0x%x", addr, data, expected_data);
|
||||
endtask
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
initial begin
|
||||
reset();
|
||||
end
|
||||
|
||||
@@ -14,7 +14,7 @@ module external_block #(
|
||||
output logic [WIDTH-1:0] rd_data,
|
||||
output logic wr_ack
|
||||
);
|
||||
timeunit 1ns;
|
||||
timeunit 1ps;
|
||||
timeprecision 1ps;
|
||||
|
||||
localparam ADDR_SHIFT = $clog2(WIDTH/8);
|
||||
|
||||
@@ -13,7 +13,7 @@ module external_reg #(
|
||||
output logic [WIDTH-1:0] rd_data,
|
||||
output logic wr_ack
|
||||
);
|
||||
timeunit 1ns;
|
||||
timeunit 1ps;
|
||||
timeprecision 1ps;
|
||||
logic [SUBWORDS-1:0][WIDTH-1:0] value;
|
||||
|
||||
@@ -69,6 +69,7 @@ initial begin
|
||||
#1ns;
|
||||
|
||||
if(!rst && req) begin
|
||||
$info("got request");
|
||||
if(req_is_wr) do_write(req, wr_data, wr_biten);
|
||||
else do_read(req);
|
||||
end
|
||||
|
||||
@@ -76,6 +76,7 @@ class SimTestCase(BaseTestCase):
|
||||
super().setUp()
|
||||
|
||||
# Create testbench from template
|
||||
if not self.rerun:
|
||||
self._generate_tb()
|
||||
|
||||
simulator = simulator_cls(self)
|
||||
|
||||
@@ -3,13 +3,13 @@ import functools
|
||||
|
||||
from .base import Simulator
|
||||
from .questa import Questa
|
||||
from .xilinx import Xilinx
|
||||
from .xilinx import XilinxXSIM
|
||||
from .stub import StubSimulator
|
||||
|
||||
ALL_SIMULATORS: List[Simulator]
|
||||
ALL_SIMULATORS = [
|
||||
Questa,
|
||||
Xilinx,
|
||||
XilinxXSIM,
|
||||
StubSimulator,
|
||||
]
|
||||
|
||||
|
||||
@@ -13,6 +13,10 @@ class Simulator:
|
||||
def __init__(self, testcase: 'SimTestCase' = None) -> None:
|
||||
self.testcase = testcase
|
||||
|
||||
@property
|
||||
def gui_mode(self) -> bool:
|
||||
return self.testcase.request.config.getoption("--gui")
|
||||
|
||||
@property
|
||||
def tb_files(self) -> List[str]:
|
||||
files = []
|
||||
|
||||
@@ -48,14 +48,21 @@ class Questa(Simulator):
|
||||
"vsim", "-quiet",
|
||||
"-voptargs=+acc",
|
||||
"-msgmode", "both",
|
||||
"-do", "set WildcardFilter [lsearch -not -all -inline $WildcardFilter Memory]",
|
||||
"-do", "log -r /*;",
|
||||
"-do", "run -all; exit;",
|
||||
"-c",
|
||||
"-l", "%s.log" % test_name,
|
||||
"-wlf", "%s.wlf" % test_name,
|
||||
"tb",
|
||||
"-do", "set WildcardFilter [lsearch -not -all -inline $WildcardFilter Memory]",
|
||||
"-do", "log -r /*;",
|
||||
]
|
||||
|
||||
if self.gui_mode:
|
||||
cmd.append("-i")
|
||||
else:
|
||||
cmd.extend([
|
||||
"-do", "run -all; exit;",
|
||||
"-c",
|
||||
])
|
||||
|
||||
for plusarg in plusargs:
|
||||
cmd.append("+" + plusarg)
|
||||
subprocess.run(cmd, check=True)
|
||||
|
||||
@@ -5,17 +5,17 @@ import shutil
|
||||
|
||||
from .base import Simulator
|
||||
|
||||
class Xilinx(Simulator):
|
||||
class XilinxXSIM(Simulator):
|
||||
"""
|
||||
Don't bother using the Xilinx simulator... Its buggy and extraordinarily slow.
|
||||
Avoid using the Xilinx simulator... Its buggy and extraordinarily slow.
|
||||
As observed in v2023.2:
|
||||
- clocking block assignments do not seem to actually simulate correctly.
|
||||
assignment statements get ignored or the values get mangled.
|
||||
- Streaming operators have all sorts of limitations.
|
||||
|
||||
Keeping this here in case someday it works better...
|
||||
- Clocking block assignments to struct members do not simulate correctly.
|
||||
assignment statements get lost.
|
||||
https://support.xilinx.com/s/question/0D54U00007ZIGfXSAX/xsim-bug-xsim-does-not-simulate-struct-assignments-in-clocking-blocks-correctly?language=en_US
|
||||
- Streaming bit-swap within a conditional returns a corrupted value
|
||||
https://support.xilinx.com/s/question/0D54U00007ZIIBPSA5/xsim-bug-xsim-corrupts-value-of-signal-that-is-bitswapped-within-a-conditional-operator?language=en_US
|
||||
"""
|
||||
name = "xilinx"
|
||||
name = "xsim"
|
||||
|
||||
@classmethod
|
||||
def is_installed(cls) -> bool:
|
||||
@@ -30,7 +30,7 @@ class Xilinx(Simulator):
|
||||
"xvlog", "--sv",
|
||||
"--log", "compile.log",
|
||||
"--include", os.path.join(os.path.dirname(__file__), ".."),
|
||||
"--define", "XSIM",
|
||||
"--define", "XILINX_XSIM",
|
||||
]
|
||||
cmd.extend(self.tb_files)
|
||||
subprocess.run(cmd, check=True)
|
||||
@@ -38,7 +38,7 @@ class Xilinx(Simulator):
|
||||
cmd = [
|
||||
"xelab",
|
||||
"--log", "elaborate.log",
|
||||
"--timescale", "1ns/1ps",
|
||||
"--timescale", "1ps/1ps",
|
||||
"--debug", "all",
|
||||
"tb",
|
||||
]
|
||||
@@ -50,13 +50,17 @@ class Xilinx(Simulator):
|
||||
|
||||
test_name = self.testcase.request.node.name
|
||||
|
||||
# call vsim
|
||||
cmd = [
|
||||
"xsim",
|
||||
"--R",
|
||||
# call xsim
|
||||
cmd = ["xsim"]
|
||||
if self.gui_mode:
|
||||
cmd.append("--gui")
|
||||
else:
|
||||
cmd.append("-R")
|
||||
|
||||
cmd.extend([
|
||||
"--log", "%s.log" % test_name,
|
||||
"tb",
|
||||
]
|
||||
])
|
||||
|
||||
for plusarg in plusargs:
|
||||
cmd.append("--testplusarg")
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
{% sv_line_anchor %}
|
||||
module tb;
|
||||
timeunit 1ns;
|
||||
timeunit 10ps;
|
||||
timeprecision 1ps;
|
||||
|
||||
`define bitswap(x) ($bits(x))'({<<{x}})
|
||||
|
||||
logic rst = '1;
|
||||
logic clk = '0;
|
||||
initial forever begin
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from ..lib.sim_testcase import SimTestCase
|
||||
|
||||
class Test(SimTestCase):
|
||||
incompatible_sim_tools = {"xilinx"}
|
||||
incompatible_sim_tools = {"xsim"} # due to cb struct assignment bug
|
||||
def test_dut(self):
|
||||
self.run_test()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from ..lib.sim_testcase import SimTestCase
|
||||
|
||||
class Test(SimTestCase):
|
||||
incompatible_sim_tools = {"xilinx"}
|
||||
incompatible_sim_tools = {"xsim"} # due to cb struct assignment bug
|
||||
def test_dut(self):
|
||||
self.run_test()
|
||||
|
||||
@@ -145,8 +145,8 @@
|
||||
|
||||
.req(hwif_out.wide_ro_reg.req),
|
||||
.req_is_wr(hwif_out.wide_ro_reg.req_is_wr),
|
||||
.wr_data(64'b0),
|
||||
.wr_biten(64'b0),
|
||||
.wr_data(32'b0),
|
||||
.wr_biten(32'b0),
|
||||
.rd_ack(hwif_in.wide_ro_reg.rd_ack),
|
||||
.rd_data(hwif_in.wide_ro_reg.rd_data),
|
||||
.wr_ack()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from ..lib.sim_testcase import SimTestCase
|
||||
|
||||
class Test(SimTestCase):
|
||||
incompatible_sim_tools = {"xsim"} # due to cb struct assignment bug
|
||||
def test_dut(self):
|
||||
self.run_test()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from ..lib.sim_testcase import SimTestCase
|
||||
|
||||
class Test(SimTestCase):
|
||||
incompatible_sim_tools = {"xsim"} # due to cb struct assignment bug
|
||||
def test_dut(self):
|
||||
self.run_test()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from ..lib.sim_testcase import SimTestCase
|
||||
|
||||
class Test(SimTestCase):
|
||||
incompatible_sim_tools = {"xsim"} # due to cb struct assignment bug
|
||||
def test_dut(self):
|
||||
self.run_test()
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
disable fork;
|
||||
|
||||
cpuif.write('h0, 'd0);
|
||||
force dut.field_storage.r1.f1.value[3] = 1'b1;
|
||||
release dut.field_storage.r1.f1.value[3];
|
||||
assign dut.field_storage.r1.f1.value = 16'd1;
|
||||
deassign dut.field_storage.r1.f1.value;
|
||||
@cb;
|
||||
@cb;
|
||||
assert(cb.parity_error == 1'b1);
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
wait fork;
|
||||
|
||||
// Mix read/writes
|
||||
for(int i=0; i<64; i++) begin
|
||||
for(int i=0; i<8; i++) begin
|
||||
fork
|
||||
automatic int i_fk = i;
|
||||
begin
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from ..lib.sim_testcase import SimTestCase
|
||||
|
||||
class Test(SimTestCase):
|
||||
incompatible_sim_tools = {"xsim"} # due to cb struct assignment bug
|
||||
def test_dut(self):
|
||||
self.run_test()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from ..lib.sim_testcase import SimTestCase
|
||||
|
||||
class Test(SimTestCase):
|
||||
incompatible_sim_tools = {"xsim"} # due to cb struct assignment bug
|
||||
def test_dut(self):
|
||||
self.run_test()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from ..lib.sim_testcase import SimTestCase
|
||||
|
||||
class Test(SimTestCase):
|
||||
incompatible_sim_tools = {"xsim"} # due to cb struct assignment bug
|
||||
def test_dut(self):
|
||||
self.run_test()
|
||||
|
||||
@@ -71,13 +71,13 @@
|
||||
cpuif.assert_read('h3000, 'h4DEAB000);
|
||||
|
||||
// rw_reg_lsb0
|
||||
`ifndef XSIM
|
||||
// Xilinx simulator has poor support for streaming operators. Skip
|
||||
`ifndef XILINX_XSIM
|
||||
// Skip due to xsim bug simulating internal RTL - bitswap inside conditional corrupts data
|
||||
cpuif.assert_read('h3004, 0);
|
||||
cpuif.write('h3004, 'h4DEAB000);
|
||||
@cb;
|
||||
assert({<<{cb.hwif_out.rw_reg_lsb0.f1.value}} == 8'hAB);
|
||||
assert({<<{cb.hwif_out.rw_reg_lsb0.f2.value}} == 11'h4DE);
|
||||
assert(`bitswap(cb.hwif_out.rw_reg_lsb0.f1.value) == 8'hAB);
|
||||
assert(`bitswap(cb.hwif_out.rw_reg_lsb0.f2.value) == 11'h4DE);
|
||||
cpuif.assert_read('h3004, 'h4DEAB000);
|
||||
`endif
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from ..lib.sim_testcase import SimTestCase
|
||||
|
||||
class Test(SimTestCase):
|
||||
incompatible_sim_tools = {"xsim"} # due to cb struct assignment bug
|
||||
def test_dut(self):
|
||||
self.run_test()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from ..lib.sim_testcase import SimTestCase
|
||||
|
||||
class Test(SimTestCase):
|
||||
incompatible_sim_tools = {"xsim"} # due to cb struct assignment bug
|
||||
def test_dut(self):
|
||||
self.run_test()
|
||||
|
||||
@@ -50,10 +50,10 @@
|
||||
cpuif.write('h14, 'h9ABC);
|
||||
cpuif.write('h16, 'hDEF1);
|
||||
@cb;
|
||||
assert({<<{cb.hwif_out.rw_reg1_lsb0.f1.value}} == 8'h34);
|
||||
assert({<<{cb.hwif_out.rw_reg1_lsb0.f2.value}} == 3'h1);
|
||||
assert({<<{cb.hwif_out.rw_reg1_lsb0.f3.value}} == 1'h1);
|
||||
assert({<<{cb.hwif_out.rw_reg1_lsb0.f4.value}} == 8'h9A);
|
||||
assert(`bitswap(cb.hwif_out.rw_reg1_lsb0.f1.value) == 8'h34);
|
||||
assert(`bitswap(cb.hwif_out.rw_reg1_lsb0.f2.value) == 3'h1);
|
||||
assert(`bitswap(cb.hwif_out.rw_reg1_lsb0.f3.value) == 1'h1);
|
||||
assert(`bitswap(cb.hwif_out.rw_reg1_lsb0.f4.value) == 8'h9A);
|
||||
cpuif.assert_read('h10, 'h1034);
|
||||
cpuif.assert_read('h12, 'h0000);
|
||||
cpuif.assert_read('h14, 'h9A10);
|
||||
@@ -67,8 +67,8 @@
|
||||
cpuif.write('h1C, 'h9ABC);
|
||||
cpuif.write('h1E, 'hDEF1);
|
||||
@cb;
|
||||
assert({<<{cb.hwif_out.rw_reg2_lsb0.f1.value}} == 4'h8);
|
||||
assert({<<{cb.hwif_out.rw_reg2_lsb0.f2.value}} == 16'hDEF1);
|
||||
assert(`bitswap(cb.hwif_out.rw_reg2_lsb0.f1.value) == 4'h8);
|
||||
assert(`bitswap(cb.hwif_out.rw_reg2_lsb0.f2.value) == 16'hDEF1);
|
||||
cpuif.assert_read('h18, 'h0000);
|
||||
cpuif.assert_read('h1A, 'h0008);
|
||||
cpuif.assert_read('h1C, 'h0000);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from ..lib.sim_testcase import SimTestCase
|
||||
|
||||
class Test(SimTestCase):
|
||||
incompatible_sim_tools = {"xsim"} # due to cb struct assignment bug
|
||||
def test_dut(self):
|
||||
self.run_test()
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
assert(cb.hwif_out.reg1_msb0.f1.value == 0);
|
||||
cpuif.write('hE, 'hDEF1);
|
||||
@cb; @cb;
|
||||
assert({<<{cb.hwif_out.reg1_msb0.f1.value}} == 64'hDEF19ABC56781234);
|
||||
assert(`bitswap(cb.hwif_out.reg1_msb0.f1.value) == 64'hDEF19ABC56781234);
|
||||
cpuif.assert_read('h8, 'h1234);
|
||||
cpuif.assert_read('hA, 'h5678);
|
||||
cpuif.assert_read('hC, 'h9ABC);
|
||||
@@ -104,8 +104,8 @@
|
||||
assert(cb.hwif_out.reg2_msb0.f2.value == 0);
|
||||
cpuif.write('h16, 'hAA12);
|
||||
@cb; @cb;
|
||||
assert({<<{cb.hwif_out.reg2_msb0.f1.value}} == 12'h234);
|
||||
assert({<<{cb.hwif_out.reg2_msb0.f2.value}} == 4'h1);
|
||||
assert(`bitswap(cb.hwif_out.reg2_msb0.f1.value) == 12'h234);
|
||||
assert(`bitswap(cb.hwif_out.reg2_msb0.f2.value) == 4'h1);
|
||||
cpuif.assert_read('h14, 'h3400);
|
||||
cpuif.assert_read('h16, 'h0012);
|
||||
|
||||
@@ -281,7 +281,7 @@
|
||||
cpuif.assert_read('hA, 'h0200);
|
||||
cpuif.assert_read('hC, 'h0070);
|
||||
cpuif.assert_read('hE, 'h0002);
|
||||
assert({<<{cb.hwif_out.reg1_msb0.f1.value}} == 'h0002_0070_0200_A000);
|
||||
assert(`bitswap(cb.hwif_out.reg1_msb0.f1.value) == 'h0002_0070_0200_A000);
|
||||
|
||||
// Check that strobes are cumulative
|
||||
cpuif.write('h8, 'h0030, 'h00F0);
|
||||
@@ -297,7 +297,7 @@
|
||||
cpuif.assert_read('hA, 'h0278);
|
||||
cpuif.assert_read('hC, 'hA07D);
|
||||
cpuif.assert_read('hE, 'hAF02);
|
||||
assert({<<{cb.hwif_out.reg1_msb0.f1.value}} == 'hAF02_A07D_0278_A230);
|
||||
assert(`bitswap(cb.hwif_out.reg1_msb0.f1.value) == 'hAF02_A07D_0278_A230);
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -2,6 +2,8 @@ from ..lib.sim_testcase import SimTestCase
|
||||
from ..lib.cpuifs.passthrough import Passthrough
|
||||
|
||||
class Test(SimTestCase):
|
||||
incompatible_sim_tools = {"xsim"} # due to cb struct assignment bug
|
||||
|
||||
cpuif = Passthrough() # test with bit strobes
|
||||
|
||||
def test_dut(self):
|
||||
|
||||
Reference in New Issue
Block a user