[ESI] Cosimulation integration tests (#259)

* [ESI] Cosimulation integration tests

* Fixes

* Set an integration test timeout.
This commit is contained in:
John Demme 2020-11-21 14:05:45 -08:00 committed by GitHub
parent ac8ea5d10c
commit 113ee95719
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 171 additions and 1 deletions

View File

@ -10,6 +10,7 @@ if (TARGET EsiCosimDpiServer)
set(ESI_COSIM_PATH ${ESI_COSIM_LIB_DIR}/libEsiCosimDpiServer.so)
endif()
set(CIRCT_INTEGRATION_TIMEOUT 60) # Set a 60s timeout on individual tests.
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py

View File

@ -0,0 +1,79 @@
#!/usr/bin/python3
import binascii
import capnp
import random
import time
class LoopbackTester:
"""Provides methods to test the untyped loopback simulation."""
# Some of these are generalizable and should be hoisted into a base class
# when other cosim tests get written.
def __init__(self, schemaPath, hostPort):
self.dpi = capnp.load(schemaPath)
self.rpc_client = capnp.TwoPartyClient(hostPort)
self.cosim = self.rpc_client.bootstrap().cast_as(self.dpi.CosimDpiServer)
def test_list(self):
ifaces = self.cosim.list().wait().ifaces
assert len(ifaces) > 0
def test_open_close(self):
ifaces = self.cosim.list().wait().ifaces
openResp = self.cosim.open(ifaces[0]).wait()
assert openResp.iface is not None
ep = openResp.iface
ep.close().wait()
def openEP(self):
ifaces = self.cosim.list().wait().ifaces
openResp = self.cosim.open(ifaces[0]).wait()
assert openResp.iface is not None
return openResp.iface
def write(self, ep):
r = random.randrange(0, 2**24)
data = r.to_bytes(3, 'big')
print(f'Sending: {binascii.hexlify(data)}')
ep.send(self.dpi.UntypedData.new_message(data=data)).wait()
return data
def read(self, ep):
while True:
recvResp = ep.recv(False).wait()
if recvResp.hasData:
break
else:
time.sleep(0.1)
assert recvResp.resp is not None
dataMsg = recvResp.resp.as_struct(self.dpi.UntypedData)
data = dataMsg.data
print(binascii.hexlify(data))
return data
def write_read(self):
ep = self.openEP()
print("Testing writes")
dataSent = self.write(ep)
print()
print("Testing reads")
dataRecv = self.read(ep)
ep.close().wait()
assert dataSent == dataRecv
def write_read_many(self, num_msgs=50):
ep = self.openEP()
print("Testing writes")
dataSent = list()
for _ in range(num_msgs):
dataSent.append(self.write(ep))
print()
print("Testing reads")
dataRecv = list()
for _ in range(num_msgs):
dataRecv.append(self.read(ep))
ep.close().wait()
assert dataSent == dataRecv

View File

@ -0,0 +1,85 @@
// PY: import loopback as test
// PY: rpc = test.LoopbackTester(rpcschemapath, simhostport)
// PY: rpc.test_list()
// PY: rpc.test_open_close()
// PY: rpc.write_read_many(5)
import Cosim_DpiPkg::*;
module main(
`ifdef VERILATOR
input logic clk,
input logic rstn
`endif
);
localparam int TYPE_SIZE_BITS =
(1 * 64) + // root message
(1 * 64) + // list header
(1 * 64); // list of length 3 bytes, rounded up to multiples of 8 bytes
`ifndef VERILATOR
logic clk;
logic rstn;
`endif
wire DataOutValid;
wire DataOutReady = 1;
wire [TYPE_SIZE_BITS-1:0] DataOut;
logic DataInValid;
logic DataInReady;
logic [TYPE_SIZE_BITS-1:0] DataIn;
Cosim_Endpoint #(
.ENDPOINT_ID(1),
.RECV_TYPE_ID(1),
.RECV_TYPE_SIZE_BITS(TYPE_SIZE_BITS),
.SEND_TYPE_ID(1),
.SEND_TYPE_SIZE_BITS(TYPE_SIZE_BITS)
) ep (
.*
);
always@(posedge clk)
begin
if (rstn)
begin
if (DataOutValid && DataOutReady)
begin
$display("[%d] Recv'd: %h", $time(), DataOut);
DataIn <= DataOut;
end
DataInValid <= DataOutValid && DataOutReady;
if (DataInValid && DataInReady)
begin
$display("[%d] Sent: %h", $time(), DataIn);
end
end
else
begin
DataInValid <= 0;
end
end
`ifndef VERILATOR
// Clock
initial
begin
clk = 1'b0;
while (1)
begin
#5;
clk = !clk;
end
end
initial
begin
rstn = 0;
#17
// Run!
rstn = 1;
end
`endif
endmodule

View File

@ -40,6 +40,10 @@ llvm_config.with_system_environment(
llvm_config.use_default_substitutions()
# Set the timeout, if requested.
if config.timeout is not None and config.timeout != "":
lit_config.maxIndividualTestTime = int(config.timeout)
# excludes: A list of directories to exclude from the testsuite. The 'Inputs'
# subdirectories contain auxiliary inputs for various tests in their parent
# directories.

View File

@ -38,6 +38,7 @@ config.circt_include_dir = "@CIRCT_MAIN_SRC_DIR@"
config.circt_shlib_dir = "@LLVM_LIBRARY_OUTPUT_INTDIR@"
config.verilator_path = "@VERILATOR_PATH@"
config.esi_cosim_path = "@ESI_COSIM_PATH@"
config.timeout = "@CIRCT_INTEGRATION_TIMEOUT@"
# Support substitution of the tools_dir with user parameters. This is
# used when we can't determine the tool dir at configuration time.

View File

@ -45,7 +45,7 @@ bool EndpointRegistry::registerEndpoint(int epId, uint64_t sendTypeId,
// Endpoint constructor args.
std::forward_as_tuple(sendTypeId, sendTypeMaxSize,
recvTypeId, recvTypeMaxSize));
return false;
return true;
}
void EndpointRegistry::iterateEndpoints(