pub(crate) fn eval_memory_address_and_access<AB: SP1CoreAirBuilder>(
        &self,
        builder: &mut AB,
        local: &MemoryInstructionsColumns<AB::Var>,
        is_real: AB::Expr,
    ) {
        // Send to the ALU table to verify correct calculation of addr_word.
        builder.send_instruction(
            AB::Expr::zero(),
            AB::Expr::zero(),
            AB::Expr::from_canonical_u32(UNUSED_PC),
            AB::Expr::from_canonical_u32(UNUSED_PC + DEFAULT_PC_INC),
            AB::Expr::zero(),
            AB::Expr::from_canonical_u32(Opcode::ADD as u32),
            local.addr_word,
            local.op_b_value,
            local.op_c_value,
            AB::Expr::zero(),
            AB::Expr::zero(),
            AB::Expr::zero(),
            AB::Expr::zero(),
            AB::Expr::zero(),
            is_real.clone(),
        );

        // Range check the addr_word to be a valid babybear word. Note that this will also
        // implicitly do a byte range check on the most significant byte.
        BabyBearWordRangeChecker::<AB::F>::range_check(
            builder,
            local.addr_word,
            local.addr_word_range_checker,
            is_real.clone(),
        );

        // Check that the 2nd and 3rd addr_word elements are bytes. We already check the most sig
        // byte in the BabyBearWordRangeChecker, and the least sig one in the AND byte lookup below.
        builder.slice_range_check_u8(&local.addr_word.0[1..3], is_real.clone());

        // We check that `addr_word >= 32`, or `addr_word > 31` to avoid registers.
        // Check that if the most significant bytes are zero, then the least significant byte is at
        // least 32.
        builder.send_byte(
            ByteOpcode::LTU.as_field::<AB::F>(),
            AB::Expr::one(),
            AB::Expr::from_canonical_u8(31),
            local.addr_word[0],
            local.most_sig_bytes_zero.result,
        );

        // SAFETY: Check that the above interaction is only sent if one of the opcode flags is set.
        // If `is_real = 0`, then `local.most_sig_bytes_zero.result = 0`, leading to no interaction.
        // Note that when `is_real = 1`, due to `IsZeroOperation`,
        // `local.most_sig_bytes_zero.result` is boolean.
        builder.when(local.most_sig_bytes_zero.result).assert_one(is_real.clone());

        // Check the most_sig_byte_zero flag.  Note that we can simply add up the three most
        // significant bytes and check if the sum is zero.  Those bytes are going to be byte
        // range checked, so the only way the sum is zero is if all bytes are 0.
        IsZeroOperation::<AB::F>::eval(
            builder,
            local.addr_word[1] + local.addr_word[2] + local.addr_word[3],
            local.most_sig_bytes_zero,
            is_real.clone(),
        );

        // Evaluate the addr_offset column and offset flags.
        self.eval_offset_value_flags(builder, local);

        // Assert that reduce(addr_word) == addr_aligned + addr_ls_two_bits.
        builder.when(is_real.clone()).assert_eq::<AB::Expr, AB::Expr>(
            local.addr_aligned + local.addr_ls_two_bits,
            local.addr_word.reduce::<AB>(),
        );

        // Check the correct value of addr_ls_two_bits. Note that this lookup will implicitly do a
        // byte range check on the least sig addr byte.
        builder.send_byte(
            ByteOpcode::AND.as_field::<AB::F>(),
            local.addr_ls_two_bits,
            local.addr_word[0],
            AB::Expr::from_canonical_u8(0b11),
            is_real.clone(),
        );

        // For operations that require reading from memory (not registers), we need to read the
        // value into the memory columns.
        builder.eval_memory_access(
            local.shard,
            local.clk + AB::F::from_canonical_u32(MemoryAccessPosition::Memory as u32),
            local.addr_aligned,
            &local.memory_access,
            is_real.clone(),
        );

        // On memory load instructions, make sure that the memory value is not changed.
        builder
            .when(local.is_lb + local.is_lbu + local.is_lh + local.is_lhu + local.is_lw)
            .assert_word_eq(*local.memory_access.value(), *local.memory_access.prev_value());
    }
Constrains the addr_aligned, addr_offset, and addr_word memory columns.

This method will do the following:
1. Calculate that the unaligned address is correctly computed to be op_b.value + op_c.value.
2. Calculate that the address offset is address % 4.
3. Assert the validity of the aligned address given the address offset and the unaligned
address.
crates/core/machine/src/memory/instructions/air.rs