Skip to content
Open
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
9 changes: 5 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ TEST_DIR := test
DOWNLOADDIR := downloads
SRC_DIR := src

EMULATOR_VERSION ?= v0.20.0
EMULATOR_TAG ?=
EMULATOR_VERSION ?= v0.21.0
EMULATOR_TAG ?= -test2

SOLIDITY_VERSION ?= 0.8.30

Expand Down Expand Up @@ -77,9 +77,10 @@ coverage-prod: dep
COVERAGE_OUTPUT_DIR ?= coverage

coverage-report: $(COVERAGE_OUTPUT_DIR)
lcov -a lcov-mock.info -a lcov-prod.info -o $(COVERAGE_OUTPUT_DIR)/lcov.info
sed 's|SF:src/AccessLogs.sol|SF:src/AccessLogsMock.sol|' lcov-mock.info > lcov-mock-patched.info
lcov -a lcov-mock-patched.info -a lcov-prod.info -o $(COVERAGE_OUTPUT_DIR)/lcov.info
lcov --summary $(COVERAGE_OUTPUT_DIR)/lcov.info | tee $(COVERAGE_OUTPUT_DIR)/coverage.txt
genhtml --ignore-errors unmapped $(COVERAGE_OUTPUT_DIR)/lcov.info -o $(COVERAGE_OUTPUT_DIR)/html
genhtml --ignore-errors unmapped --substitute 's|AccessLogsMock.sol|AccessLogs.sol|' $(COVERAGE_OUTPUT_DIR)/lcov.info -o $(COVERAGE_OUTPUT_DIR)/html

$(COVERAGE_OUTPUT_DIR):
mkdir -p $(COVERAGE_OUTPUT_DIR)
Expand Down
24 changes: 16 additions & 8 deletions helper_scripts/generate_EmulatorConstants.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,24 @@ out:write(' uint64 constant HTIF_FROMHOST_ADDRESS = 0x' ..
hex(cartesi.machine:get_reg_address("htif_fromhost")) .. ';\n')
out:write(' uint64 constant HTIF_TOHOST_ADDRESS = 0x' ..
hex(cartesi.machine:get_reg_address("htif_tohost")) .. ';\n')
out:write(' uint8 constant CMIO_YIELD_REASON_ADVANCE_STATE = 0x' ..
hex(cartesi.CMIO_YIELD_REASON_ADVANCE_STATE) .. ';\n')
out:write(' uint8 constant HTIF_YIELD_REASON_ADVANCE_STATE = 0x' ..
hex(cartesi.HTIF_YIELD_REASON_ADVANCE_STATE) .. ';\n')
out:write(' uint32 constant HASH_TREE_LOG2_WORD_SIZE = 0x' .. hex(cartesi.HASH_TREE_LOG2_WORD_SIZE) .. ';\n')
out:write(' uint32 constant HASH_TREE_WORD_SIZE = uint32(1) << HASH_TREE_LOG2_WORD_SIZE;\n')
out:write(' uint16 constant CMIO_YIELD_MANUAL_REASON_RX_ACCEPTED = 0x' ..
hex(cartesi.CMIO_YIELD_MANUAL_REASON_RX_ACCEPTED) .. ';\n')
out:write(' uint16 constant CMIO_YIELD_MANUAL_REASON_RX_REJECTED = 0x' ..
hex(cartesi.CMIO_YIELD_MANUAL_REASON_RX_REJECTED) .. ';\n')
out:write(' uint16 constant CMIO_YIELD_MANUAL_REASON_TX_EXCEPTION = 0x' ..
hex(cartesi.CMIO_YIELD_MANUAL_REASON_TX_EXCEPTION) .. ';\n')
out:write(' uint32 constant HTIF_DEV_SHIFT = 0x' .. hex(cartesi.HTIF_DEV_SHIFT) .. ';\n')
out:write(' uint32 constant HTIF_CMD_SHIFT = 0x' .. hex(cartesi.HTIF_CMD_SHIFT) .. ';\n')
out:write(' uint32 constant HTIF_REASON_SHIFT = 0x' .. hex(cartesi.HTIF_REASON_SHIFT) .. ';\n')
out:write(' uint64 constant HTIF_DEV_MASK = 0x' .. hex(cartesi.HTIF_DEV_MASK) .. ';\n')
out:write(' uint64 constant HTIF_CMD_MASK = 0x' .. hex(cartesi.HTIF_CMD_MASK) .. ';\n')
out:write(' uint64 constant HTIF_REASON_MASK = 0x' .. hex(cartesi.HTIF_REASON_MASK) .. ';\n')
out:write(' uint64 constant HTIF_DEV_YIELD = 0x' .. hex(cartesi.HTIF_DEV_YIELD) .. ';\n')
out:write(' uint64 constant HTIF_YIELD_CMD_MANUAL = 0x' .. hex(cartesi.HTIF_YIELD_CMD_MANUAL) .. ';\n')
out:write(' uint16 constant HTIF_YIELD_MANUAL_REASON_RX_ACCEPTED = 0x' ..
hex(cartesi.HTIF_YIELD_MANUAL_REASON_RX_ACCEPTED) .. ';\n')
out:write(' uint16 constant HTIF_YIELD_MANUAL_REASON_RX_REJECTED = 0x' ..
hex(cartesi.HTIF_YIELD_MANUAL_REASON_RX_REJECTED) .. ';\n')
out:write(' uint16 constant HTIF_YIELD_MANUAL_REASON_TX_EXCEPTION = 0x' ..
hex(cartesi.HTIF_YIELD_MANUAL_REASON_TX_EXCEPTION) .. ';\n')
out:write(' uint8 constant UARCH_STATE_LOG2_SIZE = ' .. cartesi.UARCH_STATE_LOG2_SIZE .. ';\n')
out:write(' uint64 constant AR_CMIO_RX_BUFFER_START = 0x' .. hex(cartesi.AR_CMIO_RX_BUFFER_START) .. ';\n')
out:write(' uint8 constant AR_CMIO_RX_BUFFER_LOG2_SIZE = 0x' .. hex(cartesi.AR_CMIO_RX_BUFFER_LOG2_SIZE) .. ';\n')
Expand Down
4 changes: 2 additions & 2 deletions helper_scripts/generate_SendCmioResponse.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ pattern="namespace cartesi \{(.*)\}"
cpp_src=`echo "${BASH_REMATCH[1]}" \
| $SED "/Explicit instantiatio/d" \
| $SED "/template/d" \
| $SED "/ uint32 length);/d" \
| $SED "/uint32 length);/d" \
| $SED "s/machine_merkle_tree::get_log2_word_size()/TREE_LOG2_WORD_SIZE/g" \
| $SED -E "s/($COMPAT_FNS)/EmulatorCompat.\1/g" \
| $SED "s/writeMemoryWithPadding(a, AR_CMIO_RX_BUFFER_START, data, dataLength, writeLengthLog2Size);/a.writeRegion(Memory.regionFromPhysicalAddress(AR_CMIO_RX_BUFFER_START.toPhysicalAddress(),Memory.alignedSizeFromLog2(uint8(writeLengthLog2Size - HASH_TREE_LOG2_WORD_SIZE))),dataHash);"/g \
| $SED -E "s/($CONSTANTS)([^a-zA-Z])/EmulatorConstants.\1\2/g" \
| $SED "s/void send_cmio_response(STATE_ACCESS a, uint16 reason, bytes data, uint32 dataLength) {/function sendCmioResponse(AccessLogs.Context memory a, uint16 reason, bytes32 dataHash, uint32 dataLength) internal pure {/" \
| $SED "s/void send_cmio_response(STATE_ACCESS a, bytes32 revertRootHash, uint16 reason, bytes data, uint32 dataLength) {/function sendCmioResponse(AccessLogs.Context memory a, bytes32 revertRootHash, uint16 reason, bytes32 dataHash, uint32 dataLength) internal pure {/" \
| $SED "s/const uint64/uint64/g" \
| $SED "s/const uint32/uint32/g" \
| $SED "/^$/N;/^\n$/D"
Expand Down
5 changes: 5 additions & 0 deletions helper_scripts/generate_UArchReset.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ CPP_RESET_PATH=${EMULATOR_DIR}"/src/uarch-reset-state.cpp"
TEMPLATE_FILE="./templates/UArchReset.sol.template"
TARGET_FILE="src/UArchReset.sol"
COMPAT_FILE="src/EmulatorCompat.sol"
CONSTANTS_FILE="src/EmulatorConstants.sol"
KEYWORD_START="START OF AUTO-GENERATED CODE"
KEYWORD_END="END OF AUTO-GENERATED CODE"

# get function names from EmulatorCompat.sol
COMPAT_FNS=`cat $COMPAT_FILE | grep -o "function [^(]*(" | $SED "s/function//g" | $SED "s/(//g"`
COMPAT_FNS=`echo $COMPAT_FNS | $SED -E "s/( |\n)/|/g"`

# get constant names from EmulatorConstants.sol
CONSTANTS=`cat $CONSTANTS_FILE | grep -E -o 'constant\s+[^ ]*' | $SED -E "s/constant//g; s/ //g" | tr '\n' '|' | sed "s/.$//"`

# grab head and tail of the template
start=`cat "$TEMPLATE_FILE" | grep "$KEYWORD_START" -n | grep -Eo "[0-9]*"`
end=`cat "$TEMPLATE_FILE" | grep "$KEYWORD_END" -n | grep -Eo "[0-9]*"`
Expand All @@ -34,6 +38,7 @@ cpp_src=`echo "${BASH_REMATCH[1]}" \
| $SED "/Explicit instantiatio/d" \
| $SED "/template/d" \
| $SED -E "s/($COMPAT_FNS)/EmulatorCompat.\1/g" \
| $SED -E "s/($CONSTANTS)([^a-zA-Z])/EmulatorConstants.\1\2/g" \
| $SED "s/void uarch_reset_state(UarchState &a) {/function reset(AccessLogs.Context memory a) internal pure {/"`

# compose the solidity file from all components
Expand Down
4 changes: 2 additions & 2 deletions shasum-download
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
fef8844a306d83eef9c30828986645f2b0ff149654490b0f7d47ec2883bcb693 downloads/machine-emulator-tests-data.deb
bc7a0cc14724167c2826967eaf62feb6a2c902b2b45a73f3c684e1c5ceaa8f69 downloads/uarch-riscv-tests-json-logs.tar.gz
fd4c5d56f5515626762602991d7e8de09f85958ac2ece813e6b9bea148dea016 downloads/machine-emulator-tests-data.deb
96843bf71e5a8cd1628ef6eb43c793f046ed643fef3aebbed545d69e4dcf606e downloads/uarch-riscv-tests-json-logs.tar.gz
76 changes: 0 additions & 76 deletions src/AdvanceStatus.sol

This file was deleted.

40 changes: 38 additions & 2 deletions src/EmulatorCompat.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ library EmulatorCompat {
using Buffer for Buffer.Context;
using Memory for uint64;

function getRevertRootHash(AccessLogs.Context memory a)
function revertState(AccessLogs.Context memory a) internal pure {
a.currentRootHash = readRevertRootHash(a);
}

function readRevertRootHash(AccessLogs.Context memory a)
internal
pure
returns (bytes32)
Expand Down Expand Up @@ -107,7 +111,7 @@ library EmulatorCompat {
);
}

function setRevertRootHash(
function writeRevertRootHash(
AccessLogs.Context memory a,
bytes32 revertRootHash
) internal pure {
Expand Down Expand Up @@ -183,6 +187,16 @@ library EmulatorCompat {
);
}

function readHtifTohost(AccessLogs.Context memory a)
internal
pure
returns (uint64)
{
return a.readWord(
EmulatorConstants.HTIF_TOHOST_ADDRESS.toPhysicalAddress()
);
}

// Conversions and arithmetic functions

function int8ToUint64(int8 val) internal pure returns (uint64) {
Expand Down Expand Up @@ -376,4 +390,26 @@ library EmulatorCompat {

return n;
}

function isYieldedManualWith(uint64 tohost, uint64 yieldReason)
internal
pure
returns (bool)
{
uint64 dev = uint64ShiftRight(
tohost & EmulatorConstants.HTIF_DEV_MASK,
EmulatorConstants.HTIF_DEV_SHIFT
);
uint64 cmd = uint64ShiftRight(
tohost & EmulatorConstants.HTIF_CMD_MASK,
EmulatorConstants.HTIF_CMD_SHIFT
);
uint64 reason = uint64ShiftRight(
tohost & EmulatorConstants.HTIF_REASON_MASK,
EmulatorConstants.HTIF_REASON_SHIFT
);
return dev == EmulatorConstants.HTIF_DEV_YIELD
&& cmd == EmulatorConstants.HTIF_YIELD_CMD_MANUAL
&& reason == yieldReason;
}
}
18 changes: 13 additions & 5 deletions src/EmulatorConstants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ library EmulatorConstants {
// START OF AUTO-GENERATED CODE

bytes32 constant UARCH_PRISTINE_STATE_HASH =
0xa2f4f0018081d795e47c7feae9300055e8551eda5bd6473e54ca80ece64ea620;
0x245a715ed3343e88ea5b2810584faea872991cca0200979e8f43056cd2db59c6;
uint64 constant UARCH_CYCLE_ADDRESS = 0x400008;
uint64 constant UARCH_CYCLE_MAX = 0x100000;
uint64 constant UARCH_HALT_FLAG_ADDRESS = 0x400000;
Expand All @@ -46,12 +46,20 @@ library EmulatorConstants {
uint64 constant IFLAGS_Y_ADDRESS = 0x300;
uint64 constant HTIF_FROMHOST_ADDRESS = 0x330;
uint64 constant HTIF_TOHOST_ADDRESS = 0x328;
uint8 constant CMIO_YIELD_REASON_ADVANCE_STATE = 0x0;
uint8 constant HTIF_YIELD_REASON_ADVANCE_STATE = 0x0;
uint32 constant HASH_TREE_LOG2_WORD_SIZE = 0x5;
uint32 constant HASH_TREE_WORD_SIZE = uint32(1) << HASH_TREE_LOG2_WORD_SIZE;
uint16 constant CMIO_YIELD_MANUAL_REASON_RX_ACCEPTED = 0x1;
uint16 constant CMIO_YIELD_MANUAL_REASON_RX_REJECTED = 0x2;
uint16 constant CMIO_YIELD_MANUAL_REASON_TX_EXCEPTION = 0x4;
uint32 constant HTIF_DEV_SHIFT = 0x38;
uint32 constant HTIF_CMD_SHIFT = 0x30;
uint32 constant HTIF_REASON_SHIFT = 0x20;
uint64 constant HTIF_DEV_MASK = 0xff00000000000000;
uint64 constant HTIF_CMD_MASK = 0xff000000000000;
uint64 constant HTIF_REASON_MASK = 0xffff00000000;
uint64 constant HTIF_DEV_YIELD = 0x2;
uint64 constant HTIF_YIELD_CMD_MANUAL = 0x1;
uint16 constant HTIF_YIELD_MANUAL_REASON_RX_ACCEPTED = 0x1;
uint16 constant HTIF_YIELD_MANUAL_REASON_RX_REJECTED = 0x2;
uint16 constant HTIF_YIELD_MANUAL_REASON_TX_EXCEPTION = 0x4;
uint8 constant UARCH_STATE_LOG2_SIZE = 22;
uint64 constant AR_CMIO_RX_BUFFER_START = 0x60000000;
uint8 constant AR_CMIO_RX_BUFFER_LOG2_SIZE = 0x15;
Expand Down
30 changes: 25 additions & 5 deletions src/SendCmioResponse.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,34 @@ library SendCmioResponse {

function sendCmioResponse(
AccessLogs.Context memory a,
bytes32 revertRootHash,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point, in every valid call, revertRootHash == a.currentRootHash. Should we drop the revertRootHash argument and have sendCmioResponse source a.currentRootHash internally?

We'd likely need to change the send_cmio_response from C++ to match, not sure whether it's feasible. From Dave's side, either API works.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember that send_cmio_response was supposed to work with other generic IO requests. I am not sure what the deal there would be. So it makes sense to leave the argument there, I think.

uint16 reason,
bytes32 dataHash,
uint32 dataLength
) internal pure {
// This function cannot fail. When a failure is detected, the operation is a no-op instead,
// so the honest party can always log and prove the resulting state transition.
// A response to a machine that is not waiting on a manual yield is a no-op.
if (!EmulatorCompat.readIflagsY(a)) {
EmulatorCompat.throwRuntimeError(a, "iflags.Y is not set");
return;
}
if (reason == EmulatorConstants.HTIF_YIELD_REASON_ADVANCE_STATE) {
// Advance-state responses are the input boundary of the rollups flow. They only apply to a
// machine waiting for an input on an rx-accepted manual yield. Sending one to a machine that
// yielded manual with any other reason (e.g., rejected an input or threw an exception) is a no-op.
uint64 tohost = EmulatorCompat.readHtifTohost(a);
if (!EmulatorCompat.isYieldedManualWith(
tohost,
EmulatorConstants.HTIF_YIELD_MANUAL_REASON_RX_ACCEPTED
)) {
return;
}
}
// A zero length data is a valid response. We just skip writing to the rx buffer.
uint32 writeLengthLog2Size = 0;
if (dataLength > 0) {
// Find the write length: the smallest power of 2 that is >= dataLength and >= tree leaf size
uint32 writeLengthLog2Size = EmulatorCompat.uint32Log2(dataLength);
writeLengthLog2Size = EmulatorCompat.uint32Log2(dataLength);
if (
writeLengthLog2Size < EmulatorConstants.HASH_TREE_LOG2_WORD_SIZE
) {
Expand All @@ -53,14 +70,17 @@ library SendCmioResponse {
) {
writeLengthLog2Size += 1;
}
// A response with data that does not fit in the rx buffer is a no-op
if (
writeLengthLog2Size
> EmulatorConstants.AR_CMIO_RX_BUFFER_LOG2_SIZE
) {
EmulatorCompat.throwRuntimeError(
a, "CMIO response data is too large"
);
return;
}
}
// Record the machine root hash to revert to in case the response is eventually rejected
EmulatorCompat.writeRevertRootHash(a, revertRootHash);
if (dataLength > 0) {
a.writeRegion(
Memory.regionFromPhysicalAddress(
EmulatorConstants.AR_CMIO_RX_BUFFER_START
Expand Down
15 changes: 15 additions & 0 deletions src/UArchReset.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@ library UArchReset {

function reset(AccessLogs.Context memory a) internal pure {
EmulatorCompat.resetState(a);
// When the machine has rejected an input, the canonical state after the operation is
// the one recorded in the revert root hash (which has a pristine uarch)
uint64 iflagsY =
EmulatorCompat.readWord(a, EmulatorConstants.IFLAGS_Y_ADDRESS);
if (iflagsY != 0) {
uint64 tohost = EmulatorCompat.readWord(
a, EmulatorConstants.HTIF_TOHOST_ADDRESS
);
if (EmulatorCompat.isYieldedManualWith(
tohost,
EmulatorConstants.HTIF_YIELD_MANUAL_REASON_RX_REJECTED
)) {
EmulatorCompat.revertState(a);
}
}
}

// END OF AUTO-GENERATED CODE
Expand Down
2 changes: 1 addition & 1 deletion templates/UArchReplay.t.sol.template
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,6 @@ contract UArchReplay_@X@_Test is AccessLogJsonParse {
);
RawAccess[] memory rawAccesses = abi.decode(raw, (RawAccess[]));
Buffer.Context memory buffer = Buffer.Context(data, 0);
_fillBufferFromRawAccesses(rawAccesses, buffer, siblingsLength);
_fillBufferFromRawAccesses(rawAccesses, buffer);
}
}
12 changes: 9 additions & 3 deletions test/AccessLogJsonParse.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,24 @@ abstract contract AccessLogJsonParse is Test {

function _fillBufferFromRawAccesses(
RawAccess[] memory rawAccesses,
Buffer.Context memory buffer,
uint256 fixedSiblingsLength
Buffer.Context memory buffer
) internal pure {
uint256 n = rawAccesses.length;
for (uint256 i = 0; i < n; i++) {
RawAccess memory a = rawAccesses[i];
if (a.log2_size == 3) {
buffer.writeBytes32(_parseHex32FromLogString(a.read_value));
} else if (
keccak256(bytes(a.accessType)) == keccak256(bytes("read"))
) {
// a leaf read carries the read value followed by the leaf hash
buffer.writeBytes32(_parseHex32FromLogString(a.read_value));
buffer.writeBytes32(_parseHex32FromLogString(a.read_hash));
} else {
buffer.writeBytes32(_parseHex32FromLogString(a.read_hash));
}
for (uint256 j = 0; j < fixedSiblingsLength; j++) {
uint256 siblingCount = a.sibling_hashes.length;
for (uint256 j = 0; j < siblingCount; j++) {
buffer.writeBytes32(
_parseHex32FromLogString(a.sibling_hashes[j])
);
Expand Down
Loading
Loading