litedram: Add support for booting without BRAM

This adds an option to disable the main BRAM and instead copy a
payload stashed along with the init code in the secondary BRAM
into DRAM and boot from there

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
pull/190/head
Benjamin Herrenschmidt 5 years ago
parent 6fe077910b
commit bf1b98b958

@ -7,33 +7,52 @@ use work.common.all;
use work.wishbone_types.all;

entity core_dram_tb is
generic (
MEMORY_SIZE : natural := (384*1024);
MAIN_RAM_FILE : string := "main_ram.bin";
DRAM_INIT_FILE : string := "";
DRAM_INIT_SIZE : natural := 16#c000#
);
end core_dram_tb;

architecture behave of core_dram_tb is
signal clk, rst: std_logic;
signal system_clk, soc_rst : std_ulogic;

-- testbench signals
constant clk_period : time := 10 ns;

-- Sim DRAM
signal wb_dram_in : wishbone_master_out;
signal wb_dram_out : wishbone_slave_out;
signal wb_dram_ctrl_in : wb_io_master_out;
signal wb_dram_ctrl_out : wb_io_slave_out;
signal wb_dram_is_csr : std_ulogic;
signal wb_dram_is_init : std_ulogic;
signal core_alt_reset : std_ulogic;
signal clk, rst: std_logic;
signal system_clk, soc_rst : std_ulogic;

-- testbench signals
constant clk_period : time := 10 ns;

-- Sim DRAM
signal wb_dram_in : wishbone_master_out;
signal wb_dram_out : wishbone_slave_out;
signal wb_dram_ctrl_in : wb_io_master_out;
signal wb_dram_ctrl_out : wb_io_slave_out;
signal wb_dram_is_csr : std_ulogic;
signal wb_dram_is_init : std_ulogic;
signal core_alt_reset : std_ulogic;

-- ROM size
function get_rom_size return natural is
begin
if MEMORY_SIZE = 0 then
return DRAM_INIT_SIZE;
else
return 0;
end if;
end function;

constant ROM_SIZE : natural := get_rom_size;
begin

soc0: entity work.soc
generic map(
SIM => true,
MEMORY_SIZE => (384*1024),
RAM_INIT_FILE => "main_ram.bin",
MEMORY_SIZE => MEMORY_SIZE,
RAM_INIT_FILE => MAIN_RAM_FILE,
RESET_LOW => false,
HAS_DRAM => true,
DRAM_SIZE => 256 * 1024 * 1024,
DRAM_INIT_SIZE => ROM_SIZE,
CLK_FREQ => 100000000
)
port map(
@ -50,48 +69,50 @@ begin
alt_reset => core_alt_reset
);

dram: entity work.litedram_wrapper
generic map(
DRAM_ABITS => 24,
DRAM_ALINES => 1
)
port map(
clk_in => clk,
rst => rst,
system_clk => system_clk,
system_reset => soc_rst,
core_alt_reset => core_alt_reset,
pll_locked => open,

wb_in => wb_dram_in,
wb_out => wb_dram_out,
wb_ctrl_in => wb_dram_ctrl_in,
wb_ctrl_out => wb_dram_ctrl_out,
wb_ctrl_is_csr => wb_dram_is_csr,
wb_ctrl_is_init => wb_dram_is_init,

serial_tx => open,
serial_rx => '1',

init_done => open,
init_error => open,

ddram_a => open,
ddram_ba => open,
ddram_ras_n => open,
ddram_cas_n => open,
ddram_we_n => open,
ddram_cs_n => open,
ddram_dm => open,
ddram_dq => open,
ddram_dqs_p => open,
ddram_dqs_n => open,
ddram_clk_p => open,
ddram_clk_n => open,
ddram_cke => open,
ddram_odt => open,
ddram_reset_n => open
);
dram: entity work.litedram_wrapper
generic map(
DRAM_ABITS => 24,
DRAM_ALINES => 1,
PAYLOAD_FILE => DRAM_INIT_FILE,
PAYLOAD_SIZE => ROM_SIZE
)
port map(
clk_in => clk,
rst => rst,
system_clk => system_clk,
system_reset => soc_rst,
core_alt_reset => core_alt_reset,
pll_locked => open,

wb_in => wb_dram_in,
wb_out => wb_dram_out,
wb_ctrl_in => wb_dram_ctrl_in,
wb_ctrl_out => wb_dram_ctrl_out,
wb_ctrl_is_csr => wb_dram_is_csr,
wb_ctrl_is_init => wb_dram_is_init,

serial_tx => open,
serial_rx => '1',

init_done => open,
init_error => open,

ddram_a => open,
ddram_ba => open,
ddram_ras_n => open,
ddram_cas_n => open,
ddram_we_n => open,
ddram_cs_n => open,
ddram_dm => open,
ddram_dq => open,
ddram_dqs_p => open,
ddram_dqs_n => open,
ddram_clk_p => open,
ddram_clk_n => open,
ddram_cke => open,
ddram_odt => open,
ddram_reset_n => open
);

clk_process: process
begin

@ -10,11 +10,12 @@ use work.wishbone_types.all;

entity toplevel is
generic (
MEMORY_SIZE : positive := 16384;
MEMORY_SIZE : integer := 16384;
RAM_INIT_FILE : string := "firmware.hex";
RESET_LOW : boolean := true;
CLK_FREQUENCY : positive := 100000000;
USE_LITEDRAM : boolean := false;
NO_BRAM : boolean := false;
DISABLE_FLATTEN_CORE : boolean := false
);
port(
@ -85,6 +86,28 @@ architecture behaviour of toplevel is

-- Dumb PWM for the LEDs, those RGB LEDs are too bright otherwise
signal pwm_counter : std_ulogic_vector(8 downto 0);

-- Fixup various memory sizes based on generics
function get_bram_size return natural is
begin
if USE_LITEDRAM and NO_BRAM then
return 0;
else
return MEMORY_SIZE;
end if;
end function;

function get_payload_size return natural is
begin
if USE_LITEDRAM and NO_BRAM then
return MEMORY_SIZE;
else
return 0;
end if;
end function;
constant BRAM_SIZE : natural := get_bram_size;
constant PAYLOAD_SIZE : natural := get_payload_size;
begin

uart_pmod_rts_n <= '0';
@ -92,13 +115,14 @@ begin
-- Main SoC
soc0: entity work.soc
generic map(
MEMORY_SIZE => MEMORY_SIZE,
MEMORY_SIZE => BRAM_SIZE,
RAM_INIT_FILE => RAM_INIT_FILE,
RESET_LOW => RESET_LOW,
SIM => false,
CLK_FREQ => CLK_FREQUENCY,
HAS_DRAM => USE_LITEDRAM,
DRAM_SIZE => 256 * 1024 * 1024,
DRAM_INIT_SIZE => PAYLOAD_SIZE,
DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE
)
port map (
@ -159,7 +183,7 @@ begin
);
ddram_clk_dummy <= '0';

end generate;
end generate;

has_dram: if USE_LITEDRAM generate
signal dram_init_done : std_ulogic;
@ -189,7 +213,9 @@ begin
dram: entity work.litedram_wrapper
generic map(
DRAM_ABITS => 24,
DRAM_ALINES => 14
DRAM_ALINES => 14,
PAYLOAD_FILE => RAM_INIT_FILE,
PAYLOAD_SIZE => PAYLOAD_SIZE
)
port map(
clk_in => ext_clk,

@ -10,11 +10,12 @@ use work.wishbone_types.all;

entity toplevel is
generic (
MEMORY_SIZE : positive := 16384;
MEMORY_SIZE : integer := 16384;
RAM_INIT_FILE : string := "firmware.hex";
RESET_LOW : boolean := true;
CLK_FREQUENCY : positive := 100000000;
USE_LITEDRAM : boolean := false;
NO_BRAM : boolean := false;
DISABLE_FLATTEN_CORE : boolean := false
);
port(
@ -70,18 +71,40 @@ architecture behaviour of toplevel is
-- Control/status
signal core_alt_reset : std_ulogic;

-- Fixup various memory sizes based on generics
function get_bram_size return natural is
begin
if USE_LITEDRAM and NO_BRAM then
return 0;
else
return MEMORY_SIZE;
end if;
end function;

function get_payload_size return natural is
begin
if USE_LITEDRAM and NO_BRAM then
return MEMORY_SIZE;
else
return 0;
end if;
end function;
constant BRAM_SIZE : natural := get_bram_size;
constant PAYLOAD_SIZE : natural := get_payload_size;
begin

-- Main SoC
soc0: entity work.soc
generic map(
MEMORY_SIZE => MEMORY_SIZE,
MEMORY_SIZE => BRAM_SIZE,
RAM_INIT_FILE => RAM_INIT_FILE,
RESET_LOW => RESET_LOW,
SIM => false,
CLK_FREQ => CLK_FREQUENCY,
HAS_DRAM => USE_LITEDRAM,
DRAM_SIZE => 512 * 1024 * 1024,
DRAM_INIT_SIZE => PAYLOAD_SIZE,
DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE
)
port map (
@ -171,7 +194,9 @@ begin
dram: entity work.litedram_wrapper
generic map(
DRAM_ABITS => 25,
DRAM_ALINES => 15
DRAM_ALINES => 15,
PAYLOAD_FILE => RAM_INIT_FILE,
PAYLOAD_SIZE => PAYLOAD_SIZE
)
port map(
clk_in => ext_clk,

@ -23,6 +23,7 @@
#define SYS_REG_INFO 0x08
#define SYS_REG_INFO_HAS_UART (1ull << 0)
#define SYS_REG_INFO_HAS_DRAM (1ull << 1)
#define SYS_REG_INFO_HAS_BRAM (1ull << 2)
#define SYS_REG_BRAMINFO 0x10
#define SYS_REG_DRAMINFO 0x18
#define SYS_REG_CLKINFO 0x20
@ -30,6 +31,7 @@
#define SYS_REG_CTRL_DRAM_AT_0 (1ull << 0)
#define SYS_REG_CTRL_CORE_RESET (1ull << 1)
#define SYS_REG_CTRL_SOC_RESET (1ull << 2)
#define SYS_REG_DRAMINITINFO 0x30

/*
* Register definitions for the potato UART

@ -6,7 +6,8 @@ import pathlib

class LiteDRAMGenerator(Generator):
def run(self):
board = self.config.get('board')
board = self.config.get('board')
payload = self.config.get('payload')

# Collect a bunch of directory path
script_dir = os.path.dirname(sys.argv[0])

@ -10,6 +10,9 @@ entity litedram_wrapper is
generic (
DRAM_ABITS : positive;
DRAM_ALINES : positive;
-- Pseudo-ROM payload
PAYLOAD_SIZE : natural;
PAYLOAD_FILE : string;
-- Debug
LITEDRAM_TRACE : boolean := false
);
@ -144,6 +147,10 @@ begin

-- Init code BRAM memory slave
init_ram_0: entity work.dram_init_mem
generic map(
EXTRA_PAYLOAD_FILE => PAYLOAD_FILE,
EXTRA_PAYLOAD_SIZE => PAYLOAD_SIZE
)
port map(
clk => system_clk,
wb_in => wb_init_in,

@ -5,66 +5,117 @@ 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
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 := 16384;
constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "litedram_core.init";
constant INIT_RAM_SIZE : integer := 16384;
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);
constant INIT_RAM_FILE : string := "litedram_core.init";

type ram_t is array(0 to (INIT_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);
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;
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
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;
return temp_ram;
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;

signal init_ram : ram_t := init_load_ram(INIT_RAM_FILE);
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;
variable adr : integer;
begin
if rising_edge(clk) then
wb_out.ack <= '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
wb_out.dat <= 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;
wb_out.ack <= '1';
end if;
end if;
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';

@ -54,12 +54,18 @@ void main(void)
printf("UART ");
if (ftr & SYS_REG_INFO_HAS_DRAM)
printf("DRAM ");
if (ftr & SYS_REG_INFO_HAS_BRAM)
printf("BRAM ");
printf("\n");
val = readq(SYSCON_BASE + SYS_REG_BRAMINFO);
printf(" BRAM: %lld KB\n", val / 1024);
if (ftr & SYS_REG_INFO_HAS_BRAM) {
val = readq(SYSCON_BASE + SYS_REG_BRAMINFO);
printf(" BRAM: %lld KB\n", val / 1024);
}
if (ftr & SYS_REG_INFO_HAS_DRAM) {
val = readq(SYSCON_BASE + SYS_REG_DRAMINFO);
printf(" DRAM: %lld MB\n", val / (1024 * 1024));
val = readq(SYSCON_BASE + SYS_REG_DRAMINITINFO);
printf(" DRAM INIT: %lld KB\n", val / 1024);
}
val = readq(SYSCON_BASE + SYS_REG_CLKINFO);
printf(" CLK: %lld MHz\n", val / 1000000);
@ -70,5 +76,15 @@ void main(void)
MIGEN_GIT_SHA1, LITEX_GIT_SHA1);
sdrinit();
}
printf("Booting from BRAM...\n");
if (ftr & SYS_REG_INFO_HAS_BRAM)
printf("Booting from BRAM...\n");
else {
void *s = (void *)(DRAM_INIT_BASE + 0x4000);
void *d = (void *)DRAM_BASE;
int sz = (0x10000 - 0x4000);
printf("Copying payload to DRAM...\n");
memcpy(d, s, sz);
printf("Booting from DRAM...\n");
flush_cpu_icache();
}
}

@ -5,8 +5,13 @@ 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;
@ -16,11 +21,30 @@ end entity dram_init_mem;

architecture rtl of dram_init_mem is

constant INIT_RAM_SIZE : integer := 16384;
constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "litedram_core.init";
constant INIT_RAM_SIZE : integer := 16384;
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);
constant INIT_RAM_FILE : string := "litedram_core.init";

type ram_t is array(0 to (INIT_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);
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;
@ -28,6 +52,11 @@ architecture rtl of dram_init_mem is
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);
@ -35,25 +64,45 @@ architecture rtl of dram_init_mem is
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;

signal init_ram : ram_t := init_load_ram(INIT_RAM_FILE);
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;
variable adr : integer;
begin
if rising_edge(clk) then
wb_out.ack <= '0';
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
wb_out.dat <= init_ram(adr);
obuf <= init_ram(adr);
else
for i in 0 to 3 loop
if wb_in.sel(i) = '1' then
@ -62,8 +111,10 @@ begin
end if;
end loop;
end if;
wb_out.ack <= '1';
oack <= '1';
end if;
wb_out.ack <= oack;
wb_out.dat <= obuf;
end if;
end process;


File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
//--------------------------------------------------------------------------------
// Auto-generated by Migen (0d16e03) & LiteX (564d731a) on 2020-05-22 17:57:16
// Auto-generated by Migen (0d16e03) & LiteX (564d731a) on 2020-05-26 20:37:38
//--------------------------------------------------------------------------------
module litedram_core(
input wire clk,

@ -5,66 +5,117 @@ 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
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 := 16384;
constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "litedram_core.init";
constant INIT_RAM_SIZE : integer := 16384;
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);
constant INIT_RAM_FILE : string := "litedram_core.init";

type ram_t is array(0 to (INIT_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);
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;
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
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;
return temp_ram;
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;

signal init_ram : ram_t := init_load_ram(INIT_RAM_FILE);
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;
variable adr : integer;
begin
if rising_edge(clk) then
wb_out.ack <= '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
wb_out.dat <= 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;
wb_out.ack <= '1';
end if;
end if;
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';

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
//--------------------------------------------------------------------------------
// Auto-generated by Migen (0d16e03) & LiteX (564d731a) on 2020-05-22 17:57:18
// Auto-generated by Migen (0d16e03) & LiteX (564d731a) on 2020-05-26 20:37:40
//--------------------------------------------------------------------------------
module litedram_core(
input wire clk,

@ -5,66 +5,118 @@ 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
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 := 16384;
constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "litedram/generated/sim/litedram_core.init";
constant INIT_RAM_SIZE : integer := 16384;
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);
constant INIT_RAM_FILE : string := "litedram/generated/sim/litedram_core.init";

type ram_t is array(0 to (INIT_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);
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;
file ram_file : text open read_mode is name;
file payload_file : text open read_mode is EXTRA_PAYLOAD_FILE;
variable temp_word : std_logic_vector(63 downto 0);
variable temp_ram : ram_t := (others => (others => '0'));
variable ram_line : line;
begin
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;
return temp_ram;
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
procedure init_load_payload(ram: inout ram_t; filename: string) is
end if;
return temp_ram;
end function;

signal init_ram : ram_t := init_load_ram(INIT_RAM_FILE);
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;
variable adr : integer;
begin
if rising_edge(clk) then
wb_out.ack <= '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
wb_out.dat <= 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;
wb_out.ack <= '1';
end if;
end if;
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';

@ -7,7 +7,7 @@ a64b5a7d14004a39
6421f000782107c6
3d80000060213f00
798c07c6618c0000
618c108c658cf000
618c10a4658cf000
4e8004217d8903a6
0000000048000002
0000000000000000
@ -510,7 +510,7 @@ a64b5a7d14004a39
0000000000000000
0000000000000000
0000000000000000
384295003c4c0001
384296003c4c0001
fbc1fff07c0802a6
f8010010fbe1fff8
3be10020f821fe91
@ -519,61 +519,83 @@ f8c101a838800140
38c101987c651b78
7fe3fb78f8e101b0
f92101c0f90101b8
48000c89f94101c8
48000da5f94101c8
7c7e1b7860000000
4800080d7fe3fb78
480008bd7fe3fb78
3821017060000000
480012487fc3f378
480013647fc3f378
0100000000000000
4e80002000000280
0000000000000000
7c0007ac00000000
4e8000204c00012c
0000000000000000
3c4c000100000000
7c0802a638429474
7d908026fbe1fff8
f801001091810008
48000719f821ff91
7c0802a63842955c
7d800026fbe1fff8
91810008f8010010
480007b1f821ff91
3c62ffff60000000
4bffff4d38637dc8
4bffff3538637de8
548400023880ffff
7c8026ea7c0004ac
3fe0c0003c62ffff
63ff000838637de8
3c62ffff4bffff29
38637e087bff0020
7c0004ac4bffff19
63ff000838637e08
3c62ffff4bffff11
38637e287bff0020
7c0004ac4bffff01
73e900017fe0feea
3c62ffff41820010
4bfffefd38637e20
4e00000073e90002
4bfffee538637e40
4d80000073e90002
3c62ffff41820010
4bfffee538637e28
3bff7fc83fe2ffff
4bfffed57fe3fb78
608400103c80c000
7c0004ac78840020
3c62ffff7c8026ea
38637e307884b282
419200284bfffeb1
608400183c80c000
4bfffecd38637e48
4e00000073e90004
3c62ffff41820010
4bfffeb538637e50
3be2804860000000
4bfffea57fe3fb78
3c80c00041920028
7884002060840010
7c8026ea7c0004ac
7884b2823c62ffff
4bfffe7d38637e58
3c80c000418e004c
7884002060840018
7c8026ea7c0004ac
788465023c62ffff
4bfffe5538637e78
608400303c80c000
7c0004ac78840020
3c62ffff7c8026ea
38637e5078846502
3d20c0004bfffe89
38637e987884b282
3d20c0004bfffe31
7929002061290020
7d204eea7c0004ac
3c62ffff3c80000f
38637e7060844240
4bfffe5d7c892392
4bfffe557fe3fb78
3ca2ffff41920028
38637eb860844240
4bfffe057c892392
4bfffdfd7fe3fb78
3ca2ffff418e0028
3c62ffff3c82ffff
38847ea038a57e90
4bfffe3538637ea8
6000000048000469
38637ed83c62ffff
382100704bfffe21
7d90812081810008
00000000480010c0
38847ee838a57ed8
4bfffddd38637ef0
60000000480004c1
3c62ffff41920020
4bfffdc538637f20
8181000838210070
480011807d818120
38637f383c62ffff
3c80f0004bfffda9
6084400038a0ffff
7884002054a50422
480008553c604000
3c62ffff60000000
4bfffd7d38637f58
e801001038210070
ebe1fff881810008
7d8181207c0803a6
000000004bfffde4
0000018003000000
612908083d20c010
7c0004ac79290020
@ -583,26 +605,26 @@ f801001091810008
4e8000207d20572a
0000000000000000
3c4c000100000000
7c0802a6384292bc
7c0802a63842930c
614a08003d40c010
794a002039200001
f821ffa1f8010010
7d20572a7c0004ac
38637fa83c62ffff
600000004bfffd91
3862802860000000
600000004bfffce1
e801001038210060
4e8000207c0803a6
0100000000000000
3c4c000100000080
7c0802a638429264
7c0802a6384292b4
6129000c3d204000
3fc0aaaa48000f91
3fc0aaaa48000ffd
f821ff713f804000
63deaaaa3fa04000
639c00043fe04000
93df000063bd0008
93dd000093dc0000
4bfffd9993c90000
4bfffce993c90000
813f000060000000
7d29f278815c0000
7d2900347f8af000
@ -622,7 +644,7 @@ f821ff713f804000
93dd000093dc0000
3d20400093c90000
93c900006129000c
600000004bfffcfd
600000004bfffc4d
7f89f000813c0000
3bff0001419e000c
813d00007fff07b4
@ -638,7 +660,7 @@ f821ff713f804000
3bff0001419e0028
3c62ffff7fff07b4
7fe4fb7838a00100
4bfffc0538637ef0
4bfffb5538637f70
4800000c60000000
409effe02fbf0000
3ce0802039000004
@ -648,7 +670,7 @@ f821ff713f804000
7d2900d0792907e0
7d293838394a0004
912afffc7d294278
4bfffc294200ffe4
4bfffb794200ffe4
3900000460000000
7d0903a63ce08020
3d40400060e70003
@ -662,7 +684,7 @@ f821ff713f804000
2fbe00004200ffd4
3c62ffff419e001c
7fc4f37838a00004
4bfffb4538637f18
4bfffa9538637f98
3d20400060000000
6129000839400000
914900003ba00000
@ -672,7 +694,7 @@ f821ff713f804000
9149000061290010
394000033d204000
9149000061290014
600000004bfffb6d
600000004bfffabd
3940000039200004
3d2a10007d2903a6
8129000879291764
@ -682,12 +704,12 @@ f821ff713f804000
2fbd00004200ffdc
3c62ffff419e001c
7fa4eb7838a00004
4bfffaa538637f40
4bfff9f538637fc0
7ffefa1460000000
7fffea143bc00000
409e00a42f9f0000
38637f683c62ffff
600000004bfffa81
38637fe83c62ffff
600000004bfff9d1
3f8040007f5602a6
639c00043f604000
3fa0400039200001
@ -696,7 +718,7 @@ f821ff713f804000
63de000c39200002
39200003913d0000
7ff602a6913e0000
600000004bfffaad
600000004bfff9fd
815b00007d3602a6
815d0000815c0000
7cb602a6815e0000
@ -704,17 +726,17 @@ f821ff713f804000
7ca42b967d3fd050
3c62ffff7c844b96
788404a078a504a0
3bc0000138637f78
600000004bfff9f1
3bc0000138637ff8
600000004bfff941
7fc3f37838210090
0000000048000c68
0000000048000cd4
0000068001000000
38428ec83c4c0001
3c62ffff7c0802a6
48000bf538637fd0
38428f183c4c0001
600000007c0802a6
48000c6138628050
3f60c010f821ff71
637b10003be00000
4bfff9a57b7b0020
4bfff8f57b7b0020
7c0004ac60000000
3f40c0107fe0df2a
7b5a0020635a1008
@ -753,38 +775,38 @@ f821ff713f804000
4082001c2c230000
7f80df2a7c0004ac
7f80d72a7c0004ac
48000af438210090
48000b6038210090
7f80df2a7c0004ac
4bffffec38600001
0100000000000000
3c4c000100000680
3d20c00038428d44
3d20c00038428d94
6129200060000000
f922803879290020
f92280b879290020
612900203d20c000
7c0004ac79290020
3d40001c7d204eea
7d295392614a2000
394a0018e9428038
394a0018e94280b8
7c0004ac3929ffff
4e8000207d2057ea
0000000000000000
3c4c000100000000
6000000038428ce4
39290010e9228038
6000000038428d34
39290010e92280b8
7d204eea7c0004ac
4082ffe871290008
e94280385469063e
e94280b85469063e
7d2057ea7c0004ac
000000004e800020
0000000000000000
38428ca03c4c0001
38428cf03c4c0001
fbc1fff07c0802a6
3bc3fffffbe1fff8
f821ffd1f8010010
2fbf00008ffe0001
38210030409e0010
48000a2038600000
48000a8c38600000
409e000c2b9f000a
4bffff813860000d
4bffff797fe3fb78
@ -834,283 +856,297 @@ f924000039290002
392900014e800020
000000004bffffe8
0000000000000000
2b8900193923ff9f
3863ffe04d9d0020
4e8000207c6307b4
3900000078aae8c2
7d2903a6392a0001
78a9e8c242000030
1d29fff8792a1f24
7c8452147d035214
392000007ca92a14
7d4903a639450001
4e80002042000018
7d23412a7d24402a
4bffffc439080008
7d4849ae7d4448ae
4bffffdc39290001
0000000000000000
3923ff9f00000000
4d9d00202b890019
7c6307b43863ffe0
000000004e800020
0000000000000000
3c4c000100000000
7c0802a638428abc
7d9080263d203736
792907c661293534
9181000865293332
480007d961293130
7c7d1b78f821ffa1
3be000007cde3378
3d206665f9210020
792907c661296463
6129393865296261
7ca92b78f9210028
409e00802fa90000
409e00082fbf0000
7fbf20403be00001
419d005838600000
3b9fffff2e270000
7d3bf1d27f65f392
7ca12a147ca92850
4192001088650020
600000004bffff41
2fbb00005463063e
7f65db78e93d0000
3b9cffff7c69e1ae
e93d0000409effc8
7fe9fa1438600001
38210060fbfd0000
7d90812081810008
2b9e001048000774
7929e102409e0014
7fff07b43bff0001
7d29f3924bffff68
000000004bfffff0
0000058003000000
384289b03c4c0001
480006e97c0802a6
eb630000f821ffb1
7c9c23787c7f1b78
3bc000007cbd2b78
4bfffe797fa3eb78
7fa3f04060000000
e95f0000409d0014
7fa9e0407d3b5050
38210050419c0010
480006f038600001
3bde00017d3df0ae
e93f0000992a0000
f93f000039290001
000000004bffffb8
0000058001000000
384289303c4c0001
480006617c0802a6
7c7d1b78f821ffa1
7ca32b787c9b2378
38a0000a38800000
eb5d00007cde3378
7d1943787cfc3b78
4bfffcb57d3f4b78
3940000060000000
2fbe00007c6307b4
2faa0000409e006c
39400001409e0008
7f8348007d3f5214
409d00447d2a07b4
2f8300007c6a1850
3929000178690020
3d408000419c0010
409e00087f835000
2c29000139200001
418200143929ffff
7d5a3850e8fd0000
419c00307faad840
3860000038210060
2b9c001048000604
7bdee102409e0014
7d4a07b4394a0001
7fdee3924bffff7c
9b2700004bfffff0
394a0001e95d0000
4bffffa8f95d0000
38428aa03c4c0001
3d2037367c0802a6
612935347d908026
65293332792907c6
6129313091810008
f821ffa1480007d9
7cde33787c7d1b78
f92100203be00000
612964633d206665
65296261792907c6
f921002861293938
2fa900007ca92b78
2fbf0000409e0080
3be00001409e0008
386000007fbf2040
2e270000419d0058
7f65f3923b9fffff
7ca928507d3bf1d2
886500207ca12a14
4bffff4141920010
5463063e60000000
e93d00002fbb0000
7c69e1ae7f65db78
409effc83b9cffff
38600001e93d0000
fbfd00007fe9fa14
8181000838210060
480007747d908120
409e00142b9e0010
3bff00017929e102
4bffff687fff07b4
4bfffff07d29f392
0300000000000000
3c4c000100000580
7c0802a638428994
f821ffb1480006e9
7c7f1b78eb630000
7cbd2b787c9c2378
7fa3eb783bc00000
600000004bfffe0d
409d00147fa3f040
7d3b5050e95f0000
419c00107fa9e040
3860000138210050
7d3df0ae480006f0
992a00003bde0001
39290001e93f0000
4bffffb8f93f0000
0100000000000000
3c4c000100000780
7c0802a638428834
f821fed148000539
f86100607c741b79
4182006838600000
419e00602fa40000
3e42ffff39210040
3b4100203ac4ffff
60000000f9210070
392280303ae00000
3ba100603a527fe8
89250000f9210078
2fa90000ebc10060
7ff4f050419e0010
419c00207fbfb040
993e000039200000
7e941850e8610060
382101307e8307b4
2b89002548000508
409e048839450001
8925000038e00000
f8a10068e9010070
7d2741ae7cea07b4
8d25000139070001
2b8900647d0807b4
2b890069419e0058
2b890075419e0050
2b890078419e0048
2b890058419e0040
2b890070419e0038
2b890063419e0030
2b890073419e0028
2b890025419e0020
2b89004f419e0018
2b89006f419e0010
409eff8838e70001
2b890025394a0002
7d1a42147d4a07b4
992800207d5a5214
409e00209aea0020
f9210060393e0001
993e000039200025
38a90002e9210068
892100414bffff04
3a2600087fffb050
3a600030eb660000
3929ffd23b010042
4082039c712900fd
3b2000043aa00000
3a0000013b800000
7ddb00d039e0002d
2b89006c48000108
88f8000138d80001
419d0118419e033c
419e02402b890063
2b89004f419d0038
2b890058419e01e8
3949ffd0419e0188
2b8a0009554a063e
395c0001419d00c4
993c00207f81e214
480000b0795c0020
419e03042b890068
419e000c2b890069
409effc82b890064
7d41e2142b890075
7f6adb789aea0020
57291838419e0034
7e0948363929ffff
418200207f694839
e921006099e80000
f921006039290001
7d52482a7b291f24
e88100607dca5038
38e0000a7d465378
7f45d378f9410080
7e689b7839200000
7c9e20507fa3eb78
4bfffc9d7c84f850
e9410080e8810060
38c0000a7ea7ab78
7d4553787c9e2050
7fa3eb787c84f850
3b1800014bfffaed
e901006089380000
3c4c000100000580
7c0802a638428914
f821ffa148000661
7c9b23787c7d1b78
388000007ca32b78
7cde337838a0000a
7cfc3b78eb5d0000
7d3f4b787d194378
600000004bfffc49
7c6307b439400000
409e006c2fbe0000
409e00082faa0000
7d3f521439400001
7d2a07b47f834800
7c6a1850409d0044
786900202f830000
419c001039290001
7f8350003d408000
39200001409e0008
3929ffff2c290001
e8fd000041820014
7faad8407d5a3850
38210060419c0030
4800060438600000
409e00142b9c0010
394a00017bdee102
4bffff7c7d4a07b4
4bfffff07fdee392
e95d00009b270000
f95d0000394a0001
000000004bffffa8
0000078001000000
384288183c4c0001
480005397c0802a6
7c741b79f821fed1
38600000f8610060
2fa4000041820068
39210040419e0060
3ac4ffff60000000
f92100703b410020
3ae0000060000000
3a428068392280b0
f92100783ba10060
ebc1006089250000
419e00102fa90000
7fbf50407d5e4050
7e268b78419dfee4
2b8900734bfffe90
419d006c419e016c
419e00d42b89006f
409efef02b890070
38e000107d21e214
7c8af8507f66db78
390000209ae90020
7f45d37839200002
4bfffc0d7fa3eb78
e8a10078e8810060
7c9e20507fa3eb78
4bfffb757c84f850
7ea7ab78e8810060
7f65db7838c00010
4bffff5c7c9e2050
419e00182b890078
419e01cc2b89007a
4bfffeb82b890075
7d21e2143aa00001
7c8af85038e00010
9ae900207e689b78
7f45d3787b291f24
7d72482a7fa3eb78
7f6b583839200000
f96100807d665b78
e88100604bfffb89
7fbfb0407ff4f050
39200000419c0020
e8610060993e0000
7e8307b47e941850
4800050838210130
394500012b890025
38e00000409e0488
e901007089250000
7cea07b4f8a10068
390700017d2741ae
7d0807b48d250001
419e00582b890064
419e00502b890069
419e00482b890075
419e00402b890078
419e00382b890058
419e00302b890070
419e00282b890063
419e00202b890073
419e00182b890025
419e00102b89004f
38e700012b89006f
394a0002409eff88
7d4a07b42b890025
7d5a52147d1a4214
9aea002099280020
393e0001409e0020
39200025f9210060
e9210068993e0000
4bffff0438a90002
7fffb05089210041
eb6600003a260008
3b0100423a600030
712900fd3929ffd2
3aa000004082039c
3b8000003b200004
39e0002d3a000001
480001087ddb00d0
38d800012b89006c
419e033c88f80001
2b890063419d0118
419d0038419e0240
419e01e82b89004f
419e01882b890058
554a063e3949ffd0
419d00c42b8a0009
7f81e214395c0001
795c0020993c0020
2b890068480000b0
2b890069419e0304
2b890064419e000c
2b890075409effc8
9aea00207d41e214
419e00347f6adb78
3929ffff57291838
7f6948397e094836
99e8000041820020
39290001e9210060
7b291f24f9210060
7dca50387d52482a
7d465378e8810060
f941008038e0000a
392000007f45d378
7fa3eb787e689b78
7c84f8507c9e2050
e88100604bfffc9d
7ea7ab78e9410080
7c9e205038c0000a