1+ #[ cfg( feature = "u16limb_circuit" ) ]
2+ use crate :: instructions:: riscv:: memory:: LoadStoreWordInstruction ;
13use crate :: {
24 Value ,
35 circuit_builder:: { CircuitBuilder , ConstraintSystem } ,
@@ -7,16 +9,15 @@ use crate::{
79 riscv:: {
810 LbInstruction , LbuInstruction , LhInstruction , LhuInstruction , RIVInstruction ,
911 constants:: UInt ,
10- memory:: {
11- LbOp , LbuOp , LhOp , LhuOp , LwInstruction , LwOp , SBOp , SHOp , SWOp , SbInstruction ,
12- ShInstruction , SwInstruction ,
13- } ,
12+ memory:: { LbOp , LbuOp , LhOp , LhuOp , SBOp , SHOp , SbInstruction , ShInstruction } ,
1413 } ,
1514 } ,
1615 scheme:: mock_prover:: { MOCK_PC_START , MockProver } ,
1716 structs:: ProgramParams ,
1817} ;
19- use ceno_emul:: { ByteAddr , Change , InsnKind , ReadOp , StepRecord , Word , WriteOp , encode_rv32} ;
18+ use ceno_emul:: {
19+ ByteAddr , Change , InsnKind , InsnKind :: SW , ReadOp , StepRecord , Word , WriteOp , encode_rv32,
20+ } ;
2021#[ cfg( feature = "u16limb_circuit" ) ]
2122use ff_ext:: BabyBearExt4 ;
2223use ff_ext:: { ExtensionField , GoldilocksExt2 } ;
@@ -139,6 +140,100 @@ fn impl_opcode_store<E: ExtensionField + Hash, I: RIVInstruction, Inst: Instruct
139140 MockProver :: assert_satisfied_raw ( & cb, raw_witin, & [ insn_code] , None , Some ( lkm) ) ;
140141}
141142
143+ #[ cfg( feature = "u16limb_circuit" ) ]
144+ fn impl_opcode_store_word_dynamic < E : ExtensionField + Hash , Inst : Instruction < E > > (
145+ imm : i32 ,
146+ is_load : bool ,
147+ ) {
148+ let mut cs = ConstraintSystem :: < E > :: new ( || "riscv" ) ;
149+ let mut cb = CircuitBuilder :: new ( & mut cs) ;
150+ let config = cb
151+ . namespace (
152+ || Inst :: name ( ) ,
153+ |cb| {
154+ let config = Inst :: construct_circuit ( cb, & ProgramParams :: default ( ) ) ;
155+ Ok ( config)
156+ } ,
157+ )
158+ . unwrap ( )
159+ . unwrap ( ) ;
160+
161+ let insn_kind = if is_load { InsnKind :: LW } else { SW } ;
162+ let insn_code = encode_rv32 ( insn_kind, 2 , 3 , 0 , imm) ;
163+ let rs1_word = Word :: from ( 0x4000000_u32 ) ;
164+ let unaligned_addr = ByteAddr :: from ( rs1_word. wrapping_add_signed ( imm) ) ;
165+
166+ if is_load {
167+ let mem_value = 0x40302010 ;
168+ let prev_rd_word = Word :: from ( 0x12345678_u32 ) ;
169+ let new_rd_word = load ( mem_value, InsnKind :: LW , unaligned_addr. shift ( ) ) ;
170+ let rd_change = Change {
171+ before : prev_rd_word,
172+ after : new_rd_word,
173+ } ;
174+ let ( raw_witin, lkm) = Inst :: assign_instances (
175+ & config,
176+ & mut ShardContext :: default ( ) ,
177+ cb. cs . num_witin as usize ,
178+ cb. cs . num_structural_witin as usize ,
179+ & [ StepRecord :: new_im_instruction (
180+ 12 ,
181+ MOCK_PC_START ,
182+ insn_code,
183+ rs1_word,
184+ rd_change,
185+ ReadOp {
186+ addr : unaligned_addr. waddr ( ) ,
187+ value : mem_value,
188+ previous_cycle : 4 ,
189+ } ,
190+ 8 ,
191+ ) ] ,
192+ )
193+ . unwrap ( ) ;
194+ MockProver :: assert_satisfied_raw ( & cb, raw_witin, & [ insn_code] , None , Some ( lkm) ) ;
195+ } else {
196+ let prev_mem_value = 0x40302010 ;
197+ let rs2_word = Word :: from ( 0x12345678_u32 ) ;
198+ let new_mem_value = sw ( prev_mem_value, rs2_word) ;
199+ let ( raw_witin, lkm) = Inst :: assign_instances (
200+ & config,
201+ & mut ShardContext :: default ( ) ,
202+ cb. cs . num_witin as usize ,
203+ cb. cs . num_structural_witin as usize ,
204+ & [ StepRecord :: new_s_instruction (
205+ 12 ,
206+ MOCK_PC_START ,
207+ insn_code,
208+ rs1_word,
209+ rs2_word,
210+ WriteOp {
211+ addr : unaligned_addr. waddr ( ) ,
212+ value : Change {
213+ before : prev_mem_value,
214+ after : new_mem_value,
215+ } ,
216+ previous_cycle : 4 ,
217+ } ,
218+ 8 ,
219+ ) ] ,
220+ )
221+ . unwrap ( ) ;
222+
223+ let expected_mem_written =
224+ UInt :: from_const_unchecked ( Value :: new_unchecked ( new_mem_value) . as_u16_limbs ( ) . to_vec ( ) ) ;
225+ let mem_written_expr = cb. get_debug_expr ( DebugIndex :: MemWrite as usize ) [ 0 ] . clone ( ) ;
226+ cb. require_equal (
227+ || "assert_mem_written" ,
228+ mem_written_expr,
229+ expected_mem_written. value ( ) ,
230+ )
231+ . unwrap ( ) ;
232+
233+ MockProver :: assert_satisfied_raw ( & cb, raw_witin, & [ insn_code] , None , Some ( lkm) ) ;
234+ }
235+ }
236+
142237fn impl_opcode_load < E : ExtensionField + Hash , I : RIVInstruction , Inst : Instruction < E > > ( imm : i32 ) {
143238 let mut cs = ConstraintSystem :: < E > :: new ( || "riscv" ) ;
144239 let mut cb = CircuitBuilder :: new ( & mut cs) ;
@@ -196,11 +291,40 @@ fn impl_opcode_sh(imm: i32) {
196291 impl_opcode_store :: < GoldilocksExt2 , SHOp , ShInstruction < GoldilocksExt2 > > ( imm)
197292}
198293
294+ #[ cfg( not( feature = "u16limb_circuit" ) ) ]
199295fn impl_opcode_sw ( imm : i32 ) {
200296 assert_eq ! ( imm & 0x03 , 0 ) ;
201297 impl_opcode_store :: < GoldilocksExt2 , SWOp , SwInstruction < GoldilocksExt2 > > ( imm)
202298}
203299
300+ #[ cfg( feature = "u16limb_circuit" ) ]
301+ fn impl_opcode_sw ( imm : i32 ) {
302+ assert_eq ! ( imm & 0x03 , 0 ) ;
303+ impl_opcode_store_word_dynamic :: < GoldilocksExt2 , LoadStoreWordInstruction < GoldilocksExt2 > > (
304+ imm, false ,
305+ ) ;
306+ }
307+
308+ #[ cfg( feature = "u16limb_circuit" ) ]
309+ fn impl_opcode_sw_u16 ( imm : i32 ) {
310+ impl_opcode_store_word_dynamic :: < BabyBearExt4 , LoadStoreWordInstruction < BabyBearExt4 > > (
311+ imm, false ,
312+ ) ;
313+ }
314+
315+ fn impl_opcode_lw ( imm : i32 ) {
316+ assert_eq ! ( imm & 0x03 , 0 ) ;
317+ impl_opcode_store_word_dynamic :: < GoldilocksExt2 , LoadStoreWordInstruction < GoldilocksExt2 > > (
318+ imm, true ,
319+ ) ;
320+ }
321+
322+ fn impl_opcode_lw_u16 ( imm : i32 ) {
323+ impl_opcode_store_word_dynamic :: < BabyBearExt4 , LoadStoreWordInstruction < BabyBearExt4 > > (
324+ imm, true ,
325+ ) ;
326+ }
327+
204328#[ test]
205329fn test_sb ( ) {
206330 let cases = vec ! [ ( 0 , ) , ( 5 , ) , ( 10 , ) , ( 15 , ) , ( -4 , ) , ( -3 , ) , ( -2 , ) , ( -1 , ) ] ;
@@ -230,7 +354,7 @@ fn test_sw() {
230354 for & ( imm, ) in & cases {
231355 impl_opcode_sw ( imm) ;
232356 #[ cfg( feature = "u16limb_circuit" ) ]
233- impl_opcode_sw ( imm) ;
357+ impl_opcode_sw_u16 ( imm) ;
234358 }
235359}
236360
@@ -319,8 +443,9 @@ fn test_lw() {
319443 let cases = vec ! [ ( 0 , ) , ( 4 , ) , ( -4 , ) ] ;
320444
321445 for & ( imm, ) in & cases {
322- impl_opcode_load :: < GoldilocksExt2 , LwOp , LwInstruction < GoldilocksExt2 > > ( imm) ;
323- #[ cfg( feature = "u16limb_circuit" ) ]
324- impl_opcode_load :: < BabyBearExt4 , LwOp , LwInstruction < BabyBearExt4 > > ( imm) ;
446+ {
447+ impl_opcode_lw ( imm) ;
448+ impl_opcode_lw_u16 ( imm) ;
449+ }
325450 }
326451}
0 commit comments