Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
W
wr-switch-hdl
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
white-rabbit
wr-switch-hdl
Commits
c8010652
Commit
c8010652
authored
Mar 19, 2012
by
Tomasz Wlostowski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
swcore: new allocator with bug-free RAM
parent
6933ea22
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
378 additions
and
0 deletions
+378
-0
swc_page_alloc_ram_bug.vhd
modules/wrsw_swcore/new_allocator/swc_page_alloc_ram_bug.vhd
+378
-0
No files found.
modules/wrsw_swcore/new_allocator/swc_page_alloc_ram_bug.vhd
0 → 100644
View file @
c8010652
-------------------------------------------------------------------------------
-- Title : Fast page allocator/deallocator
-- Project : WhiteRabbit switch
-------------------------------------------------------------------------------
-- File : swc_page_allocator.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-04-08
-- Last update: 2012-03-18
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: Module implements a fast (2 cycle) paged memory allocator.
-- The allocator can serve 4 types of requests:
-- - Allocate a page with given use count (alloc_i = 1). The use count tells
-- the allocator how many clients requested that page (and hence, how many free
-- requests are required to return the page to free pages poll)
-- - Free a page (free_i = 1) - check the use count stored for the page. If it's
-- bigger than 1, decrease the use count, if it's 1 mark the page as free.
-- - Force free a page (force_free_i = 1): immediately frees the page regardless
-- of its current use_count.
-- - Set use count (set_usecnt_i = 1): sets the use count value for the given page.
-- Used to define the reference count for pages pre-allocated in advance by
-- the input blocks.
-------------------------------------------------------------------------------
--
-- Copyright (c) 2010 Tomasz Wlostowski, Maciej Lipinski / CERN
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source 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 Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-04-08 1.0 twlostow Created
-- 2010-10-11 1.1 mlipinsk comments added !!!!!
-- 2012-01-24 2.0 twlostow completely changed (uses FIFO)
-- 2012-03-05 2.1 mlipinsk added debugging stuff + made interchangeable with old (still buggy)
-- 2012-03-15 2.2 twlostow fixed really ugly missing pages bug
-------------------------------------------------------------------------------
library
ieee
;
use
ieee
.
std_logic_1164
.
all
;
use
ieee
.
numeric_std
.
all
;
use
work
.
swc_swcore_pkg
.
all
;
use
work
.
genram_pkg
.
all
;
entity
swc_page_allocator_new
is
generic
(
-- number of pages in the allocator pool
g_num_pages
:
integer
:
=
2048
;
-- number of bits of the page address
g_page_addr_width
:
integer
:
=
11
;
g_num_ports
:
integer
:
=
10
;
-- number of bits of the user (reference) count value
g_usecount_width
:
integer
:
=
4
);
port
(
clk_i
:
in
std_logic
;
-- clock & reset
rst_n_i
:
in
std_logic
;
-- "Allocate" command strobe (active HI), starts allocation process of a page with use
-- count given on usecnt_i. Address of the allocated page is returned on
-- pgaddr_o and is valid when done_o is HI.
alloc_i
:
in
std_logic
;
-- "Free" command strobe (active HI), releases the page at address pgaddr_i if it's current
-- use count is equal to 1, otherwise decreases the page's use count.
free_i
:
in
std_logic
;
force_free_i
:
in
std_logic
;
-- free strobe (active HI), releases the page
-- at address pgaddr_i regardless of the user
-- count of the page
-- it is used in case a package is corrupted
-- and what have already been
-- saved, needs to be released
set_usecnt_i
:
in
std_logic
;
-- enables to set user count to already
-- alocated page, used in the case of the
-- address of the first page of a package,
-- we need to allocate this page in advance
-- not knowing the user count, so the user count
-- needs to be set to already allocated page
-- "Use count" value for the page to be allocated. If the page is to be
-- used by multiple output queues, each of them will attempt to free it.
usecnt_i
:
in
std_logic_vector
(
g_usecount_width
-1
downto
0
);
pgaddr_i
:
in
std_logic_vector
(
g_page_addr_width
-1
downto
0
);
pgaddr_o
:
out
std_logic_vector
(
g_page_addr_width
-1
downto
0
);
free_last_usecnt_o
:
out
std_logic
;
done_o
:
out
std_logic
;
-- "early" done output (active HI).
-- Indicates that
-- the alloc/release cycle is going to
-- end 1 cycle in advance, so the
-- multiport scheduler can optimize
-- it's performance
nomem_o
:
out
std_logic
;
dbg_double_free_o
:
out
std_logic
;
dbg_double_force_free_o
:
out
std_logic
;
dbg_q_write_o
:
out
std_logic
;
dbg_q_read_o
:
out
std_logic
;
dbg_initializing_o
:
out
std_logic
);
end
swc_page_allocator_new
;
architecture
syn
of
swc_page_allocator_new
is
signal
real_nomem
,
out_nomem
:
std_logic
;
signal
rd_ptr
,
wr_ptr
:
unsigned
(
g_page_addr_width
-1
downto
0
);
signal
free_pages
:
unsigned
(
g_page_addr_width
downto
0
);
signal
q_write
,
q_read
:
std_logic
;
signal
pending_free
:
std_logic
;
signal
read_usecnt
:
std_logic_vector
(
g_usecount_width
-1
downto
0
);
signal
initializing
:
std_logic
;
signal
usecnt_write
:
std_logic
;
signal
usecnt_addr
:
std_logic_vector
(
g_page_addr_width
-1
downto
0
);
signal
usecnt_rddata
,
usecnt_wrdata
:
std_logic_vector
(
g_usecount_width
-1
downto
0
);
signal
q_output_addr
,
q_input_addr
:
std_logic_vector
(
g_page_addr_width
-1
downto
0
);
signal
alloc_d0
:
std_logic
;
signal
force_free_d0
:
std_logic
;
signal
free_d0
:
std_logic
;
signal
done_int
:
std_logic
;
signal
ram_ones
:
std_logic_vector
(
g_page_addr_width
+
g_usecount_width
-1
downto
0
);
--debuggin sygnals
signal
tmp_dbg_dealloc
:
std_logic
;
-- used for symulation debugging, don't remove
signal
tmp_page
:
std_logic_vector
(
g_page_addr_width
-1
downto
0
);
signal
free_blocks
:
unsigned
(
g_page_addr_width
downto
0
);
signal
usecnt_not_zero
:
std_logic
;
signal
real_nomem_d0
:
std_logic
;
begin
-- syn
ram_ones
<=
(
others
=>
'1'
);
U_Queue_RAM
:
swc_rd_wr_ram
generic
map
(
g_data_width
=>
g_page_addr_width
,
g_size
=>
2
**
g_page_addr_width
)
port
map
(
clk_i
=>
clk_i
,
rst_n_i
=>
rst_n_i
,
we_i
=>
q_write
,
wa_i
=>
std_logic_vector
(
wr_ptr
),
wd_i
=>
q_input_addr
,
ra_i
=>
std_logic_vector
(
rd_ptr
),
rd_o
=>
q_output_addr
);
q_write
<=
'1'
when
(
free_d0
=
'1'
and
unsigned
(
usecnt_rddata
)
=
1
)
or
(
force_free_d0
=
'1'
)
else
initializing
;
q_read
<=
'1'
when
(
alloc_d0
=
'1'
)
and
(
real_nomem_d0
=
'0'
)
else
'0'
;
q_input_addr
<=
std_logic_vector
(
wr_ptr
)
when
initializing
=
'1'
else
pgaddr_i
;
--U_Queue_RAM : generic_dpram
-- generic map (
-- g_data_width => g_page_addr_width,
-- g_size => 2**g_page_addr_width,
-- g_with_byte_enable => false,
-- g_dual_clock => false)
-- port map (
-- rst_n_i => rst_n_i,
-- clka_i => clk_i,
-- bwea_i => ram_ones((g_page_addr_width+7)/8 - 1 downto 0),
-- wea_i => q_write,
-- aa_i => std_logic_vector(wr_ptr),
-- da_i => pgaddr_i,
-- clkb_i => clk_i,
-- bweb_i => ram_ones((g_page_addr_width+7)/8 - 1 downto 0),
-- web_i => initializing,
-- ab_i => std_logic_vector(rd_ptr),
-- db_i => std_logic_vector(rd_ptr),
-- qb_o => q_output_addr);
U_UseCnt_RAM
:
swc_rd_wr_ram
generic
map
(
g_data_width
=>
g_usecount_width
,
g_size
=>
2
**
g_page_addr_width
)
port
map
(
clk_i
=>
clk_i
,
rst_n_i
=>
rst_n_i
,
we_i
=>
usecnt_write
,
wa_i
=>
usecnt_addr
,
wd_i
=>
usecnt_wrdata
,
ra_i
=>
usecnt_addr
,
rd_o
=>
usecnt_rddata
);
usecnt_addr
<=
q_output_addr
when
alloc_d0
=
'1'
else
pgaddr_i
;
usecnt_write
<=
(
alloc_d0
or
set_usecnt_i
or
free_d0
or
force_free_d0
)
and
not
initializing
;
usecnt_wrdata
<=
usecnt_i
when
(
set_usecnt_i
=
'1'
or
alloc_d0
=
'1'
)
else
f_gen_dummy_vec
(
'0'
,
g_usecount_width
)
when
force_free_i
=
'1'
else
std_logic_vector
(
unsigned
(
usecnt_rddata
)
-
1
);
p_debug
:
process
(
clk_i
)
begin
if
rising_edge
(
clk_i
)
then
if
(
free_d0
=
'1'
and
unsigned
(
usecnt_rddata
)
=
0
)
then
dbg_double_free_o
<=
'1'
;
else
dbg_double_free_o
<=
'0'
;
end
if
;
if
(
force_free_d0
=
'1'
and
unsigned
(
usecnt_rddata
)
=
0
)
then
dbg_double_force_free_o
<=
'1'
;
else
dbg_double_force_free_o
<=
'0'
;
end
if
;
end
if
;
end
process
;
--U_UseCnt_RAM : generic_dpram
-- generic map (
-- g_data_width => g_usecount_width,
-- g_size => 2**g_page_addr_width,
-- g_with_byte_enable => false,
-- g_dual_clock => false)
-- port map (
-- rst_n_i => rst_n_i,
-- clka_i => clk_i,
-- wea_i => usecnt_write,
-- bwea_i => ram_ones((g_usecount_width+7)/8 - 1 downto 0),
-- aa_i => usecnt_addr,
-- da_i => usecnt_wrdata,
-- qa_o => usecnt_rddata,
-- clkb_i => clk_i,
-- bweb_i => ram_ones((g_usecount_width+7)/8 - 1 downto 0),
-- web_i => initializing,
-- ab_i => std_logic_vector(rd_ptr),
-- db_i => f_gen_dummy_vec('0', g_usecount_width));
p_pointers
:
process
(
clk_i
)
begin
if
rising_edge
(
clk_i
)
then
if
rst_n_i
=
'0'
then
initializing
<=
'1'
;
rd_ptr
<=
(
others
=>
'0'
);
wr_ptr
<=
(
others
=>
'0'
);
real_nomem
<=
'0'
;
free_pages
<=
to_unsigned
(
g_num_pages
-1
,
free_pages
'length
);
else
real_nomem_d0
<=
real_nomem
;
if
(
initializing
=
'1'
)
then
if
(
wr_ptr
=
g_num_pages
-1
)
then
initializing
<=
'0'
;
wr_ptr
<=
to_unsigned
(
g_num_pages
-1
,
wr_ptr
'length
);
else
wr_ptr
<=
wr_ptr
+
1
;
end
if
;
else
if
(
q_write
=
'1'
)
then
wr_ptr
<=
wr_ptr
+
1
;
end
if
;
if
(
q_read
=
'1'
)
then
rd_ptr
<=
rd_ptr
+
1
;
end
if
;
if
(
q_write
=
'1'
and
q_read
=
'0'
)
then
real_nomem
<=
'0'
;
free_pages
<=
free_pages
+
1
;
elsif
(
q_write
=
'0'
and
q_read
=
'1'
)
then
if
(
free_pages
=
1
)
then
real_nomem
<=
'1'
;
end
if
;
free_pages
<=
free_pages
-
1
;
end
if
;
end
if
;
end
if
;
end
if
;
end
process
;
p_delay_alloc
:
process
(
clk_i
)
begin
if
rising_edge
(
clk_i
)
then
if
rst_n_i
=
'0'
or
initializing
=
'1'
then
alloc_d0
<=
'0'
;
free_d0
<=
'0'
;
force_free_d0
<=
'0'
;
else
alloc_d0
<=
alloc_i
and
not
alloc_d0
;
free_d0
<=
free_i
and
not
free_d0
;
force_free_d0
<=
force_free_i
and
not
force_free_d0
;
end
if
;
end
if
;
end
process
;
pgaddr_o
<=
q_output_addr
;
p_gen_done
:
process
(
clk_i
)
begin
if
rising_edge
(
clk_i
)
then
if
(
rst_n_i
=
'0'
)
or
(
initializing
=
'1'
)
then
done_int
<=
'0'
;
else
if
(
done_int
=
'1'
)
then
done_int
<=
'0'
;
elsif
(((
alloc_i
=
'1'
and
real_nomem
=
'0'
)
or
set_usecnt_i
=
'1'
or
free_i
=
'1'
or
force_free_i
=
'1'
)
and
initializing
=
'0'
)
then
done_int
<=
'1'
;
end
if
;
end
if
;
end
if
;
end
process
;
done_o
<=
done_int
;
-- and not(free_d0 or alloc_d0);
-- q_write <= (not initializing) when (free_d0 = '1' and unsigned(usecnt_rddata) = 1) or (force_free_i = '1' and done_int = '0') else '0';
p_gen_nomem_output
:
process
(
clk_i
)
begin
if
rising_edge
(
clk_i
)
then
if
rst_n_i
=
'0'
then
out_nomem
<=
'0'
;
else
if
(
out_nomem
=
'0'
and
(
free_blocks
<
to_unsigned
(
10
,
free_blocks
'length
)))
then
out_nomem
<=
'1'
;
elsif
(
out_nomem
=
'1'
and
(
free_blocks
>
to_unsigned
((
3
*
g_num_ports
),
free_blocks
'length
)))
then
out_nomem
<=
real_nomem
;
end
if
;
end
if
;
end
if
;
end
process
;
nomem_o
<=
out_nomem
;
-- idle_o <= not (initializing or free_d0 or alloc_d0);
free_last_usecnt_o
<=
(
not
initializing
)
when
(
free_d0
=
'1'
and
unsigned
(
usecnt_rddata
)
=
1
)
else
'0'
;
free_blocks
<=
free_pages
;
dbg_q_read_o
<=
q_read
;
dbg_q_write_o
<=
q_write
;
dbg_initializing_o
<=
initializing
;
end
syn
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment