用于生成vhdl以转换为std_逻辑向量和从std_逻辑向量转换为std_逻辑向量的实用程序,以及用于创建python描述的测试台的实用程序。

slvcodec的Python项目详细描述


slvcodec是一个分析vhdl并生成:

  • Functions to convert arbitrary VHDL types to and from std_logic_vector.
  • Generate testbenches for entities that read inputs from a file, and write outputs to a file.
  • Utilities so that unit tests for VHDL code can easily to be written in python.

生成转换为标准逻辑向量和转换为标准逻辑向量的函数

下面是一个vhdl包的示例。

libraryieee;useieee.numeric_std.all;packagecomplexisconstantFIXED_WIDTH:natural:=8;subtypefixed_tisunsigned(FIXED_WIDTH-1downto0);typecomplex_tisrecordreal:fixed_t;imag:fixed_t;endrecord;typearray_of_complexisarray(naturalrange<>)ofcomplex_t;endpackage;

下面的python脚本用于生成包含 用于将类型转换为std_logic_vector和从std_logic_vector转换类型的函数。

importosfromslvcodecimportfiletestbench_generatorthisdir=os.path.dirname(__file__)defmake_slvcodec_package():complex_pkg_fn=os.path.join(thisdir,'complex_pkg.vhd')directory=os.path.join(thisdir,'generated')os.mkdir(directory)filetestbench_generator.add_slvcodec_files(directory,[complex_pkg_fn])if__name__=='__main__':make_slvcodec_package()

下面是生成的vhdl的外观。

libraryieee;useieee.std_logic_1164.all;useieee.numeric_std.all;usework.complex.all;usework.slvcodec.all;packagecomplex_slvcodecisfunctionto_slvcodec(constantdata:array_of_complex)returnstd_logic_vector;functionfrom_slvcodec(constantslv:std_logic_vector)returnarray_of_complex;constantfixed_t_slvcodecwidth:natural:=fixed_width;constantcomplex_t_slvcodecwidth:natural:=2*fixed_width;functionto_slvcodec(constantdata:complex_t)returnstd_logic_vector;functionfrom_slvcodec(constantslv:std_logic_vector)returncomplex_t;endpackage;packagebodycomplex_slvcodecisfunctionto_slvcodec(constantdata:array_of_complex)returnstd_logic_vectorisconstantW:natural:=complex_t_slvcodecwidth;constantN:natural:=data'length;variableslv:std_logic_vector(N*W-1downto0);beginforiiin0toN-1loopslv((ii+1)*W-1downtoii*W):=to_slvcodec(data(ii));endloop;returnslv;endfunction;functionfrom_slvcodec(constantslv:std_logic_vector)returnarray_of_complexisconstantW:natural:=complex_t_slvcodecwidth;constantN:natural:=slv'length/W;variablemapped:std_logic_vector(slv'length-1downto0);variableoutput:array_of_complex(N-1downto0);beginmapped:=slv;foriiin0toN-1loopoutput(ii):=from_slvcodec(mapped((ii+1)*W-1downtoii*W));endloop;returnoutput;endfunction;functionto_slvcodec(constantdata:complex_t)returnstd_logic_vectorisconstantW0:natural:=0;constantW1:natural:=W0+fixed_width;constantW2:natural:=W1+fixed_width;variableslv:std_logic_vector(complex_t_slvcodecwidth-1downto0);beginslv(W1-1downtoW0):=to_slvcodec(data.real);slv(W2-1downtoW1):=to_slvcodec(data.imag);returnslv;endfunction;functionfrom_slvcodec(constantslv:std_logic_vector)returncomplex_tisconstantW0:natural:=0;constantW1:natural:=W0+fixed_width;constantW2:natural:=W1+fixed_width;variabledata:complex_t;variablemapped:std_logic_vector(complex_t_slvcodecwidth-1downto0);beginmapped:=slv;data.real:=from_slvcodec(mapped(W1-1downtoW0));data.imag:=from_slvcodec(mapped(W2-1downtoW1));returndata;endfunction;endpackagebody;

生成基于文件的测试台

下面是一个示例实体,它只返回复杂数据类型的大小平方 我们之前定义的。

libraryieee;useieee.numeric_std.all;usework.complex.all;entitycomplex_mag2isport(i:incomplex_t;o:outunsigned(FIXED_WIDTH+1-1downto0));endentity;architecturearchofcomplex_mag2issignalreal2:signed(FIXED_WIDTH*2-1downto0);signalimag2:signed(FIXED_WIDTH*2-1downto0);signalmag2:unsigned(FIXED_WIDTH*2-1downto0);signalscaled_mag2:unsigned(FIXED_WIDTH+1-1downto0);beginreal2<=i.real*i.real;imag2<=i.imag*i.imag;mag2<=unsigned(real2)+unsigned(imag2);scaled_mag2<=mag2(FIXED_WIDTH*2-1-1downtoFIXED_WIDTH-2);o<=scaled_mag2;endarchitecture;

我们可以使用slvcodec生成一个从文件中读取输入数据的测试平台, 并将输出数据写入另一个文件。

importosfromslvcodecimportfiletestbench_generatorthisdir=os.path.dirname(__file__)defmake_slvcodec_package():complex_pkg_fn=os.path.join(thisdir,'complex_pkg.vhd')directory=os.path.join(thisdir,'generated')os.mkdir(directory)slvcodec_files=filetestbench_generator.add_slvcodec_files(directory,[complex_pkg_fn])returnslvcodec_filesdefmake_complex_mag2_testbench():base_filenames=[os.path.join(thisdir,'complex_pkg.vhd'),os.path.join(thisdir,'complex_mag2.vhd'),]slvcodec_fns=make_slvcodec_package()with_slvcodec_fns=base_filenames+slvcodec_fnsdirectory=os.path.join(thisdir,'generated')generated_fns,generated_wrapper_fns,resolved=filetestbench_generator.prepare_files(directory=directory,filenames=with_slvcodec_fns,top_entity='complex_mag2')returngenerated_fnsif__name__=='__main__':make_complex_mag2_testbench()

这将生成以下vhdl测试工作台。

libraryieee;useieee.std_logic_1164.all;usework.slvcodec.all;useieee.numeric_std.all;usework.complex.all;usework.complex_slvcodec.all;entitycomplex_mag2_tbisgeneric(CLOCK_PERIOD:time:=10ns;RUNNER_CFG:string;OUTPUT_PATH:string);endentity;architecturearchofcomplex_mag2_tbistypet_inputisrecordi:complex_t;endrecord;typet_outputisrecordo:unsigned((1+fixed_width)-1downto0);endrecord;constantt_input_slvcodecwidth:natural:=2*fixed_width;functionto_slvcodec(constantdata:t_input)returnstd_logic_vector;functionfrom_slvcodec(constantslv:std_logic_vector)returnt_input;functionto_slvcodec(constantdata:t_input)returnstd_logic_vectorisconstantW0:natural:=0;constantW1:natural:=W0+2*fixed_width;variableslv:std_logic_vector(t_input_slvcodecwidth-1downto0);beginslv(W1-1downtoW0):=to_slvcodec(data.i);returnslv;endfunction;functionfrom_slvcodec(constantslv:std_logic_vector)returnt_inputisconstantW0:natural:=0;constantW1:natural:=W0+2*fixed_width;variabledata:t_input;variablemapped:std_logic_vector(t_input_slvcodecwidth-1downto0);beginmapped:=slv;data.i:=from_slvcodec(mapped(W1-1downtoW0));returndata;endfunction;constantt_output_slvcodecwidth:natural:=(1+fixed_width);functionto_slvcodec(constantdata:t_output)returnstd_logic_vector;functionfrom_slvcodec(constantslv:std_logic_vector)returnt_output;functionto_slvcodec(constantdata:t_output)returnstd_logic_vectorisconstantW0:natural:=0;constantW1:natural:=W0+(1+fixed_width);variableslv:std_logic_vector(t_output_slvcodecwidth-1downto0);beginslv(W1-1downtoW0):=to_slvcodec(data.o);returnslv;endfunction;functionfrom_slvcodec(constantslv:std_logic_vector)returnt_outputisconstantW0:natural:=0;constantW1:natural:=W0+(1+fixed_width);variabledata:t_output;variablemapped:std_logic_vector(t_output_slvcodecwidth-1downto0);beginmapped:=slv;data.o:=from_slvcodec(mapped(W1-1downtoW0));returndata;endfunction;signalinput_data:t_input;signaloutput_data:t_output;signalinput_slv:std_logic_vector(t_input_slvcodecwidth-1downto0);signaloutput_slv:std_logic_vector(t_output_slvcodecwidth-1downto0);signalclk:std_logic;signalread_clk:std_logic;signalwrite_clk:std_logic;begininput_data<=from_slvcodec(input_slv);output_slv<=to_slvcodec(output_data);file_reader:entitywork.ReadFilegenericmap(FILENAME=>OUTPUT_PATH&"/indata.dat",PASSED_RUNNER_CFG=>RUNNER_CFG,WIDTH=>t_input_slvcodecwidth)portmap(clk=>read_clk,out_data=>input_slv);file_writer:entitywork.WriteFilegenericmap(FILENAME=>OUTPUT_PATH&"/outdata.dat",WIDTH=>t_output_slvcodecwidth)portmap(clk=>write_clk,in_data=>output_slv);clock_generator:entitywork.ClockGeneratorgenericmap(CLOCK_PERIOD=>CLOCK_PERIOD,CLOCK_OFFSET=>0ns)portmap(clk=>clk);read_clock_generator:entitywork.ClockGeneratorgenericmap(CLOCK_PERIOD=>CLOCK_PERIOD,CLOCK_OFFSET=>CLOCK_PERIOD/10)portmap(clk=>read_clk);write_clock_generator:entitywork.ClockGeneratorgenericmap(CLOCK_PERIOD=>CLOCK_PERIOD,CLOCK_OFFSET=>4*CLOCK_PERIOD/10)portmap(clk=>write_clk);dut:entitywork.complex_mag2portmap(i=>input_data.i,o=>output_data.o);endarchitecture;

但是生成一个只读取和写入输入和输出数据的测试平台 除非我们有一种生成 输入数据,并检查输出数据。slvcodec包含执行此操作的工具 和Python一起。

基于python的测试

我们使用make_input_data方法定义了一个python类,该方法返回 指定输入数据的字典,以及接收 一个输入数据字典列表和一个输出数据字典列表,它引发一个 exeception是输出数据不正确。

classComplexMag2Test:def__init__(self,resolved,generics,top_params):# Here we're taking advantage of the fact that when the test is intialized it# has access to the parsed VHDL.  We use that to get the value of the constant# FIXED_WIDTH that is defined in complex_pkg.vhd.self.fixed_width=resolved['packages']['complex'].constants['fixed_width'].value()self.max_fixed=pow(2,self.fixed_width-1)-1self.min_fixed=-pow(2,self.fixed_width-1)self.n_data=100deffixed_to_float(self,f):r=f/pow(2,self.fixed_width-2)returnrdefmake_input_data(self,seed=None,n_data=3000):input_data=[{'i':{'real':random.randint(self.min_fixed,self.max_fixed),'imag':random.randint(self.min_fixed,self.max_fixed)},}foriinrange(self.n_data)]returninput_datadefcheck_output_data(self,input_data,output_data):inputs=[self.fixed_to_float(d['i']['real'])+self.fixed_to_float(d['i']['imag'])*1jfordininput_data]input_float_mag2s=[abs(v)*abs(v)forvininputs]outputs=[self.fixed_to_float(d['o'])fordinoutput_data]differences=[abs(expected-actual)forexpected,actualinzip(input_float_mag2s,outputs)]allowed_error=1/pow(2,self.fixed_width-2)assertall([d<allowed_errorfordindifferences])

然后使用slvcodec.test_utils.register_test_with_vunit生成适当的测试台和输入 数据文件,并向vunit注册生成的测试。然后vunit可以正常运行。

fromslvcodecimporttest_utils,configimportosif__name__=='__main__':random.seed(0)# Initialize vunit with command line parameters.vu=config.setup_vunit()# Set up logging.config.setup_logging(vu.log_level)# Get filenames for testthis_dir=os.path.dirname(os.path.realpath(__file__))filenames=[os.path.join(this_dir,'complex_pkg.vhd'),os.path.join(this_dir,'complex_mag2.vhd'),]# Register the test with VUnit.test_output_directory=os.path.join(this_dir,'generated')test_utils.register_test_with_vunit(vu=vu,directory=test_output_directory,filenames=filenames,top_entity='complex_mag2',all_generics=[{}],test_class=ComplexMag2Test,top_params={},)# Run the tests with VUnitvu.set_sim_option('disable_ieee_warnings',True)vu.main()

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
如何使用运行时从JAVA运行openssl命令?   不使用线程安全类(如AtomicInteger和SynchronizedList)的java ProducerConsumer问题   匹配字符串的java模式   在java中使用泛型接口作为返回类型   java将可能具有序列化JSON值的hashmap作为节点添加到JSON字符串中   Eclipse无法从Java8流推断正确的类型   java无法了解标准JButton的大小   java我能用一个循环优化这个函数吗(在第一种方法中)?   Apache CXF中基于WebSocket的java SOAP?   java想要运行奇偶和求和三步   矩阵上随机元素的java集值   java布尔相等:0==a,操作数顺序重要吗?   java Eclipse不会退出我的插件   java如何在spring的SOAP拦截器中获取HttpServletRequest和HttpServletResponse