Skip to content

Commit

Permalink
Support basic blocks.
Browse files Browse the repository at this point in the history
  • Loading branch information
tomusdrw committed Dec 6, 2024
1 parent 6324ed2 commit 4bcbbce
Show file tree
Hide file tree
Showing 12 changed files with 114 additions and 293 deletions.
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

0 comments on commit 4bcbbce

Please sign in to comment.