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

Initial Basic blocks support #238

Merged
merged 2 commits into from
Dec 6, 2024
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
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@reduxjs/toolkit": "^2.2.8",
"@tanstack/react-virtual": "^3.10.9",
"@typeberry/block": "^0.0.1-1a02906",
"@typeberry/pvm-debugger-adapter": "0.0.1-3038a52",
"@typeberry/pvm-debugger-adapter": "0.0.1-4978606",
"@typeberry/spectool-wasm": "^0.13.0",
"@uiw/react-codemirror": "^4.23.6",
"class-variance-authority": "^0.7.0",
Expand Down
61 changes: 39 additions & 22 deletions src/components/Instructions/InstructionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,6 @@ const getWorkerValueFromState = (
? (worker[state][propName] as RegistersArray)[propNameIndex]
: (worker[state][propName] as number);

function getBackgroundColor(status: Status | undefined, isHighlighted: boolean) {
if (status === Status.OK && isHighlighted) {
return getStatusColor();
}

return getStatusColor(status);
}

const AddressCell = ({
breakpointAddresses,
programRow,
Expand Down Expand Up @@ -83,32 +75,25 @@ export const InstructionItem = forwardRef(
const { numeralSystem } = useContext(NumeralSystemContext);

const workers = useAppSelector(selectWorkers);
const pcInAllWorkers = (state: "currentState" | "previousState") =>
workers.map((worker) => getWorkerValueFromState(worker, state, "pc"));
const workersWithCurrentPc = workers.filter((worker) => worker.currentState.pc === programRow.address);

const isActive = (programRow: ProgramRow) => {
return pcInAllWorkers("currentState").includes(programRow.address);
};

const fillSearch = useCallback(() => {
onClick(programRow);
}, [programRow, onClick]);

const isHighlighted = isActive(programRow);
const bgColor = getBackgroundColor(status, isHighlighted).toUpperCase();

const bgOpacity =
pcInAllWorkers("currentState").filter((pc) => pc === programRow.address).length /
pcInAllWorkers("currentState").length;
const { backgroundColor, hasTooltip } = getHighlightStatus(workers, programRow, status);

const renderContent = () => {
return (
<TableRow
ref={ref}
className={classNames("hover:bg-gray-300", { "opacity-50": isLast })}
test-id="instruction-item"
style={{ backgroundColor: isHighlighted ? `rgba(${hexToRgb(bgColor)}, ${bgOpacity})` : "initial" }}
style={{
backgroundColor,
borderTop: programRow.block.isStart ? "2px solid #bbb" : undefined,
}}
title={programRow.block.name}
>
{instructionMode === InstructionMode.BYTECODE && (
<>
Expand Down Expand Up @@ -152,7 +137,7 @@ export const InstructionItem = forwardRef(
);
};

return bgOpacity > 0 && bgOpacity < 1 ? (
return hasTooltip ? (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>{renderContent()}</TooltipTrigger>
Expand All @@ -175,3 +160,35 @@ export const InstructionItem = forwardRef(
);
},
);

function getHighlightStatus(workers: WorkerState[], programRow: ProgramRow, status?: Status) {
const pcInAllWorkers = (state: "currentState" | "previousState") =>
workers.map((worker) => getWorkerValueFromState(worker, state, "pc"));

const isActive = (programRow: ProgramRow) => {
return pcInAllWorkers("currentState").includes(programRow.address);
};

const isHighlighted = isActive(programRow);
const bgColor = getBackgroundForStatus(status, isHighlighted).toUpperCase();

const bgOpacity =
pcInAllWorkers("currentState").filter((pc) => pc === programRow.address).length /
pcInAllWorkers("currentState").length;

const blockBackground = programRow.block.number % 2 === 0 ? "#fff" : "#efefef";
const backgroundColor = isHighlighted ? `rgba(${hexToRgb(bgColor)}, ${bgOpacity})` : blockBackground;

return {
backgroundColor,
hasTooltip: bgOpacity > 0 && bgOpacity < 1,
};
}

function getBackgroundForStatus(status: Status | undefined, isHighlighted: boolean) {
if (status === Status.OK && isHighlighted) {
return getStatusColor();
}

return getStatusColor(status);
}
217 changes: 0 additions & 217 deletions src/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,222 +1,5 @@
declare module "react-json-view-compare";

declare module "@typeberry/pvm-debugger-adapter" {
export class Mask {
isInstruction(index: number): boolean;
}

export class ProgramDecoder {
constructor(rawProgram: Uint8Array);
getCode(): Uint8Array;
getMask(): Mask;
}

export enum ArgumentType {
NO_ARGUMENTS = 0,
ONE_IMMEDIATE = 1,
TWO_IMMEDIATES = 2,
ONE_OFFSET = 3,
ONE_REGISTER_ONE_IMMEDIATE = 4,
ONE_REGISTER_TWO_IMMEDIATES = 5,
ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET = 6,
TWO_REGISTERS = 7,
TWO_REGISTERS_ONE_IMMEDIATE = 8,
TWO_REGISTERS_ONE_OFFSET = 9,
TWO_REGISTERS_TWO_IMMEDIATES = 10,
THREE_REGISTERS = 11,
}

type ImmediateDecoder = {
getUnsigned();
getSigned();
};

export type EmptyArgs = {
type: ArgumentType.NO_ARGUMENTS;
noOfBytesToSkip: number;
};

export type OneImmediateArgs = {
type: ArgumentType.ONE_IMMEDIATE;
noOfBytesToSkip: number;
immediateDecoder: ImmediateDecoder;
};

export type ThreeRegistersArgs = {
type: ArgumentType.THREE_REGISTERS;
noOfBytesToSkip: number;
firstRegisterIndex: number;
secondRegisterIndex: number;
thirdRegisterIndex: number;
};

export type TwoRegistersArgs = {
type: ArgumentType.TWO_REGISTERS;
noOfBytesToSkip: number;
firstRegisterIndex: number;
secondRegisterIndex: number;
};

export type TwoRegistersOneImmediateArgs = {
type: ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
noOfBytesToSkip: number;
firstRegisterIndex: number;
secondRegisterIndex: number;
immediateDecoder: ImmediateDecoder;
};

export type OneRegisterOneImmediateArgs = {
type: ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
noOfBytesToSkip: number;
registerIndex: number;
immediateDecoder: ImmediateDecoder;
};

export type TwoRegistersTwoImmediatesArgs = {
type: ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES;
noOfBytesToSkip: number;
firstRegisterIndex: number;
secondRegisterIndex: number;
firstImmediateDecoder: ImmediateDecoder;
secondImmediateDecoder: ImmediateDecoder;
};

export type TwoImmediatesArgs = {
type: ArgumentType.TWO_IMMEDIATES;
noOfBytesToSkip: number;
firstImmediateDecoder: ImmediateDecoder;
secondImmediateDecoder: ImmediateDecoder;
};

export type TwoRegistersOneOffsetArgs = {
type: ArgumentType.TWO_REGISTERS_ONE_OFFSET;
noOfBytesToSkip: number;
firstRegisterIndex: number;
secondRegisterIndex: number;
nextPc: number;
};

export type OneRegisterOneImmediateOneOffsetArgs = {
type: ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
noOfBytesToSkip: number;
registerIndex: number;
immediateDecoder: ImmediateDecoder;
nextPc: number;
};

export type OneRegisterTwoImmediatesArgs = {
type: ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
noOfBytesToSkip: number;
registerIndex: number;
firstImmediateDecoder: ImmediateDecoder;
secondImmediateDecoder: ImmediateDecoder;
};

export type OneOffsetArgs = {
type: ArgumentType.ONE_OFFSET;
noOfBytesToSkip: number;
nextPc: number;
};

export type Args =
| EmptyArgs
| OneImmediateArgs
| TwoRegistersArgs
| ThreeRegistersArgs
| TwoRegistersOneImmediateArgs
| TwoRegistersTwoImmediatesArgs
| OneRegisterOneImmediateOneOffsetArgs
| TwoRegistersOneOffsetArgs
| OneRegisterOneImmediateArgs
| OneOffsetArgs
| TwoImmediatesArgs
| OneRegisterTwoImmediatesArgs;

export class ArgsDecoder {
reset(code: Uint8Array, mask: Mask);
fillArgs<T extends Args>(pc: number, result: T): void;
}

export class Registers {
reset(): void;
copyFrom(regs: Registers | Uint32Array): void;
}

type Results = [
EmptyArgs,
OneImmediateArgs,
TwoImmediatesArgs,
OneOffsetArgs,
OneRegisterOneImmediateArgs,
OneRegisterTwoImmediatesArgs,
OneRegisterOneImmediateOneOffsetArgs,
TwoRegistersArgs,
TwoRegistersOneImmediateArgs,
TwoRegistersOneOffsetArgs,
TwoRegistersTwoImmediatesArgs,
ThreeRegistersArgs,
];

export function createResults(): Results;

type InitialState = {
regs?: RegistersArray;
pc?: number;
memory?: Memory;
gas?: number;
};

class Memory {}

enum Status {
OK = 255,
HALT = 0,
PANIC = 1,
FAULT = 2,
HOST = 3,
OUT_OF_GAS = 4,
}

export class Pvm {
reset(program: Uint8Array, pc: number, gas: bigint, registers: Registers, memory: Memory);
nextStep(): Status;
getRegisters(): Uint32Array;
getPC(): number;
getGas(): bigint;
getStatus(): Status;
getMemoryPage(pageNumber: number): null | Uint8Array;
setNextPC(nextPc: number);
setGasLeft(gas: bigint);
}

export class MemoryBuilder {
setWriteable(startPageIndex: number, endPageIndex: number, data: Uint8Array);
setReadable(startPageIndex: number, endPageIndex: number, data: Uint8Array);
setData(address: number, data: Uint8Array);
finalize(heapStartIndex: number, heapEndIndex: number): Memory;
}

export const decodeStandardProgram: (program: Uint8Array, args: Uint8Array) => DecodedProgram;

export type MemorySegment = {
start: number;
end: number;
data?: Uint8Array | null;
};

export type DecodedProgram = {
code: Uint8Array;
memory: {
readable: MemorySegment[];
writeable: MemorySegment[];
sbrkIndex: number;
};
registers: Uint32Array;
};

export const instructionArgumentTypeMap: Array<ArgumentType>;
}

declare module "path-browserify" {
import path from "path";
export default path;
Expand Down
Loading
Loading