发明内容
本发明要解决的技术问题是提供一种二维数组在动态随机存取存储器上的快速读写方法,能够明显提高二维数组在动态随机存取存储器上的读写速度。本发明还要提供一种可以实现该方法的动态随机存取存储器。
为了解决上述技术问题,本发明提供了一种二维数组在动态随机存取存储器上的快速读写方法,包括以下步骤:
(a)根据系统中动态随机存取存储器一行能存放的数据个数C以及具体应用中数据按行和按列的读写次数比I/J,确定M×N二维数组划分成的多个相同大小的子矩阵的列数A=(CI/J)1/2和行数B=(CJ/I)1/2;
(b)在动态随机存取存储器上按行或按列写入二维数组时,通过地址变化,将与要写入的行或列相关的每个A×B子矩阵属于该行或列的数据按顺序分别写在动态随机存取存储器的一行上,直到写完为止;
(c)在动态随机存取存储器上按行或按列读取二维数组时,通过地址变化,按顺序逐一选择动态随机存取存储器上包含要读取的行或列的数据的行,选中一行时将该行中所有属于要读取行或列的数据读出,再选下一行,直到选完为止。
进一步地,上述快速读写方法还可具有以下特点:所述步骤(a)当计算的A和B的值不是整数时,是取接近计算值的整数,并保证A×B≤C。
进一步地,上述快速读写方法还可具有以下特点:所述步骤(a)当M不能被A整除或N不能被B整除时,是增加二维数组的规模M或N使之能被整除,并且记住原来二维数组的规模,读取时根据原来二维数组的规模舍弃后面添加的无效数据。
进一步地,上述快速读写方法还可具有以下特点:读或写一行时,地址变化如下:将行地址置为该行第一个数的行地址并保持一段时间,在保持期间列地址从该行第一个数的列地址开始递增A-1次,递增值为1或B,逐次将行地址递增M/A-1次,递增值为N/B或1,每次递增后行地址均保持一段时间,在该保持期间列地址始终按相同方式变化。
进一步地,上述快速读写方法还可具有以下特点:读或写一列时,地址变化如下:将行地址置为该行第一个数的行地址并保持一段时间,在保持期间列地址从该行第一个数的列地址开始递增B-1次,相应递增值为A或1,逐次将行地址递增N/B-1次,相应递增值为1或M/A,每次递增后行地址均保持一段时间,在该保持期间列地址按相同方式变化。
进一步地,上述快速读写方法还可具有以下特点:读写一行或一列时,行、列地址由动态随机存取存储器内部的地址产生器按地址变化规则产生的,所需参数:第一个数的行地址、列地址,以及行地址和列地址的递增值和递增次数或者其中的部分参数由外部逻辑单元赋值。
本发明要解决的技术问题是提供一种多维数组在动态随机存取存储器上的快速读写方法,能够明显提高多维数组在动态随机存取存储器上的读写速度。本发明还要提供一种可以实现该方法的动态随机存取存储器。
为了解决上述技术问题,本发明提供了一种多维数组在动态随机存取存储器上的快速读写方法,包括以下步骤:
(a)确定多维数组划分成的多个相同大小的小的多维数组的各维长度,使小的多维数组的各维长度的比例等于原多维数组沿各维方向读写数据的次数比,使小的多维数组的大小等于动态随机存取存储器一行能存放的数据个数;
(b)在动态随机存取存储器上写入多维数组某维上的一排数据时,通过地址变化,将相关的每个小的多维数组属于该排的数据按顺序分别写在动态随机存取存储器的一行上,直到写完为止;
(c)在动态随机存取存储器上读取多维数组某维上的一排数据时,通过地址变化,按顺序逐一选择动态随机存取存储器上包含要读取的数据的行,选中一行时将该行中所有属于要读取的该排的数据读出,再选下一行,直到选完为止。
进一步地,上述快速读写方法还可具有以下特点:假设n维数组在应用中,沿第i维方向读写数据的次数为Ii,(1≤i≤n),假设划分的小的多维数组的第i维的长度为Ai,Ai由下面两个等式算出:
A1:A2:Λ:An-1:An=I1:I2:Λ:In-1:In
如果Ai的值不是整数时,取接近计算值的整数,并保证
进一步地,上述快速读写方法还可具有以下特点:假设原n维数组第i维长度为Mi,沿第i维方向读写一排数据时,地址变化如下:将行地址置为该排第一个数的行地址并保持一段时间,在保持期间列地址从该排第一个数的列地址开始递增Ai-1次,递增值为column_index,逐次将行地址递增Mi/Ai-1次,递增值为row_index,每次递增后行地址均保持一段时间,在该保持期间列地址始终按相同方式变化,其中:
且当i=1时,取column_index=1;
当i=n时,row_index=1。
进一步地,上述快速读写方法还可具有以下特点:读写多维数组某一排时,行、列地址由动态随机存取存储器内部的地址产生器按地址变化规则产生的,所需参数:第一个数的行地址、列地址,以及行地址和列地址的递增值和递增次数,或者其中的部分参数由外部逻辑单元赋值。
本发明提供的一种动态随机存取存储器,包含控制逻辑单元、存储单元阵列和缓存单元,所述控制逻辑单元中包括一个地址产生器,该地址产生器包括保存外部逻辑单元所赋参数值的若干寄存器,根据所述参数值产生在动态随机存取存储器上读写二维或多维数据所需的地址。
进一步地,上述动态随机存取存储器还可具有以下特点:所述地址产生器中包括了初始行地址和初始列地址、行地址和列地址递增值、行地址和列地址递增次数的参数保存或设置单元,与这些单元连接的完成行地址和列地址累加、计数的累加器和计数器,以及输出行地址和列地址的锁存单元。
进一步地,上述动态随机存取存储器还可具有以下特点:所述地址产生器在收到可开始读或写一行或一列数据的信号并完成所述参数设置后,先输出初始行地址和初始列地址,让列地址按其递增值递增设定次数,然后行地址累加上其递增值,再让列地址按相同规则变化,每次在列地址递增了设定次数后对行地址累加一次,直到行地址累加了设定次数后,完成对一行或一列数据的读或写。
进一步地,上述动态随机存取存储器还可具有以下特点:所述缓存单元为乒乓结构的形式,包括两个行缓存,以及分别连接到该两个行缓存一端的两个多路选择器。
进一步地,上述动态随机存取存储器还可具有以下特点:还包括一个带使能端的双路复用器,该双路复用器和动态随机存取存储器控制器之间设有一对握手信号ctrl_ready和data_valid,信号ctrl_ready表示其控制器准备好读写数据,信号data_valid表示动态随机存取存储器可以读写,当前传送的数据有效。
进一步地,上述动态随机存取存储器还可具有以下特点:所述控制逻辑单元与外部之间设有信号set_addr,若信号set_addr为1,表示可设置地址参数寄存器,若set_addr为0,表示可读写数据。
由上可知,本发明根据DRAM的读写规律,克服以往二维或多维数组在DRAM上以一维形式存放的缺点,设计了一种具有新的存放结构的DRAM以及相应的存取方法,使得二维或多维数组的列读写的速度有大幅的提高,而行读写的速度只有微少的降低。列读写和行读写的速度相当,可以免去转置,从而节省系统的存储空间和总的处理时间。
具体实施方式
先分析一下DRAM的读写规律。每个DRAM芯片一般有2个或4个bank,每个bank是一个以行列方式组织的存储单元阵列。DRAM访问包括三个部分:行选、列选和precharge(预充电)。行选是给DRAM芯片一个active(激活)命令和行地址,经过tRCD时间,行地址代表的那行数据将被拷到芯片内部的行缓存(row buffer)。列选是根据列地址读写行缓存上的数据。因为列选时读写都在行缓存上,所以速度很快,不管给的列地址是否连续,数据管腿可以一个时钟周期传送一个数(DDR可以一个时钟周期传送两个数),如图1和图2所示,但前提是所要访问的数据在当前打开的DRAM行。如果要访问的数据不在当前打开的DRAM行,则必须插入precharge命令,经过tRP时间,把行缓存上的数据写回bank里相应的位置,再插入active命令打开数据所在的DRAM行,然后才能访问到数据。
目前提高DRAM读写速度的技术,如DDR、DDR2和Rambus,只是提高处理器到DRAM芯片中行缓存的接口速度,使数据总线的一个时钟周期能传多个数据,但因为DRAM的核心部分-bank中的存储单元的结构变化不大,存储单元阵列和行缓存之间交互数据时仍然是一个充放电过程,所以active的延迟tRCD及precharge的延迟tRP很难减少,目前都是20ns左右。因此只有增加DRAM同行读写的概率,尽可能地减少因为异行读写而引起active和precharge的次数,才能提高DRAM的存取效率,DDR和Rambus的技术优势就才能充分显露。
根据上面所述的DRAM读写规律能解释传统以一维方式存放大型二维数组的弊端:二维数组中同一列的各个数据都分散到DRAM的各行,列读写时每读写一个数都必须插入active和precharge操作,以切换不同的DRAM行。传统的存放方式虽然使行读写时DRAM行切换次数最少,但却使列读写时DRAM行切换的次数成倍增加,总的切换次数也就成倍增加。因此必须根据列读写在所有读写中占的比例,让同一列的数据适当集中,使得DRAM行切换的总次数减少,从而减少DRAM访问的总时间,提高DRAM存取的速度。
为此,本实施例采用了以下快速的存取结构:
假设二维数组的规模是M×N(M为列数,N为行数),DRAM一行的存储单元能存C=A×B个数据。先把二维数组划分为(M/A)×(N/B)子矩阵,每个子矩阵大小是A×B(A为列数,B为行数)。存放数据时,保证每个子矩阵存放到DRAM的一行中,而且为了以后存取时地址容易产生,最好按照一定次序存放。
例如,将第(0,0)个子矩阵存在DRAM的第0行,第(0,1)个子矩阵存在DRAM的第1行,...,第(i,j)个子矩阵存在DRAM的第(i*N/B+j)行,其中0≤i≤(M/A)-1,0≤j≤(N/B)-1),...,直到最后的第((M/A)-1,(N/B)-1)个子矩阵存在DRAM的第((M/A)×(N/B)-1)行。图3是一个简单的示例,图中的矩阵是按多个子矩阵的形式表示的。
这种存放方式是通过写地址的有规律变化来实现的,下面将对读写一行或一列的伪码进行详细描述。
假设二维数组中一行或一列的第一个数在DRAM中的行列地址为(row_address[0],column_address[0]),读或写一行的过程的伪码描述如下:
row_address=row_address[0]; //设行地址为该行第一个数的行地址
for(i=0;i<(M/A);i++) //循环计数值i初始为0,每循环一次i加
1,i=M/A时直接退出循环
{
active(row_address);//激活当前行
column_address=column_address[0];//设列地址为该行第一个
数的列地址
for(j=0;j<A;j++)//循环计数值j初始为0,每循环一次j加1,
j=A时直接退出循环
{
read_or_write(column_address);//按当前列地址读或写数据
column_address++;//列地址加1
}
precharge;//预充电
row_address=row_address+(N/B);//行地址加上N/B
}
用文字简单描述读或写一行时的地址变化如下:将行地址置为该行第一个数的行地址并保持一段时间,在保持期间列地址从该行第一个数的列地址开始递增A-1次,递增值为1,逐次将行地址递增M/A-1次,递增值为N/B,每次递增后行地址均保持一段时间,在该保持期间列地址始终按相同方式变化。按这种读写方式,从存放后DRAM行的顺序看时,是依次放一列上的子矩阵,放完一列后再放下一列,从存放后DRAM行中的数据顺序看,是依次放子矩阵上一行的数据,放完后再放下一行。但本发明不局限于此,也可以让行地址的递增值为1,从存放后DRAM行的顺序看时,相当于是依次放一行上的子矩阵,放完一行后再放下一行;或/及让列地址的递增值为B,从存放后DRAM行中的数据顺序看,相当于是依次放子矩阵上一列的数据,放完后再放下一列。
读或写一列的过程的伪码描述如下:
row_address=row_address[0];//设行地址为该行第一个数的行地
址
for(i=0;i<(N/B);i++)//循环计数值i初始为0,每循环一次i加
1,i=N/B时直接退出循环
{
active(row_address);//激活当前行
column_address=column_address[0];//设列地址为该行第一个数
的列地址
for(j=0;j<B;j++)//循环计数值j初始为0,每循环一次j加1,
j=B时直接退出循环
{
read_or_write(column_address);//按当前列地址读或写数
据
column_address=column_address+A;//将列地址加A
}
precharge;//预充电
row_address++;//行地址加1
}
用文字简单描述读或写一列时的地址变化如下:将行地址置为该行第一个数的行地址并保持一段时间,在保持期间列地址从该行第一个数的列地址开始递增B-1次,递增值为A,逐次将行地址递增N/B-1次,递增值为1,每次递增后行地址均保持一段时间,在该保持期间列地址按相同方式变化。该地址变化是对应于上述实施例中的读或写一行的地址变化。在其它可能的情况下,如读或写一行时行地址递增值为1时,相应地,读或写一列时的行地址递增值应为M/A,如读或写一行时列地址递增值为B时,相应地,读或写一列时的列地址递增值应为1。
下面将讨论A和B的值如何设定,才能使发生的行切换active和precharge的总次数最小化。
由上述行和列的读写过程看,读写一行需要打开DRAM的(M/A)行;读写一列需要打开DRAM的(N/B)行。假设处理时二维数组的每个数据要按行读写I次,按列读写J次,则DRAM行切换的总次数为:
Z=(M/A)*N*I+(N/B)*M*J (1)
把B=C/A代入,并对A求导得:
dZ/dA=M*N*(J/C-I/A2)
因此A=(CI/J)1/2,B=(CJ/I)1/2时,总次数Z最少。此时A/B=I/J,可见分块矩阵的长宽比最佳等于行列读写次数的比值,跟二维数组的规模M和N值无关。
在实际设计时,A和B必须是整数,因此A不一定取(CI/J)1/2,只要取接近(CI/J)1/2的C的因子即可。DRAM芯片一行的容量C通常是2的幂数,因此A和B也取2的幂数。如果M和N不能分别被A和B整除,只需适当增加二维数组的规模M和N,使之能被整除即可,但在数组扩展时要记住原来二维数组的规模,以区分有效数据和无效数据,读取时根据原来二维数组的规模舍弃后面添加的无效数据。
以二维FFT为例,假设DRAM一行能存C=1024个数据,做行向FFT时,数据按行读1次,写1次,即I=2;做列向FFT时,按列读1次,写1次,即J=2,则A=(CI/J)1/2=32,即每个DRAM能存32×32大小的子矩阵。如果二维数组的规模是16384×16384,则图像分成512×512个大小为32×32的子矩阵,由公式(1),做二维FFT DRAM行切换的总次数Z=16,777,216。如果不采用这种快速存取结构,按传统的方式存放,相当于取A=1024,那么DRAM行切换的总次数Z=268,697,600,是快速存取结构的16倍,可见采用快速存取结构理论上能减少DRAM行切换的次数。
采用上述快速存取方案后地址产生很有规律,如果在DRAM芯片中加入简单的地址产生器,可做成专用于二维(多维)数组快速存取的DRAM芯片。如图4所示,该DRAM芯片包括:包含地址产生器的控制逻辑单元、DRAM存储单元阵列、由两个行缓存和两端的多路选择器构成的乒乓结构形式的缓存单元、双向FIFO缓冲以及带使能端的多路复用器。地址产生器的行地址线连接到DRAM存储单元阵列,列地址线连接到两个行缓存。
地址产生器结构如图5所示,为了使这种DRAM芯片更为灵活,更为通用,包括了初始行地址和初始列地址、行地址和列地址递增值、行地址递增次数等5个参数寄存器,列地址的递增次数根据左边的加法器溢出确定。图中还示出了与这些单元连接的加法器、计数器和锁存器。参数的设置如下表所示:
表1 地址产生器各设置参数说明
参数 | 说明 |
row_address[0] | 起始数据的行地址 |
row_index | 行地址的递增值 |
row_count | 行地址的递增次数 |
Column_address[0] | 起始数据的列地址 |
Column_index | 列地址的递增值 |
column_count | 列地址的递增次数 |
这些参数的设置是根据具体应用编写相应的程序,由CPU或其他有计算能力的逻辑单元执行程序,完成参数计算后写入DRAM的。设好6个参数寄存器后,左右两个锁存器的初始值分别是column_address[0]和row_address[0],即第一个数据的列地址和行地址;左边的累加器先工作,按列地址的递增值依次算出接下来各个数据的列地址,直到达到了设定的列地址递增次数;因而下一个数据不在该DRAM行,将行地址在右边的累加器加上其递增值输出,切换DRAM行,计数器row_count减1。这样每次在列地址递增了设定次数后,使能右边的累加器,计算出下一个行地址,并使计数器row_count减1;如此循环,直到row_count等于0,即行地址累加了设定次数后为止。
根据上述参数,对于上文中的两个伪码描述,均可用以下伪码实现:
row_address=row_address[0];//设行地址为该行或列起始数据的行地
址
for(i=0;i<row_count;i++)//循环计数值i初始为0,每循环一次i
加1,i等于行地址递增次数时直接退出
循环
{
active(row_address);//激活当前行
column_address=column_address[0];//设列地址为该行或列起
始数据的列地址
for(j=0;j<column_count;j++)//循环计数值j初始为0,每循环
一次j加1,j等于列地址递增次数时直接退出循环
{
read_or_write(column_address);//按当前列地址读或写数
据
column_address=column_address+column_index;//将列地址
加上其递增值
}
precharge;//预充电
row_address=row_address+row_index;//将行地址加上其递增
值
}
如此,只要设定相应的参数值,即可完成二维数组的行读写或者列读写。若把row_index和column_index都设为1,即为普通的一维数组的读写。对于多维数组的访问,通过设定相应的参数值能完成对某一维的读写,达到灵活、通用的要求。
考虑到在读写的中途可能会遇到DRAM芯片在刷新、active和precharge等不能读写的状态,因此应在DRAM芯片和DRAM控制器之间添加一对握手信号ctrl_ready和data_valid,该对信号从DRAM控制器连接到DRAM芯片上的带使能端的双路复用器,分别表示DRAM控制器准备好读写数据和DRAM芯片可以读写,当前传送的数据有效。读数时,DRAM芯片只有看到ctrl_ready有效时才往数据线写数,DRAM控制器只有看到data_valid有效时才读数;写数时,DRAM控制器只有看到data_valid有效时才写数,DRAM芯片只有看到ctrl_ready有效时才读数。
因为通过数据管腿设定参数,有管腿复用的问题,本实施例增加了一个连接到控制逻辑单元的set_addr信号,当ctrl_ready为1时,表示DRAM控制器准备好,若set_addr为1,设置地址参数寄存器,若set_addr为0,读写数据,读写数据时,地址产生器产生相应的行地址和列地址。
另外,为了提高DRAM的读写效率,增加一个行缓存,两个行缓存的两端再分别与一个多路选择器(MUX)相连,形成乒乓结构(Ping-Pong)。当一个行缓存在列读写时,另一个行缓存做precharge、active和刷新。在DRAM芯片的数据接口处适当增加双向FIFO作为缓存。
这样,该DRAM芯片通过数据线设定好地址产生器中各项参数后,地址在DRAM芯片内部产生,一行或一列数据就源源从数据线送出,可以省去地址线,减少DRAM芯片的管腿和PCB板布线,可节省芯片封装成本和PCB板布线成本;DRAM芯片也无需等待地址总线稳定后再读数,接口速度可相应提高。
总的来说,相对于目前市面上普通的DRAM芯片,本实施例适合二维数组快速存储的DRAM芯片具有如下特点和优点:
1)内含地址产生器,以支持本发明提到的二维数组的快速存取技术,工作模式也从原来的给一个地址读写一个数,变成设定若干寄存器读写一串数,使得对二维数组处理时无需转置也有很高的读写速度,对一维数组和多维数组也同样适用。
2)行读写或列读写的地址全部由内部的地址产生器产生,地址管腿可全部省掉,用于区分行访问和列访问的信号管腿CAS#和RAS#也可省掉;减少DRAM芯片的管腿和PCB板布线,可节省成本。
3)增加ctrl_ready和data_valid信号管腿用于握手,增加set_addr信号管脚用于数据管腿复用;
4)增加一个行缓存做Ping-Pong,克服了DRAM芯片在active、precharge和刷新时不能读写的缺点,使之读写速度跟SRAM相同,而容量比SRAM大得多。
设计该DRAM是为了避免二维数组转置的同时,要求二维数组的列方向数据也能快速地存取,以提高处理的速度,因此该DRAM是专用于存取二维数组的,使用时需要有SRAM配合,缓存二维数组的一行或一列的数据。目前高速的DSP和FPGA芯片内部都有SRAM(如TITMS320C6416和Xilinx Vertex II),处理核心对内部SRAM的访问通常有较高的带宽和较低的延迟,而访问外部的DRAM延迟很大,因此高速的处理核心通常不直接处理DRAM上的数据,而是先通过DMA控制器把DRAM的数据读入内部的SRAM,对SRAM的数据处理后,再通过DMA控制器把数据写回DRAM。如此DRAM只起到数据存取的作用,类似于硬盘,因此针对二维数组设计在DRAM上的快速的存取结构和专用的DRAM芯片是合理的。
本发明同样适合于多维数组在DRAM上的快速读写方法,对于三维和三维以上的数组,上述存放结构和地址变化规则也同样适用,只要把多维数组划分为若干小的相同的多维数组,每个小的多维数组存于DRAM中的一行,并按一定次序存放。因此小的多维数组的大小应等于DRAM中一行的容量;并且使小的多维数组的各维长度的比例等于原多维数组沿各维方向读写数据的次数比。具体来说,假设n维数组在应用中,沿第i维方向读写数据的次数为Ii,(1≤i≤n),假设划分的小的多维数组的第i维的长度为Ai,Ai由下面两个等式算出:
A1:A2:Λ:An-1:An=I1:I2:Λ:In-1:In (3)
如果Ai的值不是整数时,取接近计算值的整数,并保证 总的目标也是让读写多维数组时,DRAM行切换总次数最少。
在动态随机存取存储器上写入多维数组某维上的一排数据时,通过地址变化,将相关的每个小的多维数组属于该排的数据按顺序分别写在动态随机存取存储器的一行上,直到写完为止;
在动态随机存取存储器上读取多维数组某维上的一排数据时,通过地址变化,按顺序逐一选择动态随机存取存储器上包含要读取的数据的行,选中一行时将该行中所有属于要读取的该排的数据读出,再选下一行,直到选完为止。
具体的伪码描述和上文中第3个相同,只是6个参数需相应变化。假设原n维数组第i维长度为Mi,沿第i维方向读写一排数据时,地址变化如下:将行地址置为该排第一个数的行地址并保持一段时间,在保持期间列地址从该排第一个数的列地址开始递增Ai-1次,递增值为column_index,逐次将行地址递增Mi/Ai-1次,递增值为row_index,每次递增后行地址均保持一段时间,在该保持期间列地址始终按相同方式变化,其中:
且当i=1时,取column_index=1;
当i=n时,row_index=1。
读写多维数据某一排时,行、列地址由动态随机存取存储器内部的地址产生器按地址变化规则产生的,所需的参数,即第一个数的行地址、列地址,以及行地址和列地址的递增值和递增次数,或者其中的部分参数由外部逻辑单元赋值。