@@ -3,8 +3,12 @@ pragma solidity 0.8.15;
33import  {Test} from  "forge-std/Test.sol " ;
44import  {RISCV} from  "src/RISCV.sol " ;
55import  {PreimageOracle} from  "@optimism/src/cannon/PreimageOracle.sol " ;
6+ import  {CommonTest} from  "./CommonTest.sol " ;
7+ // FIXME: somehow this import gives a multiple declaration error 
8+ // This import is for the VMStatus 
9+ // import "@optimism/src/libraries/DisputeTypes.sol"; 
610
7- contract  RISCV_Test  is  Test  {
11+ contract  RISCV_Test  is  CommonTest  {
812    /// @notice Stores the VM state. 
913    ///         Total state size: 32 + 32 + 8 * 2 + 1 * 2 + 8 * 3 + 32 * 8 = 362 bytes 
1014    ///         Note that struct is not used for step execution and used only for testing 
@@ -25,7 +29,8 @@ contract RISCV_Test is Test {
2529    RISCV internal  riscv;
2630    PreimageOracle internal  oracle;
2731
28-     function setUp  () public  {
32+     function setUp  () public  virtual  override  {
33+         super .setUp ();
2934        oracle =  new  PreimageOracle (0 , 0 , 0 );
3035        riscv =  new  RISCV (oracle);
3136        vm.store (address (riscv), 0x0 , bytes32 (abi.encode (address (oracle))));
@@ -55,6 +60,25 @@ contract RISCV_Test is Test {
5560        assertTrue (postState !=  bytes32 (0 ));
5661    }
5762
63+     function test_add_succeeds  () public  {
64+         uint32  insn =  encodeRType (0x33 , 1 , 0 , 2 , 3 , 0 ); // add x1, x2, x3 
65+         (State memory  state , bytes  memory  proof ) =  constructRISCVState (0 , insn);
66+         state.registers[2 ] =  0x3030 ;
67+         state.registers[3 ] =  0x3131 ;
68+         bytes  memory  encodedState =  encodeState (state);
69+ 
70+         State memory  expect;
71+         expect.memRoot =  state.memRoot;
72+         expect.pc =  state.pc +  4 ;
73+         expect.step =  state.step +  1 ;
74+         expect.registers[1 ] =  state.registers[2 ] +  state.registers[3 ];
75+         expect.registers[2 ] =  state.registers[2 ];
76+         expect.registers[3 ] =  state.registers[3 ];
77+ 
78+         bytes32  postState =  riscv.step (encodedState, proof, 0 );
79+         assertEq (postState, outputState (expect), "unexpected post state " );
80+     }
81+ 
5882    function encodeState  (State memory  state ) internal  pure  returns  (bytes  memory ) {
5983        bytes  memory  registers;
6084        for  (uint256  i =  0 ; i <  state.registers.length ; i++ ) {
@@ -74,4 +98,59 @@ contract RISCV_Test is Test {
7498        );
7599        return  stateData;
76100    }
101+ 
102+     /// @dev RISCV VM status codes: 
103+     ///      0. Exited with success (Valid) 
104+     ///      1. Exited with success (Invalid) 
105+     ///      2. Exited with failure (Panic) 
106+     ///      3. Unfinished 
107+     // TODO: import DisputeTypes.sol. For some reason, import is not working 
108+     function vmStatus  (State memory  state ) internal  pure  returns  (uint8  out_ ) {
109+         if  (! state.exited) {
110+             return  3 ; // VMStatuses.UNFINISHED 
111+         } else  if  (state.exitCode ==  0 ) {
112+             return  0 ; // VMStatuses.VALID 
113+         } else  if  (state.exitCode ==  1 ) {
114+             return  1 ; // VMStatuses.INVALID 
115+         } else  {
116+             return  2 ; // VMStatuses.PANIC 
117+         }
118+     }
119+ 
120+     function outputState  (State memory  state ) internal  pure  returns  (bytes32  out_ ) {
121+         bytes  memory  enc =  encodeState (state);
122+         uint8  status =  vmStatus (state);
123+         assembly  {
124+             out_ :=  keccak256 (add (enc, 0x20 ), 362 )
125+             out_ :=  or (and (not (shl (248 , 0xFF )), out_), shl (248 , status))
126+         }
127+     }
128+ 
129+     function constructRISCVState  (uint64  pc , uint32  insn , uint64  addr , bytes32  val )
130+         internal 
131+         returns  (State memory  state , bytes  memory  proof )
132+     {
133+         (state.memRoot, proof) =  ffi.getAsteriscMemoryProof (pc, insn, addr, val);
134+         state.pc =  pc;
135+     }
136+ 
137+     function constructRISCVState  (uint64  pc , uint32  insn ) internal  returns  (State memory  state , bytes  memory  proof ) {
138+         (state.memRoot, proof) =  ffi.getAsteriscMemoryProof (pc, insn);
139+         state.pc =  pc;
140+     }
141+ 
142+     function encodeRType  (uint8  opcode , uint8  rd , uint8  funct3 , uint8  rs1 , uint8  rs2 , uint8  funct7 )
143+         internal 
144+         pure 
145+         returns  (uint32  insn )
146+     {
147+         // insn := [funct7] | [rs2] | [rs1] | [funct3] | [rd]  | [opcode] 
148+         // example: 0000000 | 00011 | 00010 | 000      | 00001 | 0110011 
149+         insn =  uint32 (funct7 &  0x7F ) <<  (7  +  5  +  3  +  5  +  5 );
150+         insn |=  uint32 (rs2 &  0x1F ) <<  (7  +  5  +  3  +  5 );
151+         insn |=  uint32 (rs1 &  0x1F ) <<  (7  +  5  +  3 );
152+         insn |=  uint32 (funct3 &  0x7 ) <<  (7  +  5 );
153+         insn |=  uint32 (rd &  0x1F ) <<  7 ;
154+         insn |=  uint32 (opcode &  0x7F );
155+     }
77156}
0 commit comments