Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for to-be-closed variables for machine Lua API #77

Merged
merged 6 commits into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Added static analysis for Lua code
- Added code formatter for Lua code
- Added support for to-be-closed variables for machine Lua API
- Added --version and --version-json command-line options in cartesi-machine
- Added --skip-root-hash-check command line option to speed up machine loading in tests
- Added --skip-version-check command line option to allow testing old machine snapshots
Expand All @@ -26,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Use Lua path environment variables specific for version 5.4
- Move uarch halt from assembler to C++
- Ensure that uarch does not advance to the next micro instruction when iflags.H or iflags.Y is set
- Made flash drive length and ROM image filename optional in machine config

## [0.14.0] - 2023-05-03
### Added
Expand Down
40 changes: 1 addition & 39 deletions src/cartesi-machine.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1097,14 +1097,6 @@ for _, a in ipairs(arg) do
end
end

local function get_file_length(filename)
local file = io.open(filename, "rb")
if not file then return nil end
local size = file:seek("end") -- get file size
file:close()
return size
end

local function print_root_hash(machine, print)
(print or stderr)("%u: %s\n", machine:read_mcycle(), util.hexhash(machine:get_root_hash()))
end
Expand Down Expand Up @@ -1246,35 +1238,6 @@ local function store_machine_config(config, output)
output("}\n")
end

local function resolve_flash_lengths(label_order, image_filename, length)
for _, label in ipairs(label_order) do
local filename = image_filename[label]
local len = length[label]
local filelen
if filename and filename ~= "" then
filelen = assert(
get_file_length(filename),
string.format("unable to find length of flash drive '%s' image file '%s'", label, filename)
)
if len and len ~= filelen then
error(
string.format(
"flash drive '%s' length (%u) and image file '%s' length (%u) do not match",
label,
len,
filename,
filelen
)
)
else
length[label] = filelen
end
elseif not len then
error(string.format("flash drive '%s' nas no length or image file", label))
end
end
end

local function resolve_flash_starts(label_order, start)
local auto_start = 1 << 55
if next(start) == nil then
Expand Down Expand Up @@ -1370,7 +1333,6 @@ elseif load_dir then
main_machine = create_machine(load_dir, runtime)
else
-- Resolve all device starts and lengths
resolve_flash_lengths(flash_label_order, flash_image_filename, flash_length)
resolve_flash_starts(flash_label_order, flash_start)

-- Build machine config
Expand Down Expand Up @@ -1404,7 +1366,7 @@ else
image_filename = flash_image_filename[label],
shared = flash_shared[label],
start = flash_start[label],
length = flash_length[label],
length = flash_length[label] or -1,
}
mtdparts[#mtdparts + 1] = string.format("flash.%d:-(%s)", i - 1, label)
end
Expand Down
14 changes: 14 additions & 0 deletions src/clua-i-virtual-machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -645,10 +645,24 @@ static const auto machine_obj_index = cartesi::clua_make_luaL_Reg_array({
{"reset_uarch_state", machine_obj_index_reset_uarch_state},
});

/// \brief This is the machine __close metamethod implementation.
/// \param L Lua state.
static int machine_obj_close(lua_State *L) {
auto &m = clua_check<clua_managed_cm_ptr<cm_machine>>(L, 1);
TRY_EXECUTE(cm_destroy(m.get(), err_msg));
clua_close<clua_managed_cm_ptr<cm_machine>>(L);
return 0;
}

int clua_i_virtual_machine_init(lua_State *L, int ctxidx) {
if (!clua_typeexists<clua_managed_cm_ptr<cm_machine>>(L, ctxidx)) {
clua_createtype<clua_managed_cm_ptr<cm_machine>>(L, "cartesi machine object", ctxidx);
clua_setmethods<clua_managed_cm_ptr<cm_machine>>(L, machine_obj_index.data(), 0, ctxidx);
// Override __close to actually destroy the machine
static const auto machine_class_meta = cartesi::clua_make_luaL_Reg_array({
{"__close", machine_obj_close},
});
clua_setmetamethods<clua_managed_cm_ptr<cm_machine>>(L, machine_class_meta.data(), 0, ctxidx);
}
return 1;
}
Expand Down
4 changes: 2 additions & 2 deletions src/clua-machine-util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,7 @@ static void push_cm_rom_config(lua_State *L, const cm_rom_config *r) {
if (r->bootargs != nullptr) {
clua_setstringfield(L, r->bootargs, "bootargs", -1);
}
if (r->image_filename) {
if (r->image_filename != nullptr) {
clua_setstringfield(L, r->image_filename, "image_filename", -1);
}
}
Expand Down Expand Up @@ -960,7 +960,7 @@ cm_memory_range_config *clua_check_cm_memory_range_config(lua_State *L, int tabi
}
m->shared = opt_boolean_field(L, tabidx, "shared");
m->start = check_uint_field(L, tabidx, "start");
m->length = check_uint_field(L, tabidx, "length");
m->length = opt_uint_field(L, tabidx, "length", UINT64_C(-1));
m->image_filename = opt_copy_string_field(L, tabidx, "image_filename");
return m;
}
Expand Down
13 changes: 13 additions & 0 deletions src/clua.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,18 @@ int clua_gc(lua_State *L) {
return 0;
}

/// \brief Close an object of a previously defined type
/// \tparam T Associated C++ type
/// \param L Lua state.
template <typename T>
int clua_close(lua_State *L) {
T *ptr = static_cast<T *>(lua_touserdata(L, 1));
ptr->~T();
lua_pushnil(L);
lua_setmetatable(L, 1);
return 0;
}

/// \brief Prints an object of a previously defined type
/// \tparam T Associated C++ type
/// \param L Lua state.
Expand Down Expand Up @@ -291,6 +303,7 @@ void clua_createtype(lua_State *L, const char *name, int ctxidx) {
// create new type
auto default_meta = clua_make_luaL_Reg_array({
{"__gc", &clua_gc<T>},
{"__close", &clua_close<T>},
{"__tostring", &clua_tostring<T>},
});
lua_pushstring(L, clua_rawname<T>()); // T_rawname
Expand Down
27 changes: 18 additions & 9 deletions src/machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <cinttypes>
#include <cstdio>
#include <cstring>
#include <filesystem>
#include <future>
#include <iomanip>
#include <iostream>
Expand Down Expand Up @@ -343,10 +344,6 @@ machine::machine(const machine_config &c, const machine_runtime_config &r) :
write_ilrsc(m_c.processor.ilrsc);
write_iflags(m_c.processor.iflags);

if (m_c.rom.image_filename.empty()) {
throw std::invalid_argument{"ROM image filename is undefined"};
}

// Register RAM
if (m_c.ram.image_filename.empty()) {
register_pma_entry(make_callocd_memory_pma_entry("RAM"s, PMA_RAM_START, m_c.ram.length).set_flags(m_ram_flags));
Expand All @@ -356,14 +353,26 @@ machine::machine(const machine_config &c, const machine_runtime_config &r) :
}

// Register ROM
pma_entry &rom =
register_pma_entry(make_callocd_memory_pma_entry("ROM"s, PMA_ROM_START, PMA_ROM_LENGTH, m_c.rom.image_filename)
.set_flags(m_rom_flags));
pma_entry &rom = register_pma_entry((m_c.rom.image_filename.empty() ?
make_callocd_memory_pma_entry("ROM"s, PMA_ROM_START, PMA_ROM_LENGTH) :
make_callocd_memory_pma_entry("ROM"s, PMA_ROM_START, PMA_ROM_LENGTH, m_c.rom.image_filename))
.set_flags(m_rom_flags));

// Register all flash drives
int i = 0;
for (const auto &f : m_c.flash_drive) {
register_pma_entry(make_flash_drive_pma_entry("flash drive "s + std::to_string(i++), f));
for (auto &f : m_c.flash_drive) {
const std::string flash_description = "flash drive "s + std::to_string(i++);
// Auto detect flash drive image length
if (f.length == UINT64_C(-1)) {
std::error_code ec;
f.length = std::filesystem::file_size(f.image_filename, ec);
if (ec) {
throw std::system_error{ec.value(), ec.category(),
"unable to obtain length of image file '"s + f.image_filename + "' when initializing "s +
flash_description};
}
}
register_pma_entry(make_flash_drive_pma_entry(flash_description, f));
}

// Register rollup memory ranges
Expand Down
2 changes: 1 addition & 1 deletion src/test-machine-c-api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(create_machine_default_machine_test, default_mach
BOOST_CHECK_EQUAL(error_code, CM_ERROR_INVALID_ARGUMENT);

std::string result = err_msg;
std::string origin("ROM image filename is undefined");
std::string origin("RAM length cannot be zero");
BOOST_CHECK_EQUAL(origin, result);

cm_delete_cstring(err_msg);
Expand Down
2 changes: 1 addition & 1 deletion src/tests/htif-console.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ local function test(config, console_getchar_enable)
config.htif = {
console_getchar = console_getchar_enable,
}
local machine = cartesi.machine(config)
local machine <close> = cartesi.machine(config)
machine:run(math.maxinteger)

-- should be halted
Expand Down
2 changes: 1 addition & 1 deletion src/tests/htif-rollup.lua
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ end

local function test(config)
local pattern = "\xef\xcd\xab\x89\x67\x45\x23\x01"
local machine = cartesi.machine(config)
local machine <close> = cartesi.machine(config)

-- fill input with `pattern`
local rx = config.rollup.rx_buffer
Expand Down
2 changes: 1 addition & 1 deletion src/tests/htif-yield.lua
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ local function test(config, yield_automatic_enable, yield_manual_enable)
yield_automatic = yield_automatic_enable,
yield_manual = yield_manual_enable,
}
local machine = cartesi.machine(config)
local machine <close> = cartesi.machine(config)
local break_reason
for _, v in ipairs(yields) do
if
Expand Down
10 changes: 2 additions & 8 deletions src/tests/log-with-mtime-transition.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@
local test_util = require("tests.util")
local cartesi = require("cartesi")

local rom_filename = os.tmpname()
io.open(rom_filename, "w"):close()
local rom_deleter = {}
setmetatable(rom_deleter, { __gc = function() os.remove(rom_filename) end })

local config = {
processor = {
marchid = -1,
Expand All @@ -19,14 +14,13 @@ local config = {
length = 1 << 12,
},
rom = {
image_filename = rom_filename,
image_filename = "",
},
uarch = {
ram = { length = 1 << 20, image_filename = test_util.create_test_uarch_program() },
},
}
local machine = cartesi.machine(config)
os.remove(config.uarch.ram.image_filename)
local machine <close> = cartesi.machine(config)

local old_hash = machine:get_root_hash()
local access_log = machine:step_uarch({ proofs = true })
Expand Down
13 changes: 1 addition & 12 deletions src/tests/machine-test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,9 @@ local checkin_address
local test_path = "./"
local cleanup = {}

local function get_file_length(filename)
local file = io.open(filename, "rb")
if not file then return nil end
local size = file:seek("end") -- get file size
file:close()
return size
end

local linux_image = test_util.images_path .. "linux.bin"
local rom_image = test_util.images_path .. "rom.bin"
local rootfs_image = test_util.images_path .. "rootfs.ext2"
local rootfs_length = get_file_length(rootfs_image)

-- Print help and exit
local function help()
Expand Down Expand Up @@ -475,12 +466,12 @@ test_util.make_do_test(build_machine, machine_type, {
flash_drive = {
{
start = 0x80000000000000,
length = rootfs_length,
shared = false,
image_filename = rootfs_image,
},
},
})("should replace flash drive and read something", function(machine)
local rootfs_length = machine:get_initial_config().flash_drive[1].length
-- Create temp flash file
local input_path = test_path .. "input.raw"
local command = "echo 'test data 1234567890' > "
Expand Down Expand Up @@ -525,12 +516,10 @@ test_util.make_do_test(build_machine, machine_type, {
flash_drive = {
{
start = 0x80000000000000,
length = rootfs_length,
image_filename = rootfs_image,
},
{
start = 0x90000000000000,
length = rootfs_length,
image_filename = rootfs_image,
},
{
Expand Down
3 changes: 1 addition & 2 deletions src/tests/mcycle-overflow.lua
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@ end

local function do_test(description, f)
io.write(" " .. description .. "...")
local machine = build_machine()
local machine <close> = build_machine()
f(machine)
machine:destroy()
print(" passed")
end

Expand Down
3 changes: 1 addition & 2 deletions src/tests/mtime-interrupt.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,8 @@ end

local function do_test(description, f)
io.write(" " .. description .. "...")
local machine = build_machine()
local machine <close> = build_machine()
f(machine)
machine:destroy()
print(" passed")
end

Expand Down
3 changes: 1 addition & 2 deletions src/tests/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,8 @@ end
function test_util.make_do_test(build_machine, type, config)
return function(description, f)
io.write(" " .. description .. "...\n")
local machine = build_machine(type, config)
local machine <close> = build_machine(type, config)
f(machine)
machine:destroy()
print("<<<<<<<<<<<<<<<< passed >>>>>>>>>>>>>>>")
end
end
Expand Down
6 changes: 2 additions & 4 deletions src/uarch-riscv-tests.lua
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ local function run(tests)
failed = false,
cycles = 0,
}
local machine = build_machine(ctx.ram_image)
local machine <close> = build_machine(ctx.ram_image)
io.write(ctx.ram_image, ": ")
machine:run_uarch(2 * ctx.expected_cycles)
check_test_result(machine, ctx, errors)
Expand All @@ -238,7 +238,6 @@ local function run(tests)
else
print("passed")
end
machine:destroy()
end
if error_count > 0 then
io.write(string.format("\nFAILED %d of %d tests:\n\n", error_count, #tests))
Expand Down Expand Up @@ -354,7 +353,7 @@ local function json_logs(tests)
accesses_count = 0,
}
contexts[#contexts + 1] = ctx
local machine = build_machine(ctx.ram_image)
local machine <close> = build_machine(ctx.ram_image)
io.write(ctx.ram_image, ": ")
run_machine_writing_json_logs(machine, ctx)
check_test_result(machine, ctx, errors)
Expand All @@ -364,7 +363,6 @@ local function json_logs(tests)
else
print("passed")
end
machine:destroy()
end
if error_count > 0 then
io.write(string.format("\nFAILED %d of %d tests:\n\n", error_count, #tests))
Expand Down
3 changes: 1 addition & 2 deletions tools/benchmarks/run-benchmarks.lua
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,12 @@ end
local function measure(exec_args)
local results = {}
for _ = 1, N_RUNS do
local machine = build_machine(exec_args)
local machine <close> = build_machine(exec_args)
local start = socket.gettime()
repeat
machine:run(MAX_MCYCLE)
until machine:read_iflags_H() or machine:read_mcycle() < MAX_MCYCLE
local elapsed = socket.gettime() - start
machine:destroy()
table.insert(results, elapsed)
end
return results
Expand Down