周文強(qiáng),雷淑嵐,孫維東
(中科芯集成電路有限公司,江蘇無(wú)錫 214072)
目前,在服務(wù)器、嵌入式片上系統(tǒng)(SoC)芯片中,雙倍速率內(nèi)存(DDR)得到了廣泛應(yīng)用,其標(biāo)準(zhǔn)協(xié)議也已經(jīng)發(fā)展到了現(xiàn)在的DDR5[1-2]。DDR系統(tǒng)包含DDR控制器、端口物理層(PHY)、DDR同步動(dòng)態(tài)隨機(jī)存取內(nèi)存(SDRAM)3部分[3-4],具有大容量、高速低功耗、低電壓、良好的散熱性等特點(diǎn)[5-6]。因此,在SoC系統(tǒng)芯片中DDR系統(tǒng)起著至關(guān)重要的作用。在開(kāi)啟錯(cuò)誤檢查與糾正(ECC)功能的DDR系統(tǒng)里,總線上其他各個(gè)IP核在讀寫(xiě)DDR之前,通常需要DDR控制器對(duì)DDR SDRAM初始化數(shù)據(jù),即需要預(yù)先寫(xiě)入帶有ECC數(shù)值的初始數(shù)據(jù)[7],否則DDR SDRAM中的數(shù)據(jù)是隨機(jī)值,其ECC數(shù)值是錯(cuò)誤的(仿真時(shí)是x態(tài)),當(dāng)寫(xiě)入數(shù)據(jù)寬度小于DDR memory總寬度時(shí),DDR控制器會(huì)做讀-改-寫(xiě)(RMW)操作[7],先從DDR memory中讀取數(shù)據(jù),然后與新寫(xiě)入的數(shù)據(jù)合并,接著通過(guò)控制器內(nèi)的ECC算法計(jì)算出該數(shù)據(jù)的ECC值,最后寫(xiě)入DDR memory。如果不預(yù)先初始化數(shù)據(jù),在讀取數(shù)據(jù)的階段,由于DDR memory中初始數(shù)據(jù)和ECC均為隨機(jī)值,當(dāng)被讀進(jìn)DDR控制器后,ECC校驗(yàn)時(shí)出現(xiàn)2 bit以上錯(cuò)誤,實(shí)際應(yīng)用中會(huì)使系統(tǒng)不能正常工作,而仿真時(shí)則由于出現(xiàn)x態(tài)等情況造成仿真進(jìn)入死循環(huán)。而在不支持ECC功能的DDR系統(tǒng)中,則不需要初始化數(shù)據(jù),只要先寫(xiě)后讀即可。
當(dāng)開(kāi)啟ECC功能后,在仿真驗(yàn)證時(shí)通常的辦法是通過(guò)DDR控制器里的ECC算法計(jì)算出對(duì)應(yīng)數(shù)據(jù)的ECC值,然后將ECC值連同數(shù)據(jù)一起寫(xiě)到DDR SDRAM中,這是常用的前門訪問(wèn)方式。前門訪問(wèn)方式需要通過(guò)控制器發(fā)出指令,經(jīng)過(guò)DDR PHY,最后變成DDR SDRAM指令,才能將帶有ECC值的數(shù)據(jù)寫(xiě)入DDR SDRAM,對(duì)其進(jìn)行初始化數(shù)據(jù)操作[7],這消耗了大量的仿真時(shí)間。本文針對(duì)這個(gè)問(wèn)題,提出了一種自動(dòng)識(shí)別信息并自動(dòng)計(jì)算ECC數(shù)值且靈活可配置的后門訪問(wèn)方法。該方法通過(guò)System Verilog語(yǔ)言建立了處理文件,實(shí)現(xiàn)了自動(dòng)讀取配置文件和數(shù)據(jù)文件的功能,并采用System Verilog語(yǔ)言模擬了與DDR控制器內(nèi)功能相同的ECC算法(Verilog語(yǔ)言實(shí)現(xiàn)),然后處理程序根據(jù)讀取的配置信息和數(shù)據(jù)自動(dòng)計(jì)算出對(duì)應(yīng)數(shù)據(jù)的ECC值,最后調(diào)用DDR SDRAM內(nèi)的task以后門訪問(wèn)方式將數(shù)據(jù)連同ECC值在仿真開(kāi)始時(shí)提前加載到SDRAM中。仿真結(jié)果表明,在初始化SDRAM初始數(shù)據(jù)階段幾乎不需要仿真時(shí)間,因而極大地縮短了仿真時(shí)間,同時(shí)又能達(dá)到驗(yàn)證各IP核讀寫(xiě)DDR的目的。
常用的SoC系統(tǒng)結(jié)構(gòu)包含中央處理器(CPU)、高速外設(shè)、低速外設(shè)、總線、DDR子系統(tǒng)等,如圖1所示。其中DDR memory由多個(gè)SDRAM顆粒[8-9]構(gòu)成。CPU發(fā)送/接受數(shù)據(jù)需要經(jīng)過(guò)先進(jìn)可擴(kuò)展接口(AXI)總線,然后經(jīng)過(guò)DDR控制器的AXI端口處理后,數(shù)據(jù)由DDR控制器控制,接著通過(guò)DDR PHY接口,傳輸?shù)紻DR memory或從DDR memory中讀取數(shù)據(jù)。
圖1 常用SoC系統(tǒng)芯片結(jié)構(gòu)
本文實(shí)驗(yàn)中采用的DDR系統(tǒng)[7]如圖2所示,該系統(tǒng)包括DDR控制器、DFI標(biāo)準(zhǔn)接口[10]、PHY、DDR SDRAM顆粒,并支持ECC功能。DDR memory由9個(gè)DDR3[11]SDRAM顆粒構(gòu)成,每個(gè)SDRAM顆粒數(shù)據(jù)寬度為8 bit,因此數(shù)據(jù)總寬度為72 bit,即64 bit數(shù)據(jù)加8 bit ECC值。
圖2 DDR子系統(tǒng)結(jié)構(gòu)[7]
在AXI總線[12]上其他IP核讀寫(xiě)DDR之前,必須先對(duì)DDR控制器、DDR PHY、SDRAM進(jìn)行初始化,當(dāng)開(kāi)啟ECC功能后,在初始化階段需要預(yù)先向SDRAM寫(xiě)入帶有ECC值的初始數(shù)據(jù)。如果不初始化數(shù)據(jù),則在寫(xiě)入數(shù)據(jù)寬度(如32 bit)小于DDR memory總寬度(如64 bit)的情況下,DDR控制器會(huì)做RMW操作,即先從DDR memory中讀取數(shù)據(jù),然后與新寫(xiě)入的數(shù)據(jù)合并(如合并成64 bit),接著通過(guò)控制器內(nèi)的ECC算法計(jì)算出合并數(shù)據(jù)的ECC值,最后將合并數(shù)據(jù)及ECC值寫(xiě)入DDR memory,在RMW的讀取階段,由于DDR memory中初始時(shí)數(shù)據(jù)為隨機(jī)值,對(duì)應(yīng)的ECC值也是隨機(jī)值,這些值被讀進(jìn)DDR控制器后,ECC校驗(yàn)時(shí)出現(xiàn)2 bit以上錯(cuò)誤,實(shí)際應(yīng)用中會(huì)使系統(tǒng)不能正常工作,而仿真時(shí)則由于出現(xiàn)x態(tài)等情況造成仿真進(jìn)入死循環(huán)。但是對(duì)于不支持ECC功能的DDR子系統(tǒng),則不需要預(yù)先寫(xiě)入初始數(shù)據(jù),只要先寫(xiě)后讀即可。
本文提出的方法需要建立多個(gè)數(shù)據(jù)文件(load X.dat,X=0,1,2,...)、一個(gè)配置文件load.info、一個(gè)仿真處理文件ddr_load.sv,用于實(shí)現(xiàn)數(shù)據(jù)處理及ECC計(jì)算等功能。
建立的數(shù)據(jù)文件load X.dat(X=0,1,2,...),格式如下(十六進(jìn)制):
該文件中的數(shù)據(jù)就是需要通過(guò)后門方式加載到DDR memory中的數(shù)據(jù),ECC數(shù)值不用手動(dòng)計(jì)算,在處理文件ddr_load.sv中采用System Verilog語(yǔ)言模擬了與控制器功能相同的ECC算法(Verilog語(yǔ)言),當(dāng)加載數(shù)據(jù)時(shí)算法自動(dòng)計(jì)算對(duì)應(yīng)數(shù)據(jù)的EC字節(jié)數(shù)值,最后將數(shù)據(jù)連同ECC數(shù)值一起加載到DDR memory。數(shù)據(jù)文件的產(chǎn)生方式有2種:1)可以通過(guò)編寫(xiě)腳本,運(yùn)行后自動(dòng)產(chǎn)生上述格式的隨機(jī)數(shù)據(jù)或特定數(shù)據(jù)到load X.dat數(shù)據(jù)文件中,同時(shí)產(chǎn)生配置文件load.info;2)手動(dòng)建立load X.dat數(shù)據(jù)文件和load.info配置文件。
本文實(shí)驗(yàn)中用到的是一個(gè)load0.dat數(shù)據(jù)文件,如表1所示。
表1 load0.dat中的數(shù)據(jù)(十六進(jìn)制)
驗(yàn)證中經(jīng)常有激勵(lì)需要訪問(wèn)多個(gè)不同的DDR memory地址段,為提高驗(yàn)證靈活性,本文提出的方法允許配置多個(gè)數(shù)據(jù)文件(load X.dat,X=0,1,2,...),在配置文件load.info中可配置多個(gè)數(shù)據(jù)文件的信息。配置文件load.info的配置格式為:
load_file_no為數(shù)據(jù)文件的編號(hào),從0開(kāi)始編號(hào),第一個(gè)文件編號(hào)為0(load0.dat),第二個(gè)編號(hào)為1(load1.dat),依此類推。load_addr為加載的起始地址。load_len為加載的數(shù)據(jù)長(zhǎng)度,以8 bit十六進(jìn)制數(shù)據(jù)為一組數(shù)據(jù),在數(shù)據(jù)文件load X.dat總的組數(shù)即為數(shù)據(jù)長(zhǎng)度(等同于數(shù)據(jù)文件load X.dat中的總行數(shù))。
驗(yàn)證中,根據(jù)實(shí)際需求,可以靈活配置該文件。本文實(shí)驗(yàn)中用到的配置信息為:
通過(guò)System Verilog語(yǔ)言編寫(xiě)一個(gè)ddr_load.sv處理文件,用于初始時(shí)以后門方式訪問(wèn)DDR SDRAM。在該文件中實(shí)現(xiàn)自動(dòng)提取load.info配置文件信息和讀取數(shù)據(jù)文件load X.dat的功能;同時(shí)模擬了設(shè)計(jì)中的ECC算法,以便在讀取數(shù)據(jù)文件load X.dat后自動(dòng)計(jì)算出對(duì)應(yīng)數(shù)據(jù)的ECC數(shù)值。步驟如下。
第1步,自動(dòng)提取配置文件load.info信息。處理流程如圖3所示。
圖3 自動(dòng)提取配置文件load.info信息
第2步,自動(dòng)提取數(shù)據(jù)文件load X.dat信息。部分示例代碼如下。
根據(jù)上述代碼規(guī)則,表1的數(shù)據(jù)被暫存到變量load_data中,其格式如圖4所示。
圖4中的DDR memory由9個(gè)DDR3 SDRAM顆粒拼接而成,每個(gè)SDRAM數(shù)據(jù)寬度為8 bit,因此總寬度為72 bit(64 bit數(shù)據(jù)加8 bit ECC值),按照?qǐng)D4的數(shù)據(jù)格式,每一行正好為64 bit數(shù)據(jù),其中顆粒8的1 Byte數(shù)據(jù)為每一行64 bit數(shù)據(jù)對(duì)應(yīng)的ECC數(shù)值,這1 Byte數(shù)據(jù)不需要預(yù)先計(jì)算,而是由處理文件中的ECC算法根據(jù)64 bit數(shù)據(jù)自動(dòng)計(jì)算得到,最后將64 bit數(shù)據(jù)連同8 bit ECC數(shù)值一起加載到DDR memory中。
第3步,在處理文件中采用System Verilog語(yǔ)言模擬和DDR控制器相同的ECC算法,根據(jù)提取的數(shù)據(jù),自動(dòng)計(jì)算出對(duì)應(yīng)64 bit數(shù)據(jù)的ECC數(shù)值。部分實(shí)例代碼如下:
第4步,調(diào)用DDR SDRAM的memory_write()task,將每個(gè)64 bit數(shù)據(jù)及8 bit ECC數(shù)值一起以后門方式預(yù)先加載到DDR SDRAM顆粒中,如圖5所示。
圖5 通過(guò)后門方式自動(dòng)加載數(shù)據(jù)和ECC數(shù)值
采用C語(yǔ)言編寫(xiě)一個(gè)仿真激勵(lì),該激勵(lì)中CPU對(duì)DDR3 memory的一小段地址范圍讀寫(xiě)10次,先寫(xiě)后讀,讀寫(xiě)地址范圍為0x10000000~0x10000024,讀寫(xiě)地址依次遞增(0x1000_0000+4i,i=0,1,2,...,9)。每次讀寫(xiě)數(shù)據(jù)位寬為32 bit(0x12345678×i,i=0,1,2,...,9)。本文采用的仿真工具是Synopsys VCS。為了對(duì)比結(jié)果,在同一臺(tái)服務(wù)器上,采用相同的激勵(lì)在DDR系統(tǒng)開(kāi)啟ECC功能的條件下,針對(duì)以下3種情況,即對(duì)DDR3 memory未初始化數(shù)據(jù)、通過(guò)前門訪問(wèn)初始化數(shù)據(jù)、通過(guò)本文提出的可靈活配置、自動(dòng)提取信息并計(jì)算ECC值的后門訪問(wèn)方法初始化數(shù)據(jù)及ECC值分別進(jìn)行仿真。
當(dāng)DDR系統(tǒng)開(kāi)啟ECC功能后,未對(duì)DDR3 memory進(jìn)行初始化數(shù)據(jù)的仿真結(jié)果如圖6和圖7所示。圖6中根據(jù)ddr_we_n信號(hào)可知,在寫(xiě)操作之前進(jìn)行了RWM,控制器先讀取了DDR中的數(shù)據(jù),因?yàn)槲闯跏蓟瘮?shù)據(jù),所以為x態(tài),相應(yīng)DFI接口上讀到的數(shù)據(jù)也為x態(tài),最后數(shù)據(jù)被讀進(jìn)控制器進(jìn)行RMW的修改和寫(xiě)操作。
圖6 RMW時(shí)DDR3 memory中讀階段
圖7中l(wèi)ane_in為DDR控制器內(nèi)ECC算法模塊的輸入數(shù)據(jù),該數(shù)據(jù)為RMW操作中modify后,與寫(xiě)入的32 bit數(shù)據(jù)合并后的64 bit數(shù)據(jù),第一次寫(xiě)入的32 bit數(shù)據(jù)是0x00000000。由于讀過(guò)來(lái)的數(shù)據(jù)是未初始化的x態(tài),因此經(jīng)ECC算法模塊計(jì)算后ecc_parity全是x態(tài),出現(xiàn)嚴(yán)重錯(cuò)誤,這使得仿真進(jìn)入死循環(huán)。
圖7 控制器內(nèi)ECC算法計(jì)算得到的數(shù)據(jù)
由于讀寫(xiě)數(shù)據(jù)為32 bit,小于DDR3 memory總的64 bit數(shù)據(jù)位寬,正如本文第2節(jié)中所述,由于SDRAM的初始數(shù)據(jù)和ECC都是隨機(jī)值,如圖6所示,仿真為x態(tài),進(jìn)而在DDR控制器進(jìn)行RMW操作時(shí),如圖7所示,數(shù)據(jù)經(jīng)過(guò)ECC模塊校驗(yàn)時(shí)出現(xiàn)嚴(yán)重錯(cuò)誤,導(dǎo)致仿真進(jìn)入死循環(huán)。因此,在DDR系統(tǒng)開(kāi)啟ECC功能后,必須要先對(duì)DDR memory進(jìn)行初始化數(shù)據(jù)并計(jì)算出ECC值,否則就會(huì)使仿真進(jìn)入死循環(huán)。
通過(guò)前門訪問(wèn)初始化DDR memory數(shù)據(jù)時(shí),需要配置DDR控制器中的寄存器,其中2個(gè)數(shù)據(jù)寄存器用于配置初始化memory的數(shù)據(jù),分別為SBRWDATA0(低32 bit)和SBRWDTA1(高32 bit),可隨意配置數(shù)據(jù),本實(shí)驗(yàn)中SBRWDATA0配置了0xcccccccc,SBRWDATA1配置了0xdddddddd。初始化數(shù)據(jù)的地址范圍為0x10000000~0x10000050,初始化數(shù)據(jù)過(guò)程仿真波形如圖8所示,對(duì)這段地址的memory全部初始成0xcccccccc_dddddddd,通過(guò)前門訪問(wèn)計(jì)算的ECC值為0x03。
圖8 前門訪問(wèn)初始化數(shù)據(jù)過(guò)程
從仿真結(jié)果文件看,整體仿真時(shí)間為287449118.5 ps,服務(wù)器CPU運(yùn)行時(shí)間為2039.8 s。Verilog代碼編譯時(shí)間已不計(jì)算在內(nèi)。激勵(lì)向DDR3 memory寫(xiě)第1筆數(shù)據(jù)的過(guò)程如圖9所示。另外,從圖9中可以看出,激勵(lì)在仿真時(shí)第一次寫(xiě)入的數(shù)據(jù)為0x00000000,寫(xiě)之前先做RMW操作,從圖中可以看出,先讀取了數(shù)據(jù),由于已經(jīng)通過(guò)前門訪問(wèn)初始化了數(shù)據(jù)和ECC值,這次讀的數(shù)據(jù)不再是x態(tài),而是0x03_dddddddd_cccccccc,在RMW后,寫(xiě)入的數(shù)據(jù)為0x30_dddddddd_00000000,已經(jīng)是正確的數(shù)據(jù)和ECC值了,不會(huì)出現(xiàn)4.1節(jié)的問(wèn)題。
文中提出的方法經(jīng)過(guò)仿真后,從仿真log上看,整體仿真時(shí)間為265926764.5 ps,服務(wù)器CPU運(yùn)行時(shí)間為1729.5 s。后門訪問(wèn)加載數(shù)據(jù)的時(shí)間幾乎為0。RTL編譯時(shí)間已不計(jì)算在內(nèi)。因此,對(duì)比前門訪問(wèn)仿真結(jié)果,本文提出的方法在初始化極小一段地址范圍(0x1000_0000~0x1000_0050)時(shí),在服務(wù)器CPU運(yùn)行時(shí)間上縮短2039.8 s-1729.5 s=310.3 s,縮短了約15.2%。從中可知,在開(kāi)啟ECC功能時(shí),如果初始化地址范圍擴(kuò)大到kB、MB甚至GB數(shù)量級(jí)時(shí),通過(guò)后門訪問(wèn)初始化數(shù)據(jù)的方法將節(jié)約數(shù)小時(shí)甚至更多的時(shí)間。
圖10是激勵(lì)中第一次寫(xiě)操作時(shí)引發(fā)RMW的讀階段和寫(xiě)階段,從中可知,第一次寫(xiě)入的數(shù)據(jù)為0x0000_0000,該數(shù)據(jù)和DDR中初始數(shù)據(jù)合并成了0xaabbccdd_00000000,其中0xaabbccdd為后門方式初始化后的數(shù)據(jù)。合并數(shù)據(jù)的ECC值由控制器內(nèi)ECC模塊計(jì)算,為0xff,最后一起被寫(xiě)入到DDR memory。另外,該方法也沒(méi)有出現(xiàn)4.1節(jié)的問(wèn)題,仿真能正常運(yùn)行。
圖10 RMW中的read操作和write操作
4.1節(jié)至4.3節(jié)各仿真結(jié)果對(duì)比如表2所示。未進(jìn)行ECC初始化,仿真不能正常運(yùn)行。在通過(guò)前門訪問(wèn)進(jìn)行ECC初始化后仿真正常,運(yùn)行時(shí)間為2039.8 s。而通過(guò)本文提出的方法,不僅能正常仿真,而且運(yùn)行時(shí)間為1729.5 s,比前門訪問(wèn)ECC初始化的方法縮短了約15.2%,注意這是在訪問(wèn)極小一段地址范圍的情況下得出的結(jié)果,從中可知,如果訪問(wèn)地址擴(kuò)大到kB、MB、GB等情況,本文提出的方法能節(jié)省大量時(shí)間。
表2 各仿真驗(yàn)證方法對(duì)比結(jié)果(極小一段地址空間情況下)
在DDR控制系統(tǒng)開(kāi)啟ECC功能的情況下,如果訪問(wèn)的數(shù)據(jù)寬度小于DDR memory的數(shù)據(jù)總寬度時(shí),在初始化階段需要對(duì)memory數(shù)據(jù)進(jìn)行ECC計(jì)算并初始化,否則系統(tǒng)不能正常工作。傳統(tǒng)的通過(guò)前門訪問(wèn)初始化數(shù)據(jù)的方式會(huì)占用大量的仿真時(shí)間。而本文提出的自動(dòng)識(shí)別配置信息并計(jì)算ECC值的后門訪問(wèn)方法在減少仿真時(shí)間方面具有顯著優(yōu)勢(shì),且配置靈活方便,能夠自動(dòng)提取信息并采用System Verilog語(yǔ)言模擬ECC算法自動(dòng)計(jì)算出ECC值,在仿真開(kāi)始時(shí)提前將數(shù)據(jù)和ECC數(shù)值加載到DDR memory,同時(shí)又能達(dá)到相同的驗(yàn)證目的。在初始化很小一段地址范圍(0x1000_0000~0x1000_0050)時(shí),比前門訪問(wèn)方式減少約15.2%的時(shí)間。從中可知,如果初始化地址范圍擴(kuò)大到kB、MB、GB的數(shù)量級(jí)時(shí),采用本文提出的方法將會(huì)省下大量的仿真時(shí)間、加快研發(fā)進(jìn)度,同時(shí)又能達(dá)到相同的驗(yàn)證目的。本文提出的方法適用于各類DDR系統(tǒng)(DDR2~DDR5)。