[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [f-cpu] New snapshot for EU_INC and EU_CMP



On Tue, Jul 30, 2002 at 08:54:46PM +0200, Etienne LABARRE wrote:
[...]
> > Did you find source code or documentation for package std_logic_misc?
> 
> ???? It's standard library. Packages std_logic_1164 and std_logic_misc
> are available with all vhdl tools.
> (For example, with Simili, in Simili_dir/lib/ieee/stdlogicmisc.vhd)

A `standard' is something people have agreed on. Not everything that
is found in library std or library ieee is a standard (especially if
you use Synopsys).

[...]
> ==> the code don't must depend to techno.

Therefore we only use elements that are supposed to be available
everywhere: and/or gates with 2...4 inputs, 2-input xor gates, inverters
and muxes. With the famous `6 Gate Rule', any of them count as 1 gate.
Bigger elements (like an 8-input and gate) count as 2 or more gates.

After the first synthesis experiences, I later added another rule:
2-input xors count as 2 gates, and the sum of gate delays must not
exceed 10. I call this the `6G/10T' rule.

[...]
> > I doubt that you can get away with 8 cycles. From my experience, 64-bit
> > CMP alone needs 1 level of 2-xor, 3 levels of 4-and, 1 level of 2-xor,
> > 1 level of 2-and plus 3 levels of 4-or, giving a total of 9 levels.
> 
> Hmm, i have perhap's made an error. Can you look at my code ?

You have made many errors, according to my testbench for eu_cmp.

CMP is supposed to be either 0 or -1: cmp(a, b) = a < b ? -1 : 0.

MSB1 is supposed to return the *number* of the most significant `1'
bit: msb1(0xffffffff) = 64, msb1(0) = 0. Currently it returns some
strange bit mask. Likewise for MSB0.

I'll attach a testbench for eu_cmp.
-- 
 Michael "Tired" Riepe <Michael.Riepe@stud.uni-hannover.de>
 "All I wanna do is have a little fun before I die"
-- eu_cmp_test_mr.vhdl -- Testbench for eu_cmp
-- Copyright (C) 2001, 2002 Michael Riepe <michael@stud.uni-hannover.de>
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

-- $Id: icmp64_test.vhdl,v 1.1 2002/07/26 16:58:20 michael Exp $

--pragma synthesis_off

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use std.textio.all;
use IEEE.std_logic_textio.all;
--use work.Bit_Manipulation.all;

entity eu_cmp_test is
end eu_cmp_test;

architecture Arch_1 of eu_cmp_test is
	component eu_cmp
	   generic ( eu_cmp_width : natural := 6 );
	   port (
		  eu_cmp_A    : in  std_ulogic_vector(2**eu_cmp_width-1 downto 0);
		  eu_cmp_B    : in  std_ulogic_vector(2**eu_cmp_width-1 downto 0);
		  eu_cmp_simd : in  std_ulogic_vector(eu_cmp_width-4 downto 0);
		  eu_cmp_mode : in  std_ulogic_vector(2 downto 0);
		  eu_cmp_Y    : out std_ulogic_vector(2**eu_cmp_width-1 downto 0);
		  eu_cmp_Z    : out std_ulogic_vector(2**eu_cmp_width-1 downto 0)
		  );
	end component;

	constant WIDTH : natural := 64;

	signal M : std_ulogic_vector(5 downto 0) := (others => '0');
	signal A, B, Y, Z : std_ulogic_vector(WIDTH-1 downto 0) := (others => '0');
	signal Clk : std_ulogic := '0';
	signal Rst : std_ulogic := '0';
	signal En : std_ulogic := '1';

	procedure writestr (s : string) is
		variable lout : line;
	begin
		write(lout, s);
		writeline(output, lout);
	end writestr;

	procedure print_vector (lbl : string;
							x : std_ulogic_vector;
							des : string := " := ") is
		variable lout : line;
	begin
		write(lout, lbl & des); write(lout, x); writeline(output, lout);
	end print_vector;

	procedure print_signals is
	begin
		print_vector("A", A);
		print_vector("B", B);
		print_vector("M", M);
		print_vector("Y", Y);
		print_vector("Z", Z);
	end print_signals;

	procedure do_error (lbl : string;
						a_x, a_y : std_ulogic_vector) is
	begin
		writestr("WHOA THERE!!!");
		print_signals;
		print_vector(lbl, a_x);
		print_vector(lbl, a_y, " /= ");
	end do_error;

	procedure check_numeric (lbl : string;
							 x : std_ulogic_vector;
							 y : natural) is
		variable tmp : std_ulogic_vector(x'range);
		variable lout : line;
	begin
		tmp := std_ulogic_vector(to_unsigned(y rem 2**x'length, x'length));
		if x /= tmp then
			do_error(lbl, x, tmp);
		end if;
	end check_numeric;

	procedure check_logic (lbl : string;
						   a, b : std_ulogic_vector) is
		alias x : std_ulogic_vector(a'length downto 1) is a;
		alias y : std_ulogic_vector(b'length downto 1) is b;
		variable lout : line;
	begin
		assert a'length = b'length
			report "bad args in check_logic" severity failure;
		for i in x'range loop
			next when y(i) = '-';
			next when x(i) = y(i);
			do_error(lbl, x, y);
			return;
		end loop;
	end check_logic;
begin
	-- module under test
	mut : eu_cmp
		generic map (eu_cmp_width => 6)
		port map (
			eu_cmp_A => A,
			eu_cmp_B => B,
			eu_cmp_simd => M(5 downto 3),
			eu_cmp_mode => M(2 downto 0),
			eu_cmp_Y => Y,
			eu_cmp_Z => Z
		);

	-- driver process
	process
		constant std_ulogic_0 : std_ulogic := '0';
		constant std_ulogic_1 : std_ulogic := '1';

		procedure do_clock is
		begin
			wait for 1 ns;
--			Clk <= '1';
--			wait for 1 ns;
--			Clk <= '0';
		end do_clock;

		procedure print_mode (simd : in natural) is
			variable lout : line;
		begin
			write(lout, string'("*** testing "));
			write(lout, simd);
			write(lout, string'("-bit mode ***"));
			writeline(output, lout);
		end print_mode;

		procedure test_ucmp is
			variable av, bv, tmp : std_ulogic_vector(WIDTH-1 downto 0);
			variable simd, left, right : natural;
		begin
			writestr("*** testing unsigned cmp ***");
			for gran in 0 to 3 loop
				simd := 8 * 2**gran;
				print_mode(simd);
				M <= "XXX000";
				for i in 3 to 5 loop
					if i < gran + 3 then
						M(i) <= '1';
					else
						M(i) <= '0';
					end if;
				end loop;
				for chunk in 0 to WIDTH/simd-1 loop
					right := chunk*simd;
					left := right + simd - 1;
					av := (others => 'X');
					bv := (others => 'X');
					tmp := (others => '-');
					for index in left downto right loop
						av(index) := '0';
						bv(index) := '1';
						tmp(left downto right) := (left downto right => '1');
						A <= av; B <= bv; do_clock;
						check_logic("Y", Y, tmp);
						av(index) := '1';
						bv(index) := '0';
						tmp(left downto right) := (left downto right => '0');
						A <= av; B <= bv; do_clock;
						check_logic("Y", Y, tmp);
						av(index) := '0';
					end loop;
				end loop;
			end loop;
		end test_ucmp;

		procedure test_scmp is
			variable av, bv, tmp : std_ulogic_vector(WIDTH-1 downto 0);
			variable simd, left, right : natural;
		begin
			writestr("*** testing signed cmp ***");
			for gran in 0 to 3 loop
				simd := 8 * 2**gran;
				print_mode(simd);
				M <= "XXX000";
				for i in 3 to 5 loop
					if i < gran + 3 then
						M(i) <= '1';
					else
						M(i) <= '0';
					end if;
				end loop;
				for chunk in 0 to WIDTH/simd-1 loop
					right := chunk*simd;
					left := right + simd - 1;
					av := (others => 'X');
					bv := (others => 'X');
					tmp := (others => '-');
					av(left) := '0';
					bv(left) := '1';
					tmp(left downto right) := (left downto right => '0');
					A <= av; B <= bv; do_clock;
					check_logic("Y", Y, tmp);
					av(left) := '1';
					bv(left) := '0';
					tmp(left downto right) := (left downto right => '1');
					A <= av; B <= bv; do_clock;
					check_logic("Y", Y, tmp);
					bv(left) := '1';
					for index in left-1 downto right loop
						av(index) := '0';
						bv(index) := '1';
						tmp(left downto right) := (left downto right => '1');
						A <= av; B <= bv; do_clock;
						check_logic("Y", Y, tmp);
						av(index) := '1';
						bv(index) := '0';
						tmp(left downto right) := (left downto right => '0');
						A <= av; B <= bv; do_clock;
						check_logic("Y", Y, tmp);
						av(index) := '0';
					end loop;
				end loop;
			end loop;
		end test_scmp;

		procedure test_usort is
			variable av, bv, tmp : std_ulogic_vector(WIDTH-1 downto 0);
			variable simd, left, right : natural;
		begin
			writestr("*** testing unsigned sort ***");
			for gran in 0 to 3 loop
				simd := 8 * 2**gran;
				print_mode(simd);
				M <= "XXX011";
				for i in 3 to 5 loop
					if i < gran + 3 then
						M(i) <= '1';
					else
						M(i) <= '0';
					end if;
				end loop;
				for chunk in 0 to WIDTH/simd-1 loop
					right := chunk*simd;
					left := right + simd - 1;
					av := (others => 'X');	-- XXX: should use random data
					bv := (others => 'X');	-- XXX: should use random data
					tmp := (others => '-');
					for index in left downto right loop
						av(index) := '0';
						bv(index) := '1';
						A <= av; B <= bv; do_clock;
						tmp(left downto right) := av(left downto right);
						check_logic("Y", Y, tmp);
						tmp(left downto right) := bv(left downto right);
						check_logic("Z", Z, tmp);
						av(index) := '1';
						bv(index) := '0';
						A <= av; B <= bv; do_clock;
						tmp(left downto right) := bv(left downto right);
						check_logic("Y", Y, tmp);
						tmp(left downto right) := av(left downto right);
						check_logic("Z", Z, tmp);
						av(index) := '0';
					end loop;
				end loop;
			end loop;
		end test_usort;

		procedure test_ssort is
			variable av, bv, tmp : std_ulogic_vector(WIDTH-1 downto 0);
			variable simd, left, right : natural;
		begin
			writestr("*** testing signed sort ***");
			for gran in 0 to 3 loop
				simd := 8 * 2**gran;
				print_mode(simd);
				M <= "XXX011";
				for i in 3 to 5 loop
					if i < gran + 3 then
						M(i) <= '1';
					else
						M(i) <= '0';
					end if;
				end loop;
				for chunk in 0 to WIDTH/simd-1 loop
					right := chunk*simd;
					left := right + simd - 1;
					av := (others => 'X');	-- XXX: should use random data
					bv := (others => 'X');	-- XXX: should use random data
					tmp := (others => '-');
					av(left) := '0';
					bv(left) := '1';
					A <= av; B <= bv; do_clock;
					tmp(left downto right) := bv(left downto right);
					check_logic("Y", Y, tmp);
					tmp(left downto right) := av(left downto right);
					check_logic("Z", Z, tmp);
					av(left) := '1';
					bv(left) := '0';
					A <= av; B <= bv; do_clock;
					tmp(left downto right) := av(left downto right);
					check_logic("Y", Y, tmp);
					tmp(left downto right) := bv(left downto right);
					check_logic("Z", Z, tmp);
					bv(left) := '1';
					for index in left-1 downto right loop
						av(index) := '0';
						bv(index) := '1';
						A <= av; B <= bv; do_clock;
						tmp(left downto right) := av(left downto right);
						check_logic("Y", Y, tmp);
						tmp(left downto right) := bv(left downto right);
						check_logic("Z", Z, tmp);
						av(index) := '1';
						bv(index) := '0';
						A <= av; B <= bv; do_clock;
						tmp(left downto right) := bv(left downto right);
						check_logic("Y", Y, tmp);
						tmp(left downto right) := av(left downto right);
						check_logic("Z", Z, tmp);
						av(index) := '0';
					end loop;
				end loop;
			end loop;
		end test_ssort;

		procedure test_msb (bit : in std_ulogic) is
			variable av, bv, tmp : std_ulogic_vector(WIDTH-1 downto 0);
			variable simd, left, right : natural;
			variable lout : line;
		begin
			write(lout, string'("*** testing msb"));
			write(lout, bit);
			write(lout, string'(" ***"));
			writeline(output, lout);
			for gran in 0 to 3 loop
				simd := 8 * 2**gran;
				print_mode(simd);
				M <= "XXX10X";
				M(0) <= bit;
				for i in 3 to 5 loop
					if i < gran + 3 then
						M(i) <= '1';
					else
						M(i) <= '0';
					end if;
				end loop;
				for chunk in 0 to WIDTH/simd-1 loop
					right := chunk*simd;
					left := right + simd - 1;
					av := (others => 'X');
					av(left downto right) := (left downto right => not bit);
					bv := (others => 'X');
					tmp := (others => '-');
					tmp(left downto right) := (left downto right => '0');
					A <= av; B <= bv; do_clock;
					check_logic("Y", Y, tmp);
					for index in right to left loop
						av(index) := bit;
						tmp(left downto right) := std_ulogic_vector(
							to_unsigned(index - right + 1, simd));
						A <= av; B <= bv; do_clock;
						check_logic("Y", Y, tmp);
						av(index) := 'X';
					end loop;
				end loop;
			end loop;
		end test_msb;
	begin
		test_ucmp;
--		test_scmp;
		test_usort;
--		test_ssort;
		test_msb('0');
		test_msb('1');

		-- stop simulation
		writestr("*** simulation complete ***");
		wait;
	end process;
end Arch_1;

--pragma synthesis_on

-- vi: set ts=4 sw=4 equalprg="fmt -72 -p--": please