//--------------------------------------------------------------------------------// // COPYRIGHT NOTICE // //--------------------------------------------------------------------------------// // Copyright (c) 2012, Instituto de Microelectronica de Sevilla (IMSE-CNM) // // // // All rights reserved. // // // // Redistribution and use in source and binary forms, with or without // // modification, are permitted provided that the following conditions are met: // // // // * Redistributions of source code must retain the above copyright notice, // // this list of conditions and the following disclaimer. // // // // * Redistributions in binary form must reproduce the above copyright // // notice, this list of conditions and the following disclaimer in the // // documentation and/or other materials provided with the distribution. // // // // * Neither the name of the IMSE-CNM nor the names of its contributors may // // be used to endorse or promote products derived from this software // // without specific prior written permission. // // // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE // // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //--------------------------------------------------------------------------------// package xfuzzy.xfvhdl; import java.util.ArrayList; import xfuzzy.lang.*; /** * Clase que genera el fichero VHDL con el testbench para chequear el * correcto funcionamiento del m�dulo de inferencia del controlador difuso * o para chechear el correcto funcionamiento del sistema jer�rquico. * * @author Lidia Delgado Carretero * */ public class XfvhdlTestBenchFile { //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// // ATRIBUTOS DE LA CLASE //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// /**Guarda las variables de entrada y salida del sistema jer�rquico.*/ private ArrayList<String> listaVblesSistema=new ArrayList<String>(); /**N� de entradas.*/ private int inputs; //cadena que es distinta si se trata del test bench de la //jerarqu�a o si se trata del test bench de un flc. private String Narray; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// // M�TO_DOS P�BLICOS DE LA CLASE //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// /** * M�todo que crea la cadena que ser� escrita en el fichero de * testbench. * @return Devuelve la cadena que ser� escrita en el fichero de * testbench. */ public String createTestBenchSource(Specification spec,XfvhdlFLC flc, ArrayList<XfvhdlFLC> listaFlc, ArrayList<XfvhdlCrisp> listaCrisp) { int cycles_off; XfvhdlHeadFile head; String name; int N=0, No=0; String WORK=""; String entradasArray,generic1="",generic2="", port1,cadInputs="",cadOutputs="",signalouts="", s_output=""; if(flc==null){//Se trata del test bench de jerarquia name=XfvhdlProperties.name_outputfiles; inputs=spec.getSystemModule().getInputs().length; for (int i=0;i<inputs;i++){ listaVblesSistema.add(spec.getSystemModule().getInputs()[i].getName()); } for (int i=0;i<spec.getSystemModule().getOutputs().length;i++){ listaVblesSistema.add(spec.getSystemModule().getOutputs()[i].getName()); } for(int i=0;i<listaVblesSistema.size();i++){ if(i<inputs){ N=(N> XfvhdlLeerXfl.maximoBitsEntradaDeSistema(listaVblesSistema.get(i),spec.getSystemModule().getModuleCalls(),listaFlc,listaCrisp) ? N: XfvhdlLeerXfl.maximoBitsEntradaDeSistema(listaVblesSistema.get(i),spec.getSystemModule().getModuleCalls(),listaFlc,listaCrisp)); cadInputs+="\t\t"+listaVblesSistema.get(i)+" : in std_logic_vector("+XfvhdlLeerXfl.maximoBitsEntradaDeSistema(listaVblesSistema.get(i),spec.getSystemModule().getModuleCalls(),listaFlc,listaCrisp)+" downto 1); -- Input "+(i+1)+" signal.\n"; }else{ No=(No> XfvhdlLeerXfl.bitsSalidaSistema(listaVblesSistema.get(i),spec.getSystemModule().getModuleCalls(),listaFlc,listaCrisp) ? N: XfvhdlLeerXfl.bitsSalidaSistema(listaVblesSistema.get(i),spec.getSystemModule().getModuleCalls(),listaFlc,listaCrisp)); cadOutputs+="\t\t"+listaVblesSistema.get(i)+" : out std_logic_vector(" + XfvhdlLeerXfl.bitsSalidaSistema(listaVblesSistema.get(i),spec.getSystemModule().getModuleCalls(),listaFlc,listaCrisp) + " downto 1); -- Output "+(i-inputs+1)+" signal.\n"; signalouts+="\tsignal s_output"+(i-inputs+1)+" : std_logic_vector(" + XfvhdlLeerXfl.bitsSalidaSistema(listaVblesSistema.get(i),spec.getSystemModule().getModuleCalls(),listaFlc,listaCrisp) + " downto 1);\n"; } } head = new XfvhdlHeadFile(name, inputs); cycles_off=5; entradasArray=inputs+""; Narray=N+""; s_output="s_output1"; port1=" clk : in std_logic; -- Clock signal.\n" + " reset : in std_logic; -- Reset signal.\n" + cadInputs+ cadOutputs+ " pipeline : out std_logic"; }else{ name=flc.getname(); inputs=flc.getinputs(); N=flc.getN(); No=flc.getNo(); WORK="use WORK."+name+"_Constants.all;\n\n"; entradasArray=name+"_inputs"; Narray=name+"_N"; s_output = "s_output"; generic1="\tgeneric(\n" + "\t\t"+name+"_pipe\t: integer;\n" + "\t\t"+name+"_bits\t: integer);\n"; generic2+= "\tgeneric map(\n" + "\t\t"+name+"_pipe\t=> pipe_"+name+",\n" + "\t\t"+name+"_bits\t=> bits_"+name+")\n" ; port1="\t\tclk\t\t\t: in std_logic;\n" + "\t\treset\t\t: in std_logic;\n" + entityInputPorts(inputs,Narray) + "\t\tout1\t\t: out std_logic_vector("+name+"_No downto 1);\n" + "\t\tpipeline\t: out std_logic"; head = new XfvhdlHeadFile(name,inputs); signalouts="\tsignal s_output\t\t: std_logic_vector("+name+"_No downto 1);\n"; if(flc.getSimplificado()){ cycles_off=2; }else{//no simplificado cycles_off=3; } // if (flc.getMFC_arithmetic()) // cycles_off=cycles_off+1; } String code = head.getHeadTB(); code += "\n" + "library IEEE;\n" + "use IEEE.std_logic_1164.all;\n" + "use IEEE.std_logic_arith.all;\n" + "use IEEE.std_logic_unsigned.all;\n" + "use IEEE.std_logic_textio.all;\n" + "use std.textio.all;\n\n" + WORK + "library XfuzzyLib;\n" + "use XfuzzyLib.Entities.all;\n\n\n" + "---------------------------------------------------------------------------\n" + "-- Entity description --\n" + "---------------------------------------------------------------------------\n\n" + "entity "+name+"_tb is\n\n" + "\tgeneric ("+name+"_Ntb : integer := 5);\n\n" + "end "+name+"_tb;\n\n\n" + "---------------------------------------------------------------------------\n" + "-- Architecture description --\n" + "---------------------------------------------------------------------------\n" + "\n" + "architecture FPGA of "+name+"_tb is\n\n" + "\ttype s_input_array is array(1 to " + entradasArray + ") of " + "std_logic_vector("+Narray+" downto 1);\n" + "\tsignal s_clk\t\t: std_logic;\n" + "\tsignal s_reset\t\t: std_logic;\n" + "\tsignal s_pipeline\t: std_logic;\n" + "\tsignal s_input\t\t: s_input_array;\n" + signalouts + "\n" + "\tcomponent "+name+"\n" + generic1 + "\tport(\n" + port1 + ");\n" + "\tend component;\n\n" + "begin\n\n" // UUT + "\tUUT : "+name+"\t\t\t\t-- Fuzzy logic controller instance.\n\n" + generic2 + "\tport map(\n" + "\t\tclk\t\t\t=> s_clk,\n" + "\t\treset\t\t=> s_reset,\n" + controllerSignals(inputs,flc, listaFlc, listaCrisp, spec) + "\t\tpipeline\t=> s_pipeline);\n\n" // Clock + "\tClock : process\t\t\t\t\t-- Clock signal generator.\n\n" + "\tbegin\n" + "\t\ts_clk <= '0';\n" + "\t\twait for "+(inputs>1?25:20)+" ns;\n" + "\t\ts_clk <= '1';\n" + "\t\twait for "+(inputs>1?25:20)+" ns;\n" + "\tend process;\n\n" //Test + "\tTest : process\t\t\t\t\t-- Testbench process.\n\n" + "\t\tvariable cycles_pipe : integer := "+cycles_off+";\n" + "\t\tvariable value_out\t: integer := 0;\n" + "\t\tvariable cycles_off\t: integer := 0;\n" + "\t\tvariable lin\t\t: line;\n\n" + "\t\tfile fil : text open write_mode is \"SIM.out\";\n\n" + "\t\ttype value_in_array is array (1 to "+entradasArray+", 1 to cycles_pipe) of integer;\n" + "\t\ttype input_array is array (1 to 2) of integer;\n" + "\t\tvariable value_in\t: value_in_array;\n" + "\t\tvariable input\t\t: input_array;\n\n" // + "\tbegin\n" + (inputs>1? "\t\tinput := (1,2);\n\n":"\t\tinput := (1,0);\n\n") + "\t\tif (s_reset = 'U') then\n" + "\t\t\ts_reset <= '1';\n" + "\t\t\twait for 90 ns;\n" + "\t\t\ts_reset <= '0';\n" + resetInputSignals(inputs, N) + "\t\telse\n" + "\t\t\twait until rising_edge(s_pipeline);\n" // + "\t\t\t\tfor i in 1 to " +(inputs>1? "2":"1")+ " loop\n" + "\t\t\t\t\tif (cycles_pipe > 1) then\n" + "\t\t\t\t\t\tfor j in 1 to (cycles_pipe-1) loop\n" + "\t\t\t\t\t\t\tvalue_in(input(i),j) := value_in(input(i),j+1);\n" + "\t\t\t\t\t\tend loop;\n" + "\t\t\t\t\tend if;\n" + "\t\t\t\t\tvalue_in(input(i),cycles_pipe) := conv_integer('0' & s_input(input(i)));\n" + "\t\t\t\tend loop;\n\n" // + "\t\t\t\tvalue_out := conv_integer('0' & "+s_output+");\n\n" // + "\t\t\t\tif (cycles_off >= cycles_pipe-1) then\n" + "\t\t\t\t\twrite(lin, value_in(input(1),1), right, 7);\n" + (inputs>1? "\t\t\t\t\twrite(lin, value_in(input(2),1), right, 7);\n":"") + "\t\t\t\t\twrite(lin, value_out, right, 7);\n" + "\t\t\t\t\twriteline(fil, lin);\n" + (inputs>1? "\t\t\t\t\tif (value_in(input(1),1) = 2**" + Narray + " - 1) then\n" + "\t\t\t\t\t\twrite(lin, ' ');\n" + "\t\t\t\t\t\twriteline(fil, lin);\n" + "\t\t\t\t\tend if;\n" :"") + "\t\t\t\telse\n" + "\t\t\t\t\tcycles_off := cycles_off + 1;\n" + "\t\t\t\tend if;\n\n" // + "\t\t\tif (s_input(input(1)) < 2**"+Narray+" - 2**("+Narray+" - "+name+"_Ntb)) then\n" + "\t\t\t\ts_input(input(1)) <= s_input(input(1)) + 2**("+Narray+" - "+name+"_Ntb);\n" + "\t\t\tend if;\n\n" // + "\t\t\tif (s_input(input(1)) = 2**"+Narray+" - 2**("+Narray+" - "+name+"_Ntb)) then\n" + "\t\t\t\ts_input(input(1)) <= s_input(input(1)) + 2**("+Narray+" - "+name+"_Ntb) - 1;\n" + "\t\t\tend if;\n\n" // + "\t\t\tif (s_input(input(1)) = 2**"+Narray+" - 1) then\n" + "\t\t\t\ts_input(input(1)) <= (others => '0');\n" + (inputs>1? "\t\t\t\tif (s_input(input(2)) < 2**"+Narray+" - 2**("+Narray+" - "+name+"_Ntb)) then\n" + "\t\t\t\t\ts_input(input(2)) <= s_input(input(2)) + 2**("+Narray+" - "+name+"_Ntb);\n" + "\t\t\t\tend if;\n" + "\t\t\t\tif (s_input(input(2)) = 2**"+Narray+" - 2**("+Narray+" - "+name+"_Ntb)) then\n" + "\t\t\t\t\ts_input(input(2)) <= s_input(input(2)) + 2**("+Narray+" - "+name+"_Ntb) - 1;\n" + "\t\t\t\tend if;\n" : "" ) + "\t\t\tend if;\n\n" // + (inputs>1? "\t\t\tif ((value_in(input(1),1) = 2**"+Narray+" - 1)\n" + "\t\t\tand (value_in(input(2),1) = 2**"+Narray+" - 1)) then\n" + "\t\t\t\tfor i in 1 to 2 loop\n" + "\t\t\t\t\ts_input(input(i)) <= (others => '0');\n" + "\t\t\t\tend loop;\n" : "\t\t\tif (value_in(input(1),1) = 2**"+Narray+" - 1) then\n" + "\t\t\t\ts_input(input(1)) <= (others => '0');\n" ) + "\t\t\t\treport \"-- END OF SIMULATION --\";\n" + "\t\t\t\twait; -- End of simulation.\n" + "\t\t\tend if;\n" + "\t\tend if;\n" + "\tend process;\n\n" // + "end FPGA;\n"; return code; } /**@return Subcadena que describe las entradas en el bloque Entity.*/ private String entityInputPorts(int n, String Narray){ String res=""; for(int i=0;i<n;i++){ res+="\t\tin"+(i+1)+"\t\t\t: in std_logic_vector("+Narray+" downto 1);\n"; } return res; } /**@return Subcadena que describe las conexiones de las se�ales * en la zona de Controller.*/ private String controllerSignals(int n, XfvhdlFLC flc, ArrayList<XfvhdlFLC> listaFlc, ArrayList<XfvhdlCrisp> listaCrisp, Specification spec){ String res=""; if(flc==null){ for(int i=0;i<listaVblesSistema.size();i++){ if(i<inputs){ int max = Integer.valueOf(Narray); int min = max- XfvhdlLeerXfl.maximoBitsEntradaDeSistema(listaVblesSistema.get(i),spec.getSystemModule().getModuleCalls(),listaFlc,listaCrisp)+1; res+="\t\t" + listaVblesSistema.get(i) + "\t\t\t=> s_input(" + (i + 1) + ")("+max+" downto "+min+"),\n"; }else res+="\t\t" + listaVblesSistema.get(i) + "\t\t\t=> s_output" + (i - inputs + 1) + ",\n"; } }else{ for(int i=0;i<n;i++){ res+="\t\tin" + (i + 1) + "\t\t\t=> s_input(" + (i + 1) + "),\n"; } res+="\t\tout1\t\t=> s_output,\n"; } return res; } private String resetInputSignals(int n, int nb){ String res=""; if(n==1){ res+= "\t\t\ts_input(input(1)) <= (others => '0');\n"; }else{ if(n>2){ for(int i=1;i<=n;i++){ res+="\t\t\ts_input("+i+") <= \"1"; for(int j=2;j<=nb;j++){ res+="0"; } res+="\";\n"; } } res+= "\t\t\ts_input(input(1)) <= (others => '0');\n" + "\t\t\ts_input(input(2)) <= (others => '0');\n"; } return res; } }