]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/commitdiff
TUMBL GHDL simulation testbed prepared.
authorPavel Pisa <ppisa@pikron.com>
Mon, 29 Dec 2014 00:01:13 +0000 (01:01 +0100)
committerPavel Pisa <ppisa@pikron.com>
Mon, 29 Dec 2014 00:01:13 +0000 (01:01 +0100)
Actual use is for simulate and catch problem with missing
wait for external bus data ready in some situations.

Signed-off-by: Pavel Pisa <ppisa@pikron.com>
hw/tb/Makefile [new file with mode: 0644]
hw/tb/convert_bin2bits.c [new file with mode: 0644]
hw/tb/lx_tumbl_tb.vhd [new file with mode: 0644]

diff --git a/hw/tb/Makefile b/hw/tb/Makefile
new file mode 100644 (file)
index 0000000..84e51f8
--- /dev/null
@@ -0,0 +1,55 @@
+GHDL=ghdl
+tumbl_SRC=mbl_pkg.vhd mem.vhd fetch.vhd exeq.vhd decode.vhd core_ctrl.vhd
+tumbl_DIR=../tumbl
+lx_rocon_tumbl_SRC=lx_rocon_imem.vhd lx_rocon_dmem.vhd lx_rocon_gprf_abd.vhd lx_rocon_tumbl.vhd
+lx_rocon_tumbl_DIR=../lx-rocon_tumbl
+lx_fncapprox_SRC=lx_fncapprox_pkg.vhd lx_fncapprox_dsp48.vhd rom_table.vhd lx_fncapprox.vhd
+lx_fncapprox_DIR=../lx-fncapprox
+lx_util_SRC=util_pkg.vhd lx_rocon_pkg.vhd xilinx_dualport_bram.vhd
+lx_util_DIR=..
+lx_rocon_SRC=dff3.vhd qcounter.vhd \
+       irc_proc_inc.vhd crc.vhd cnt_div.vhd measurement_register.vhd lxmaster_transmitter.vhd \
+       lxmaster_receiver.vhd lx_crosdom_ser_fifo.vhd irc_reader.vhd irc_proc_main.vhd \
+       dff2.vhd bus_tumbl.vhd bus_measurement.vhd bus_lxmaster.vhd bus_irc.vhd lx_rocon_top.vhd
+lx_rocon_DIR=..
+
+MODULES=tumbl lx_util lx_rocon_tumbl
+
+SRC=$(foreach m, $(MODULES), $($(m)_SRC:%=$($(m)_DIR)/%))
+
+$(warning SRC=$(SRC))
+
+#SRC+=lx_rocon_top_tb.vhd
+SRC+=lx_tumbl_tb.vhd
+
+CFLAGS += -Wall
+
+GHDLFLAGS+=
+ANALYZEFLAGS+=--std=93c --ieee=synopsys -fexplicit
+
+#SIM_FLAGS=--stop-time=1000ns #--ieee-asserts=disable
+
+all:   test-tumbl
+
+convert_bin2bits : convert_bin2bits.o
+
+imem.bits : imem.bin convert_bin2bits
+       ./convert_bin2bits $< >$@
+
+test-tumbl: analyze-all imem.bits
+       $(GHDL) $(GHDLFLAGS) -m $(ANALYZEFLAGS) lx_tumbl_tb
+       $(GHDL) $(GHDLFLAGS) -r  lx_tumbl_tb --stop-time=10000ns --vcd=$@.vcd
+
+test-rocon: analyze-all
+       $(GHDL) $(GHDLFLAGS) -m $(ANALYZEFLAGS) lx_rocon_top_tb
+       $(GHDL) $(GHDLFLAGS) -r lx_rocon_top_tb --stop-time=10000ns --vcd=$@.vcd
+
+analyze-all: $(SRC)
+       $(GHDL) $(GHDLFLAGS) -a $(ANALYZEFLAGS) $(SRC)
+
+
+clean:
+       rm -f convert_bin2bits
+       rm -f *.o
+       $(GHDL) --clean
+       $(RM) work-obj93.cf
diff --git a/hw/tb/convert_bin2bits.c b/hw/tb/convert_bin2bits.c
new file mode 100644 (file)
index 0000000..5289a40
--- /dev/null
@@ -0,0 +1,101 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+fprintbin(FILE *stream, uint32_t num, unsigned dig)
+{
+  uint32_t mask = 1 << (dig - 1);
+  for(; mask; mask >>= 1) {
+    if (fputc((num & mask)?'1':'0', stream) == EOF)
+      return -1;
+  }
+  return dig;
+}
+
+int main(int argc, char *argv[])
+{
+  char *fin_fname = NULL;
+  FILE *fin;
+  int ret = 0;
+  int vector_bits      = 32;
+  size_t vector_bytes  = 0;
+  int vector_be        = 1;
+  int vector_be_ralign = 0;
+
+  if (argc >= 2)
+    fin_fname = argv[1];
+
+  if (!vector_bytes)
+    vector_bytes = (vector_bits + 7) / 8;
+
+  if (!vector_bits)
+    vector_bits = vector_bytes * 8;
+
+  if (fin_fname != NULL) {
+    fin = fopen(fin_fname, "rb");
+    if (fin == NULL) {
+      fprintf(stderr, "%s: cannot open input file %s\n", argv[0], fin_fname);
+      exit(1);
+    }
+  } else {
+    fin = stdin;
+  }
+
+  {
+    uint8_t buff[vector_bytes];
+    size_t read_res;
+    uint8_t *p;
+    uint8_t b;
+    size_t br;
+    size_t bn;
+
+    do {
+      read_res = fread(buff, 1, vector_bytes, fin);
+      if (read_res == 0)
+        break;
+      if (read_res == -1) {
+        fprintf(stderr, "%s: data read error\n", argv[0]);
+        ret = 1;
+        break;
+      }
+      if (read_res < vector_bytes) {
+        fprintf(stderr, "%s: partial read of last element\n", argv[0]);
+        ret = 1;
+        memset(buff + read_res, 0, vector_bytes - read_res);
+      }
+
+      p = buff + (vector_be? 0: vector_bytes - 1);
+      bn = (vector_be & !vector_be_ralign)? 8: vector_bits % 8;
+
+      for (br = vector_bits; br; br -= bn, bn = 8) {
+        if (bn > br)
+          bn = br;
+        b = *p;
+        if (vector_be) {
+          if (!vector_be_ralign)
+            b >>= (8 - bn);
+          p++;
+        } else {
+          p--;
+        }
+        if (fprintbin(stdout, b, bn) < 0) {
+          fprintf(stderr, "%s: output stream write error\n", argv[0]);
+          ret = 1;
+          break;
+        }
+      }
+
+      if (fputc('\n', stdout) == EOF) {
+        ret = -1;
+        break;
+      }
+    } while(1);
+  }
+
+  if (fin_fname != NULL)
+    fclose(fin);
+
+  return ret;
+}
diff --git a/hw/tb/lx_tumbl_tb.vhd b/hw/tb/lx_tumbl_tb.vhd
new file mode 100644 (file)
index 0000000..f816fa8
--- /dev/null
@@ -0,0 +1,209 @@
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.numeric_std.all;
+
+LIBRARY std;
+USE std.textio.all;
+
+USE work.mbl_pkg.all;
+USE work.lx_rocon_pkg.all;
+
+
+
+ENTITY lx_tumbl_tb IS
+END lx_tumbl_tb;
+
+ARCHITECTURE behavior OF lx_tumbl_tb IS
+
+       --Clock signals
+       signal clk_cpu        : std_logic := '0';
+       signal clk_50m        : std_logic := '0';
+       -- Clock period definitions
+       --constant clk_period_cpu : time := 13.8 ns;
+       constant clk_period_50m : time := 20 ns;
+       constant cycle_cnt_limit : natural := 2**20 - 1;
+       signal cycle_cnt      : integer range 0 to cycle_cnt_limit;
+
+       signal tumbl_reset_s  : std_logic := '1';
+
+       -- Internal memory signals
+       signal imem_en_s      : std_logic := '0';
+       signal dmem_en_s      : std_logic := '0';
+
+       signal imem_we_s      : std_logic_vector(3 downto 0) := "0000";
+       signal dmem_we_s      : std_logic_vector(3 downto 0) := "0000";
+
+       signal imem_data_o_s  : std_logic_vector(31 downto 0);
+       signal dmem_data_o_s  : std_logic_vector(31 downto 0);
+
+       signal imem_data_i_s  : std_logic_vector(31 downto 0);
+       signal dmem_data_i_s  : std_logic_vector(31 downto 0);
+
+       signal imem_address_s : std_logic_vector(8 downto 0);
+       signal dmem_address_s : std_logic_vector(9 downto 0);
+
+       signal xmemb_sel_s    : std_logic;
+       signal xmemb_i_s      : DMEMB2CORE_Type;
+       signal xmemb_o_s      : CORE2DMEMB_Type;
+
+       signal imem_ready_s   : std_logic := '0';
+       signal imem_fill_addr_s : natural range 0 to 2**8-1 := 0;
+
+BEGIN
+       -- Instantiate the Unit Under Test (UUT)
+   uut: lx_rocon_tumbl
+       generic map
+       (
+               IMEM_ABITS_g         => 9,
+               DMEM_ABITS_g         => 10,
+               --
+               USE_HW_MUL_g         => true,
+               USE_BARREL_g         => true,
+               COMPATIBILITY_MODE_g => false
+       )
+       port map
+       (
+               clk_i        => clk_cpu,
+               rst_i        => tumbl_reset_s,
+               halt_i       => '0',
+               int_i        => '0',
+               trace_i      => '0',
+               trace_kick_i => '0',
+
+               pc_o         => open,
+               halted_o     => open,
+               halt_code_o  => open,
+
+               -- Internal memory (instruction)
+               imem_clk_i   => clk_cpu,
+               imem_en_i    => imem_en_s,
+               imem_we_i    => imem_we_s,
+               imem_addr_i  => imem_address_s,
+               imem_data_i  => imem_data_i_s,
+               imem_data_o  => imem_data_o_s,
+
+               -- Internal memory (data)
+               dmem_clk_i   => clk_cpu,
+               dmem_en_i    => dmem_en_s,
+               dmem_we_i    => dmem_we_s,
+               dmem_addr_i  => dmem_address_s,
+               dmem_data_i  => dmem_data_i_s,
+               dmem_data_o  => dmem_data_o_s,
+
+               -- External memory bus
+               xmemb_sel_o  => xmemb_sel_s,
+               xmemb_i      => xmemb_i_s,
+               xmemb_o      => xmemb_o_s
+       );
+
+       clk_cpu <= clk_50m;
+       xmemb_i_s.int <= '0'; -- No interrupt
+
+       setup_process :process
+       begin
+               wait until clk_cpu'event and clk_cpu = '1';
+               if cycle_cnt < cycle_cnt_limit and imem_ready_s = '1' then
+                       cycle_cnt <= cycle_cnt + 1;
+               end if;
+
+               if cycle_cnt < 8 then
+                       tumbl_reset_s <= '1';
+               else
+                       tumbl_reset_s <= '0';
+               end if;
+       end process;
+
+       setup_imem_process : process
+               file imem_file : text open READ_MODE is "imem.bits";
+               variable my_line : LINE;
+               variable bits_line : LINE;
+               variable mem_location : bit_vector(31 downto 0);
+       begin
+               wait until clk_50m'event and clk_50m = '1';
+
+               if endfile(imem_file) then
+                       if imem_ready_s = '0' then
+                               write(my_line, string'("reading imem complete"));
+                               writeline(output, my_line);
+                       end if;
+                       imem_ready_s <= '1';
+                       imem_we_s <= "0000";
+                       imem_en_s <= '0';
+               else
+                       imem_address_s <= std_logic_vector(to_unsigned(imem_fill_addr_s, 9));
+                       readline(imem_file, bits_line);
+                       read(bits_line, mem_location);
+                       imem_data_i_s <= to_stdLogicVector(mem_location);
+                       imem_we_s <= "1111";
+                       imem_en_s <= '1';
+                       imem_fill_addr_s <= imem_fill_addr_s + 1;
+               end if;
+
+       end process;
+
+       xmemb_process :process
+               variable xmemb_addr_v : std_logic_vector(14 downto 0);
+               variable my_line : LINE;
+               variable delay_access_v : std_logic;
+       begin
+               wait until clk_cpu'event and clk_cpu = '1';
+
+               -- Enable clken only when available for Tumbl
+               if cycle_cnt >= 34 and cycle_cnt <= 34 then
+                       delay_access_v := '1';
+               else
+                       delay_access_v := '0';
+               end if;
+
+               xmemb_i_s.clken <= not delay_access_v;
+
+               xmemb_i_s.data  <= (others => 'X');
+
+               xmemb_addr_v := xmemb_o_s.addr;
+
+               if xmemb_o_s.rd = '1' then
+                       if delay_access_v = '1' then
+                               xmemb_i_s.data(31 downto 16) <= x"F0F0";
+                       else
+                               xmemb_i_s.data(31 downto 16) <= x"ACCE";
+                               xmemb_i_s.data(15 downto 2) <= xmemb_addr_v(13 downto 0);
+                               xmemb_i_s.data(1 downto 0) <= "00";
+                       end if;
+
+                       write(my_line, string'("@"));
+                       write(my_line, cycle_cnt);
+                       write(my_line, string'(" tumbl read @("));
+                       write(my_line, to_bitvector(xmemb_o_s.addr));
+                       write(my_line, string'(")"));
+                       writeline(output, my_line);
+               end if;
+
+               if xmemb_o_s.bls /= "0000" then
+                       write(my_line, string'("@"));
+                       write(my_line, cycle_cnt);
+                       write(my_line, string'(" tumbl write "));
+                       write(my_line, to_bitvector(xmemb_i_s.data));
+                       write(my_line, string'(" -> @("));
+                       write(my_line, to_bitvector(xmemb_o_s.addr));
+                       write(my_line, string'(")"));
+                       writeline(output, my_line);
+               end if;
+       end process;
+
+
+       clk_50m_process :process
+       begin
+               clk_50m <= '1';
+               wait for clk_period_50m/2;
+               clk_50m <= '0';
+               wait for clk_period_50m/2;
+       end process;
+
+       -- Stimulus process
+       stim_proc: process
+       begin
+               -- External ModelSim script
+               wait;
+       end process;
+
+END;