Let’s play with SDK emulator on Docker. For more details about the SDK Emulator, refer to documentation.

Running SDK emulator in Docker enables developers to prototype, test, and debug SDK functionalities without requiring physical hardware, significantly enhancing productivity.
Currently, we support running emulator via a prebuilt Docker container. A dedicated git repository for emulator will be opened in the future.

  1. Pull Docker Image
    First, download a prebuilt Docker image from Docker Hub.
     # USAGE : docker pull <repository>:<tag>
     docker pull xcenadev/sdk:1.0.0
    

    Note: repository and tag information will be shared as part of the deployment chain.

  2. Start Docker Container
     # USAGE : docker run -dit --name <container_name> --device=/dev/kvm --cap-add=SYS_ADMIN -e USER=$USER <repository>:<tag>
     docker run -dit --name xcena_sdk --device=/dev/kvm --cap-add=SYS_ADMIN -e USER=$USER xcenadev/sdk:1.0.0
    
  3. Verify the Container is Running
    To confirm that the container has started successfully, use the docker ps command:
    docker ps
     # Expected output:
     # CONTAINER ID   IMAGE               COMMAND     CREATED          STATUS          PORTS     NAMES
     # abcdef123456   xcenadev/sdk:1.0.0  "/bin/bash" 2 minutes ago    Up 2 minutes              xcena_sdk
    
  4. Connect to the Running Container
    To connect to the running container and access its shell environment, use the following command:
    # USAGE : docker exec -it <container_name> /bin/bash
    docker exec -it xcena_sdk /bin/bash
    

    Recommendation: It is recommended to connect to the container using two separate shells:

    1. One shell for attaching the CXL Protocol analyzer and monitoring logs.
    2. Another shell for running QEMU and interacting with the emulated environment.
  5. Attach CXL Protocol analyzer (before running QEMU)
    To analyze CXL packet interactions, attach the protocol analyzer. Logs are collected outside of QEMU. Monitor the log file in real time:
     # Move to the emulator directory
     cd emulator
        
     # Create xcena.log file if it doesn't exist
     touch xcena.log
    
     # Monitor the log file in real time
     tail -f xcena.log
    

    Example log entries:

     [QEMU] [ELBI ] Opcode : Cfg_Read   Addr : 0xe10        Size : 4    Data :         0x80000001   DOE.Status
     [QEMU] [ELBI ] Opcode : Cfg_Write  Addr : 0xe18        Size : 4    Data :         0x00000000   DOE.MBox.Rd
     [QEMU] [ELBI ] Opcode : Cfg_Read   Addr : 0xe10        Size : 4    Data :         0x00000000   DOE.Status
     [QEMU] [ELBI ] Opcode : Mem_Read   Addr : 0xfd401204   Size : 4    Data :         0x00000000   CXL HDM.Control
     [QEMU] [ELBI ] Opcode : Mem_Read   Addr : 0xfd401204   Size : 4    Data :         0x00000000   CXL HDM.Control
     [QEMU] [ELBI ] Opcode : Mem_Write  Addr : 0xfd401204   Size : 4    Data :         0x00000002   CXL HDM.Control
     [QEMU] [CDM  ] Opcode : Cfg_Read   Addr : 0x50c        Size : 2    Data :             0x0002   CXL.Control+CXL.Status
     [QEMU] [CDM  ] Opcode : Cfg_Write  Addr : 0x50c        Size : 2    Data :             0x0006   CXL.Control+CXL.Status
     [QEMU] [ELBI ] Opcode : Mem_Read   Addr : 0xfd401220   Size : 4    Data :         0x00002000   CXL HDM.Dec[0].Control
     [QEMU] [CDM  ] Opcode : Cfg_Read   Addr : 0x78         Size : 2    Data :             0x2910   PCIe.DevCtrl+PCIe.DevStat
     [QEMU] [CDM  ] Opcode : Cfg_Write  Addr : 0x78         Size : 2    Data :             0x5910   PCIe.DevCtrl+PCIe.DevStat
     [QEMU] [Bar2 ] Opcode : Mem_Read   Addr : 0xfd200180   Size : 8    Data : 0x0000350ac00a19c1   BAR2
     [QEMU] [Bar2 ] Opcode : Mem_Read   Addr : 0xfd201180   Size : 8    Data : 0x00003504000019c1   BAR2
     [QEMU] [ELBI ] Opcode : Mem_Read   Addr : 0xfd401220   Size : 4    Data :         0x00002000   CXL HDM.Dec[0].Control
     [QEMU] [ELBI ] Opcode : Mem_Read   Addr : 0xfd401210   Size : 4    Data :         0x00000000   CXL HDM.Dec[0].BaseLo
     [QEMU] [ELBI ] Opcode : Mem_Read   Addr : 0xfd401214   Size : 4    Data :         0x00000000   CXL HDM.Dec[0].BaseHi
     [QEMU] [ELBI ] Opcode : Mem_Read   Addr : 0xfd401218   Size : 4    Data :         0x00000000   CXL HDM.Dec[0].SizeLo
     [QEMU] [ELBI ] Opcode : Mem_Read   Addr : 0xfd40121c   Size : 4    Data :         0x00000000   CXL HDM.Dec[0].SizeHi
     [QEMU] [ELBI ] Opcode : Mem_Write  Addr : 0xfd401220   Size : 4    Data :         0x00003000   CXL HDM.Dec[0].Control
     [QEMU] [ELBI ] Opcode : Mem_Read   Addr : 0xfd401220   Size : 4    Data :         0x00003000   CXL HDM.Dec[0].Control
    
  6. Verify CXL Interface inside QEMU
    After QEMU launches, test basic CXL interface functionality. Analyzing packet data with a CXL analyzer can provide valuable insights.
    • Launch QEMU
      cd emulator
      ./run.sh
      
    • CXL device detection
        root@localhost:~# lspci
        ... ...
        0d:00.0 CXL: Device babe:face (rev 01)
      
    • Check cxl region, and dax mode
        root@localhost:~# cxl list
        [
        {
            "memdevs":[
            {
                "memdev":"mem0",
                "ram_size":12616466432,
                "serial":0,
                "host":"0000:0d:00.0",
                "firmware_version":"metisx-1.0.0"
            }
            ]
        },
        {
            "regions":[
            {
                "region":"region0",
                "resource":53955526656,
                "size":12616466432,
                "type":"ram",
                "interleave_ways":1,
                "interleave_granularity":256,
                "decode_state":"commit",
                "qos_class_mismatch":true
            }
            ]
        }
        ]
        root@localhost:~# daxctl list
        [
        {
            "chardev":"dax0.0",
            "size":12616466432,
            "target_node":0,
            "align":2097152,
            "mode":"devdax"
        }
        ]
      
    • Test .mem write & read
        cd app/rwmem
        ./build.sh
        ./dax 0x2000 0x100 0x1234
        ./dax 0x2000 0x100
      
  7. Run SDK Examples
    Execute example applications included in ~/sdk/example.
     cd ~/sdk/example/sort
     ./build.sh
     ./map_sort
    
  8. Develop a new application
    To develop a new application efficiently in the QEMU environment, use virtfs to transfer files to the container. The ~/app folder in QEMU is connected via virtfs to the ~/sdk/app folder in the docker container, allowing you to easily transfer and access your application files.
    In the Docker Container:
     # Copy a new file to the shared folder
     cp myApp.cpp ~/sdk/app
    

    In QEMU:

     # Verify the file in QEMU
     ls ~/app/myApp.cpp
    
  9. Exiting Emulator
    1. Exit QEMU
      To exit the QEMU environment safely, use the following key combination (in QEMU):
       Ctrl + a, x
      

    After exiting QEMU, you can either disconnect from the Docker container (Option 2) or stop/remove it (Option 3).

    1. Disconnect from Docker Container
      If you want to disconnect without stopping the container, use the following key combination (in Docker):
       Ctrl + p, Ctrl + q
      

      To reattach to the container, use the following command:

       docker attach xcena_sdk
      
    2. Stop and Remove Docker Container

      If you want to stop or remove the container, run following commands:

       # Stop the running container
       docker stop xcena_sdk
      
       # Remove the container
       docker rm xcena_sdk