soc_core: add csr_alignment to allow 64-bit alignment with 64-bit CPUs
This commit is contained in:
parent
927b7c13a2
commit
f4770219fa
|
@ -21,6 +21,13 @@ from litex.soc.interconnect.csr import CSRStatus
|
||||||
|
|
||||||
from litex.build.tools import generated_banner
|
from litex.build.tools import generated_banner
|
||||||
|
|
||||||
|
# FIXME: use OrderedDict for constants?
|
||||||
|
def get_constant(name, constants):
|
||||||
|
for n, v in constants:
|
||||||
|
if n == name:
|
||||||
|
return v
|
||||||
|
return None
|
||||||
|
|
||||||
def get_cpu_mak(cpu):
|
def get_cpu_mak(cpu):
|
||||||
# select between clang and gcc
|
# select between clang and gcc
|
||||||
clang = os.getenv("CLANG", "")
|
clang = os.getenv("CLANG", "")
|
||||||
|
@ -97,7 +104,7 @@ def get_mem_header(regions, flash_boot_address, shadow_base):
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def _get_rw_functions_c(reg_name, reg_base, nwords, busword, read_only, with_access_functions):
|
def _get_rw_functions_c(reg_name, reg_base, nwords, busword, alignment, read_only, with_access_functions):
|
||||||
r = ""
|
r = ""
|
||||||
|
|
||||||
r += "#define CSR_"+reg_name.upper()+"_ADDR "+hex(reg_base)+"L\n"
|
r += "#define CSR_"+reg_name.upper()+"_ADDR "+hex(reg_base)+"L\n"
|
||||||
|
@ -120,7 +127,7 @@ def _get_rw_functions_c(reg_name, reg_base, nwords, busword, read_only, with_acc
|
||||||
if size > 1:
|
if size > 1:
|
||||||
r += "\t"+ctype+" r = csr_readl("+hex(reg_base)+"L);\n"
|
r += "\t"+ctype+" r = csr_readl("+hex(reg_base)+"L);\n"
|
||||||
for byte in range(1, nwords):
|
for byte in range(1, nwords):
|
||||||
r += "\tr <<= "+str(busword)+";\n\tr |= csr_readl("+hex(reg_base+4*byte)+"L);\n"
|
r += "\tr <<= "+str(busword)+";\n\tr |= csr_readl("+hex(reg_base+alignment//8*byte)+"L);\n"
|
||||||
r += "\treturn r;\n}\n"
|
r += "\treturn r;\n}\n"
|
||||||
else:
|
else:
|
||||||
r += "\treturn csr_readl("+hex(reg_base)+"L);\n}\n"
|
r += "\treturn csr_readl("+hex(reg_base)+"L);\n}\n"
|
||||||
|
@ -133,12 +140,13 @@ def _get_rw_functions_c(reg_name, reg_base, nwords, busword, read_only, with_acc
|
||||||
value_shifted = "value >> "+str(shift)
|
value_shifted = "value >> "+str(shift)
|
||||||
else:
|
else:
|
||||||
value_shifted = "value"
|
value_shifted = "value"
|
||||||
r += "\tcsr_writel("+value_shifted+", "+hex(reg_base+4*word)+"L);\n"
|
r += "\tcsr_writel("+value_shifted+", "+hex(reg_base+alignment//8*word)+"L);\n"
|
||||||
r += "}\n"
|
r += "}\n"
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def get_csr_header(regions, constants, with_access_functions=True, with_shadow_base=True, shadow_base=0x80000000):
|
def get_csr_header(regions, constants, with_access_functions=True, with_shadow_base=True, shadow_base=0x80000000):
|
||||||
|
alignment = get_constant("CONFIG_CSR_ALIGNMENT", constants)
|
||||||
r = generated_banner("//")
|
r = generated_banner("//")
|
||||||
r += "#ifndef __GENERATED_CSR_H\n#define __GENERATED_CSR_H\n"
|
r += "#ifndef __GENERATED_CSR_H\n#define __GENERATED_CSR_H\n"
|
||||||
if with_access_functions:
|
if with_access_functions:
|
||||||
|
@ -161,8 +169,9 @@ def get_csr_header(regions, constants, with_access_functions=True, with_shadow_b
|
||||||
if not isinstance(obj, Memory):
|
if not isinstance(obj, Memory):
|
||||||
for csr in obj:
|
for csr in obj:
|
||||||
nr = (csr.size + busword - 1)//busword
|
nr = (csr.size + busword - 1)//busword
|
||||||
r += _get_rw_functions_c(name + "_" + csr.name, origin, nr, busword, isinstance(csr, CSRStatus), with_access_functions)
|
r += _get_rw_functions_c(name + "_" + csr.name, origin, nr, busword, alignment,
|
||||||
origin += 4*nr
|
isinstance(csr, CSRStatus), with_access_functions)
|
||||||
|
origin += alignment//8*nr
|
||||||
|
|
||||||
r += "\n/* constants */\n"
|
r += "\n/* constants */\n"
|
||||||
for name, value in constants:
|
for name, value in constants:
|
||||||
|
@ -185,6 +194,7 @@ def get_csr_header(regions, constants, with_access_functions=True, with_shadow_b
|
||||||
|
|
||||||
|
|
||||||
def get_csr_csv(csr_regions=None, constants=None, memory_regions=None):
|
def get_csr_csv(csr_regions=None, constants=None, memory_regions=None):
|
||||||
|
alignment = 32 if constants is None else get_constant("CONFIG_CSR_ALIGNMENT", constants)
|
||||||
r = generated_banner("#")
|
r = generated_banner("#")
|
||||||
|
|
||||||
if csr_regions is not None:
|
if csr_regions is not None:
|
||||||
|
@ -196,7 +206,7 @@ def get_csr_csv(csr_regions=None, constants=None, memory_regions=None):
|
||||||
for csr in obj:
|
for csr in obj:
|
||||||
nr = (csr.size + busword - 1)//busword
|
nr = (csr.size + busword - 1)//busword
|
||||||
r += "csr_register,{}_{},0x{:08x},{},{}\n".format(name, csr.name, origin, nr, "ro" if isinstance(csr, CSRStatus) else "rw")
|
r += "csr_register,{}_{},0x{:08x},{},{}\n".format(name, csr.name, origin, nr, "ro" if isinstance(csr, CSRStatus) else "rw")
|
||||||
origin += 4*nr
|
origin += alignment//8*nr
|
||||||
|
|
||||||
if constants is not None:
|
if constants is not None:
|
||||||
for name, value in constants:
|
for name, value in constants:
|
||||||
|
|
|
@ -150,7 +150,7 @@ class SoCCore(Module):
|
||||||
# MAIN_RAM parameters
|
# MAIN_RAM parameters
|
||||||
integrated_main_ram_size=0, integrated_main_ram_init=[],
|
integrated_main_ram_size=0, integrated_main_ram_init=[],
|
||||||
# CSR parameters
|
# CSR parameters
|
||||||
csr_data_width=8, csr_address_width=14,
|
csr_data_width=8, csr_alignment=32, csr_address_width=14,
|
||||||
# Identifier parameters
|
# Identifier parameters
|
||||||
ident="", ident_version=False,
|
ident="", ident_version=False,
|
||||||
# UART parameters
|
# UART parameters
|
||||||
|
@ -210,7 +210,10 @@ class SoCCore(Module):
|
||||||
self.integrated_sram_size = integrated_sram_size
|
self.integrated_sram_size = integrated_sram_size
|
||||||
self.integrated_main_ram_size = integrated_main_ram_size
|
self.integrated_main_ram_size = integrated_main_ram_size
|
||||||
|
|
||||||
|
assert csr_data_width in [8, 32, 64]
|
||||||
|
assert csr_alignment in [32, 64]
|
||||||
self.csr_data_width = csr_data_width
|
self.csr_data_width = csr_data_width
|
||||||
|
self.csr_alignment = csr_alignment
|
||||||
self.csr_address_width = csr_address_width
|
self.csr_address_width = csr_address_width
|
||||||
|
|
||||||
self.with_ctrl = with_ctrl
|
self.with_ctrl = with_ctrl
|
||||||
|
@ -291,6 +294,7 @@ class SoCCore(Module):
|
||||||
bus_csr=csr_bus.Interface(csr_data_width, csr_address_width))
|
bus_csr=csr_bus.Interface(csr_data_width, csr_address_width))
|
||||||
self.add_csr_master(self.wishbone2csr.csr)
|
self.add_csr_master(self.wishbone2csr.csr)
|
||||||
self.config["CSR_DATA_WIDTH"] = csr_data_width
|
self.config["CSR_DATA_WIDTH"] = csr_data_width
|
||||||
|
self.config["CSR_ALIGNMENT"] = csr_alignment
|
||||||
self.register_mem("csr", self.soc_mem_map["csr"], self.wishbone2csr.wishbone)
|
self.register_mem("csr", self.soc_mem_map["csr"], self.wishbone2csr.wishbone)
|
||||||
|
|
||||||
# Add UART
|
# Add UART
|
||||||
|
@ -495,7 +499,9 @@ class SoCCore(Module):
|
||||||
# Collect and create CSRs
|
# Collect and create CSRs
|
||||||
self.submodules.csrbankarray = csr_bus.CSRBankArray(self,
|
self.submodules.csrbankarray = csr_bus.CSRBankArray(self,
|
||||||
self.get_csr_dev_address,
|
self.get_csr_dev_address,
|
||||||
data_width=self.csr_data_width, address_width=self.csr_address_width)
|
data_width=self.csr_data_width,
|
||||||
|
address_width=self.csr_address_width,
|
||||||
|
alignment=self.csr_alignment)
|
||||||
|
|
||||||
# Add CSRs interconnect
|
# Add CSRs interconnect
|
||||||
self.submodules.csrcon = csr_bus.InterconnectShared(
|
self.submodules.csrcon = csr_bus.InterconnectShared(
|
||||||
|
|
|
@ -32,7 +32,8 @@ _layout = [
|
||||||
|
|
||||||
|
|
||||||
class Interface(Record):
|
class Interface(Record):
|
||||||
def __init__(self, data_width=8, address_width=14):
|
def __init__(self, data_width=8, address_width=14, alignment=32):
|
||||||
|
self.alignment = alignment
|
||||||
Record.__init__(self, set_layout_parameters(_layout,
|
Record.__init__(self, set_layout_parameters(_layout,
|
||||||
data_width=data_width, address_width=address_width))
|
data_width=data_width, address_width=address_width))
|
||||||
|
|
||||||
|
@ -160,19 +161,23 @@ class CSRBank(csr.GenericBank):
|
||||||
|
|
||||||
sel = Signal()
|
sel = Signal()
|
||||||
self.comb += sel.eq(self.bus.adr[9:] == address)
|
self.comb += sel.eq(self.bus.adr[9:] == address)
|
||||||
|
if bus.alignment == 64:
|
||||||
|
self.comb += If(self.bus.adr[0], sel.eq(0))
|
||||||
|
|
||||||
|
adr_shift = log2_int(bus.alignment//32)
|
||||||
|
|
||||||
for i, c in enumerate(self.simple_csrs):
|
for i, c in enumerate(self.simple_csrs):
|
||||||
self.comb += [
|
self.comb += [
|
||||||
c.r.eq(self.bus.dat_w[:c.size]),
|
c.r.eq(self.bus.dat_w[:c.size]),
|
||||||
c.re.eq(sel & \
|
c.re.eq(sel & \
|
||||||
self.bus.we & \
|
self.bus.we & \
|
||||||
(self.bus.adr[:self.decode_bits] == i))
|
(self.bus.adr[adr_shift:adr_shift+self.decode_bits] == i))
|
||||||
]
|
]
|
||||||
|
|
||||||
brcases = dict((i, self.bus.dat_r.eq(c.w)) for i, c in enumerate(self.simple_csrs))
|
brcases = dict((i, self.bus.dat_r.eq(c.w)) for i, c in enumerate(self.simple_csrs))
|
||||||
self.sync += [
|
self.sync += [
|
||||||
self.bus.dat_r.eq(0),
|
self.bus.dat_r.eq(0),
|
||||||
If(sel, Case(self.bus.adr[:self.decode_bits], brcases))
|
If(sel, Case(self.bus.adr[adr_shift:adr_shift+self.decode_bits], brcases))
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,8 @@ __attribute__((unused)) static void cdelay(int i)
|
||||||
|
|
||||||
#ifdef CSR_SDRAM_BASE
|
#ifdef CSR_SDRAM_BASE
|
||||||
|
|
||||||
|
#define DFII_ADDR_SHIFT CONFIG_CSR_ALIGNMENT/8
|
||||||
|
|
||||||
void sdrsw(void)
|
void sdrsw(void)
|
||||||
{
|
{
|
||||||
sdram_dfii_control_write(DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N);
|
sdram_dfii_control_write(DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N);
|
||||||
|
@ -103,7 +105,7 @@ void sdrrdbuf(int dq)
|
||||||
|
|
||||||
for(p=0;p<DFII_NPHASES;p++)
|
for(p=0;p<DFII_NPHASES;p++)
|
||||||
for(i=first_byte;i<DFII_PIX_DATA_SIZE;i+=step)
|
for(i=first_byte;i<DFII_PIX_DATA_SIZE;i+=step)
|
||||||
printf("%02x", MMPTR(sdram_dfii_pix_rddata_addr[p]+4*i));
|
printf("%02x", MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*i));
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +169,7 @@ void sdrrderr(char *count)
|
||||||
cdelay(15);
|
cdelay(15);
|
||||||
for(p=0;p<DFII_NPHASES;p++)
|
for(p=0;p<DFII_NPHASES;p++)
|
||||||
for(i=0;i<DFII_PIX_DATA_SIZE;i++)
|
for(i=0;i<DFII_PIX_DATA_SIZE;i++)
|
||||||
prev_data[p*DFII_PIX_DATA_SIZE+i] = MMPTR(sdram_dfii_pix_rddata_addr[p]+4*i);
|
prev_data[p*DFII_PIX_DATA_SIZE+i] = MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*i);
|
||||||
|
|
||||||
for(j=0;j<_count;j++) {
|
for(j=0;j<_count;j++) {
|
||||||
command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
|
command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
|
||||||
|
@ -176,7 +178,7 @@ void sdrrderr(char *count)
|
||||||
for(i=0;i<DFII_PIX_DATA_SIZE;i++) {
|
for(i=0;i<DFII_PIX_DATA_SIZE;i++) {
|
||||||
unsigned char new_data;
|
unsigned char new_data;
|
||||||
|
|
||||||
new_data = MMPTR(sdram_dfii_pix_rddata_addr[p]+4*i);
|
new_data = MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*i);
|
||||||
errs[p*DFII_PIX_DATA_SIZE+i] |= prev_data[p*DFII_PIX_DATA_SIZE+i] ^ new_data;
|
errs[p*DFII_PIX_DATA_SIZE+i] |= prev_data[p*DFII_PIX_DATA_SIZE+i] ^ new_data;
|
||||||
prev_data[p*DFII_PIX_DATA_SIZE+i] = new_data;
|
prev_data[p*DFII_PIX_DATA_SIZE+i] = new_data;
|
||||||
}
|
}
|
||||||
|
@ -211,7 +213,7 @@ void sdrwr(char *startaddr)
|
||||||
|
|
||||||
for(p=0;p<DFII_NPHASES;p++)
|
for(p=0;p<DFII_NPHASES;p++)
|
||||||
for(i=0;i<DFII_PIX_DATA_SIZE;i++)
|
for(i=0;i<DFII_PIX_DATA_SIZE;i++)
|
||||||
MMPTR(sdram_dfii_pix_wrdata_addr[p]+4*i) = 0x10*p + i;
|
MMPTR(sdram_dfii_pix_wrdata_addr[p]+DFII_ADDR_SHIFT*i) = 0x10*p + i;
|
||||||
|
|
||||||
sdram_dfii_piwr_address_write(addr);
|
sdram_dfii_piwr_address_write(addr);
|
||||||
sdram_dfii_piwr_baddress_write(0);
|
sdram_dfii_piwr_baddress_write(0);
|
||||||
|
@ -309,7 +311,7 @@ int write_level(void)
|
||||||
cdelay(100);
|
cdelay(100);
|
||||||
for(i=0;i<NBMODULES;i++) {
|
for(i=0;i<NBMODULES;i++) {
|
||||||
printf("m%d: |", i);
|
printf("m%d: |", i);
|
||||||
dq_address = sdram_dfii_pix_rddata_addr[0]+4*(NBMODULES-1-i);
|
dq_address = sdram_dfii_pix_rddata_addr[0]+DFII_ADDR_SHIFT*(NBMODULES-1-i);
|
||||||
|
|
||||||
/* rst delay */
|
/* rst delay */
|
||||||
write_delay_rst(i);
|
write_delay_rst(i);
|
||||||
|
@ -458,7 +460,7 @@ static int read_level_scan(int module, int bitslip)
|
||||||
/* Write test pattern */
|
/* Write test pattern */
|
||||||
for(p=0;p<DFII_NPHASES;p++)
|
for(p=0;p<DFII_NPHASES;p++)
|
||||||
for(i=0;i<DFII_PIX_DATA_SIZE;i++)
|
for(i=0;i<DFII_PIX_DATA_SIZE;i++)
|
||||||
MMPTR(sdram_dfii_pix_wrdata_addr[p]+4*i) = prs[DFII_PIX_DATA_SIZE*p+i];
|
MMPTR(sdram_dfii_pix_wrdata_addr[p]+DFII_ADDR_SHIFT*i) = prs[DFII_PIX_DATA_SIZE*p+i];
|
||||||
sdram_dfii_piwr_address_write(0);
|
sdram_dfii_piwr_address_write(0);
|
||||||
sdram_dfii_piwr_baddress_write(0);
|
sdram_dfii_piwr_baddress_write(0);
|
||||||
command_pwr(DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS|DFII_COMMAND_WRDATA);
|
command_pwr(DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS|DFII_COMMAND_WRDATA);
|
||||||
|
@ -483,9 +485,9 @@ static int read_level_scan(int module, int bitslip)
|
||||||
cdelay(15);
|
cdelay(15);
|
||||||
working = 1;
|
working = 1;
|
||||||
for(p=0;p<DFII_NPHASES;p++) {
|
for(p=0;p<DFII_NPHASES;p++) {
|
||||||
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+(NBMODULES-module-1)])
|
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*(NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+(NBMODULES-module-1)])
|
||||||
working = 0;
|
working = 0;
|
||||||
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
|
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
|
||||||
working = 0;
|
working = 0;
|
||||||
}
|
}
|
||||||
#ifdef ECP5DDRPHY
|
#ifdef ECP5DDRPHY
|
||||||
|
@ -554,9 +556,9 @@ static void read_level(int module)
|
||||||
cdelay(15);
|
cdelay(15);
|
||||||
working = 1;
|
working = 1;
|
||||||
for(p=0;p<DFII_NPHASES;p++) {
|
for(p=0;p<DFII_NPHASES;p++) {
|
||||||
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+(NBMODULES-module-1)])
|
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*(NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+(NBMODULES-module-1)])
|
||||||
working = 0;
|
working = 0;
|
||||||
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
|
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
|
||||||
working = 0;
|
working = 0;
|
||||||
}
|
}
|
||||||
#ifdef ECP5DDRPHY
|
#ifdef ECP5DDRPHY
|
||||||
|
@ -592,9 +594,9 @@ static void read_level(int module)
|
||||||
cdelay(15);
|
cdelay(15);
|
||||||
working = 1;
|
working = 1;
|
||||||
for(p=0;p<DFII_NPHASES;p++) {
|
for(p=0;p<DFII_NPHASES;p++) {
|
||||||
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+(NBMODULES-module-1)])
|
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*(NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+(NBMODULES-module-1)])
|
||||||
working = 0;
|
working = 0;
|
||||||
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
|
if(MMPTR(sdram_dfii_pix_rddata_addr[p]+DFII_ADDR_SHIFT*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
|
||||||
working = 0;
|
working = 0;
|
||||||
}
|
}
|
||||||
#ifdef ECP5DDRPHY
|
#ifdef ECP5DDRPHY
|
||||||
|
|
Loading…
Reference in New Issue