2.1 项目背景及可行性分析
这个项目旨在利用JBits实时可重构系统完成一个基于二维离散小波变换核的全面设计过程 ,这包括仿真 ,调试 ,以及搭建 硬件与可重构计算平台的接口。 JBits API的发展使对Xilinx 4000 系列和Virtex系列 器件配置比特流成为可能 。应用JBits API, 设计者可以绕开传统的逻辑综合和物理实现步骤 而允许高速比特流的重构。比较于asic 使用JBits 可以创造更高性能的电路以用于实时可重构系统 。因此 JBits API成为 设计一个有效的基于fpga的 实时可重构和可进化设计的必要工具。
2.2 应用背景
随着信息技术的飞速发展,计算机系统面临的问题越来越复杂,如何保证复杂系统的可靠性成为一个不容忽视的问题。可进化硬件给我们提供了一个很好的解决方案。可进化硬件EHW(Evolvable Hardware)是将进化算法和可编程逻辑元件融合在一起而产生的一种新的硬件研究流派。当所使用的环境发生变化时,或被放置于未知的环境中时,这种硬件会自动地改变内部结构,使之经常处于最适合状态,快速高效地完成规定的任务。
可编程门阵列(FPGA)以其独有的优点为国外多数研究人员用作硬件进化平台。EHW利用FPGA的在线可编程技术(ISP)及动态重构技术,将FPGA的配置信息作为染色体,通过遗传算法(GA)对其进行反复的适应度计算,交叉和变异,最终进化出符号环境要求的个体(即电路配置),从而使电路适合环境的变化。
与此同时,随着FPGA技术的发展,芯片的性能越来越强、规模越来越大、开发的周期越来越长,使得芯片设计业正面临一系列新的 问题:设计质量难以控制,设计成本也越来越高。IP(Intelligence Property)技术解决了当今芯片设计业所面临的难题。IP是指可用来生成ASIC和PLD的逻辑功能块,又称IP核(IP Core)或虚拟器件(VC)。设计者可以重复使用已经设计并经过验证的IP核,从而专注于整个系统的设计,提高设计的效率和正确性,降低成本。目前数字IP已得到了充分的发展,可以很方便地购买到IP核并整合到SoC的设计中。
图 1 FPGA 中的 可进化ip核和 普通 ip核
因此,可以考虑将进化硬件的思想应用于IP核的设计中,设计一种可进化的IP核,根据当前的环境进化出相应的电路,并能够在普通的可重构器件中实现。
2.3 研究现状
1 可进化IP核
从进化硬件的经验可知,系统通常只有一部分是适应性的(可进化的),另一部分可以通过传统的不可变的电路来实现。同样,使用IP核构造的系统也是有些IP核是可进化的,有些IP核是不可变的。可进化的那些IP核称为可进化组件或可进化IP核。
可进化IP核像普通的IP核一样被存储在组件库中,在被下载并放在一个可重构器件中后,它们将自动地进化它们的内部电路。当不再需要适应性行为时,可以从可重构器件中删除可进化IP核。可进化IP核和普通IP核的复用方式相同。
2 可进化IP核的一般体系结构
如图1所示,可进化IP核由可重构电路,基因单元和控制器构成(本文中可重构电路是指可进化IP核内的一个部分;可重构器件是指整个可重构平台,如FPGA)。这里要强调的是,基因单元不包含适应度计算,它只实现基因的操作、染色体存储和适应度存储。适应度的计算和环境由其它的核来提供。基因单元生成一些配置并上载到可重构电路中去,环境对这些配置进行评估,并将适应度值发送给IP核。可进化IP核实际上是一个由环境控制的电路生成器。
环境(由其它核提出)和可进化IP核之间的通信如下:首先IP核被初始化(生成初始化种群),然后进入如下无限循环——当环境发生变化后,环境计算当前电路配置的适应度,并判断电路是否适应环境。如果染色体存储器中的配置不可用,则向IP核发出控制信息,IP核开始进化。即基因单元把硬件配置信息作为染色体,根据适应度对其进行交叉、变异等遗传操作,生成一个新的种群。环境对新种群进行适应度计算,并判断是否有满足当前环境的个体(配置)。若没有,向IP核发控制信息,遗传单元继续对电路配置进行进化,直至有满足当前环境的配置为止;若有,则将适应度值发给IP核,IP核用这个新生成的最优配置来重配置可重构电路,并在染色体存储器中保存当前最优配置及其适应度值,等待来自环境的下一个请求。
环境总是要求下载当前最优的进化电路,因此,IP核必须保存目前为止最优的配置,并且在需要的时候提供出去。可进化IP核总是屏蔽重构过程,因此它对于外部环境来说是不可见的。
对于一些特殊的应用,必须为它们开发专用的可进化IP核,因为反映应用的要求基因单元和可重构电路的体系结构将使进化过程优于一个随机的搜索。由于适应度计算是在IP核外进行的,因此IP核原则上支持动态适应度函数和无限的进化。可进化IP核可以用软件实现。
三 项目实施方案
3.1方案基本功能框图
图2 系统框图
图3 DWT2D核原理图
图 4 由四个RTP核构成的四拍FIR滤波器
1.硬件部分
可进化IP核的实现
3.1 实现中的问题
可复用的IP核通常有软核、固核和硬核三种。本文讨论的是软核。本文的目标是,设计和实现以HDL源代码(例如,VHDL)表示的可进化IP核。其优点是IP核的表示独立于平台,这样它们就可以在各种不同的目标结构中运行。要解决的主要问题是,可进化的IP核的内部可重构电路的自动重构(因为它们是可进化的)。
图 5 用vertex slice 实现的虚拟可重构电路
当一个可进化IP核从一个组件库中被下载到可重构器件的一个指定位置时,它的内部可重构电路必须进行重构。这就意味着这个可重构器件中的一些可编程块必须能配置这个可重构器件的其它内部可编程块。另外,这个可进化IP核(它的基因单元)能被放置于这个可编程阵列(即可重构器件)的任何位置,也就是说,这个可重构器件中必须支持内部重构。
FPGA以其动态可重构的优点,无疑是可进化IP核的最佳实现平台。然而,通常的FPGA并不支持内部重构,而只允许通过一个特殊的配置接口外部重构(如图5)。目前,只存在一种支持内部重构的平台,就是单元阵列,但这种芯片目前还相当少。因此,为了在普通FPGA器件实现可进化IP核,使之能在实际应用中发挥作用,必须采用其它的一些方法。硬件虚拟化是基于FPGA的系统常用的一种设计技术。从这个思想出发,本文采用了一个被称为虚拟可重构电路的技术来实现可进化硬件中的内部可重构电路。但文中对设计虚拟可重构电路的概念进行了扩展。
3.2 虚拟可重构电路
一些FPGA芯片支持部分重构,也就是允许可重构系统的一部分重构,而不影响其余部分的运行。部分重构的优点在于,其重构所花的时间比全部重构更少。本文以支持部分重构的Xilinx Virtex FPGA为例,来说明虚拟可重构电路的实现。IP核可以动态地下载到FPGA或从FPGA删除。所有的操作都通过Virtex重构端口和Jbits接口来完成。当一个可进化IP核被下载时,它的重构位串在指定位置构靠下列单元;虚拟可重构电路、基因单元和控制器。
图5表明,虚拟可重构电路实际上是一种在普通FPGA上实现的新的可重构电路。本例中由八个可编程元素构成,由Virtex单元(slice)实现。Virtex单元实现新的可编程元素阵列、新的布线电路和新的配置存储器。虚拟电路能内部重构,但如果有其它新的配置存储器与之连接,也可从FPGA的I/O引脚配置。
这种方法的优点在于:可根据具体的应用需要准确地设计可编程元素阵列、布线电路和配置存储器。虚拟可重构电路的重构方式和粒度能准确地反映具体应用的需要。通过虚拟可重构电路,很容易把领域知识插入到基因单元和可重构电路的体系结构中,从而获得电路软件模型的精确实现。
图6给出了一个虚拟可编程元素的例子。这个虚拟可重构电路由8个这样的元素构成,有4个输入和2个输出。这些虚拟可编程元素称为可重配置功能块CFB(Configurable Functional Blocks)。每个CFB对应一个配置位串(这里的位串为6位),其中两个配置位决定了CFB的功能,其它四位定义了输入的连接信息。布线电路由多路器组成,它们由配置存储器中的位串控制。配置存储器由Virtex单元构成,一个Virtex单元包含两个触发器,用于存储配置位串中的两位。配置存储器的所有位都连到多路器,多路器控制布线和CFB中功能的选择。
虚拟可重构电路中CFB的数量由具体的应用决定。虚拟可重构电路用结构级VHDL语言来描述,但是一些基本的电路(例如“MAX”电路)用行为级来描述。虚拟可重构能在不同的目标器件下综合,目标器件并不需要支持部分重构。
图 6 虚拟可重构电路及其中一个CFB的实现
3.3 基因单元和控制器
基因单元和控制器的实现通常有两种选择:采用普通微处理器实现,或者设计一个专用的电路来实现。
专用的电路是指一种进化算法的硬件实现,目前在可进化硬件领域已经开发了很多这样的实现。这种算法的优点是电路的进化速度快,适合于复杂的应用。
采用微处理器实现时,可以购买或免费获得现成的微处理器软核,如Xilinx提供的MicroBlaze和PicoBlaze微控制器IP核,Altera生产Nios核,等等。此外,如果给出的目标可重构器件中有片上处理器,可以使用片上处理器,Xilinx Virtex II Pro XC2VP50芯片包含四个PowerPC处理器。处理器必须通过编程来执行程序,它们能和核周围的环境进行通信并完成对染色体的基因操作。此外,处理器还负责内部虚拟可重构电路的重构。
2. 软件部分
(1)bit n 的生成过程
图 7 输出地址bit n 的生成
图 8 输入地址bit n 的生成
(2)部分代码
1 #Configuring F and G look-up tables with JBits
/* define row and column values */
int row = 5; int col = 4;
/* define logic function for F LUT */
int[] F_LUT_Vals = Expr.F_LUT(“~(F1&F2&F3&F4)”);
/* define logic function for G LUT */
int[] G_LUT_Vals = Expr.G_LUT(“~(F1|F2|F3|F4)”);
/* set the F LUT value for slice 0 */
jbits.set(row, col, LUT.SLICE0_F, F_LUT_Vals);
/* set the G LUT value for slice 1 */
jbits.set(row, col, LUT.SLICE1_G, G_LUT_Vals);
2 #: Adding and configuring an OutputCore
/* create a signal to run to the cross bar pins on the Slaac1V X2 */
Bus XBar = new Bus(“XP_XBAR”, null, 20);
/* create a new board */
Slaac1VBoard slaac1V = new Slaac1VBoard(“SLAAC1V”);
/* add a cross bar output core to slaac1V board instance */
int XBarOutput = slaac1V.addOutput(Xbar.getName(), XBar);
/* configure the IOB resources output operation */
slaac1V.setOutputInvertT(XBarOutput, true);
/* implement the slaac1V board */
slaac1V.implement(0, “slaac1V.ucf”);
3 #Code showing how Slaac1V SRAMs are distinguished through signal names.
/* define memory signals for Slaac1V X2 memories 0 and 1 */
Bus addr[] = new Bus[2];
Bus data[] = new Bus[2];
/* memory address */
addr[0] = new Bus(“XP_MEM0_ADDR”, null, 18); /* SRAM 0 */
addr[1] = new Bus(“XP_MEM1_ADDR”, null, 18); /* SRAM 1 */
/* memory data */
data[0] = new Bus(“XP_MEM0_DATA”, null, 12); /* SRAM 0 */
data[1] = new Bus(“XP_MEM1_DATA”, null, 12); /* SRAM 1 */
4 #AdderTree input index computations and partitioning process
/* calculate the “parent” adder index */
int log = (int) Math.ceil(Math.log((double)range)/Math.log(2.0));
int parentAdder = low + (int) Math.pow(2.0,log - 1);
/* calculate the right sided adder input index */
range = high - parentAdder;
log = (int) Math.ceil(Math.log((double)range)/Math.log(2.0));
int RHSIndex = ((int) Math.pow(2.0, log - 1)) + parentAdder;
/* calculate the left sided adder input index */
range = parentAdder - low;
log = (int) Math.ceil(Math.log((double)range)/Math.log(2.0));
int LHSIndex = ((int) Math.pow(2.0, log - 1)) + low;
/* partition left hand side of parent adder recursively */
AIndex[parentAdder - 1] = LHSIndex - 1;
deriveAdderTree(low, parentAdder);
/* partition right hand side of parent adder recursively */
if (RHSIndex != parentAdder)
{
BIndex[parentAdder - 1] = RHSIndex - 1;
deriveAdderTree(parentAdder, high);
}
else /* required if there is an odd number of tree inputs */
{
BIndex[parentAdder - 1] = treeInPort.length - 1;
}
5 # Slaac1VBoard.java code
public class Slaac1VBoard extends Board
{
public Slaac1VBoard(String name) throws CoreParameterException
{
super(name);
setXCVPackage(xcvPackage);
setGCLK(GCLK);
};
private XCVPackage xcvPackage[] =
{
new xcv1000_fg680(), new xcv1000_fg680(), new xcv1000_fg680()
};
private static int GCLK = 2;
}; /* end of Slaac1V board class. */
3.2 需要的开发平台
硬件平台软件平台
PC机Linux
XUPV5-LX110T开发板QT
Matlab
ISE
ModelSim
Jbit
全部0条评论
快来发表一下你的评论吧 !