fix compile errors

This commit is contained in:
Peter McGoron 2023-04-18 15:47:57 -04:00
parent be4ed8afcf
commit ab4c23fa14
7 changed files with 175 additions and 103 deletions

2
.gitignore vendored
View File

@ -5,7 +5,7 @@ firmware/litex_json2dts_zephyr.py
firmware/overlay.config firmware/overlay.config
firmware/overlay.cmake firmware/overlay.cmake
firmware/overlay.dts firmware/overlay.dts
firmware/pin_io.h firmware/pin_io.c
misc/ misc/
software/build/ software/build/
*.fst *.fst

View File

@ -149,6 +149,12 @@ The kernel is `/software/build/zephyr/zephyr.bin`
If you make a change to `CMakeLists.txt` or to `prj.conf`, run `make clean` If you make a change to `CMakeLists.txt` or to `prj.conf`, run `make clean`
before `make`. before `make`.
Make can run in parallel using `-j${NUMBER_OF_PROCESSORS}`. Add this to the
`buidl/zephyr/zephyr.bin` in `/software/Makefile` to makeyour builds faster.
Remove this argument when you are attemping to fix compile errors and warnings
(it will make the build output easier to read) but put it back when you fix
them.
# Loading the Software and Firmware # Loading the Software and Firmware
## Network Setup ## Network Setup
@ -438,6 +444,12 @@ TODO: Ethernet debugging output.
## Control and Status Registers in Software ## Control and Status Registers in Software
CSR read and write functions are generated by `/firmware/generate_csr_locations.py`.
You should not need to directly call `write` and `read` on raw addresses.
If you add a new CSR, add it to the generator script.
### Implementation Information
CSRs can be used in software by using `litex_write8`, CSRs can be used in software by using `litex_write8`,
`litex_read16`, etc. In the Zephyr source, look at `litex_read16`, etc. In the Zephyr source, look at
`soc/riscv/litex-vexriscv/soc.h` for the complete implementation. `soc/riscv/litex-vexriscv/soc.h` for the complete implementation.
@ -449,7 +461,6 @@ Do not directly write to CSR ports without using `litex_writeN` and
not careful you will not access the registers correctly and you will not careful you will not access the registers correctly and you will
crash the software. crash the software.
# Controlling Computer # Controlling Computer
## Creole ## Creole

View File

@ -2,11 +2,11 @@
DEVICETREE_GEN_DIR=. DEVICETREE_GEN_DIR=.
all: rtl_codegen build/digilent_arty/digilent_arty.bit overlay.dts overlay.cmake pin_io.h all: rtl_codegen build/digilent_arty/digilent_arty.bit overlay.dts overlay.cmake pin_io.c
rtl_codegen: rtl_codegen:
cd rtl && make cd rtl && make
build/digilent_arty/digilent_arty.bit: rtl_codegen soc.py build/digilent_arty/digilent_arty.bit: soc.py
python3 soc.py python3 soc.py
clean: clean:
rm -rf build csr.json overlay.config overlay.dts pin_io.h rm -rf build csr.json overlay.config overlay.dts pin_io.h
@ -14,5 +14,5 @@ overlay.dts overlay.cmake: csr.json litex_json2dts_zephyr.py
# NOTE: Broken in LiteX 2022.4. # NOTE: Broken in LiteX 2022.4.
$(DEVICETREE_GEN_DIR)/litex_json2dts_zephyr.py --dts overlay.dts --config overlay.cmake csr.json $(DEVICETREE_GEN_DIR)/litex_json2dts_zephyr.py --dts overlay.dts --config overlay.cmake csr.json
pin_io.h: csr.json generate_csr_locations.py pin_io.c: csr.json generate_csr_locations.py
python3 generate_csr_locations.py > pin_io.h python3 generate_csr_locations.py > pin_io.c

View File

@ -3,76 +3,142 @@ import json
import sys import sys
""" """
This file takes the csr.json file output by LiteX and extracts all This file uses csr.json and csr_bitwidth.json and writes functions
CSRs that are handled by Upsilon directly. See the output file csr.json that handle reads and writes to MMIO.
for layout.
""" """
class CSRGenerator: class CSRGenerator:
def __init__(self, json_file, registers, f): def __init__(self, csrjson, bitwidthjson, registers, outf, dacmax, adcmax):
self.registers = registers self.registers = registers
self.j = json.load(open(json_file)) self.csrs = json.load(open(csrjson))
self.file = f self.bws = json.load(open(bitwidthjson))
self.file = outf
self.dacmax = dacmax
self.adcmax = adcmax
def get_reg(self, name, num): def get_reg(self, name, num):
if num is None: if num is None:
regname = f"base_{name}" regname = f"base_{name}"
else: else:
regname = f"base_{name}_{num}" regname = f"base_{name}_{num}"
return f'{self.j["csr_registers"][regname]["addr"]}' return self.csrs["csr_registers"][regname]["addr"]
def get_bitwidth_type(self, name):
b = self.bws[name]
if b <= 8:
return 8
elif b <= 16:
return 16
elif b <= 32:
return 32
elif b <= 64:
return 64
else:
raise Exception('unsupported width', b)
def print(self, *args): def print(self, *args):
print(*args, end='', file=self.file) print(*args, end='', file=self.file)
def print_array(self, name, num): def print_write_fun(self, name, regnum):
if num == 1: typ = self.get_bitwidth_type(name)
self.print(f'static const uintptr_t {name} = {self.get_reg(name, None)};\n') self.print('static inline void\n')
else: self.print(f'write_{name}(uint{typ}_t v')
self.print(f'static const uintptr_t {name}[{num}] = {{', self.get_reg(name, 0))
for i in range(1,num):
self.print(',', self.get_reg(name, i))
self.print('};\n\n')
def print_registers(self): if regnum != 1:
for name,num in self.registers: self.print(f', int num')
self.print_array(name, num) self.print(')\n{\n')
def print_file(self):
self.print(f'''#pragma once if regnum != 1:
#define ADC_MAX {adc_num} self.print('\t', f'static const uintptr_t loc[{regnum}]', '= {\n')
#define DAC_MAX {dac_num} self.print('\t\t', self.get_reg(name,0), '\n')
for i in range(1,regnum):
self.print('\t\t,', self.get_reg(name, i), '\n')
self.print('\t};\n')
self.print('''
if (num < 0 || num >= ARRAY_SIZE(loc)) {
LOG_ERR("invalid location %d", num);
k_fatal_halt(K_ERR_KERNEL_OOPS);
}
''') ''')
self.print_registers() self.print('\t', f'litex_write{typ}(v, {"loc[num]" if regnum != 1 else self.get_reg(name, None)});', '\n}\n\n')
def print_read_fun(self, name, regnum):
typ = self.get_bitwidth_type(name)
self.print(f'static inline uint{typ}_t\nread_{name}')
if regnum != 1:
self.print(f'(int num)', '\n{\n')
else:
self.print('(void)\n{\n')
if regnum != 1:
self.print('\t', f'static const uintptr_t loc[{regnum}]', '= {\n')
self.print('\t\t', self.get_reg(name,0), '\n')
for i in range(1,regnum):
self.print('\t\t,', self.get_reg(name, i), '\n')
self.print('\t};\n')
self.print('''
if (num < 0 || num >= ARRAY_SIZE(loc)) {
LOG_ERR("invalid location %d", num);
k_fatal_halt(K_ERR_KERNEL_OOPS);
}
''')
self.print('\t', f'return litex_read{typ}({"loc[num]" if regnum != 1 else self.get_reg(name, None)}', ');\n}\n\n')
def print_file(self):
self.print('''
#pragma once
static inline void litex_write64(uint64_t value, unsigned long addr)
{
#if CONFIG_LITEX_CSR_DATA_WIDTH >= 32
sys_write32(value >> 32, addr);
sys_write32(value, addr + 0x4);
#else
# error Unsupported CSR data width
#endif
}
''')
self.print('#define DAC_MAX', self.dacmax, '\n')
self.print('#define ADC_MAX', self.adcmax, '\n')
for reg in self.registers:
self.print_read_fun(reg[1],reg[2])
if not reg[0]: #read only
self.print_write_fun(reg[1],reg[2])
if __name__ == "__main__": if __name__ == "__main__":
dac_num = 8 dac_num = 8
adc_num = 8 adc_num = 8
registers = [ registers = [
("dac_sel", dac_num), # Read-only, name, number
("dac_finished", dac_num), (False, "dac_sel", dac_num),
("dac_arm", dac_num), (True, "dac_finished", dac_num),
("from_dac", dac_num), (False, "dac_arm", dac_num),
("to_dac", dac_num), (True, "from_dac", dac_num),
("wf_arm", dac_num), (False, "to_dac", dac_num),
("wf_halt_on_finish", dac_num), (False, "wf_arm", dac_num),
("wf_finished", dac_num), (False, "wf_halt_on_finish", dac_num),
("wf_running", dac_num), (True, "wf_finished", dac_num),
("wf_time_to_wait", dac_num), (True, "wf_running", dac_num),
("wf_refresh_start", dac_num), (False, "wf_time_to_wait", dac_num),
("wf_refresh_finished", dac_num), (False, "wf_refresh_start", dac_num),
("wf_start_addr", dac_num), (True, "wf_refresh_finished", dac_num),
(False, "wf_start_addr", dac_num),
("adc_finished", adc_num), (True, "adc_finished", adc_num),
("adc_arm", adc_num), (False, "adc_arm", adc_num),
("from_adc", adc_num), (True, "from_adc", adc_num),
("adc_sel_0", 1), (False, "adc_sel_0", 1),
("cl_in_loop", 1), (True, "cl_in_loop", 1),
("cl_cmd", 1), (False, "cl_cmd", 1),
("cl_word_in", 1), (False, "cl_word_in", 1),
("cl_word_out", 1), (False, "cl_word_out", 1),
("cl_start_cmd", 1), (False, "cl_start_cmd", 1),
("cl_finish_cmd", 1), (True, "cl_finish_cmd", 1),
] ]
CSRGenerator("csr.json", registers, sys.stdout).print_file() CSRGenerator("csr.json", "csr_bitwidth.json", registers, sys.stdout, dac_num, adc_num).print_file()

View File

@ -128,10 +128,9 @@ class Base(Module, AutoCSR):
self.kwargs["i_adc_sdo"] = platform.request("adc_sdo") self.kwargs["i_adc_sdo"] = platform.request("adc_sdo")
self.kwargs["o_adc_sck"] = platform.request("adc_sck") self.kwargs["o_adc_sck"] = platform.request("adc_sck")
with open("io_widths.h", mode='w') as f: with open("csr_bitwidth.json", mode='w') as f:
print('#pragma once', file=f) import json
for key in self.csrdict: json.dump(self.csrdict, f)
print(f'#define {key.upper()}_LEN {self.csrdict[key]}', file=f)
self.specials += Instance("base", **self.kwargs) self.specials += Instance("base", **self.kwargs)

View File

@ -3,9 +3,10 @@ unexport CFLAGS
unexport CPPFLAGS unexport CPPFLAGS
unexport LDFLAGS unexport LDFLAGS
# TODO: Number of processors
build/zephyr/zephyr.bin: build/Makefile build/zephyr/zephyr.bin: build/Makefile
cd build && make -j7 cd build && make -j7
build/Makefile: ../creole/creole.c src/*.c ../firmware/overlay.dts ../firmware/pin_io.h prj.conf CMakeLists.txt build/Makefile: ../creole/creole.c src/*.c ../firmware/overlay.dts ../firmware/pin_io.c prj.conf CMakeLists.txt
mkdir -p build mkdir -p build
cd build && cmake .. cd build && cmake ..
clean: clean:

View File

@ -14,12 +14,12 @@
#include <zephyr/logging/log.h> #include <zephyr/logging/log.h>
#include "upsilon.h" #include "upsilon.h"
#include "access.h" #include "access.h"
#include "pin_io.h"
#include "control_loop_cmds.h" #include "control_loop_cmds.h"
LOG_MODULE_REGISTER(access); LOG_MODULE_REGISTER(access);
#include "pin_io.c"
/* The values from converters are not aligned to an 8-bit byte. /* The values from converters are not aligned to 32 bits.
* These values are still in twos compliment and have to be * These values are still in twos compliment and have to be
* manually sign-extended. * manually sign-extended.
*/ */
@ -61,8 +61,8 @@ dac_release(int dac)
return -EFAULT; return -EFAULT;
if (dac_locked[dac] == 1) { if (dac_locked[dac] == 1) {
*dac_arm[dac] = 0; write_dac_arm(0, dac);
while (!*dac_finished[dac]); while (!read_dac_finished(dac));
} }
int e = k_mutex_unlock(dac_mutex + dac); int e = k_mutex_unlock(dac_mutex + dac);
@ -81,20 +81,20 @@ dac_read_write(int dac, creole_word send, k_timeout_t timeout,
return e; return e;
dac_switch(dac, DAC_SPI_PORT, K_NO_WAIT); dac_switch(dac, DAC_SPI_PORT, K_NO_WAIT);
litex_write32(send, to_dac[dac]); write_to_dac(send, dac);
litex_write8(1, dac_arm[dac]); write_dac_arm(1, dac);
/* Recursive locks should busy wait. */ /* Non-recursive locks should busy wait. */
/* 10ns * (2 * 10 cycles per half DAC cycle) /* 10ns * (2 * 10 cycles per half DAC cycle)
* 24 bits * 24 bits
*/ */
if (dac_locked[dac] > 1) if (dac_locked[dac] > 1)
k_sleep(K_NSEC(10*2*10*24)); k_sleep(K_NSEC(10*2*10*24));
while (!litex_read8(dac_finished[dac])); while (!read_dac_finished(dac));
if (recv) if (recv)
*recv = sign_extend(litex_read32(from_dac[dac]), 20); *recv = sign_extend(read_from_dac(dac), 20);
litex_write8(0, dac_arm[dac]); write_dac_arm(0, dac);
dac_release(dac); dac_release(dac);
return 0; return 0;
@ -107,7 +107,7 @@ dac_switch(int dac, int setting, k_timeout_t timeout)
if (e != 0) if (e != 0)
return e; return e;
litex_write8(setting, dac_sel[dac]); write_dac_sel(setting, dac);
dac_release(dac); dac_release(dac);
return 0; return 0;
@ -140,8 +140,8 @@ adc_release(int adc)
return -EFAULT; return -EFAULT;
if (adc_locked[adc] == 1) { if (adc_locked[adc] == 1) {
*adc_arm[adc] = 0; write_adc_arm(0, adc);
while (!*adc_finished[adc]); while (!read_adc_finished(adc));
} }
int e = k_mutex_unlock(adc_mutex + adc); int e = k_mutex_unlock(adc_mutex + adc);
@ -164,7 +164,7 @@ adc_switch(int adc, int setting, k_timeout_t timeout)
if (e != 0) if (e != 0)
return e; return e;
litex_write8(setting, adc_sel_0); write_adc_sel_0(setting);
adc_release(adc); adc_release(adc);
return 0; return 0;
@ -178,15 +178,15 @@ adc_read(int adc, k_timeout_t timeout, creole_word *wrd)
return e; return e;
adc_switch(adc, ADC_SPI_PORT, K_NO_WAIT); adc_switch(adc, ADC_SPI_PORT, K_NO_WAIT);
litex_write8(1, adc_arm[adc]); write_adc_arm(1, adc);
/* Recursive locks should busy wait. */ /* Recursive locks should busy wait. */
if (adc_locked[adc] > 1) if (adc_locked[adc] > 1)
k_sleep(K_NSEC(550 + 24*2*10*10)); k_sleep(K_NSEC(550 + 24*2*10*10));
while (!litex_read8(adc_finished[adc])); while (!read_adc_finished(adc));
*wrd = sign_extend(litex_read32(from_adc[adc]), 20); *wrd = sign_extend(read_from_adc(adc), 20);
litex_write8(0, adc_arm[adc]); write_adc_arm(0, adc);
adc_release(adc); adc_release(adc);
return 0; return 0;
@ -231,11 +231,11 @@ cloop_read(int code, uint32_t *high_reg, uint32_t *low_reg,
if (cloop_take(timeout) != 0) if (cloop_take(timeout) != 0)
return 0; return 0;
litex_write8(code, cl_cmd); write_cl_cmd(code);
litex_write8(1, cl_start_cmd); write_cl_start_cmd(1);
while (!litex_read8(cl_finish_cmd)); while (!read_cl_finish_cmd());
v = litex_read64(cl_word_out); v = read_cl_word_out();
litex_write8(0, cl_start_cmd); write_cl_start_cmd(0);
*high_reg = v >> 32; *high_reg = v >> 32;
*low_reg = v & 0xFFFFFFFF; *low_reg = v & 0xFFFFFFFF;
@ -251,11 +251,11 @@ cloop_write(int code, uint32_t high_val, uint32_t low_val,
if (cloop_take(timeout) != 0) if (cloop_take(timeout) != 0)
return 0; return 0;
litex_write8(code, cl_cmd); write_cl_cmd(code);
litex_write64((uint64_t) high_val << 32 | low_val, cl_word_in); write_cl_word_in((uint64_t) high_val << 32 | low_val);
litex_write8(1, cl_start_cmd); write_cl_start_cmd(1);
while (!litex_read8(cl_finish_cmd)); while (!read_cl_finish_cmd());
litex_write8(0, cl_start_cmd); write_cl_start_cmd(0);
cloop_release(); cloop_release();
return 1; return 1;
@ -284,11 +284,9 @@ waveform_take(int waveform, k_timeout_t timeout)
static void static void
waveform_disarm_wait(int wf) waveform_disarm_wait(int wf)
{ {
litex_write8(0, wf_arm[wf]); write_wf_arm(0, wf);
if (*wf_running[wf]) { /* TODO: add wait */
// k_sleep(K_NSEC(10* *wf_time_to_wait[wf])); while (read_wf_running(wf));
while (litex_read8(wf_running[wf]));
}
} }
int int
@ -328,10 +326,10 @@ waveform_load(uint32_t buf[MAX_WL_SIZE], int slot, k_timeout_t timeout)
if (waveform_take(slot, timeout) != 0) if (waveform_take(slot, timeout) != 0)
return 0; return 0;
litex_write32((uint32_t) buf, wf_start_addr[slot]); write_wf_start_addr((uint32_t) buf, slot);
litex_write8(1, wf_refresh_start[slot]); write_wf_refresh_start(1, slot);
while (!litex_read8(wf_refresh_finished[slot])); while (!read_wf_refresh_finished(slot));
litex_write8(0, wf_refresh_start[slot]); write_wf_refresh_start(0, slot);
waveform_release(slot); waveform_release(slot);
return 1; return 1;
@ -340,8 +338,8 @@ waveform_load(uint32_t buf[MAX_WL_SIZE], int slot, k_timeout_t timeout)
int int
waveform_halt_until_finished(int slot) waveform_halt_until_finished(int slot)
{ {
litex_write8(1, wf_halt_on_finish[slot]); write_wf_halt_on_finish(1, slot);
while (!litex_read(wf_finished[slot])); while (!read_wf_finished(slot));
return 1; return 1;
} }
@ -357,9 +355,9 @@ waveform_arm(int slot, bool halt_on_finish, uint32_t wait, k_timeout_t timeout)
dac_switch(slot, DAC_WF_PORT, K_NO_WAIT); dac_switch(slot, DAC_WF_PORT, K_NO_WAIT);
litex_write8(halt_on_finish, wf_halt_on_finish[slot]); write_wf_halt_on_finish(halt_on_finish, slot);
litex_write16(wait, wf_time_to_wait[slot]); write_wf_time_to_wait(wait, slot);
litex_write8(1, wf_arm[slot]); write_wf_arm(1, slot);
return 1; return 1;
} }
@ -403,9 +401,6 @@ access_release_thread(void)
} }
} }
for (int i = 0; i < DAC_MAX; i++) {
}
for (int i = 0; i < ADC_MAX; i++) { for (int i = 0; i < ADC_MAX; i++) {
while (adc_release(i) == 0) while (adc_release(i) == 0)
adc_locked[i]--; adc_locked[i]--;