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.cmake
firmware/overlay.dts
firmware/pin_io.h
firmware/pin_io.c
misc/
software/build/
*.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`
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
## Network Setup
@ -438,6 +444,12 @@ TODO: Ethernet debugging output.
## 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`,
`litex_read16`, etc. In the Zephyr source, look at
`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
crash the software.
# Controlling Computer
## Creole

View File

@ -2,11 +2,11 @@
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:
cd rtl && make
build/digilent_arty/digilent_arty.bit: rtl_codegen soc.py
build/digilent_arty/digilent_arty.bit: soc.py
python3 soc.py
clean:
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.
$(DEVICETREE_GEN_DIR)/litex_json2dts_zephyr.py --dts overlay.dts --config overlay.cmake csr.json
pin_io.h: csr.json generate_csr_locations.py
python3 generate_csr_locations.py > pin_io.h
pin_io.c: csr.json generate_csr_locations.py
python3 generate_csr_locations.py > pin_io.c

View File

@ -3,76 +3,142 @@ import json
import sys
"""
This file takes the csr.json file output by LiteX and extracts all
CSRs that are handled by Upsilon directly. See the output file csr.json
for layout.
This file uses csr.json and csr_bitwidth.json and writes functions
that handle reads and writes to MMIO.
"""
class CSRGenerator:
def __init__(self, json_file, registers, f):
def __init__(self, csrjson, bitwidthjson, registers, outf, dacmax, adcmax):
self.registers = registers
self.j = json.load(open(json_file))
self.file = f
self.csrs = json.load(open(csrjson))
self.bws = json.load(open(bitwidthjson))
self.file = outf
self.dacmax = dacmax
self.adcmax = adcmax
def get_reg(self, name, num):
if num is None:
regname = f"base_{name}"
else:
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):
print(*args, end='', file=self.file)
def print_array(self, name, num):
if num == 1:
self.print(f'static const uintptr_t {name} = {self.get_reg(name, None)};\n')
else:
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_write_fun(self, name, regnum):
typ = self.get_bitwidth_type(name)
self.print('static inline void\n')
self.print(f'write_{name}(uint{typ}_t v')
def print_registers(self):
for name,num in self.registers:
self.print_array(name, num)
def print_file(self):
self.print(f'''#pragma once
#define ADC_MAX {adc_num}
#define DAC_MAX {dac_num}
if regnum != 1:
self.print(f', int num')
self.print(')\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_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__":
dac_num = 8
adc_num = 8
registers = [
("dac_sel", dac_num),
("dac_finished", dac_num),
("dac_arm", dac_num),
("from_dac", dac_num),
("to_dac", dac_num),
("wf_arm", dac_num),
("wf_halt_on_finish", dac_num),
("wf_finished", dac_num),
("wf_running", dac_num),
("wf_time_to_wait", dac_num),
("wf_refresh_start", dac_num),
("wf_refresh_finished", dac_num),
("wf_start_addr", dac_num),
# Read-only, name, number
(False, "dac_sel", dac_num),
(True, "dac_finished", dac_num),
(False, "dac_arm", dac_num),
(True, "from_dac", dac_num),
(False, "to_dac", dac_num),
(False, "wf_arm", dac_num),
(False, "wf_halt_on_finish", dac_num),
(True, "wf_finished", dac_num),
(True, "wf_running", dac_num),
(False, "wf_time_to_wait", dac_num),
(False, "wf_refresh_start", dac_num),
(True, "wf_refresh_finished", dac_num),
(False, "wf_start_addr", dac_num),
("adc_finished", adc_num),
("adc_arm", adc_num),
("from_adc", adc_num),
(True, "adc_finished", adc_num),
(False, "adc_arm", adc_num),
(True, "from_adc", adc_num),
("adc_sel_0", 1),
("cl_in_loop", 1),
("cl_cmd", 1),
("cl_word_in", 1),
("cl_word_out", 1),
("cl_start_cmd", 1),
("cl_finish_cmd", 1),
(False, "adc_sel_0", 1),
(True, "cl_in_loop", 1),
(False, "cl_cmd", 1),
(False, "cl_word_in", 1),
(False, "cl_word_out", 1),
(False, "cl_start_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["o_adc_sck"] = platform.request("adc_sck")
with open("io_widths.h", mode='w') as f:
print('#pragma once', file=f)
for key in self.csrdict:
print(f'#define {key.upper()}_LEN {self.csrdict[key]}', file=f)
with open("csr_bitwidth.json", mode='w') as f:
import json
json.dump(self.csrdict, f)
self.specials += Instance("base", **self.kwargs)

View File

@ -3,9 +3,10 @@ unexport CFLAGS
unexport CPPFLAGS
unexport LDFLAGS
# TODO: Number of processors
build/zephyr/zephyr.bin: build/Makefile
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
cd build && cmake ..
clean:

View File

@ -14,12 +14,12 @@
#include <zephyr/logging/log.h>
#include "upsilon.h"
#include "access.h"
#include "pin_io.h"
#include "control_loop_cmds.h"
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
* manually sign-extended.
*/
@ -61,8 +61,8 @@ dac_release(int dac)
return -EFAULT;
if (dac_locked[dac] == 1) {
*dac_arm[dac] = 0;
while (!*dac_finished[dac]);
write_dac_arm(0, dac);
while (!read_dac_finished(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;
dac_switch(dac, DAC_SPI_PORT, K_NO_WAIT);
litex_write32(send, to_dac[dac]);
litex_write8(1, dac_arm[dac]);
write_to_dac(send, 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)
* 24 bits
*/
if (dac_locked[dac] > 1)
k_sleep(K_NSEC(10*2*10*24));
while (!litex_read8(dac_finished[dac]));
while (!read_dac_finished(dac));
if (recv)
*recv = sign_extend(litex_read32(from_dac[dac]), 20);
litex_write8(0, dac_arm[dac]);
*recv = sign_extend(read_from_dac(dac), 20);
write_dac_arm(0, dac);
dac_release(dac);
return 0;
@ -107,7 +107,7 @@ dac_switch(int dac, int setting, k_timeout_t timeout)
if (e != 0)
return e;
litex_write8(setting, dac_sel[dac]);
write_dac_sel(setting, dac);
dac_release(dac);
return 0;
@ -140,8 +140,8 @@ adc_release(int adc)
return -EFAULT;
if (adc_locked[adc] == 1) {
*adc_arm[adc] = 0;
while (!*adc_finished[adc]);
write_adc_arm(0, adc);
while (!read_adc_finished(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)
return e;
litex_write8(setting, adc_sel_0);
write_adc_sel_0(setting);
adc_release(adc);
return 0;
@ -178,15 +178,15 @@ adc_read(int adc, k_timeout_t timeout, creole_word *wrd)
return e;
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. */
if (adc_locked[adc] > 1)
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);
litex_write8(0, adc_arm[adc]);
*wrd = sign_extend(read_from_adc(adc), 20);
write_adc_arm(0, adc);
adc_release(adc);
return 0;
@ -231,11 +231,11 @@ cloop_read(int code, uint32_t *high_reg, uint32_t *low_reg,
if (cloop_take(timeout) != 0)
return 0;
litex_write8(code, cl_cmd);
litex_write8(1, cl_start_cmd);
while (!litex_read8(cl_finish_cmd));
v = litex_read64(cl_word_out);
litex_write8(0, cl_start_cmd);
write_cl_cmd(code);
write_cl_start_cmd(1);
while (!read_cl_finish_cmd());
v = read_cl_word_out();
write_cl_start_cmd(0);
*high_reg = v >> 32;
*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)
return 0;
litex_write8(code, cl_cmd);
litex_write64((uint64_t) high_val << 32 | low_val, cl_word_in);
litex_write8(1, cl_start_cmd);
while (!litex_read8(cl_finish_cmd));
litex_write8(0, cl_start_cmd);
write_cl_cmd(code);
write_cl_word_in((uint64_t) high_val << 32 | low_val);
write_cl_start_cmd(1);
while (!read_cl_finish_cmd());
write_cl_start_cmd(0);
cloop_release();
return 1;
@ -284,11 +284,9 @@ waveform_take(int waveform, k_timeout_t timeout)
static void
waveform_disarm_wait(int wf)
{
litex_write8(0, wf_arm[wf]);
if (*wf_running[wf]) {
// k_sleep(K_NSEC(10* *wf_time_to_wait[wf]));
while (litex_read8(wf_running[wf]));
}
write_wf_arm(0, wf);
/* TODO: add wait */
while (read_wf_running(wf));
}
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)
return 0;
litex_write32((uint32_t) buf, wf_start_addr[slot]);
litex_write8(1, wf_refresh_start[slot]);
while (!litex_read8(wf_refresh_finished[slot]));
litex_write8(0, wf_refresh_start[slot]);
write_wf_start_addr((uint32_t) buf, slot);
write_wf_refresh_start(1, slot);
while (!read_wf_refresh_finished(slot));
write_wf_refresh_start(0, slot);
waveform_release(slot);
return 1;
@ -340,8 +338,8 @@ waveform_load(uint32_t buf[MAX_WL_SIZE], int slot, k_timeout_t timeout)
int
waveform_halt_until_finished(int slot)
{
litex_write8(1, wf_halt_on_finish[slot]);
while (!litex_read(wf_finished[slot]));
write_wf_halt_on_finish(1, slot);
while (!read_wf_finished(slot));
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);
litex_write8(halt_on_finish, wf_halt_on_finish[slot]);
litex_write16(wait, wf_time_to_wait[slot]);
litex_write8(1, wf_arm[slot]);
write_wf_halt_on_finish(halt_on_finish, slot);
write_wf_time_to_wait(wait, slot);
write_wf_arm(1, slot);
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++) {
while (adc_release(i) == 0)
adc_locked[i]--;