;

연암과 다산 사이

블로그 이미지
문패 달고 보니까 넘 커다란 이름이네요 ^^; 행여 고래 등 사이에 끼인 새우가 되지 않기를 ㅎㅎ 연암은 고미숙님의 '열하일기, 웃음과 역설의 유쾌한 시공간'에서, 다산은 '다산연구소' (http://www.edasan.org)에서 삘 받았슴다. 잼난 놀이터가 되었으면... ^^
by 명랑만화
  • Total hit
  • Today hit
  • Yesterday hit
02-08 00:04

%% LeCroy Exerciser Script - For NVMe Emulation

* Reference : PETrainerScriptManual_v*.pdf
http://teledynelecroy.com/protocolanalyzer/pci-express/summit-z3-16-exerciser-with-smbus-support

 

* LeCroy Exerciser Script
http://ya-n-ds.tistory.com/3108 : PCIe Commands
http://ya-n-ds.tistory.com/3116 : NVMe (1) Preparation for IO
http://ya-n-ds.tistory.com/3131 : NVMe (2) IO Command ( + MCTP, Completion options )

 

< Step 0. Option Preparation for NVMe Host Emulation >
# Exerciser BAR Menu : Setup -> Generation Options -> Transactions
- Host Memory Regions : Mem_64, Address 0x4_2FAA_8000, Length 0x1_0000 ( 4KB Blocks )

 

 

< Step 1. PCIe Configuration >
Config=Definitions
{
    HOST_REQUESTER_ID                  = (1:0:0)
    DEVICE_ID                          = (2:1:0)

 

    BAR0_ADDRESS = 0xEC03_0000  ;; Little Endian
    BAR0_ADDRESS_BIG_END = 0x0000_003EC

 

    BAR2_ADDRESS_BIG_END = 0x0000_002EC ;; Little Endian = 0xEC02_0000

 

    PXCAP_BASE_ADDR = 0x0000_0070 ;; PCIe Capability Base Address ( Device HW dependency )
    PXCAP_PXDC_OFFSET = 0x0000_0008 ;; PCIe Device Congrol register offset

 

    MSI_X_TABLE_OFFSET = 0x0000_4000  ;; Device HW dependency, This can be read from MSIXCP.MTAB register

    MSI_X_TABLE_BASE_ADDR = ( BAR0_ADDRESS + MSI_X_TABLE_OFFSET )

 

    MSI_X_CAP_BASE_ADDR = 0xB0  ;; Device HW dependency

 

    HOST_MSIX_INTR0_BASE_ADDR_BIG_END = 0x0000_E0FE  ;; MSI-X Interrupt0 BA in Host, Littel Endian = 0xFEE0_0000
    HOST_MSIX_INTR1_BASE_ADDR_BIG_END = 0x0000_E2FE  ;; MSI-X Interrupt1 BA in Host, Littel Endian = 0xFEE2_0000
    HOST_MSIX_INTR0_MSG_DATA_BIG_END = 0xB040_0000  ;; MSI-X Interrupt0 Message Data, Littel Endian = 0x0000_40B0
    HOST_MSIX_INTR1_MSG_DATA_BIG_END = 0xA040_0000  ;; MSI-X Interrupt1 Message Data, Littel Endian = 0x0000_40A0
}

 

template = TLP
{
    Name = "Temp_ConfigWrite0"
   
    TLPType=CfgWr0
    Length = 1
    RequesterId = HOST_REQUESTER_ID
    FirstDwBe = 0xF
    DeviceId = DEVICE_ID
}

 

template = TLP
{
    Name = "Temp_ConfigRead0"
   
    TLPType=CfgRd0
    Length = 1
    RequesterId = HOST_REQUESTER_ID
    FirstDwBe = 0xF
    DeviceId = DEVICE_ID
}

 

template = TLP
{
    Name = "Temp_MWr32_OneDword"
   
    TLPType = MWr32
    Length = 1
    RequesterId = HOST_REQUESTER_ID
    FirstDwBe = 0xF
}

 

template = TLP
{
    Name = "Temp_MRd32_OneDword"
   
    TLPType = MRd32
    Length = 1
    RequesterId = HOST_REQUESTER_ID
    FirstDwBe = 0xF
}

 

 

< Step 1. PCIe Preparation for NVMe >
packet="Temp_ConfigWrite0"
{   
    Register = 0x10
    Payload = ( BAR0_ADDRESS_BIG_END ) ; Payload is in Big-endian
}

 

;;wait=TLP { TLPType = Cpl } ;; Wait Completion before Next Command

 

packet="Temp_ConfigWrite0"
{
    Register = 0x14  ;; BAR0 Upper Address for 64bit access
    Payload = ( 0 )
}

 

packet="Temp_ConfigWrite0"
{
    Register = 0x18
    Payload = ( BAR2_ADDRESS_BIG_END )
}

 

packet="Temp_ConfigWrite0"
{
    Register = 0x1C  ;; BAR2 Upper Address for 64bit access
    Payload = ( 0 )
}

 

packet="Temp_ConfigWrite0"
{
    FirstDwBe = 0x3
    Register = 0x4
    Payload = ( 0x46050000 ) 
 ;; 2nd Byte : bit[10] Interrupt Disable(Pin-based), bit[8] SERR# Enalbe,
 ;; 1st Byte : bit[6] Parity Error Enable, bit[2] BME, bit[1]MSE
}

 

Packet=TLP
{
    PSN = 60
    TLPType = CfgWr0
    FirstDwBe = 0x3
    Register = ( PXCAP_BASE_ADDR + PXCAP_PXDC_OFFSET )
    Payload = 0x30280000 ;; MPS='0x1'(256B), ERO='1', MRRS='0x2'(512B), ENS='1'
 ;; 1st Byte : bit[7:5] Max Payload size, bit[4] Enhanced Relaxed Ordering(ERO)
 ;; 2nd Byte : bit[14:12] Max Read Request size, bit[11] Enable No Snoop
}

 

;; Set MSI-X Table Entries
;; Vector 0
packet="Temp_MWr32_OneDword"
{
    Address = MSI_X_TABLE_BASE_ADDR
    Payload = ( HOST_MSIX_INTR0_BASE_ADDR_BIG_END )  ;; Lower Address
}

 

packet="Temp_MWr32_OneDword"
{
    Tag = 1
    Address = ( MSI_X_TABLE_BASE_ADDR + 4 )
    Payload = ( 0 )  ;; Upper Address
}

 

packet="Temp_MWr32_OneDword"
{
    Tag = 2
    Address = ( MSI_X_TABLE_BASE_ADDR + 8 )
    Payload = ( HOST_MSIX_INTR0_MSG_DATA_BIG_END )
}

 

packet="Temp_MWr32_OneDword"
{
    Tag = 3
    Address = ( MSI_X_TABLE_BASE_ADDR + 0xC )
    Payload = ( 0 )  ;; Vector Control - bit[0] Vector Mask bit
}


;; Vector 1
packet="Temp_MWr32_OneDword"
{
    Address = ( MSI_X_TABLE_BASE_ADDR + 0x10 )
    Payload = ( HOST_MSIX_INTR1_BASE_ADDR_BIG_END )
}

 

packet="Temp_MWr32_OneDword"
{
    Tag = 1
    Address = ( MSI_X_TABLE_BASE_ADDR + 0x14 )
    Payload = ( 0 ) ;
}

 

packet="Temp_MWr32_OneDword"
{
    Tag = 2
    Address = ( MSI_X_TABLE_BASE_ADDR + 0x18 )
    Payload = ( HOST_MSIX_INTR1_MSG_DATA_BIG_END )
}

 

packet="Temp_MWr32_OneDword"
{
    Tag = 3
    Address = ( MSI_X_TABLE_BASE_ADDR + 0x1C )
    Payload = ( 0 )
}

 

;; Enable MSI-X
packet="Temp_MWr32_OneDword"
{   
    Register = MSI_X_CAP_BASE_ADDR
    FirstDwBe = 0x8  ; Last byte only
    Payload = ( 0x11001F80 )
 ;; Capability ID[7:0]=11h, Next Cap ID[15:8]=00h
 ;; Message Control : Table Size bit[26:16](RO), Function Mask[30], MSI-X Enable[31]
}

 

packet="Temp_ConfigRead0"
{   
    Register = 0x8  ;; Rev.ID, Class Code
}

 

packet="Temp_ConfigRead0"
{   
    Register = 0x10  ;; BAR0
}

 

 

< Step 2. Initialization for NVMe >
;; Set CQ, SQ Entry Size
packet="Temp_MWr32_OneDword"
{
    Tag = 1
    Address = ( CONTROLLER_REGISTERS_BASE + 0x14 ) ;; CC(Controller Configuration)
   
    Payload = ( 0x00004600 )  ;; 0x0046_0000
    ;; bit[23:20] - I/O Completion Queue Entry Size // 2^n ea - 2^4=16ea
    ;; bit[19:16] - I/O Submission Queue Entry Size // 2^n ea - 2^6=64ea
}

 

;; Poll for the Ready to go to zero
Loop=Begin { Count=50000 }

packet="Temp_MRd32_OneDword"
{
    Address = ( CONTROLLER_REGISTERS_BASE + 0x1C ) ;; CSTS(Controller Status)
    
    StoreData = ( FROM_MEM64, 0 )
    ;; Store the data returned by Memory Read TLP into Mem64 HostMemRegion with offset=0
}

  Loop=Break ;; Break from Loop when the condition is met
  {
    Location=Mem64
    Offset = 0
    FieldSize = Dword
    Endian = Little
    FieldAction = MaskAND 
    Mask = 0x1
    Result = 0  ;; Check bit[0] Ready bit is '0'
  }

Loop=End

 

;; Set ACQS and ASQS in AQA(Admin Queue Attributes)
packet="Temp_OneDwordWrite"
{
    Tag = 0
    Address = ( CONTROLLER_REGISTERS_BASE + 0x24 )

    Payload = ( 0x7F00_7F00 )  ;; 128ea
    ; bit[27:16] ACQS(Admin Completion Queue Size)
    ; bit[11:0] ASQS(Admin Completion Queue Size)
}

 

;; Set Admin Submission Queue address base - ASQ
;; This address corresponds to the base address set for Mem_64 Host region
packet="Temp_MWr32_OneDword"
{
    Tag = 1
    Address = ( CONTROLLER_REGISTERS_BASE + 0x28 )  ;; Lower Address
    Payload = ( 0x0080AA2F )  ;; 0x2FAA_8000
}

packet="Temp_MWr32_OneDword"
{
    Tag = 2
    Address = ( CONTROLLER_REGISTERS_BASE + 0x2C )  ;; Upper Address
    Payload = ( 0x04000000 )  ;; 0x0000_0004
}


;; Set Admin completion Queue address base - ACQ
packet="Temp_MWr32_OneDword"
{
    Tag = 1
    Address = ( CONTROLLER_REGISTERS_BASE + 0x30 )  ;; Lower Addrss
    Payload = ( 0x00A0AA2F )  ;; 0x2FAA_A000
}

packet="Temp_MWr32_OneDword"
{
    Tag = 2
    Address = ( CONTROLLER_REGISTERS_BASE + 0x34 )  ;; Upper Address
    Payload = ( 0x04000000 )  ;; 0x0000_0004
}

 

;; Disable NVM by writing to the CC register
packet="Temp_MWr32_OneDword"
{
    Tag = 1
    Address = ( CONTROLLER_REGISTERS_BASE + 0x14 )
    Payload = ( 0x00004600 )  ;; 0x0046_0000 bit[0] CC.EN=0
}
wait=1000000

 

;; Enable NVM by writing to the CC register
packet="Temp_MWr32_OneDword"
{
    Tag = 1
    Address = ( CONTROLLER_REGISTERS_BASE + 0x14 )
    Payload = ( 01004600 )  ;; 0x0046_0001 bit[0] CC.EN=1
}

 

;; Poll for the Ready status : CC.EN='1' -> Ready='1'
Loop=Begin { Count=50000 }

packet="Temp_MRd32_OneDword"
{
    Address = ( CONTROLLER_REGISTERS_BASE + 0x1C )
    StoreData = ( FROM_MEM64, 0 )
}

  Loop=Break
  {
    Location=Mem64
    Offset = 0 ;
    FieldSize = Dword
    Endian = Little
    FieldAction = MaskAND
    Mask = 0x1
    Result = 0x1
  }
wait=200000 ;; 200us

Loop=End

 

 

< Step 3. Queue Creation for NVMe IO >
;; Read the config registers needed for automatic NVMe decoding of the trace
packet="Temp_ConfigRead0"
{   
    Register = 0x8  ;; Revision ID, Class Code
}
wait=TLP { TLPType = CplD }

 

packet="Temp_ConfigRead0"
{   
    Register = 0x10 ;; BAR0
}

 

packet="Temp_MRd32_OneDword"
{
    Address = ( CONTROLLER_REGISTERS_BASE + 0x24 )  ;; AQA - ACQ Size, ASQ Size  
}

 

packet="Temp_MRd32_OneDword"
{
    Address = ( CONTROLLER_REGISTERS_BASE + 0x28 )  ;; ASQ Base Address - Lower
}

 

packet="Temp_MRd32_OneDword"
{
    Address = ( CONTROLLER_REGISTERS_BASE + 0x2C )  ;; ASQ Base Address - Upper
}

packet="Temp_MRd32_OneDword"
{
    Address = ( CONTROLLER_REGISTERS_BASE + 0x30 )  ;; ACQ Base Address - Lower
}

 

packet="Temp_MRd32_OneDword"
{
    Address = ( CONTROLLER_REGISTERS_BASE + 0x34 )  ;; ACQ Base Address - Upper
}

 

;; Pre-program command in the Host Memory Region. This is the Mem_64 Host region
;; defined in the generation options file "nvme_host_gen_options.gen"
Structure=NVMe
{
    Location=Mem64  ;; Mem_64, Address 0x4_2FAA_8000
    Offset = 0
    NVMeStructType=AdminCommand
    OpcodeAdmin = ADMIN_CREATE_CQ
    CID = 0  ;; Command Identifier
    PRP1_Low = 0x2FAC8000
    PRP1_High = 0x4
    Queue_ID = 1
    QueueSize = IO_QUEUE_SIZE   
    PhysContig = Yes
    IntEnable = Yes
    IntVector = 1
}

 

Structure=NVMe
{
    Location=Mem64
    Offset = 64
    NVMeStructType=AdminCommand
    OpcodeAdmin = ADMIN_CREATE_SQ
    CID = 1
    Queue_ID = 1
    QueueSize = IO_QUEUE_SIZE
    PhysContig = Yes
    CQID = 1
    QPriority = Urgent
    PRP1_Low = 0x2FAB8000
    PRP1_High = 0x4
}

 

;; Write Admin Submission Queue Tail Doorbell - 1st
packet="Temp_MWr32_OneDword"
{
    Tag = 0
    Address = ( CONTROLLER_REGISTERS_BASE + 0x1000 )  ;; Admin SQ Doorbell
    Payload = ( 0x01000000 )  ;; 0x0000_0001
}

 

wait=TLP
{
    TLPType = MWr32
    Address = HOST_MSIX_INTR0_BASE_ADDR  ;; 0xFEE0_0000 - for Admin CQ
}

 

;; Write Admin Completion Queue Head Doorbell - 1st
packet="Temp_MWr32_OneDword"
{
    Tag = 1
    Address = ( CONTROLLER_REGISTERS_BASE + 0x1004 )  ;; Admin CQ Doorbell
    Payload = ( 0x1000000 )  ;; 0x0000_0001
}

 

;; Write Admin Submission Queue Tail Doorbell - 2nd
packet="Temp_MWr32_OneDword"
{
    Tag = 2
    Address = ( CONTROLLER_REGISTERS_BASE + 0x1000 )
    Payload = ( 0x02000000 )  ;; 0x0000_0002
}

 

wait=TLP
{
    TLPType = MWr32
    Address = HOST_MSIX_INTR0_BASE_ADDR  ;; 0xFEE0_0000 - for Admin CQ
}

 

;; Write Admin Completion Queue Head Doorbell - 2nd
packet="Temp_MWr32_OneDword"
{
    Tag = 3
    Address = ( CONTROLLER_REGISTERS_BASE + 0x1004 )
    Payload = ( 0x02000000 )  ;; 0x0000_0002
}
 

 

AND

ARTICLE CATEGORY

분류 전체보기 (4477)
올드Boy다이어리 (532)
올드Boy@Jeju (83)
올드Boy@Road (131)
올드Boy@Book (58)
숨은길찾기 (14)
스펙트럼 (105)
우물밖엿보기 (32)
교회에말걸기 (226)
이어지는글들 (52)
하하호호히히 (75)
어?...아하! (126)
대한늬우스 (1673)
세계는지금 (268)
차한잔의여유 (64)
La Vita E Bella (230)
좋은나라만들기 (92)
트위터세상 (67)
사람&말 (625)
호모파베르 (20)

RECENT ARTICLE

RECENT COMMENT

RECENT TRACKBACK

CALENDAR

«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28

ARCHIVE