OpenCores
URL https://opencores.org/ocsvn/the_wizardry_project/the_wizardry_project/trunk

Subversion Repositories the_wizardry_project

[/] [the_wizardry_project/] [trunk/] [Wizardry/] [VHDL/] [Wizardry Top Level/] [Address Generation/] [JOP/] [cache.vhd] - Rev 22

Compare with Previous | Blame | View Log

--
--
--  This file is a part of JOP, the Java Optimized Processor
--
--  Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
--  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 3 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, see <http://www.gnu.org/licenses/>.
--
 
 
--
--	cache.vhd
--
--	Bytecode caching
--
--	jpc_with (set in top-level) configures the size.
--	Upper limit is 12 bits (4KB) due to the restriction in the
--	.jop file format (see JOPWriter.java). Changing this breaks
--	compatibility with other versions of JOP.
--
--	2005-01-11	first version
--	2005-05-03	configurable size (jpc_width)
--	2005-05-09	correction for ModelSim
--
 
-- library std;
-- use std.textio.all;
 
 
Library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
 
use work.jop_types.all;
 
-- 2**jpc_width is the caches size in bytes
-- 2**block_bits is the number of blocks
 
entity cache is
generic (jpc_width : integer; block_bits : integer; tag_width : integer := 18);
 
port (
 
	clk, reset	: in std_logic;
 
	bc_len		: in std_logic_vector(METHOD_SIZE_BITS-1 downto 0);		-- length of method in words
	bc_addr		: in std_logic_vector(17 downto 0);		-- memory address of bytecode
 
	find		: in std_logic;							-- start lookup
 
	-- start of method in bc cache
	-- in 32 bit words - we load only at word boundries
	bcstart		: out std_logic_vector(jpc_width-3 downto 0);
 
	rdy			: out std_logic;						-- lookup finished
	in_cache	: out std_logic							-- method is in cache
 
);
end cache;
 
architecture rtl of cache is
 
--
--	signals for mem interface
--
	type state_type		is (
							idle, s1, s2
						);
	signal state 		: state_type;
 
	constant blocks		: integer := 2**block_bits;
 
	signal block_addr	: std_logic_vector(block_bits-1 downto 0);
	-- tag_width can be used to reduce cachable area - saves a lot in the comperators
	signal use_addr		: std_logic_vector(tag_width-1 downto 0);
 
	type tag_array is array (0 to blocks-1) of std_logic_vector(tag_width-1 downto 0);
	signal tag			: tag_array;
 
	-- pointer to next block to be used on a miss
	signal nxt			: unsigned(block_bits-1 downto 0);
 
	-- (length of the method)-1 in blocks, 0 is one block
	signal nr_of_blks	: unsigned(block_bits-1 downto 0);
 
	signal clr_val		: std_logic_vector(blocks-1 downto 0);
 
begin
 
	bcstart <= block_addr & std_logic_vector(to_unsigned(0, jpc_width-2-block_bits));
	use_addr <= bc_addr(tag_width-1 downto 0);
 
	nr_of_blks <= resize(unsigned(bc_len(METHOD_SIZE_BITS-1 downto jpc_width-2-block_bits)), block_bits);
 
process(clk, reset, find)
 
begin
	if (reset='1') then
		state <= idle;
		rdy <= '1';
		in_cache <= '0';
		block_addr <= (others => '0');
		nxt <= (others => '0');
 
		for i in 0 to blocks-1 loop
			tag(i) <= (others => '0');
		end loop;
 
	elsif rising_edge(clk) then
 
		case state is
 
			when idle =>
				state <= idle;
				rdy <= '1';
				if find = '1' then
					rdy <= '0';
					state <= s1;
				end if;
 
			-- check for a hit
			when s1 =>
 
				in_cache <= '0';
				state <= s2;
				block_addr <= std_logic_vector(nxt);
 
				-- Does this generate optimal logic?
				-- Only one if will be true. Therefore, there
				-- should be a place for optimization
 
	-- comment this out for no caching
				for i in 0 to blocks-1 loop
					if tag(i) = use_addr then
						block_addr <= std_logic_vector(to_unsigned(i, block_bits));
						in_cache <= '1';
						state <= idle;
					end if;
				end loop;
--
-- remove the comment to force a single method
-- block cache
--
-- block_addr <= (others => '0');
-- in_cache <= '0';
-- state <= s2;
 
			-- correct tag memory on a miss
			when s2 =>
 
				for i in 0 to blocks-1 loop
					-- these two statements are xor - optimization?
					if clr_val(i) = '1' then
						tag(i) <= (others => '0');
					end if;
					if nxt = to_unsigned(i, block_bits) then
						tag(i) <= use_addr;
					end if;
				end loop;
 
				state <= idle;
				-- optimization to not advance the next pointer
				-- on short methods
--				if unsigned(bc_len) > 14 then
					nxt <= nxt + nr_of_blks + 1;
--				end if;
 
 
		end case;
 
	end if;
end process;
 
--
--	Determine which block entries have to be cleared in the tag registers.
--
--	clr_val could b registered as we can calculate
-- process(nxt, nr_of_blks) begin
process(clk)
 
	variable val		: integer;
begin
 
	if rising_edge(clk) then
 
		for i in 0 to blocks-1 loop
-- write(output, "cache...");
-- val := i;
-- write(output, integer'image(val));
-- val := blocks;
-- write(output, integer'image(val));
			if i<=nr_of_blks then
				clr_val(to_integer(nxt+i)) <= '1';
			else
				clr_val(to_integer(nxt+i)) <= '0';
			end if;
		end loop;
	end if;
 
end process;
 
 
end rtl;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.