Merge pull request #229 from ozbenh/litedram

Litedram: Misc improvements and support for different DRAM geometries
jtag-port
Michael Neuling 4 years ago committed by GitHub
commit d200733252
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -120,6 +120,8 @@ begin
generic map( generic map(
DRAM_ABITS => 24, DRAM_ABITS => 24,
DRAM_ALINES => 1, DRAM_ALINES => 1,
DRAM_DLINES => 16,
DRAM_PORT_WIDTH => 128,
PAYLOAD_FILE => DRAM_INIT_FILE, PAYLOAD_FILE => DRAM_INIT_FILE,
PAYLOAD_SIZE => ROM_SIZE PAYLOAD_SIZE => ROM_SIZE
) )

@ -43,6 +43,8 @@ begin
generic map( generic map(
DRAM_ABITS => 24, DRAM_ABITS => 24,
DRAM_ALINES => 1, DRAM_ALINES => 1,
DRAM_DLINES => 16,
DRAM_PORT_WIDTH => 128,
PAYLOAD_FILE => DRAM_INIT_FILE, PAYLOAD_FILE => DRAM_INIT_FILE,
PAYLOAD_SIZE => DRAM_INIT_SIZE PAYLOAD_SIZE => DRAM_INIT_SIZE
) )
@ -293,6 +295,43 @@ begin
check_data(make_pattern(i)); check_data(make_pattern(i));
end loop; end loop;


report "Pre-fill a line";
a(11) := '1';
clr_acks;
wb_write(add_off(a, 0), x"1111111100000000", x"ff");
wb_write(add_off(a, 8), x"3333333322222222", x"ff");
wb_write(add_off(a, 16), x"5555555544444444", x"ff");
wb_write(add_off(a, 24), x"7777777766666666", x"ff");
wb_write(add_off(a, 32), x"9999999988888888", x"ff");
wb_write(add_off(a, 40), x"bbbbbbbbaaaaaaaa", x"ff");
wb_write(add_off(a, 48), x"ddddddddcccccccc", x"ff");
wb_write(add_off(a, 56), x"ffffffffeeeeeeee", x"ff");
wb_write(add_off(a, 64), x"1111111100000000", x"ff");
wb_write(add_off(a, 72), x"3333333322222222", x"ff");
wb_write(add_off(a, 80), x"5555555544444444", x"ff");
wb_write(add_off(a, 88), x"7777777766666666", x"ff");
wb_write(add_off(a, 96), x"9999999988888888", x"ff");
wb_write(add_off(a,104), x"bbbbbbbbaaaaaaaa", x"ff");
wb_write(add_off(a,112), x"ddddddddcccccccc", x"ff");
wb_write(add_off(a,120), x"ffffffffeeeeeeee", x"ff");
wait_acks(16);

report "Scattered from middle of line...";
clr_acks;
wb_read(add_off(a,24));
wb_read(add_off(a,32));
wb_read(add_off(a, 0));
wb_read(add_off(a,16));
wait_acks(4);
read_data(d);
assert d = x"7777777766666666" report "bad data (24), got " & to_hstring(d) severity failure;
read_data(d);
assert d = x"9999999988888888" report "bad data (32), got " & to_hstring(d) severity failure;
read_data(d);
assert d = x"1111111100000000" report "bad data (0), got " & to_hstring(d) severity failure;
read_data(d);
assert d = x"5555555544444444" report "bad data (16), got " & to_hstring(d) severity failure;

std.env.finish; std.env.finish;
end process; end process;
end architecture; end architecture;

@ -341,6 +341,8 @@ begin
generic map( generic map(
DRAM_ABITS => 24, DRAM_ABITS => 24,
DRAM_ALINES => 14, DRAM_ALINES => 14,
DRAM_DLINES => 16,
DRAM_PORT_WIDTH => 128,
PAYLOAD_FILE => RAM_INIT_FILE, PAYLOAD_FILE => RAM_INIT_FILE,
PAYLOAD_SIZE => PAYLOAD_SIZE PAYLOAD_SIZE => PAYLOAD_SIZE
) )

@ -258,6 +258,8 @@ begin
generic map( generic map(
DRAM_ABITS => 25, DRAM_ABITS => 25,
DRAM_ALINES => 15, DRAM_ALINES => 15,
DRAM_DLINES => 16,
DRAM_PORT_WIDTH => 128,
PAYLOAD_FILE => RAM_INIT_FILE, PAYLOAD_FILE => RAM_INIT_FILE,
PAYLOAD_SIZE => PAYLOAD_SIZE PAYLOAD_SIZE => PAYLOAD_SIZE
) )

@ -10,8 +10,10 @@ use work.helpers.all;


entity litedram_wrapper is entity litedram_wrapper is
generic ( generic (
DRAM_ABITS : positive; DRAM_ABITS : positive;
DRAM_ALINES : positive; DRAM_ALINES : natural;
DRAM_DLINES : natural;
DRAM_PORT_WIDTH : positive;


-- Pseudo-ROM payload -- Pseudo-ROM payload
PAYLOAD_SIZE : natural; PAYLOAD_SIZE : natural;
@ -63,10 +65,10 @@ entity litedram_wrapper is
ddram_cas_n : out std_ulogic; ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic; ddram_we_n : out std_ulogic;
ddram_cs_n : out std_ulogic; ddram_cs_n : out std_ulogic;
ddram_dm : out std_ulogic_vector(1 downto 0); ddram_dm : out std_ulogic_vector(DRAM_DLINES/8-1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0); ddram_dq : inout std_ulogic_vector(DRAM_DLINES-1 downto 0);
ddram_dqs_p : inout std_ulogic_vector(1 downto 0); ddram_dqs_p : inout std_ulogic_vector(DRAM_DLINES/8-1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(1 downto 0); ddram_dqs_n : inout std_ulogic_vector(DRAM_DLINES/8-1 downto 0);
ddram_clk_p : out std_ulogic; ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic; ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic; ddram_cke : out std_ulogic;
@ -87,10 +89,10 @@ architecture behaviour of litedram_wrapper is
ddram_cas_n : out std_ulogic; ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic; ddram_we_n : out std_ulogic;
ddram_cs_n : out std_ulogic; ddram_cs_n : out std_ulogic;
ddram_dm : out std_ulogic_vector(1 downto 0); ddram_dm : out std_ulogic_vector(DRAM_DLINES/8-1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0); ddram_dq : inout std_ulogic_vector(DRAM_DLINES-1 downto 0);
ddram_dqs_p : inout std_ulogic_vector(1 downto 0); ddram_dqs_p : inout std_ulogic_vector(DRAM_DLINES/8-1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(1 downto 0); ddram_dqs_n : inout std_ulogic_vector(DRAM_DLINES/8-1 downto 0);
ddram_clk_p : out std_ulogic; ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic; ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic; ddram_cke : out std_ulogic;
@ -117,11 +119,11 @@ architecture behaviour of litedram_wrapper is
user_port_native_0_cmd_addr : in std_ulogic_vector(DRAM_ABITS-1 downto 0); user_port_native_0_cmd_addr : in std_ulogic_vector(DRAM_ABITS-1 downto 0);
user_port_native_0_wdata_valid : in std_ulogic; user_port_native_0_wdata_valid : in std_ulogic;
user_port_native_0_wdata_ready : out std_ulogic; user_port_native_0_wdata_ready : out std_ulogic;
user_port_native_0_wdata_we : in std_ulogic_vector(15 downto 0); user_port_native_0_wdata_we : in std_ulogic_vector(DRAM_PORT_WIDTH/8-1 downto 0);
user_port_native_0_wdata_data : in std_ulogic_vector(127 downto 0); user_port_native_0_wdata_data : in std_ulogic_vector(DRAM_PORT_WIDTH-1 downto 0);
user_port_native_0_rdata_valid : out std_ulogic; user_port_native_0_rdata_valid : out std_ulogic;
user_port_native_0_rdata_ready : in std_ulogic; user_port_native_0_rdata_ready : in std_ulogic;
user_port_native_0_rdata_data : out std_ulogic_vector(127 downto 0) user_port_native_0_rdata_data : out std_ulogic_vector(DRAM_PORT_WIDTH-1 downto 0)
); );
end component; end component;
@ -131,11 +133,11 @@ architecture behaviour of litedram_wrapper is
signal user_port0_cmd_addr : std_ulogic_vector(DRAM_ABITS-1 downto 0); signal user_port0_cmd_addr : std_ulogic_vector(DRAM_ABITS-1 downto 0);
signal user_port0_wdata_valid : std_ulogic; signal user_port0_wdata_valid : std_ulogic;
signal user_port0_wdata_ready : std_ulogic; signal user_port0_wdata_ready : std_ulogic;
signal user_port0_wdata_we : std_ulogic_vector(15 downto 0); signal user_port0_wdata_we : std_ulogic_vector(DRAM_PORT_WIDTH/8-1 downto 0);
signal user_port0_wdata_data : std_ulogic_vector(127 downto 0); signal user_port0_wdata_data : std_ulogic_vector(DRAM_PORT_WIDTH-1 downto 0);
signal user_port0_rdata_valid : std_ulogic; signal user_port0_rdata_valid : std_ulogic;
signal user_port0_rdata_ready : std_ulogic; signal user_port0_rdata_ready : std_ulogic;
signal user_port0_rdata_data : std_ulogic_vector(127 downto 0); signal user_port0_rdata_data : std_ulogic_vector(DRAM_PORT_WIDTH-1 downto 0);


signal wb_ctrl_adr : std_ulogic_vector(29 downto 0); signal wb_ctrl_adr : std_ulogic_vector(29 downto 0);
signal wb_ctrl_dat_w : std_ulogic_vector(31 downto 0); signal wb_ctrl_dat_w : std_ulogic_vector(31 downto 0);
@ -150,14 +152,24 @@ architecture behaviour of litedram_wrapper is
signal wb_init_out : wb_io_slave_out; signal wb_init_out : wb_io_slave_out;


-- DRAM data port width -- DRAM data port width
constant DRAM_DBITS : natural := 128; constant DRAM_DBITS : natural := DRAM_PORT_WIDTH;
-- DRAM data port sel bits
constant DRAM_SBITS : natural := (DRAM_DBITS / 8); constant DRAM_SBITS : natural := (DRAM_DBITS / 8);


-- WB geometry (just a few shortcuts)
constant WBL : positive := wb_in.dat'length;
constant WBSL : positive := wb_in.sel'length;

-- Select a WB word inside DRAM port width
constant WB_WORD_COUNT : positive := DRAM_DBITS/WBL;
constant WB_WSEL_BITS : positive := log2(WB_WORD_COUNT);
constant WB_WSEL_RIGHT : positive := log2(WBL/8);

-- BRAM organisation: We never access more than wishbone_data_bits at -- BRAM organisation: We never access more than wishbone_data_bits at
-- a time so to save resources we make the array only that wide, and -- a time so to save resources we make the array only that wide, and
-- use consecutive indices for to make a cache "line" -- use consecutive indices for to make a cache "line"
-- --
-- ROW_SIZE is the width in bytes of the BRAM (based on litedram, so 128-bits) -- ROW_SIZE is the width in bytes of the BRAM, ie, litedram port width
constant ROW_SIZE : natural := DRAM_DBITS / 8; constant ROW_SIZE : natural := DRAM_DBITS / 8;
-- ROW_PER_LINE is the number of row (litedram transactions) in a line -- ROW_PER_LINE is the number of row (litedram transactions) in a line
constant ROW_PER_LINE : natural := LINE_SIZE / ROW_SIZE; constant ROW_PER_LINE : natural := LINE_SIZE / ROW_SIZE;
@ -184,11 +196,12 @@ architecture behaviour of litedram_wrapper is
-- TAG_BITS is the number of bits of the tag part of the address -- TAG_BITS is the number of bits of the tag part of the address
constant TAG_BITS : natural := REAL_ADDR_BITS - SET_SIZE_BITS; constant TAG_BITS : natural := REAL_ADDR_BITS - SET_SIZE_BITS;
-- WAY_BITS is the number of bits to select a way -- WAY_BITS is the number of bits to select a way
constant WAY_BITS : natural := log2(NUM_WAYS); constant WAY_BITS : natural := log2(NUM_WAYS);


subtype row_t is integer range 0 to BRAM_ROWS-1; subtype row_t is integer range 0 to BRAM_ROWS-1;
subtype index_t is integer range 0 to NUM_LINES-1; subtype index_t is integer range 0 to NUM_LINES-1;
subtype way_t is integer range 0 to NUM_WAYS-1; subtype way_t is integer range 0 to NUM_WAYS-1;
subtype row_in_line_t is unsigned(ROW_LINEBITS-1 downto 0);


-- The cache data BRAM organized as described above for each way -- The cache data BRAM organized as described above for each way
subtype cache_row_t is std_ulogic_vector(DRAM_DBITS-1 downto 0); subtype cache_row_t is std_ulogic_vector(DRAM_DBITS-1 downto 0);
@ -207,6 +220,9 @@ architecture behaviour of litedram_wrapper is
subtype cache_way_valids_t is std_ulogic_vector(NUM_WAYS-1 downto 0); subtype cache_way_valids_t is std_ulogic_vector(NUM_WAYS-1 downto 0);
type cache_valids_t is array(index_t) of cache_way_valids_t; type cache_valids_t is array(index_t) of cache_way_valids_t;


-- "Temporary" valid bits for the rows of the currently refilled line
type row_per_line_valid_t is array(0 to ROW_PER_LINE - 1) of std_ulogic;

-- Storage. Hopefully "cache_rows" is a BRAM, the rest is LUTs -- Storage. Hopefully "cache_rows" is a BRAM, the rest is LUTs
signal cache_tags : cache_tags_array_t; signal cache_tags : cache_tags_array_t;
signal cache_valids : cache_valids_t; signal cache_valids : cache_valids_t;
@ -217,10 +233,10 @@ architecture behaviour of litedram_wrapper is
-- --
-- Store queue signals -- Store queue signals
-- --
-- We store a single wishbone dword per entry (64-bit) but all -- We store a single wishbone dword per entry (64-bit)
-- 16 sel bits for the DRAM. -- along with the wishbone sel bits and the necessary address
-- XXX Investigate storing only AD3 and 8 sel bits if it's better -- bits to select which part of DRAM port to write to.
constant STOREQ_BITS : positive := wishbone_data_bits + DRAM_SBITS; constant STOREQ_BITS : positive := WBL + WBSL + WB_WSEL_BITS;


signal storeq_rd_ready : std_ulogic; signal storeq_rd_ready : std_ulogic;
signal storeq_rd_valid : std_ulogic; signal storeq_rd_valid : std_ulogic;
@ -233,7 +249,7 @@ architecture behaviour of litedram_wrapper is
-- Cache management signals -- Cache management signals
-- --


-- Cache state machine -- Cache state machine
type state_t is (IDLE, -- Normal load hit processing type state_t is (IDLE, -- Normal load hit processing
REFILL_CLR_TAG, -- Cache refill clear tag REFILL_CLR_TAG, -- Cache refill clear tag
REFILL_WAIT_ACK); -- Cache refill wait ack REFILL_WAIT_ACK); -- Cache refill wait ack
@ -247,8 +263,8 @@ architecture behaviour of litedram_wrapper is
-- Read pipeline (to handle cache RAM latency) -- Read pipeline (to handle cache RAM latency)
signal read_ack_0 : std_ulogic := '0'; signal read_ack_0 : std_ulogic := '0';
signal read_ack_1 : std_ulogic := '0'; signal read_ack_1 : std_ulogic := '0';
signal read_ad3_0 : std_ulogic; signal read_wsl_0 : std_ulogic_vector(WB_WSEL_BITS-1 downto 0) := (others => '0');
signal read_ad3_1 : std_ulogic; signal read_wsl_1 : std_ulogic_vector(WB_WSEL_BITS-1 downto 0) := (others => '0');
signal read_way_0 : way_t; signal read_way_0 : way_t;
signal read_way_1 : way_t; signal read_way_1 : way_t;


@ -261,7 +277,8 @@ architecture behaviour of litedram_wrapper is
OP_LOAD_HIT, OP_LOAD_HIT,
OP_LOAD_MISS, OP_LOAD_MISS,
OP_STORE_HIT, OP_STORE_HIT,
OP_STORE_MISS); OP_STORE_MISS,
OP_STORE_DELAYED);


signal req_index : index_t; signal req_index : index_t;
signal req_row : row_t; signal req_row : row_t;
@ -269,10 +286,9 @@ architecture behaviour of litedram_wrapper is
signal req_tag : cache_tag_t; signal req_tag : cache_tag_t;
signal req_op : req_op_t; signal req_op : req_op_t;
signal req_laddr : std_ulogic_vector(REAL_ADDR_BITS-1 downto 0); signal req_laddr : std_ulogic_vector(REAL_ADDR_BITS-1 downto 0);
signal req_ad3 : std_ulogic; signal req_wsl : std_ulogic_vector(WB_WSEL_BITS-1 downto 0);
signal req_we : std_ulogic_vector(DRAM_SBITS-1 downto 0); signal req_we : std_ulogic_vector(DRAM_SBITS-1 downto 0);
signal req_wdata : std_ulogic_vector(DRAM_DBITS-1 downto 0); signal req_wdata : std_ulogic_vector(DRAM_DBITS-1 downto 0);
signal accept_store : std_ulogic;
signal stall : std_ulogic; signal stall : std_ulogic;


-- Line refill command signals and latches -- Line refill command signals and latches
@ -281,6 +297,8 @@ architecture behaviour of litedram_wrapper is
signal refill_way : way_t; signal refill_way : way_t;
signal refill_index : index_t; signal refill_index : index_t;
signal refill_row : row_t; signal refill_row : row_t;
signal refill_end_row : row_in_line_t;
signal refill_rows_vlid : row_per_line_valid_t;


-- Cache RAM interface -- Cache RAM interface
type cache_ram_out_t is array(way_t) of cache_row_t; type cache_ram_out_t is array(way_t) of cache_row_t;
@ -306,21 +324,25 @@ architecture behaviour of litedram_wrapper is
return to_integer(unsigned(addr(SET_SIZE_BITS - 1 downto ROW_OFF_BITS))); return to_integer(unsigned(addr(SET_SIZE_BITS - 1 downto ROW_OFF_BITS)));
end; end;


-- Return the index of a row within a line
function get_row_of_line(row: row_t) return row_in_line_t is
variable row_v : unsigned(ROW_BITS-1 downto 0);
begin
row_v := to_unsigned(row, ROW_BITS);
return row_v(ROW_LINEBITS-1 downto 0);
end;
-- Returns whether this is the last row of a line. It takes a DRAM address -- Returns whether this is the last row of a line. It takes a DRAM address
function is_last_row_addr(addr: std_ulogic_vector(REAL_ADDR_BITS-1 downto ROW_OFF_BITS)) function is_last_row_addr(addr: std_ulogic_vector(REAL_ADDR_BITS-1 downto ROW_OFF_BITS);
last: row_in_line_t)
return boolean is return boolean is
constant ones : std_ulogic_vector(ROW_LINEBITS-1 downto 0) := (others => '1');
begin begin
return addr(LINE_OFF_BITS-1 downto ROW_OFF_BITS) = ones; return unsigned(addr(LINE_OFF_BITS-1 downto ROW_OFF_BITS)) = last;
end; end;


-- Returns whether this is the last row of a line -- Returns whether this is the last row of a line
function is_last_row(row: row_t) return boolean is function is_last_row(row: row_t; last: row_in_line_t) return boolean is
variable row_v : std_ulogic_vector(ROW_BITS-1 downto 0);
constant ones : std_ulogic_vector(ROW_LINEBITS-1 downto 0) := (others => '1');
begin begin
row_v := std_ulogic_vector(to_unsigned(row, ROW_BITS)); return get_row_of_line(row) = last;
return row_v(ROW_LINEBITS-1 downto 0) = ones;
end; end;


-- Return the address of the next row in the current cache line. It takes a -- Return the address of the next row in the current cache line. It takes a
@ -387,8 +409,6 @@ begin
report "geometry bits don't add up" severity FAILURE; report "geometry bits don't add up" severity FAILURE;
assert (REAL_ADDR_BITS = TAG_BITS + ROW_BITS + ROW_OFF_BITS) assert (REAL_ADDR_BITS = TAG_BITS + ROW_BITS + ROW_OFF_BITS)
report "geometry bits don't add up" severity FAILURE; report "geometry bits don't add up" severity FAILURE;
assert (128 = DRAM_DBITS)
report "Can't yet handle a DRAM width that isn't 128-bits" severity FAILURE;


-- alternate core reset address set when DRAM is not initialized. -- alternate core reset address set when DRAM is not initialized.
core_alt_reset <= not init_done; core_alt_reset <= not init_done;
@ -493,7 +513,7 @@ begin
-- --
-- Write mux: cache refills from DRAM or writes from Wishbone -- Write mux: cache refills from DRAM or writes from Wishbone
-- --
if state = IDLE then if req_op = OP_STORE_HIT and req_hit_way = i then
-- Write from wishbone -- Write from wishbone
wr_addr <= std_ulogic_vector(to_unsigned(req_row, ROW_BITS)); wr_addr <= std_ulogic_vector(to_unsigned(req_row, ROW_BITS));
wr_data <= req_wdata; wr_data <= req_wdata;
@ -570,7 +590,7 @@ begin
end generate; end generate;


-- --
-- Wishbone interface: -- Wishbone request interface:
-- --
-- - Incoming wishbone request latch (to help with timing) -- - Incoming wishbone request latch (to help with timing)
-- - Read response pipeline (to match BRAM output buffer delay) -- - Read response pipeline (to match BRAM output buffer delay)
@ -632,16 +652,15 @@ begin
-- --
-- Read response pipeline -- Read response pipeline
-- --
-- XXX Might have to put store acks in there too (see comment in wb_response)
read_pipe: process(system_clk) read_pipe: process(system_clk)
begin begin
if rising_edge(system_clk) then if rising_edge(system_clk) then
read_ack_0 <= '1' when req_op = OP_LOAD_HIT else '0'; read_ack_0 <= '1' when req_op = OP_LOAD_HIT else '0';
read_ad3_0 <= req_ad3; read_wsl_0 <= req_wsl;
read_way_0 <= req_hit_way; read_way_0 <= req_hit_way;


read_ack_1 <= read_ack_0; read_ack_1 <= read_ack_0;
read_ad3_1 <= read_ad3_0; read_wsl_1 <= read_wsl_0;
read_way_1 <= read_way_0; read_way_1 <= read_way_0;


if TRACE then if TRACE then
@ -670,58 +689,54 @@ begin
end if; end if;
end process; end process;


wb_reponse: process(all) --
variable rdata : std_ulogic_vector(DRAM_DBITS-1 downto 0); -- Wishbone response generation
variable store_done : std_ulogic; --

wb_rseponse: process(all)
variable rdata : std_ulogic_vector(DRAM_DBITS-1 downto 0);
variable store_done : std_ulogic;
variable accept_store : std_ulogic;
variable wsel : natural range 0 to WB_WORD_COUNT-1;
begin begin
-- Can we accept a store ? This is set when IDLE and the store -- Can we accept a store ? This is set when the store queue & command
-- queue & command queue are not full. -- queue are not full.
-- --
-- Note: This is only used to control the WB request latch, stall -- This does *not* mean that we will accept the store, there are other
-- and store "early complete". We don't want to use this to control -- reasons to delay them (see OP_STORE_DELAYED).
-- cmd_valid to DRAM as this would create a circular dependency inside
-- LiteDRAM as cmd_ready I think is driven from cmd_valid.
-- --
-- The state machine that controls the command queue must thus -- A store is fully accepted when *both* req_op is not OP_STORE_DELAYED
-- reproduce this logic at least partially. -- and accept_store is '1'.
-- --
-- Note also that user_port0_cmd_ready from LiteDRAM is combinational -- The reason for this split is to avoid a circular dependency inside
-- from user_port0_cmd_valid. IE. we won't know that LiteDRAM cannot -- LiteDRAM, since cmd_ready from litedram is driven from cmd_valid (*)
-- accept a command until we try to send one. -- we don't want to generate cmd_valid from cmd_ready. So we generate
-- it instead from all the *other* conditions that make a store valid.
-- --
if state = IDLE then -- (*) It's my understanding that user_port0_cmd_ready from LiteDRAM is
accept_store <= user_port0_cmd_ready and storeq_wr_ready; -- ombinational from user_port0_cmd_valid along with a bunch of other

-- internal signals. IE. we won't know that LiteDRAM cannot accept a
-- Corner case !!! The read acks pipeline takes two extra cycles -- command until we try to send one.
-- which means a store ack can collide with a previous load hit --
-- ack. Thus we stall stores if we have a load ack pending. accept_store := user_port0_cmd_ready and storeq_wr_ready;
if read_ack_0 = '1' or read_ack_1 = '1' then
accept_store <= '0'; -- Generate stalls. For stores we stall if we can't accept it.
end if; -- For loads, we stall if we are going to take a load miss or
-- are in the middle of a refill and it isn't a partial hit.
if req_op = OP_STORE_MISS or req_op = OP_STORE_HIT then
stall <= not accept_store;
elsif req_op = OP_LOAD_MISS or req_op = OP_STORE_DELAYED then
stall <= '1';
else else
accept_store <= '0'; stall <= '0';
end if; end if;
-- Generate stalls. For loads, we stall if we are going to take a load
-- miss or are in the middle of a refill. For stores, if we can't
-- accept it.
case state is
when IDLE =>
case req_op is
when OP_LOAD_MISS =>
stall <= '1';
when OP_STORE_MISS | OP_STORE_HIT =>
stall <= not accept_store;
when others =>
stall <= '0';
end case;
when others =>
stall <= '1';
end case;
-- Data out mux -- Data out mux
rdata := cache_out(read_way_1); rdata := cache_out(read_way_1);
wb_out.dat <= rdata(127 downto 64) when read_ad3_1 = '1' else rdata(63 downto 0);
-- Hard wired for 64-bit wishbone
wsel := to_integer(unsigned(read_wsl_1));
wb_out.dat <= rdata((wsel+1)*WBL-1 downto wsel*WBL);


-- Early-complete stores on wishbone. -- Early-complete stores on wishbone.
if req_op = OP_STORE_HIT or req_op = OP_STORE_MISS then if req_op = OP_STORE_HIT or req_op = OP_STORE_MISS then
@ -736,7 +751,8 @@ begin
-- Generate Wishbone ACKs on read hits and store complete -- Generate Wishbone ACKs on read hits and store complete
-- --
-- This can happen on store right behind loads ! This is why -- This can happen on store right behind loads ! This is why
-- we don't accept a new store right behind a load ack above. -- we delay a store when a load ack is in the pipeline in the
-- request decoder below.
-- --
wb_out.ack <= read_ack_1 or store_ack_1; wb_out.ack <= read_ack_1 or store_ack_1;
assert read_ack_1 = '0' or store_ack_1 = '0' report assert read_ack_1 = '0' or store_ack_1 = '0' report
@ -748,60 +764,99 @@ begin
-- Cache request decode -- Cache request decode
-- --
request_decode: process(all) request_decode: process(all)
variable valid : std_ulogic; variable valid : boolean;
variable is_hit : std_ulogic; variable is_hit : boolean;
variable hit_way : way_t; variable store_delay : boolean;
variable hit_way : way_t;
begin begin
-- Extract line, row and tag from request -- Extract line, row and tag from request
req_index <= get_index(wb_req.adr); req_index <= get_index(wb_req.adr);
req_row <= get_row(wb_req.adr(REAL_ADDR_BITS-1 downto 0)); req_row <= get_row(wb_req.adr(REAL_ADDR_BITS-1 downto 0));
req_tag <= get_tag(wb_req.adr); req_tag <= get_tag(wb_req.adr);


-- Calculate address of beginning of cache line, will be -- Calculate address of beginning of cache row, will be
-- used for cache miss processing if needed -- used for cache miss processing if needed
req_laddr <= wb_req.adr(REAL_ADDR_BITS - 1 downto LINE_OFF_BITS) & req_laddr <= wb_req.adr(REAL_ADDR_BITS - 1 downto ROW_OFF_BITS) &
(LINE_OFF_BITS-1 downto 0 => '0'); (ROW_OFF_BITS-1 downto 0 => '0');




-- Do we have a valid request in the WB latch ? -- Do we have a valid request in the WB latch ?
if state = IDLE then valid := wb_req.cyc = '1' and wb_req.stb = '1';
valid := wb_req.cyc and wb_req.stb;
else
valid := '0';
end if;


-- Store signals -- Store signals (hard wired for 64-bit wishbone at the moment)
req_ad3 <= wb_req.adr(3); req_wsl <= wb_req.adr(WB_WSEL_RIGHT+WB_WSEL_BITS-1 downto WB_WSEL_RIGHT);
req_wdata <= wb_req.dat & wb_req.dat; for i in 0 to WB_WORD_COUNT-1 loop
req_we <= wb_req.sel & "00000000" when req_ad3 = '1' else if to_integer(unsigned(req_wsl)) = i then
"00000000" & wb_req.sel; req_we(WBSL*(i+1)-1 downto WBSL*i) <= wb_req.sel;
else
req_we(WBSL*(i+1)-1 downto WBSL*i) <= x"00";
end if;
req_wdata(WBL*(i+1)-1 downto WBL*i) <= wb_req.dat;
end loop;


-- Test if pending request is a hit on any way -- Test if pending request is a hit on any way
hit_way := 0; hit_way := 0;
is_hit := '0'; is_hit := false;
for i in way_t loop for i in way_t loop
if valid = '1' and cache_valids(req_index)(i) = '1' then if valid and
(cache_valids(req_index)(i) = '1' or
(state = REFILL_WAIT_ACK and
req_index = refill_index and i = refill_way and
refill_rows_vlid(req_row mod ROW_PER_LINE) = '1')) then
if read_tag(i, cache_tags(req_index)) = req_tag then if read_tag(i, cache_tags(req_index)) = req_tag then
hit_way := i; hit_way := i;
is_hit := '1'; is_hit := true;
end if; end if;
end if; end if;
end loop; end loop;


-- We need to delay stores under some circumstances to avoid
-- collisions with the refill machine.
--
-- Corner case !!! The read acks pipeline takes two extra cycles
-- which means a store ack can collide with a previous load hit
-- ack. Thus we stall stores if we have a load ack pending.
--
if read_ack_0 = '1' or read_ack_1 = '1' then
-- Clash with pending read acks, delay..
store_delay := true;
elsif state /= IDLE then
-- If the reload machine is active, we cannot accept a store
-- for now.
--
-- We could improve this a bit by allowing stores if we have sent
-- all the requests down to litedram (we are only waiting for the
-- responses) *and* either of those conditions is true:
--
-- * It's a miss (doesn't require a write to BRAM) and isn't
-- for the line being reloaded (otherwise we might reload
-- stale data into the cache).
-- * It's a hit on a different way than the one being reloaded
-- in which case there is no conflict for BRAM access.
--
-- Otherwise we delay it...
--
store_delay := true;
else
store_delay := false;
end if;

-- Generate the req op. We only allow OP_LOAD_* when in the -- Generate the req op. We only allow OP_LOAD_* when in the
-- IDLE state as our PLRU and ACK generation rely on this, -- IDLE state as our PLRU and ACK generation rely on this,
-- stores are allowed in IDLE state. -- stores are allowed in IDLE state.
-- --
req_op <= OP_NONE; req_op <= OP_NONE;
if valid = '1' then if valid then
if wb_req.we = '1' then if wb_req.we = '1' then
if is_hit = '1' then if store_delay then
req_op <= OP_STORE_DELAYED;
elsif is_hit then
req_op <= OP_STORE_HIT; req_op <= OP_STORE_HIT;
else else
req_op <= OP_STORE_MISS; req_op <= OP_STORE_MISS;
end if; end if;
else else
if is_hit = '1' then if is_hit then
req_op <= OP_LOAD_HIT; req_op <= OP_LOAD_HIT;
else else
req_op <= OP_LOAD_MISS; req_op <= OP_LOAD_MISS;
@ -833,21 +888,38 @@ begin


storeq_control : process(all) storeq_control : process(all)
variable stq_data : wishbone_data_type; variable stq_data : wishbone_data_type;
variable stq_sel : std_ulogic_vector(DRAM_SBITS-1 downto 0); variable stq_sel : wishbone_sel_type;
variable stq_wsl : std_ulogic_vector(WB_WSEL_BITS-1 downto 0);
begin begin
storeq_wr_data <= wb_req.dat & req_we; storeq_wr_data <= wb_req.dat & wb_req.sel &
wb_req.adr(WB_WSEL_RIGHT+WB_WSEL_BITS-1 downto WB_WSEL_RIGHT);


-- Only accept store if we can send a command -- Only queue stores if we can also send a command
if req_op = OP_STORE_HIT or req_op = OP_STORE_MISS then if req_op = OP_STORE_HIT or req_op = OP_STORE_MISS then
storeq_wr_valid <= user_port0_cmd_ready; storeq_wr_valid <= user_port0_cmd_ready;
else else
storeq_wr_valid <= '0'; storeq_wr_valid <= '0';
end if; end if;


stq_data := storeq_rd_data(storeq_rd_data'left downto DRAM_SBITS); -- Store signals (hard wired for 64-bit wishbone at the moment)
stq_sel := storeq_rd_data(DRAM_SBITS-1 downto 0); stq_data := storeq_rd_data(storeq_rd_data'left downto WBSL+WB_WSEL_BITS);
user_port0_wdata_data <= stq_data & stq_data; stq_sel := storeq_rd_data(WBSL+WB_WSEL_BITS-1 downto WB_WSEL_BITS);
user_port0_wdata_we <= stq_sel; stq_wsl := storeq_rd_data(WB_WSEL_BITS-1 downto 0);
for i in 0 to WB_WORD_COUNT-1 loop
if to_integer(unsigned(stq_wsl)) = i then
user_port0_wdata_we(WBSL*(i+1)-1 downto WBSL*i) <= stq_sel;
else
user_port0_wdata_we(WBSL*(i+1)-1 downto WBSL*i) <= x"00";
end if;
user_port0_wdata_data(WBL*(i+1)-1 downto WBL*i) <= stq_data;
end loop;

-- Note: Current litedram ignores user_port0_wdata_valid. We
-- must make sure to always have the data available at the
-- output of the store queue when we send the write command.
--
-- Thankfully this is always the case with this design.
--
user_port0_wdata_valid <= storeq_rd_valid; user_port0_wdata_valid <= storeq_rd_valid;
storeq_rd_ready <= user_port0_wdata_ready; storeq_rd_ready <= user_port0_wdata_ready;


@ -858,13 +930,13 @@ begin
to_hstring(wb_req.adr(DRAM_ABITS+3 downto 0)) & to_hstring(wb_req.adr(DRAM_ABITS+3 downto 0)) &
" data:" & to_hstring(req_wdata) & " data:" & to_hstring(req_wdata) &
" we:" & to_hstring(req_we) & " we:" & to_hstring(req_we) &
" V:" & std_ulogic'image(accept_store); " V:" & std_ulogic'image(user_port0_cmd_ready);
else else
report "Store miss to:" & report "Store miss to:" &
to_hstring(wb_req.adr(DRAM_ABITS+3 downto 0)) & to_hstring(wb_req.adr(DRAM_ABITS+3 downto 0)) &
" data:" & to_hstring(req_wdata) & " data:" & to_hstring(req_wdata) &
" we:" & to_hstring(req_we) & " we:" & to_hstring(req_we) &
" V:" & std_ulogic'image(accept_store); " V:" & std_ulogic'image(user_port0_cmd_ready);
end if; end if;
if storeq_wr_valid = '1' and storeq_wr_ready = '1' then if storeq_wr_valid = '1' and storeq_wr_ready = '1' then
report "storeq push " & to_hstring(storeq_wr_data); report "storeq push " & to_hstring(storeq_wr_data);
@ -879,10 +951,10 @@ begin
-- LiteDRAM command mux -- LiteDRAM command mux
dram_commands: process(all) dram_commands: process(all)
begin begin
if state = IDLE and (req_op = OP_STORE_HIT or req_op = OP_STORE_MISS) then if req_op = OP_STORE_HIT or req_op = OP_STORE_MISS then
-- For stores, forward signals directly. Only send command if -- For stores, forward signals directly. Only send command if
-- the FIFO can accept a store -- the FIFO can accept a store.
user_port0_cmd_addr <= wb_req.adr(DRAM_ABITS+3 downto 4); user_port0_cmd_addr <= wb_req.adr(DRAM_ABITS+ROW_OFF_BITS-1 downto ROW_OFF_BITS);
user_port0_cmd_we <= '1'; user_port0_cmd_we <= '1';
user_port0_cmd_valid <= storeq_wr_ready; user_port0_cmd_valid <= storeq_wr_ready;
else else
@ -891,6 +963,9 @@ begin
user_port0_cmd_valid <= refill_cmd_valid; user_port0_cmd_valid <= refill_cmd_valid;
user_port0_cmd_we <= '0'; user_port0_cmd_we <= '0';
end if; end if;

-- Note: litedram ignores this signal and assumes we are
-- always ready to accept read data.
user_port0_rdata_ready <= '1'; -- Always 1 user_port0_rdata_ready <= '1'; -- Always 1
end process; end process;


@ -918,6 +993,11 @@ begin
assert refill_cmd_valid = '0' report "refill cmd valid in IDLE state !" assert refill_cmd_valid = '0' report "refill cmd valid in IDLE state !"
severity failure; severity failure;


-- Reset per-row valid flags, only used in WAIT_ACK
for i in 0 to ROW_PER_LINE - 1 loop
refill_rows_vlid(i) <= '0';
end loop;

-- If NO_LS_OVERLAP is set, disallow a load miss if the store -- If NO_LS_OVERLAP is set, disallow a load miss if the store
-- queue still has data in it. -- queue still has data in it.
wait_qdrain := false; wait_qdrain := false;
@ -931,8 +1011,9 @@ begin
refill_way <= to_integer(unsigned(plru_victim(req_index))); refill_way <= to_integer(unsigned(plru_victim(req_index)));


-- Keep track of our index and way for subsequent stores -- Keep track of our index and way for subsequent stores
refill_index <= req_index; refill_index <= req_index;
refill_row <= get_row(req_laddr); refill_row <= get_row(req_laddr);
refill_end_row <= get_row_of_line(get_row(req_laddr)) - 1;


-- Prep for first DRAM read -- Prep for first DRAM read
-- --
@ -941,7 +1022,7 @@ begin
-- "dram_commands". In fact, we could make refill_cmd_addr -- "dram_commands". In fact, we could make refill_cmd_addr
-- only contain the "counter" bits and wire it with the -- only contain the "counter" bits and wire it with the
-- other bits from req_laddr. -- other bits from req_laddr.
refill_cmd_addr <= req_laddr(DRAM_ABITS+3 downto 4); refill_cmd_addr <= req_laddr(DRAM_ABITS+ROW_OFF_BITS-1 downto ROW_OFF_BITS);
refill_cmd_valid <= '1'; refill_cmd_valid <= '1';


if TRACE then if TRACE then
@ -982,7 +1063,7 @@ begin
if TRACE then if TRACE then
report "got refill cmd ack !"; report "got refill cmd ack !";
end if; end if;
if is_last_row_addr(refill_cmd_addr) then if is_last_row_addr(refill_cmd_addr, refill_end_row) then
refill_cmd_valid <= '0'; refill_cmd_valid <= '0';
cmds_done := true; cmds_done := true;
if TRACE then if TRACE then
@ -1003,8 +1084,12 @@ begin
if TRACE then if TRACE then
report "got refill data ack !"; report "got refill data ack !";
end if; end if;

-- Mark partial line valid
refill_rows_vlid(refill_row mod ROW_PER_LINE) <= '1';

-- Check for completion -- Check for completion
if cmds_done and is_last_row(refill_row) then if cmds_done and is_last_row(refill_row, refill_end_row) then
if TRACE then if TRACE then
report "all refill data done !"; report "all refill data done !";
end if; end if;

@ -1,17 +1,18 @@
[*] [*]
[*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI [*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI
[*] Sun May 31 12:53:52 2020 [*] Mon Jun 22 06:32:16 2020
[*] [*]
[dumpfile] "/home/ANT.AMAZON.COM/benh/hackplace/microwatt/foo.ghw" [dumpfile] "/home/ANT.AMAZON.COM/benh/hackplace/microwatt/foo.ghw"
[dumpfile_mtime] "Sun May 31 12:50:15 2020" [dumpfile_mtime] "Mon Jun 22 06:28:35 2020"
[dumpfile_size] 1134118 [dumpfile_size] 1680014
[savefile] "/home/ANT.AMAZON.COM/benh/hackplace/microwatt/litedram/extras/wave_tb.gtkw" [savefile] "/home/ANT.AMAZON.COM/benh/hackplace/microwatt/litedram/extras/wave_tb.gtkw"
[timestart] 1312950000 [timestart] 1920580000
[size] 2509 1371 [size] 2509 1371
[pos] -1 -1 [pos] -1 -1
*-24.248457 1386890000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 *-24.248457 1935000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] top. [treeopen] top.
[treeopen] top.dram_tb. [treeopen] top.dram_tb.
[treeopen] top.dram_tb.dram.
[sst_width] 301 [sst_width] 301
[signals_width] 433 [signals_width] 433
[sst_expanded] 1 [sst_expanded] 1
@ -26,7 +27,6 @@ top.dram_tb.clk
@22 @22
#{top.dram_tb.wb_in.dat[63:0]} top.dram_tb.wb_in.dat[63] top.dram_tb.wb_in.dat[62] top.dram_tb.wb_in.dat[61] top.dram_tb.wb_in.dat[60] top.dram_tb.wb_in.dat[59] top.dram_tb.wb_in.dat[58] top.dram_tb.wb_in.dat[57] top.dram_tb.wb_in.dat[56] top.dram_tb.wb_in.dat[55] top.dram_tb.wb_in.dat[54] top.dram_tb.wb_in.dat[53] top.dram_tb.wb_in.dat[52] top.dram_tb.wb_in.dat[51] top.dram_tb.wb_in.dat[50] top.dram_tb.wb_in.dat[49] top.dram_tb.wb_in.dat[48] top.dram_tb.wb_in.dat[47] top.dram_tb.wb_in.dat[46] top.dram_tb.wb_in.dat[45] top.dram_tb.wb_in.dat[44] top.dram_tb.wb_in.dat[43] top.dram_tb.wb_in.dat[42] top.dram_tb.wb_in.dat[41] top.dram_tb.wb_in.dat[40] top.dram_tb.wb_in.dat[39] top.dram_tb.wb_in.dat[38] top.dram_tb.wb_in.dat[37] top.dram_tb.wb_in.dat[36] top.dram_tb.wb_in.dat[35] top.dram_tb.wb_in.dat[34] top.dram_tb.wb_in.dat[33] top.dram_tb.wb_in.dat[32] top.dram_tb.wb_in.dat[31] top.dram_tb.wb_in.dat[30] top.dram_tb.wb_in.dat[29] top.dram_tb.wb_in.dat[28] top.dram_tb.wb_in.dat[27] top.dram_tb.wb_in.dat[26] top.dram_tb.wb_in.dat[25] top.dram_tb.wb_in.dat[24] top.dram_tb.wb_in.dat[23] top.dram_tb.wb_in.dat[22] top.dram_tb.wb_in.dat[21] top.dram_tb.wb_in.dat[20] top.dram_tb.wb_in.dat[19] top.dram_tb.wb_in.dat[18] top.dram_tb.wb_in.dat[17] top.dram_tb.wb_in.dat[16] top.dram_tb.wb_in.dat[15] top.dram_tb.wb_in.dat[14] top.dram_tb.wb_in.dat[13] top.dram_tb.wb_in.dat[12] top.dram_tb.wb_in.dat[11] top.dram_tb.wb_in.dat[10] top.dram_tb.wb_in.dat[9] top.dram_tb.wb_in.dat[8] top.dram_tb.wb_in.dat[7] top.dram_tb.wb_in.dat[6] top.dram_tb.wb_in.dat[5] top.dram_tb.wb_in.dat[4] top.dram_tb.wb_in.dat[3] top.dram_tb.wb_in.dat[2] top.dram_tb.wb_in.dat[1] top.dram_tb.wb_in.dat[0] #{top.dram_tb.wb_in.dat[63:0]} top.dram_tb.wb_in.dat[63] top.dram_tb.wb_in.dat[62] top.dram_tb.wb_in.dat[61] top.dram_tb.wb_in.dat[60] top.dram_tb.wb_in.dat[59] top.dram_tb.wb_in.dat[58] top.dram_tb.wb_in.dat[57] top.dram_tb.wb_in.dat[56] top.dram_tb.wb_in.dat[55] top.dram_tb.wb_in.dat[54] top.dram_tb.wb_in.dat[53] top.dram_tb.wb_in.dat[52] top.dram_tb.wb_in.dat[51] top.dram_tb.wb_in.dat[50] top.dram_tb.wb_in.dat[49] top.dram_tb.wb_in.dat[48] top.dram_tb.wb_in.dat[47] top.dram_tb.wb_in.dat[46] top.dram_tb.wb_in.dat[45] top.dram_tb.wb_in.dat[44] top.dram_tb.wb_in.dat[43] top.dram_tb.wb_in.dat[42] top.dram_tb.wb_in.dat[41] top.dram_tb.wb_in.dat[40] top.dram_tb.wb_in.dat[39] top.dram_tb.wb_in.dat[38] top.dram_tb.wb_in.dat[37] top.dram_tb.wb_in.dat[36] top.dram_tb.wb_in.dat[35] top.dram_tb.wb_in.dat[34] top.dram_tb.wb_in.dat[33] top.dram_tb.wb_in.dat[32] top.dram_tb.wb_in.dat[31] top.dram_tb.wb_in.dat[30] top.dram_tb.wb_in.dat[29] top.dram_tb.wb_in.dat[28] top.dram_tb.wb_in.dat[27] top.dram_tb.wb_in.dat[26] top.dram_tb.wb_in.dat[25] top.dram_tb.wb_in.dat[24] top.dram_tb.wb_in.dat[23] top.dram_tb.wb_in.dat[22] top.dram_tb.wb_in.dat[21] top.dram_tb.wb_in.dat[20] top.dram_tb.wb_in.dat[19] top.dram_tb.wb_in.dat[18] top.dram_tb.wb_in.dat[17] top.dram_tb.wb_in.dat[16] top.dram_tb.wb_in.dat[15] top.dram_tb.wb_in.dat[14] top.dram_tb.wb_in.dat[13] top.dram_tb.wb_in.dat[12] top.dram_tb.wb_in.dat[11] top.dram_tb.wb_in.dat[10] top.dram_tb.wb_in.dat[9] top.dram_tb.wb_in.dat[8] top.dram_tb.wb_in.dat[7] top.dram_tb.wb_in.dat[6] top.dram_tb.wb_in.dat[5] top.dram_tb.wb_in.dat[4] top.dram_tb.wb_in.dat[3] top.dram_tb.wb_in.dat[2] top.dram_tb.wb_in.dat[1] top.dram_tb.wb_in.dat[0]
#{top.dram_tb.wb_in.adr[31:0]} top.dram_tb.wb_in.adr[31] top.dram_tb.wb_in.adr[30] top.dram_tb.wb_in.adr[29] top.dram_tb.wb_in.adr[28] top.dram_tb.wb_in.adr[27] top.dram_tb.wb_in.adr[26] top.dram_tb.wb_in.adr[25] top.dram_tb.wb_in.adr[24] top.dram_tb.wb_in.adr[23] top.dram_tb.wb_in.adr[22] top.dram_tb.wb_in.adr[21] top.dram_tb.wb_in.adr[20] top.dram_tb.wb_in.adr[19] top.dram_tb.wb_in.adr[18] top.dram_tb.wb_in.adr[17] top.dram_tb.wb_in.adr[16] top.dram_tb.wb_in.adr[15] top.dram_tb.wb_in.adr[14] top.dram_tb.wb_in.adr[13] top.dram_tb.wb_in.adr[12] top.dram_tb.wb_in.adr[11] top.dram_tb.wb_in.adr[10] top.dram_tb.wb_in.adr[9] top.dram_tb.wb_in.adr[8] top.dram_tb.wb_in.adr[7] top.dram_tb.wb_in.adr[6] top.dram_tb.wb_in.adr[5] top.dram_tb.wb_in.adr[4] top.dram_tb.wb_in.adr[3] top.dram_tb.wb_in.adr[2] top.dram_tb.wb_in.adr[1] top.dram_tb.wb_in.adr[0] #{top.dram_tb.wb_in.adr[31:0]} top.dram_tb.wb_in.adr[31] top.dram_tb.wb_in.adr[30] top.dram_tb.wb_in.adr[29] top.dram_tb.wb_in.adr[28] top.dram_tb.wb_in.adr[27] top.dram_tb.wb_in.adr[26] top.dram_tb.wb_in.adr[25] top.dram_tb.wb_in.adr[24] top.dram_tb.wb_in.adr[23] top.dram_tb.wb_in.adr[22] top.dram_tb.wb_in.adr[21] top.dram_tb.wb_in.adr[20] top.dram_tb.wb_in.adr[19] top.dram_tb.wb_in.adr[18] top.dram_tb.wb_in.adr[17] top.dram_tb.wb_in.adr[16] top.dram_tb.wb_in.adr[15] top.dram_tb.wb_in.adr[14] top.dram_tb.wb_in.adr[13] top.dram_tb.wb_in.adr[12] top.dram_tb.wb_in.adr[11] top.dram_tb.wb_in.adr[10] top.dram_tb.wb_in.adr[9] top.dram_tb.wb_in.adr[8] top.dram_tb.wb_in.adr[7] top.dram_tb.wb_in.adr[6] top.dram_tb.wb_in.adr[5] top.dram_tb.wb_in.adr[4] top.dram_tb.wb_in.adr[3] top.dram_tb.wb_in.adr[2] top.dram_tb.wb_in.adr[1] top.dram_tb.wb_in.adr[0]
@23
#{top.dram_tb.wb_in.sel[7:0]} top.dram_tb.wb_in.sel[7] top.dram_tb.wb_in.sel[6] top.dram_tb.wb_in.sel[5] top.dram_tb.wb_in.sel[4] top.dram_tb.wb_in.sel[3] top.dram_tb.wb_in.sel[2] top.dram_tb.wb_in.sel[1] top.dram_tb.wb_in.sel[0] #{top.dram_tb.wb_in.sel[7:0]} top.dram_tb.wb_in.sel[7] top.dram_tb.wb_in.sel[6] top.dram_tb.wb_in.sel[5] top.dram_tb.wb_in.sel[4] top.dram_tb.wb_in.sel[3] top.dram_tb.wb_in.sel[2] top.dram_tb.wb_in.sel[1] top.dram_tb.wb_in.sel[0]
@28 @28
top.dram_tb.wb_in.cyc top.dram_tb.wb_in.cyc
@ -67,6 +67,9 @@ top.dram_tb.dram.user_port0_cmd_valid
top.dram_tb.dram.refill_cmd_valid top.dram_tb.dram.refill_cmd_valid
@420 @420
top.dram_tb.dram.req_index top.dram_tb.dram.req_index
@421
top.dram_tb.dram.req_row
@420
top.dram_tb.dram.req_hit_way top.dram_tb.dram.req_hit_way
@28 @28
top.dram_tb.dram.req_ad3 top.dram_tb.dram.req_ad3

@ -21,7 +21,7 @@ end entity dram_init_mem;


architecture rtl of dram_init_mem is architecture rtl of dram_init_mem is


constant INIT_RAM_SIZE : integer := 16384; constant INIT_RAM_SIZE : integer := 24576;
constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8); constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE; constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1); constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1);

@ -38,16 +38,14 @@ def build_init_code(build_dir, is_sim):
sw_inc_dir = os.path.join(sw_dir, "include") sw_inc_dir = os.path.join(sw_dir, "include")
gen_inc_dir = os.path.join(sw_inc_dir, "generated") gen_inc_dir = os.path.join(sw_inc_dir, "generated")
src_dir = os.path.join(gen_src_dir, "sdram_init") src_dir = os.path.join(gen_src_dir, "sdram_init")
lxbios_src_dir = os.path.join(soc_directory, "software", "liblitedram") lxbios_src_dir = os.path.join(soc_directory, "software")
lxbios_inc_dir = os.path.join(soc_directory, "software", "include")
print(" sw dir:", sw_dir) print(" sw dir:", sw_dir)
print("gen_inc_dir:", gen_inc_dir) print("gen_inc_dir:", gen_inc_dir)
print(" src dir:", src_dir) print(" src dir:", src_dir)
print(" lx src dir:", lxbios_src_dir) print(" lx src dir:", lxbios_src_dir)
print(" lx inc dir:", lxbios_inc_dir)


# Generate mem.h # Generate mem.h (hard wire size, it's not important)
mem_h = "#define MAIN_RAM_BASE 0x40000000" mem_h = "#define MAIN_RAM_BASE 0x40000000\n#define MAIN_RAM_SIZE 0x10000000"
write_to_file(os.path.join(gen_inc_dir, "mem.h"), mem_h) write_to_file(os.path.join(gen_inc_dir, "mem.h"), mem_h)


# Environment # Environment
@ -61,7 +59,6 @@ def build_init_code(build_dir, is_sim):
add_var("SRC_DIR", src_dir) add_var("SRC_DIR", src_dir)
add_var("GENINC_DIR", sw_inc_dir) add_var("GENINC_DIR", sw_inc_dir)
add_var("LXSRC_DIR", lxbios_src_dir) add_var("LXSRC_DIR", lxbios_src_dir)
add_var("LXINC_DIR", lxbios_inc_dir)
if is_sim: if is_sim:
add_var("EXTRA_CFLAGS", "-D__SIM__") add_var("EXTRA_CFLAGS", "-D__SIM__")
write_to_file(os.path.join(gen_inc_dir, "variables.mak"), "".join(env_vars)) write_to_file(os.path.join(gen_inc_dir, "variables.mak"), "".join(env_vars))
@ -143,7 +140,7 @@ def generate_one(t):


def main(): def main():


targets = ['arty','nexys-video', 'sim'] targets = ['arty','nexys-video', 'genesys2', 'sim']
for t in targets: for t in targets:
generate_one(t) generate_one(t)

@ -0,0 +1,41 @@
# This file is Copyright (c) 2018-2019 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD

{
# General ------------------------------------------------------------------
"cpu": "None", # Type of CPU used for init/calib (vexriscv, lm32)
"cpu_variant":"standard",
"speedgrade": -2, # FPGA speedgrade
"memtype": "DDR3", # DRAM type

# PHY ----------------------------------------------------------------------
"cmd_latency": 0, # Command additional latency
"sdram_module": "MT41J256M16", # SDRAM modules of the board or SO-DIMM
"sdram_module_nb": 4, # Number of byte groups
"sdram_rank_nb": 1, # Number of ranks
"sdram_phy": K7DDRPHY, # Type of FPGA PHY

# Electrical ---------------------------------------------------------------
"rtt_nom": "60ohm", # Nominal termination
"rtt_wr": "60ohm", # Write termination
"ron": "34ohm", # Output driver impedance

# Frequency ----------------------------------------------------------------
"input_clk_freq": 200e6, # Input clock frequency
"sys_clk_freq": 100e6, # System clock frequency (DDR_clk = 4 x sys_clk)
"iodelay_clk_freq": 200e6, # IODELAYs reference clock frequency

# Core ---------------------------------------------------------------------
"cmd_buffer_depth": 16, # Depth of the command buffer

# User Ports ---------------------------------------------------------------
"user_ports": {
"native_0": {
"type": "native",
},
},

# CSR Port -----------------------------------------------------------------
"csr_alignment" : 32,
"csr_data_width" : 32,
}

@ -3,8 +3,10 @@
include variables.mak include variables.mak
OBJ = $(BUILD_DIR)/obj OBJ = $(BUILD_DIR)/obj


LXINC_DIR=$(LXSRC_DIR)/include

PROGRAM = sdram_init PROGRAM = sdram_init
OBJECTS = $(OBJ)/head.o $(OBJ)/main.o $(OBJ)/sdram.o $(OBJ)/console.o OBJECTS = $(OBJ)/head.o $(OBJ)/main.o $(OBJ)/sdram.o $(OBJ)/memtest.o $(OBJ)/console.o


#### Compiler #### Compiler


@ -22,7 +24,13 @@ OBJCOPY = $(CROSS_COMPILE)objcopy
#### Flags #### Flags


CPPFLAGS = -nostdinc -D__USE_LIBC $(EXTRA_CFLAGS) CPPFLAGS = -nostdinc -D__USE_LIBC $(EXTRA_CFLAGS)
CPPFLAGS += -I$(SRC_DIR)/libc/include -I$(LXSRC_DIR) -I$(LXINC_DIR) -I$(GENINC_DIR) -I$(SRC_DIR)/include -I$(SRC_DIR)/../../../include
# These includes must be first ...
CPPFLAGS += -I$(GENINC_DIR) -I$(SRC_DIR)/include -I$(SRC_DIR)/../../../include -I$(SRC_DIR)/libc/include

# .. and these last, otherwise litex overrides some of our stuff
CPPFLAGS += -I$(LXSRC_DIR) -I$(LXINC_DIR) -I$(LXINC_DIR)/base -I$(LXSRC_DIR)/liblitedram

CPPFLAGS += -isystem $(shell $(CC) -print-file-name=include) CPPFLAGS += -isystem $(shell $(CC) -print-file-name=include)
CFLAGS = -Os -g -Wall -std=c99 -m64 -mabi=elfv2 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -fno-delete-null-pointer-checks CFLAGS = -Os -g -Wall -std=c99 -m64 -mabi=elfv2 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -fno-delete-null-pointer-checks
ASFLAGS = $(CPPFLAGS) $(CFLAGS) ASFLAGS = $(CPPFLAGS) $(CFLAGS)
@ -48,7 +56,9 @@ endif


all: objdir $(OBJ)/$(PROGRAM).hex all: objdir $(OBJ)/$(PROGRAM).hex


$(OBJ)/sdram.o: $(LXSRC_DIR)/sdram.c $(OBJ)/sdram.o: $(LXSRC_DIR)/liblitedram/sdram.c
$(call Q,CC, $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@, $@)
$(OBJ)/memtest.o: $(LXSRC_DIR)/libbase/memtest.c
$(call Q,CC, $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@, $@) $(call Q,CC, $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@, $@)
$(OBJ)/console.o: $(SRC_DIR)/../../../lib/console.c $(OBJ)/console.o: $(SRC_DIR)/../../../lib/console.c
$(call Q,CC, $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@, $@) $(call Q,CC, $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@, $@)

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */


#define STACK_TOP 0xff004000 #define STACK_TOP 0xff006000


#define FIXUP_ENDIAN \ #define FIXUP_ENDIAN \
tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \ tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \

@ -1,6 +1,8 @@
#ifndef __SYSTEM_H #ifndef __SYSTEM_H
#define __SYSTEM_H #define __SYSTEM_H


#include <stdint.h>

#include "microwatt_soc.h" #include "microwatt_soc.h"
#include "io.h" #include "io.h"


@ -32,6 +34,9 @@ static inline uint64_t timer0_value_read(void)
return val; return val;
} }


static inline void init_progression_bar(int max) { }
static inline void show_progress(int now) { }

static inline void csr_write_simple(unsigned long v, unsigned long a) static inline void csr_write_simple(unsigned long v, unsigned long a)
{ {
return writel(v, a); return writel(v, a);

@ -7,10 +7,10 @@


#include <generated/git.h> #include <generated/git.h>


#include "console.h"
#include "microwatt_soc.h" #include "microwatt_soc.h"
#include "io.h" #include "io.h"
#include "sdram.h" #include "sdram.h"
#include "console.h"
#include "elf64.h" #include "elf64.h"


#define FLASH_LOADER_USE_MAP #define FLASH_LOADER_USE_MAP
@ -225,9 +225,9 @@ dump:


static void boot_sdram(void) static void boot_sdram(void)
{ {
void *s = (void *)(DRAM_INIT_BASE + 0x4000); void *s = (void *)(DRAM_INIT_BASE + 0x6000);
void *d = (void *)DRAM_BASE; void *d = (void *)DRAM_BASE;
int sz = (0x10000 - 0x4000); int sz = (0x10000 - 0x6000);
printf("Copying payload to DRAM...\n"); printf("Copying payload to DRAM...\n");
memcpy(d, s, sz); memcpy(d, s, sz);
printf("Booting from DRAM...\n"); printf("Booting from DRAM...\n");

@ -21,7 +21,7 @@ end entity dram_init_mem;


architecture rtl of dram_init_mem is architecture rtl of dram_init_mem is


constant INIT_RAM_SIZE : integer := 16384; constant INIT_RAM_SIZE : integer := 24576;
constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8); constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE; constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1); constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1);

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// Auto-generated by Migen (b1b2b29) & LiteX (20ff2462) on 2020-06-13 00:02:02 // Auto-generated by Migen (4fea1bd) & LiteX (83d24d08) on 2020-07-08 17:33:20
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
module litedram_core( module litedram_core(
input wire clk, input wire clk,

@ -0,0 +1,123 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;

library work;
use work.wishbone_types.all;
use work.utils.all;

entity dram_init_mem is
generic (
EXTRA_PAYLOAD_FILE : string := "";
EXTRA_PAYLOAD_SIZE : integer := 0
);
port (
clk : in std_ulogic;
wb_in : in wb_io_master_out;
wb_out : out wb_io_slave_out
);
end entity dram_init_mem;

architecture rtl of dram_init_mem is

constant INIT_RAM_SIZE : integer := 24576;
constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1);
constant INIT_RAM_FILE : string := "litedram_core.init";

type ram_t is array(0 to (TOTAL_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);

-- XXX FIXME: Have a single init function called twice with
-- an offset as argument
procedure init_load_payload(ram: inout ram_t; filename: string) is
file payload_file : text open read_mode is filename;
variable ram_line : line;
variable temp_word : std_logic_vector(63 downto 0);
begin
for i in 0 to RND_PAYLOAD_SIZE-1 loop
exit when endfile(payload_file);
readline(payload_file, ram_line);
hread(ram_line, temp_word);
ram((INIT_RAM_SIZE/4) + i*2) := temp_word(31 downto 0);
ram((INIT_RAM_SIZE/4) + i*2+1) := temp_word(63 downto 32);
end loop;
assert endfile(payload_file) report "Payload too big !" severity failure;
end procedure;

impure function init_load_ram(name : string) return ram_t is
file ram_file : text open read_mode is name;
variable temp_word : std_logic_vector(63 downto 0);
variable temp_ram : ram_t := (others => (others => '0'));
variable ram_line : line;
begin
report "Payload size:" & integer'image(EXTRA_PAYLOAD_SIZE) &
" rounded to:" & integer'image(RND_PAYLOAD_SIZE);
report "Total RAM size:" & integer'image(TOTAL_RAM_SIZE) &
" bytes using " & integer'image(INIT_RAM_ABITS) &
" address bits";
for i in 0 to (INIT_RAM_SIZE/8)-1 loop
exit when endfile(ram_file);
readline(ram_file, ram_line);
hread(ram_line, temp_word);
temp_ram(i*2) := temp_word(31 downto 0);
temp_ram(i*2+1) := temp_word(63 downto 32);
end loop;
if RND_PAYLOAD_SIZE /= 0 then
init_load_payload(temp_ram, EXTRA_PAYLOAD_FILE);
end if;
return temp_ram;
end function;

impure function init_zero return ram_t is
variable temp_ram : ram_t := (others => (others => '0'));
begin
return temp_ram;
end function;

impure function initialize_ram(filename: string) return ram_t is
begin
report "Opening file " & filename;
if filename'length = 0 then
return init_zero;
else
return init_load_ram(filename);
end if;
end function;
signal init_ram : ram_t := initialize_ram(INIT_RAM_FILE);

attribute ram_style : string;
attribute ram_style of init_ram: signal is "block";

signal obuf : std_ulogic_vector(31 downto 0);
signal oack : std_ulogic;
begin

init_ram_0: process(clk)
variable adr : integer;
begin
if rising_edge(clk) then
oack <= '0';
if (wb_in.cyc and wb_in.stb) = '1' then
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_in.we = '0' then
obuf <= init_ram(adr);
else
for i in 0 to 3 loop
if wb_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
oack <= '1';
end if;
wb_out.ack <= oack;
wb_out.dat <= obuf;
end if;
end process;

wb_out.stall <= '0';

end architecture rtl;

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -21,7 +21,7 @@ end entity dram_init_mem;


architecture rtl of dram_init_mem is architecture rtl of dram_init_mem is


constant INIT_RAM_SIZE : integer := 16384; constant INIT_RAM_SIZE : integer := 24576;
constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8); constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE; constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1); constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1);

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// Auto-generated by Migen (b1b2b29) & LiteX (20ff2462) on 2020-06-13 00:02:04 // Auto-generated by Migen (4fea1bd) & LiteX (83d24d08) on 2020-07-08 17:33:22
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
module litedram_core( module litedram_core(
input wire clk, input wire clk,

@ -21,7 +21,7 @@ end entity dram_init_mem;


architecture rtl of dram_init_mem is architecture rtl of dram_init_mem is


constant INIT_RAM_SIZE : integer := 16384; constant INIT_RAM_SIZE : integer := 24576;
constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8); constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE; constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1); constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1);

@ -5,7 +5,7 @@ a64b5a7d14004a39
2402004ca64b7b7d 2402004ca64b7b7d
602100003c200000 602100003c200000
6421ff00782107c6 6421ff00782107c6
3d80000060213f00 3d80000060215f00
798c07c6618c0000 798c07c6618c0000
618c10e0658cff00 618c10e0658cff00
4e8004217d8903a6 4e8004217d8903a6
@ -518,7 +518,7 @@ a64b5a7d14004a39
4e80002060000000 4e80002060000000
0000000000000000 0000000000000000
3c4c000100000000 3c4c000100000000
7c0802a638429cc4 7c0802a638429ec4
fbe1fff8fbc1fff0 fbe1fff8fbc1fff0
f821ff51f8010010 f821ff51f8010010
f88100d83be10020 f88100d83be10020
@ -527,67 +527,67 @@ f88100d83be10020
f8e100f038c100d8 f8e100f038c100d8
f90100f87fe3fb78 f90100f87fe3fb78
f9410108f9210100 f9410108f9210100
6000000048001239 60000000480014a9
7fe3fb787c7e1b78 7fe3fb787c7e1b78
6000000048000c21 6000000048000e91
7fc3f378382100b0 7fc3f378382100b0
00000000480017f8 0000000048001a68
0000028001000000 0000028001000000
000000004e800020 000000004e800020
0000000000000000 0000000000000000
4c00012c7c0007ac 4c00012c7c0007ac
000000004e800020 000000004e800020
0000000000000000 0000000000000000
38429c203c4c0001 38429e203c4c0001
7d8000267c0802a6 7d8000267c0802a6
9181000848001735 91810008480019a5
48000c1df821fed1 48000e8df821fed1
3c62ffff60000000 3c62ffff60000000
4bffff3938637bb8 4bffff3938637c28
548400023880ffff 548400023880ffff
7c8026ea7c0004ac 7c8026ea7c0004ac
3fe0c0003c62ffff 3fe0c0003c62ffff
63ff000838637bd8 63ff000838637c48
3c62ffff4bffff15 3c62ffff4bffff15
38637bf87bff0020 38637c687bff0020
7c0004ac4bffff05 7c0004ac4bffff05
73e900017fe0feea 73e900017fe0feea
3c62ffff41820010 3c62ffff41820010
4bfffee938637c10 4bfffee938637c80
4e00000073e90002 4e00000073e90002
3c62ffff41820010 3c62ffff41820010
4bfffed138637c18 4bfffed138637c88
4d80000073e90004 4d80000073e90004
3c62ffff41820010 3c62ffff41820010
4bfffeb938637c20 4bfffeb938637c90
4d00000073e90008 4d00000073e90008
3c62ffff41820010 3c62ffff41820010
4bfffea138637c28 4bfffea138637c98
4182001073e90010 4182001073e90010
38637c383c62ffff 38637ca83c62ffff
3f62ffff4bfffe8d 3f62ffff4bfffe8d
7f63db783b7b7f70 7f63db783b7b7f28
418e00284bfffe7d 418e00284bfffe7d
608400103c80c000 608400103c80c000
7c0004ac78840020 7c0004ac78840020
3c62ffff7c8026ea 3c62ffff7c8026ea
38637c487884b582 38637cb87884b582
4192004c4bfffe55 4192004c4bfffe55
608400183c80c000 608400183c80c000
7c0004ac78840020 7c0004ac78840020
3c62ffff7c8026ea 3c62ffff7c8026ea
38637c6078846022 38637cd078846022
3c80c0004bfffe2d 3c80c0004bfffe2d
7884002060840030 7884002060840030
7c8026ea7c0004ac 7c8026ea7c0004ac
7884b2823c62ffff 7884b2823c62ffff
4bfffe0938637c78 4bfffe0938637ce8
612900203d20c000 612900203d20c000
7c0004ac79290020 7c0004ac79290020
3c80000f7d204eea 3c80000f7d204eea
6084424079290600 6084424079290600
7c8923923c62ffff 7c8923923c62ffff
4bfffdd938637c90 4bfffdd938637d00
3fa0c000418a0258 3fa0c000418a0258
7bbd002063bd0038 7bbd002063bd0038
7fa0eeea7c0004ac 7fa0eeea7c0004ac
@ -604,7 +604,7 @@ f9410108f9210100
57ff063e4bfffd29 57ff063e4bfffd29
7fe6fb783c62ffff 7fe6fb783c62ffff
7f84e3787fc5f378 7f84e3787fc5f378
4bfffd5138637cb0 4bfffd5138637d20
7d29fb787f89f378 7d29fb787f89f378
419e01642f890000 419e01642f890000
7d29f8387f89f038 7d29f8387f89f038
@ -624,9 +624,9 @@ f9410108f9210100
7f80feaa7c0004ac 7f80feaa7c0004ac
579c063e4bfffc81 579c063e4bfffc81
7f84e3783c62ffff 7f84e3783c62ffff
4bfffcb138637cd0 4bfffcb138637d40
4082009073890002 4082009073890002
38637cf03c62ffff 38637d603c62ffff
7c0004ac4bfffc9d 7c0004ac4bfffc9d
392000067f40f7aa 392000067f40f7aa
7d20ffaa7c0004ac 7d20ffaa7c0004ac
@ -644,7 +644,7 @@ f9410108f9210100
579c063e7f80feaa 579c063e7f80feaa
738900014bfffbe1 738900014bfffbe1
3c62ffff4082ffdc 3c62ffff4082ffdc
4bfffc1138637d08 4bfffc1138637d78
614a60083d40c000 614a60083d40c000
7c0004ac794a0020 7c0004ac794a0020
5529021e7d20562a 5529021e7d20562a
@ -652,62 +652,62 @@ f9410108f9210100
7d20572a7c0004ac 7d20572a7c0004ac
4bfffbe17f63db78 4bfffbe17f63db78
3c62ffff7bbd0020 3c62ffff7bbd0020
38637d187fa4eb78 38637d887fa4eb78
3be000014bfffbcd 3be000014bfffbcd
4bfffbc17f63db78 4bfffbc17f63db78
3ca2ffff41920028 3ca2ffff41920028
3c62ffff3c82ffff 3c62ffff3c82ffff
38847d4838a57d38 38847db838a57da8
4bfffba138637d50 4bfffba138637dc0
6000000048000605 6000000048000311
3c62ffff418e0024 3c62ffff418e0024
4bfffb8938637d80 4bfffb8938637df0
4800014438600000 4800014438600000
3ba000003be00000 3ba000003be00000
2fbf00004bffffb0 2fbf00004bffffb0
3c62ffff419e0084 3c62ffff419e0084
4bfffb6138637d98 4bfffb6138637e08
38a000403c9df000 38a000403c9df000
3861007078840020 3861007078840020
6000000048000aa9 6000000048000d19
3d400002e9210070 3d400002e9210070
794a83e4614a464c 794a83e4614a464c
614a457f79290600 614a457f79290600
419e00807fa95000 419e00807fa95000
38637db03c62ffff 38637e203c62ffff
886100774bfffb1d 886100774bfffb1d
8921007589410076 8921007589410076
88e1007389010074 88e1007389010074
88a1007188c10072 88a1007188c10072
f861006088810070 f861006088810070
38637e303c62ffff 38637ea03c62ffff
3c62ffff4bfffaed 3c62ffff4bfffaed
4bfffae138637e60 4bfffae138637ed0
38a0ffff3c80ff00 38a000003c80ff00
54a5042260844000 60a5a00060846000
3c60400078840020 3c60400078840020
6000000048000a21 6000000048000c91
38637e803c62ffff 38637ef03c62ffff
4bfffb354bfffab5 4bfffb354bfffab5
892100754bffff28 892100754bffff28
409e00102f890001 409e00102f890001
2f890015a1210082 2f890015a1210082
3c62ffff419e0010 3c62ffff419e0010
4bffff6c38637dd0 4bffff6c38637e40
3f02ffffebe10090 3f02ffffebe10090
3b2100b03bc00000 3b2100b03bc00000
7fffea143b187de8 7fffea143b187e58
a12100a87bff0020 a12100a87bff0020
419d00347f89f040 419d00347f89f040
3c62ffff80810088 3c62ffff80810088
4bfffa5138637e10 4bfffa5138637e80
e86100884bfffad1 e86100884bfffad1
419eff582fa3ffff 419eff582fa3ffff
8181000838210130 8181000838210130
480012607d838120 480014d07d838120
38a000383c9ff000 38a000383c9ff000
7f23cb7878840020 7f23cb7878840020
6000000048000979 6000000048000be9
2f890001812100b0 2f890001812100b0
eb4100d0409e004c eb4100d0409e004c
eb8100b8eb6100c0 eb8100b8eb6100c0
@ -716,14 +716,14 @@ eb8100b8eb6100c0
4bfff9e93f9cf000 4bfff9e93f9cf000
7b4500207c9de214 7b4500207c9de214
7f63db7878840020 7f63db7878840020
6000000048000931 6000000048000ba1
7fe9fa14a12100a6 7fe9fa14a12100a6
3bde00017bff0020 3bde00017bff0020
4bffff507bde0020 4bffff507bde0020
409efdcc2b9c0020 409efdcc2b9c0020
409efdc42b9e00ba 409efdc42b9e00ba
409efdbc2b9f0018 409efdbc2b9f0018
38637d003c62ffff 38637d703c62ffff
4bfffd784bfff995 4bfffd784bfff995
0300000000000000 0300000000000000
3d20c80000000880 3d20c80000000880
@ -734,134 +734,40 @@ eb8100b8eb6100c0
7d20572a7c0004ac 7d20572a7c0004ac
000000004e800020 000000004e800020
0000000000000000 0000000000000000
384296003c4c0001 384298003c4c0001
3d40c8007c0802a6 3d40c8007c0802a6
3920000e614a0800 3920000e614a0800
f8010010794a0020 f8010010794a0020
7c0004acf821ffa1 7c0004acf821ffa1
3c62ffff7d20572a 3c62ffff7d20572a
4bfff91138637f90 4bfff91138637f50
3821006060000000 3821006060000000
7c0803a6e8010010 7c0803a6e8010010
000000004e800020 000000004e800020
0000008001000000 0000008001000000
384295a83c4c0001 384297a83c4c0001
3d40c8007c0802a6 3d40c8007c0802a6
39200001614a0800 39200001614a0800
f8010010794a0020 f8010010794a0020
7c0004acf821ffa1 7c0004acf821ffa1
3c62ffff7d20572a 3c62ffff7d20572a
4bfff8b938637f50 4bfff8b938637f08
3821006060000000 3821006060000000
7c0803a6e8010010 7c0803a6e8010010
000000004e800020 000000004e800020
0000008001000000 0000008001000000
384295503c4c0001 384297503c4c0001
390000807c0802a6 3c62ffff7c0802a6
3d40aaaa7d0903a6 38637f303c804000
614aaaaa3d204000 f821ff71480012d5
f821ff8148001069
3929000491490000
4bfff8d54200fff8
3940008060000000
7d4903a63d00aaaa
3be000003d204000
814900006108aaaa
419e000c7f8a4000
7fff07b43bff0001
4200ffe839290004
3d40555539000080
3d2040007d0903a6
91490000614a5555
4200fff839290004
600000004bfff879
3d00555539400080
3d2040007d4903a6
8149000061085555
419e000c7f8a4000
7fff07b43bff0001
4200ffe839290004
419e001c2fbf0000
38a001003c62ffff
38637e987fe4fb78
600000004bfff7b5
3ce0802039000100
60e700037d0903a6
392000013d404000
7928f84278e70020
7d2900d0792907e0
7d293838394a0004
912afffc7d294278
4bfff7e54200ffe4
3900010060000000
7d0903a63ce08020
3d40400060e70003
392000013ba00000
7928f84278e70020
7d2900d0792907e0
7d2942787d293838
7f884840810a0000
3bbd0001419e000c
394a00047fbd07b4
2fbd00004200ffd4
3c62ffff419e001c
7fa4eb7838a00100
4bfff70138637ec0
3920002060000000
7d2903a639400000
794800203d2a1000
394a000139290002
9109000079291764
4bfff7454200ffe8
3920002060000000
7d2903a639400000
3d2a10003bc00000
8129000879291764
7f8950005529043e
3bde0001419e000c
394a00017fde07b4
2fbe00004200ffdc
3c62ffff419e001c
7fc4f37838a00020
4bfff67938637ee8
7fffea1460000000
7ffff21438600000
409e00ac2f9f0000
38637f103c62ffff
600000004bfff655
394000807c9602a6
7d4903a678840020
3d49080039200000
f92a0000794a1f24
4200fff039290001
7c9f20507ff602a6
63ff80003fe0000c
4bfff6857fff2396
7bff002060000000
390000807d3602a6
7d0903a679290020
e90a00003d404000
4200fff8394a0008
7d2548507cb602a6
60a580003ca0000c
7ca54b963c62ffff
38637f207fe4fb78
4bfff5c178a50320
3860000160000000
48000df438210080
0100000000000000
3c4c000100000380
7c0802a63842925c
38637f783c62ffff
f821ff7148000d75
3be000003f60c800 3be000003f60c800
7b7b0020637b1000 7b7b0020637b1000
600000004bfff575 600000004bfff865
7fe0df2a7c0004ac 7fe0df2a7c0004ac
635a10043f40c800 635a10043f40c800
7c0004ac7b5a0020 7c0004ac7b5a0020
3fa0c8007fe0d72a 3fa0c8007fe0d72a
63bd080c4bfffc11 63bd080c4bffff01
7c0004ac7bbd0020 7c0004ac7bbd0020
3fc0c8007fe0ef2a 3fc0c8007fe0ef2a
7bde002063de0810 7bde002063de0810
@ -876,33 +782,205 @@ f821ff7148000d75
7d20ef2a7c0004ac 7d20ef2a7c0004ac
7c0004ac39200002 7c0004ac39200002
3860000f7d20f72a 3860000f7d20f72a
7c0004ac4bfffb55 7c0004ac4bfffe45
392000037fe0ef2a 392000037fe0ef2a
7d20f72a7c0004ac 7d20f72a7c0004ac
4bfffb393860000f 4bfffe293860000f
7c0004ac39200006 7c0004ac39200006
3b8000017d20ef2a 3b8000017d20ef2a
7f80f72a7c0004ac 7f80f72a7c0004ac
4bfffb193860000f 4bfffe093860000f
7c0004ac39200920 7c0004ac39200920
7c0004ac7d20ef2a 7c0004ac7d20ef2a
3860000f7fe0f72a 3860000f7fe0f72a
392004004bfffafd 392004004bfffded
7d20ef2a7c0004ac 7d20ef2a7c0004ac
7fe0f72a7c0004ac 7fe0f72a7c0004ac
4bfffae138600003 4bfffdd138600003
4bfffbcd4bfffb79 3c8010004bfffe69
4082001c2c230000 480004653c604000
7f80df2a7c0004ac 2c23000060000000
7f80d72a7c0004ac 7c0004ac4082001c
48000c7038210090 7c0004ac7f80df2a
7f80df2a7c0004ac 382100907f80d72a
4bffffec38600001 7c0004ac480011c4
386000017f80df2a
000000004bffffec
0000068001000000
384295b83c4c0001
7884f0827c0802a6
3d20aaaa39440001
6129aaaa7d4903a6
f821ffc148001141
3be000007c7d1b78
4bfff73d4200006c
395f000160000000
7d4903a63d00aaaa
3bc0000039200000
420000586108aaaa
3d405555391f0001
392000007d0903a6
42000060614a5555
600000004bfff701
3d005555395f0001
392000007d4903a6
4200005061085555
7fc3f37838210040
7bea176448001118
7d3d512e3bff0001
792a17644bffff88
7f8a40007d5d502e
3bde0001419e000c
392900017fde07b4
792817644bffff8c
7d5d412e39290001
792a17644bffff94
7f8a40007d5d502e
3bde0001419e000c
392900017fde07b4
000000004bffff94
0000038001000000
384294b03c4c0001
7884f0827c0802a6
2fa5000039440001
392000017d4903a6
f821ffc148001039
3be000007c7d1b78
420000347cbe2b78
600000004bfff631
2ebe0000395f0001
38e000007d4903a6
3860000039200001
420000447ce607b4
4800104438210040
792af842419e002c
7d2900d0792907e0
7d2952787129d008
792a17647be80020
7d1d512e3bff0001
392900014bffffa4
4bffffe45529043e
7928f8424196003c
7d2900d0792907e0
7d2942787129d008
7d1d402e79281764
7f8830005508043e
39430001419e000c
38e700017d4307b4
392900014bffff80
4bffffd45529043e
0100000000000000
3c4c000100000380
7c0802a6384293bc
390400017884f082
7d0903a63d408020
39200001614a0003
48000f35794a0020
7cbd2b79f821ff71
3be000007c7b1b78
3f82ffff42000060
3b9c7f283bc00000
4bfff4b17f83e378
4bfff51d60000000
391f000160000000
7d0903a63ce08020
2fbd000060e70003
3920000139400000
4200005078e70020
4bfff4797f83e378
3821009060000000
48000f147fc3f378
7928f84241820028
7d2900d0792907e0
7d2942787d295038
3bff00017be81764
4bffff7c7d3b412e
7929002039290001
419e00384bffffe8
792907e07928f842
7d2938387d2900d0
794817647d294278
7e8848407d1b402e
3bde00014196000c
394a00017fde07b4
392900014bffff7c
4bffffd879290020
0100000000000000 0100000000000000
3c4c000100000680 3c4c000100000580
60000000384290d4 7c0802a63842929c
6000000039228010 f821ff8148000e35
8929000039428008 7c7d1b787c9e2378
3c62ffff7c641b78
38637f787cbc2b78
4bfff3b17bdfe8c2
2fbc000060000000
409e003438800000
38ff00017d3602a6
7ce903a6792a0020
3900ffff39200000
7d3602a642000074
7d2950501c9e0320
7c844b9279290020
38637f903c62ffff
600000004bfff365
600000004bfff3d1
391f00017d3602a6
792a00207d0903a6
4200004039200000
1c9e03207d3602a6
792900207d295050
7c844b923c62ffff
4bfff32138637fa8
3821008060000000
79271f2448000dc4
7d1d392a39290001
79281f244bffff80
7d1d402a39290001
000000004bffffb4
0000048001000000
384291a03c4c0001
2ba402007c0802a6
f821ff6148000d29
3b8002007c7e1b78
7c9c2378419d0008
7c9d23782ba40080
3ba00080409d0008
7c9f23782ba40400
3be00400409d0008
7fc4f3783c62ffff
4bfff29138637fc0
7f84e37860000000
4bfffb8d7fc3f378
7fa4eb7838a00000
7fc3f3787c791b78
38a000014bfffc81
7c7a1b787fe4fb78
4bfffd617fc3f378
7d291a147d39d214
2f8900007c7b1b78
3c62ffff419e0068
7f24cb787b85f882
4bfff23138637fd8
3c62ffff60000000
7f44d3787ba5f082
4bfff21938637ff0
6000000060000000
7f64db787be5f082
4bfff20138628008
6000000060000000
4bfff1f138628020
3860000060000000
48000c84382100a0
3862803060000000
600000004bfff1d5
38a000007fc3f378
4bfffde97fe4fb78
4bffffd438600001
0100000000000000
3c4c000100000780
6000000038429064
6000000039228098
8929000039428090
419e002c2f890000 419e002c2f890000
39290014e92a0000 39290014e92a0000
7d204eaa7c0004ac 7d204eaa7c0004ac
@ -916,7 +994,7 @@ e94a00005469063e
7d2057ea7c0004ac 7d2057ea7c0004ac
000000004e800020 000000004e800020
0000000000000000 0000000000000000
384290503c4c0001 38428fe03c4c0001
fbc1fff07c0802a6 fbc1fff07c0802a6
3bc3fffffbe1fff8 3bc3fffffbe1fff8
f821ffd1f8010010 f821ffd1f8010010
@ -928,7 +1006,7 @@ f821ffd1f8010010
4bffff397fe3fb78 4bffff397fe3fb78
000000004bffffd0 000000004bffffd0
0000028001000000 0000028001000000
38428ff03c4c0001 38428f803c4c0001
612900203d20c000 612900203d20c000
7c0004ac79290020 7c0004ac79290020
3d00c0007d204eea 3d00c0007d204eea
@ -940,8 +1018,8 @@ f821ffd1f8010010
7c0004ac794a0020 7c0004ac794a0020
3d00c0007d4056ea 3d00c0007d4056ea
6000000060000000 6000000060000000
6108200038e28010 6108200038e28098
f902800879080020 f902809079080020
610820003d00001c 610820003d00001c
7948f8047d294392 7948f8047d294392
4182008079080fc3 4182008079080fc3
@ -949,15 +1027,15 @@ f902800879080020
994700006108200c 994700006108200c
3940ff8079080020 3940ff8079080020
7d4047aa7c0004ac 7d4047aa7c0004ac
7c0004ace9428008 7c0004ace9428090
e94280087d2057aa e94280907d2057aa
394a00047929c202 394a00047929c202
7d2057aa7c0004ac 7d2057aa7c0004ac
39400003e9228008 39400003e9228090
7c0004ac3929000c 7c0004ac3929000c
e92280087d404faa e92280907d404faa
7c0004ac39290010 7c0004ac39290010
e92280087d404faa e92280907d404faa
3929000839400007 3929000839400007
7d404faa7c0004ac 7d404faa7c0004ac
3d40c0004e800020 3d40c0004e800020
@ -1028,7 +1106,7 @@ f924000039290002
7c6307b43863ffe0 7c6307b43863ffe0
000000004e800020 000000004e800020
0000000000000000 0000000000000000
38428cd03c4c0001 38428c603c4c0001
3d2037367c0802a6 3d2037367c0802a6
612935347d908026 612935347d908026
65293332792907c6 65293332792907c6
@ -1062,7 +1140,7 @@ fbfd00007fe9fa14
4bfffff07d29f392 4bfffff07d29f392
0300000000000000 0300000000000000
3c4c000100000580 3c4c000100000580
7c0802a638428bc4 7c0802a638428b54
f821ffb1480006e9 f821ffb1480006e9
7c7f1b78eb630000 7c7f1b78eb630000
7cbd2b787c9c2378 7cbd2b787c9c2378
@ -1078,7 +1156,7 @@ f821ffb1480006e9
4bffffb8f93f0000 4bffffb8f93f0000
0100000000000000 0100000000000000
3c4c000100000580 3c4c000100000580
7c0802a638428b44 7c0802a638428ad4
f821ffa148000661 f821ffa148000661
7c9b23787c7d1b78 7c9b23787c7d1b78
388000007ca32b78 388000007ca32b78
@ -1109,16 +1187,16 @@ e95d00009b270000
f95d0000394a0001 f95d0000394a0001
000000004bffffa8 000000004bffffa8
0000078001000000 0000078001000000
38428a483c4c0001 384289d83c4c0001
480005397c0802a6 480005397c0802a6
7c741b79f821fed1 7c741b79f821fed1
38600000f8610060 38600000f8610060
2fa4000041820068 2fa4000041820068
39210040419e0060 39210040419e0060
3ac4ffff3e42ffff 3ac4ffff60000000
f92100703b410020 f92100703b410020
3ae0000060000000 3ae0000060000000
3a527fb839228000 3a42804039228088
f92100783ba10060 f92100783ba10060
ebc1006089250000 ebc1006089250000
419e00102fa90000 419e00102fa90000
@ -1349,9 +1427,9 @@ e8010010ebc1fff0
203a46464f204853 203a46464f204853
7479622078257830 7479622078257830
00000000000a7365 00000000000a7365
6633623461653832 3830643432643338
0000000000000000 0000000000000000
0039326232623162 0064623161656634
4d4152446574694c 4d4152446574694c
6620746c69756220 6620746c69756220
6567694d206d6f72 6567694d206d6f72
@ -1393,42 +1471,45 @@ e8010010ebc1fff0
20676e69746f6f42 20676e69746f6f42
415244206d6f7266 415244206d6f7266
0000000a2e2e2e4d 0000000a2e2e2e4d
20747365746d654d
6c69616620737562
252f6425203a6465
73726f7272652064
000000000000000a
20747365746d654d
6961662061746164
2f6425203a64656c
726f727265206425
0000000000000a73
20747365746d654d
6961662072646461
2f6425203a64656c
726f727265206425
0000000000000a73
20747365746d654d
00000000000a4b4f
64656570736d654d
3a73657469725720
7370624d646c2520
203a736461655220
0a7370624d646c25
0000000000000000
6f6e204d41524453 6f6e204d41524453
207265646e752077 207265646e752077
6572617764726168 6572617764726168
6c6f72746e6f6320 6c6f72746e6f6320
000000000000000a 000000000000000a
696c616974696e49 696c616974696e49
52445320676e697a 41524420676e697a
00000a2e2e2e4d41 383025783040204d
0000000a2e2e2e78
6f6e204d41524453 6f6e204d41524453
207265646e752077 207265646e752077
6572617774666f73 6572617774666f73
6c6f72746e6f6320 6c6f72746e6f6320
000000000000000a 000000000000000a
64656570736d654d
7025783020746120
000000000a2e2e2e
203a736574697257
7370624d20646c25
000000000000000a
20203a7364616552
7370624d20646c25
000000000000000a
20747365746d654d
2e70257830207461
00000000000a2e2e
726520737562202d
2520203a73726f72
00000a646c252f64
652072646461202d
25203a73726f7272
00000a646c252f64
652061746164202d
25203a73726f7272
00000a646c252f64
20747365746d654d
00000000000a4f4b
20747365746d654d
00000000000a4b4f
0000000000000000 0000000000000000
00000000000000ff 00000000000000ff
000000000000ffff 000000000000ffff

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save