refactor compiles
This commit is contained in:
parent
054609a459
commit
cf95a0fd20
|
@ -49,7 +49,6 @@ hardware-get:
|
|||
docker cp upsilon-hardware:/home/user/upsilon/gateware/arty.dtb ../boot/
|
||||
docker cp upsilon-hardware:/home/user/upsilon/gateware/mmio.py ../boot/
|
||||
docker cp upsilon-hardware:/home/user/upsilon/gateware/csr.json ../boot/
|
||||
docker cp upsilon-hardware:/home/user/upsilon/gateware/csr_bitwidth.json ../boot/
|
||||
hardware-clean:
|
||||
-docker container stop upsilon-hardware
|
||||
-docker container rm upsilon-hardware
|
||||
|
|
|
@ -15,59 +15,23 @@ import collections
|
|||
import argparse
|
||||
import json
|
||||
import sys
|
||||
|
||||
class MMIORegister:
|
||||
def __init__(self, name, read_only=False, number=1, exntype=None):
|
||||
"""
|
||||
Describes a MMIO register.
|
||||
:param name: The name of the MMIO register, excluding the prefix
|
||||
defining its module (i.e. ``base_``) and excluding its
|
||||
numerical suffix.
|
||||
:param read_only: True if the register is read only. Defaults to
|
||||
``False``.
|
||||
:param number: The number of MMIO registers with the same name
|
||||
and number suffixes. The number suffixes must go from 0
|
||||
to ``number - 1`` with no gaps.
|
||||
"""
|
||||
self.name = name
|
||||
self.read_only = read_only
|
||||
self.number = number
|
||||
self.exntype = exntype
|
||||
|
||||
# These are filled in by the CSR file.
|
||||
self.size = None
|
||||
|
||||
def mmio_factory(num, exntype):
|
||||
"""
|
||||
Return a function that simplifies the creation of instances of
|
||||
:py:class:`MMIORegister` with the same number and exception type.
|
||||
|
||||
:param num: Number of registers with the same name (minus suffix).
|
||||
:param exntype: MicroPython exception type.
|
||||
:return: A function ``f(name, read_only=False)``. Each argument is
|
||||
the same as the one in the initializer of py:class:`MMIORegister`.
|
||||
"""
|
||||
def f(name, read_only=False):
|
||||
return MMIORegister(name, read_only, number=num, exntype=exntype)
|
||||
return f
|
||||
import mmio_descr
|
||||
|
||||
class CSRHandler:
|
||||
"""
|
||||
Class that wraps the CSR file and fills in registers with information
|
||||
from those files.
|
||||
"""
|
||||
def __init__(self, csrjson, bitwidthjson, registers):
|
||||
def __init__(self, csrjson, registers):
|
||||
"""
|
||||
Reads in the CSR files.
|
||||
|
||||
:param csrjson: Filename of a LiteX "csr.json" file.
|
||||
:param bitwidthjson: Filename of an Upsilon "bitwidthjson" file.
|
||||
:param registers: A list of :py:class:`MMIORegister`s.
|
||||
:param registers: A list of ``mmio_descr`` ``Descr``s.
|
||||
:param outf: Output file.
|
||||
"""
|
||||
self.registers = registers
|
||||
self.csrs = json.load(open(csrjson))
|
||||
self.bws = json.load(open(bitwidthjson))
|
||||
|
||||
def update_reg(self, reg):
|
||||
"""
|
||||
|
@ -76,17 +40,19 @@ class CSRHandler:
|
|||
:param reg: The register.
|
||||
:raises Exception: When the bit width exceeds 64.
|
||||
"""
|
||||
b = self.bws[reg.name]
|
||||
regsize = None
|
||||
b = reg.blen
|
||||
if b <= 8:
|
||||
reg.size = 8
|
||||
regsize = 8
|
||||
elif b <= 16:
|
||||
reg.size = 16
|
||||
regsize = 16
|
||||
elif b <= 32:
|
||||
reg.size = 32
|
||||
regsize = 32
|
||||
elif b <= 64:
|
||||
reg.size = 64
|
||||
regsize = 64
|
||||
else:
|
||||
raise Exception(f"unsupported width {b} in {reg.name}")
|
||||
setattr(reg, "regsize", regsize)
|
||||
|
||||
def get_reg_addr(self, reg, num=None):
|
||||
"""
|
||||
|
@ -135,7 +101,7 @@ class InterfaceGenerator:
|
|||
self.print(self.header())
|
||||
for r in self.csr.registers:
|
||||
self.print(self.fun(r, "read"))
|
||||
if not r.read_only:
|
||||
if not r.rwperm != "read-only":
|
||||
self.print(self.fun(r, "write"))
|
||||
|
||||
class MicropythonGenerator(InterfaceGenerator):
|
||||
|
@ -144,9 +110,9 @@ class MicropythonGenerator(InterfaceGenerator):
|
|||
|
||||
def get_accessor(self, reg, num):
|
||||
addr = self.csr.get_reg_addr(reg, num)
|
||||
if reg.size in [8, 16, 32]:
|
||||
return [f"machine.mem{reg.size}[{addr}]"]
|
||||
return [f"machine.mem32[{addr}]", f"machine.mem32[{addr + 4}]"]
|
||||
if reg.regsize in [8, 16, 32]:
|
||||
return [f"machine.mem{reg.regsize}[{addr}]"]
|
||||
return [f"machine.mem32[{addr + 4}]", f"machine.mem32[{addr}]"]
|
||||
|
||||
def print_write_register(self, indent, varname, reg, num):
|
||||
acc = self.get_accessor(reg, num)
|
||||
|
@ -181,16 +147,16 @@ class MicropythonGenerator(InterfaceGenerator):
|
|||
else:
|
||||
pfun = self.print_read_register
|
||||
|
||||
if reg.number != 1:
|
||||
if reg.num != 1:
|
||||
if printed_argument:
|
||||
a(', ')
|
||||
a('num')
|
||||
a('):\n')
|
||||
|
||||
if reg.number == 1:
|
||||
if reg.num == 1:
|
||||
a(pfun('\t', 'val', reg, None))
|
||||
else:
|
||||
for i in range(0,reg.number):
|
||||
for i in range(0,reg.num):
|
||||
if i == 0:
|
||||
a(f'\tif ')
|
||||
else:
|
||||
|
@ -198,46 +164,16 @@ class MicropythonGenerator(InterfaceGenerator):
|
|||
a(f'num == {i}:\n')
|
||||
a(pfun('\t\t', 'val', reg, i))
|
||||
a(f'\telse:\n')
|
||||
a(f'\t\traise {r.exntype}(regnum)\n')
|
||||
a(f'\t\traise Exception(regnum)\n')
|
||||
a('\n')
|
||||
|
||||
return rs
|
||||
|
||||
def header(self):
|
||||
return """import machine
|
||||
class InvalidDACException(Exception):
|
||||
pass
|
||||
class InvalidADCException(Exception):
|
||||
pass
|
||||
"""
|
||||
return "import machine\n"
|
||||
|
||||
if __name__ == "__main__":
|
||||
dac_num = 8
|
||||
adc_num = 8
|
||||
dac_reg = mmio_factory(dac_num, "InvalidDACException")
|
||||
adc_reg = mmio_factory(adc_num, "InvalidADCException")
|
||||
|
||||
registers = [
|
||||
dac_reg("dac_sel"),
|
||||
dac_reg("dac_finished", read_only=True),
|
||||
dac_reg("dac_arm"),
|
||||
dac_reg("dac_recv_buf", read_only=True),
|
||||
dac_reg("dac_send_buf"),
|
||||
|
||||
adc_reg("adc_finished", read_only=True),
|
||||
adc_reg("adc_arm"),
|
||||
adc_reg("adc_recv_buf", read_only=True),
|
||||
adc_reg("adc_sel"),
|
||||
|
||||
MMIORegister("cl_in_loop", read_only=True),
|
||||
MMIORegister("cl_cmd"),
|
||||
MMIORegister("cl_word_in"),
|
||||
MMIORegister("cl_word_out", read_only=True),
|
||||
MMIORegister("cl_start_cmd"),
|
||||
MMIORegister("cl_finish_cmd", read_only=True),
|
||||
MMIORegister("cl_z_report", read_only=True),
|
||||
]
|
||||
csrh = CSRHandler(sys.argv[1], sys.argv[2], registers)
|
||||
for r in registers:
|
||||
csrh = CSRHandler(sys.argv[1], mmio_descr.registers)
|
||||
for r in mmio_descr.registers:
|
||||
csrh.update_reg(r)
|
||||
MicropythonGenerator(csrh, sys.stdout).print_file()
|
||||
|
|
|
@ -11,15 +11,15 @@ class Descr:
|
|||
"""
|
||||
self.name = name
|
||||
self.blen = blen
|
||||
self.doc = textwrap.deindent(descr)
|
||||
self.doc = textwrap.dedent(descr)
|
||||
self.num =num
|
||||
self.read_only = read_only == "read-only"
|
||||
self.rwperm = rwperm
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, jsdict, name):
|
||||
return cls(name, jsdict[name]["len"], jsdict[name]["ro"], jsdict[name]["num"], jsdict[name]["doc"])
|
||||
def store_to_dict(self, d):
|
||||
d[self.name = {
|
||||
d[self.name] = {
|
||||
"len": self.blen,
|
||||
"doc": self.doc,
|
||||
"num": self.num,
|
||||
|
@ -27,7 +27,7 @@ class Descr:
|
|||
}
|
||||
|
||||
registers = [
|
||||
Descr("adc_sel", 3, "read-write", """\
|
||||
Descr("adc_sel", 3, "read-write", 8, """\
|
||||
Select which on-FPGA SPI master controls the ADC.
|
||||
|
||||
Valid settings:
|
||||
|
@ -36,7 +36,7 @@ registers = [
|
|||
* ``0b10``: ADC is controlled by MMIO registers, but conversion is
|
||||
disabled. This is used to flush output from an out-of-sync ADC.
|
||||
* ``0b100``: ADC 0 only. ADC is controlled by control loop."""),
|
||||
Descr("adc_finished", "read-only", """\
|
||||
Descr("adc_finished", 1, "read-only", 8, """\
|
||||
Signals that an ADC master has finished an SPI cycle.
|
||||
|
||||
Values:
|
||||
|
@ -47,9 +47,8 @@ registers = [
|
|||
|
||||
This flag is on only when ``adc_arm`` is high. The flag does not
|
||||
mean that data has been received successfully, only that the master
|
||||
has finished it's SPI transfer.
|
||||
"""),
|
||||
Descr("adc_arm", "read-write", """\
|
||||
has finished it's SPI transfer."""),
|
||||
Descr("adc_arm", 1, "read-write", 8, """\
|
||||
Start a DAC master SPI transfer.
|
||||
|
||||
If ``adc_arm`` is raised from and the master is currently not in a SPI
|
||||
|
@ -84,7 +83,7 @@ registers = [
|
|||
|
||||
If ``adc_sel`` is not set to 0 then the transfer will proceed
|
||||
as normal, but no data will be received from the ADC."""),
|
||||
Descr("adc_recv_buf", "read-only", """\
|
||||
Descr("adc_recv_buf", 18, "read-only", 8, """\
|
||||
ADC Master receive buffer.
|
||||
|
||||
This buffer is stable if there is no ADC transfer caused by ``adc_arm``
|
||||
|
@ -94,14 +93,14 @@ registers = [
|
|||
registers. SPI transfers by other masters will not affect this register.
|
||||
buffer."""),
|
||||
|
||||
Descr("dac_sel", 2, "read-write", """\
|
||||
Descr("dac_sel", 2, "read-write", 8, """\
|
||||
Select which on-FPGA SPI master controls the DAC.
|
||||
|
||||
Valid settings:
|
||||
|
||||
* ``0``: DAC is controlled by MMIO registers.
|
||||
* ``0b10``: DAC 0 only. DAC is controlled by control loop."""),
|
||||
Descr("dac_finished", 1, "read-only", """\
|
||||
Descr("dac_finished", 1, "read-only", 8, """\
|
||||
Signals that the DAC master has finished transmitting data.
|
||||
|
||||
Values:
|
||||
|
@ -113,7 +112,7 @@ registers = [
|
|||
This flag is on only when ``dac_arm`` is high. The flag does not
|
||||
mean that data has been received or transmitted successfully, only that
|
||||
the master has finished it's SPI transfer."""),
|
||||
Descr("dac_arm", 1, "read-write", """\
|
||||
Descr("dac_arm", 1, "read-write", 8, """\
|
||||
Start a DAC master SPI transfer.
|
||||
|
||||
If ``dac_arm`` is raised from and the master is currently not in a SPI
|
||||
|
@ -138,7 +137,7 @@ registers = [
|
|||
|
||||
If ``dac_sel`` is set to another master then the transfer will proceed
|
||||
as normal, but no data will be sent to or received from the DAC."""),
|
||||
Descr("dac_recv_buf", 24, "read-only", """\
|
||||
Descr("dac_recv_buf", 24, "read-only", 8, """\
|
||||
DAC master receive buffer.
|
||||
|
||||
This buffer is stable if there is no DAC transfer caused by ``dac_arm``
|
||||
|
@ -147,7 +146,7 @@ registers = [
|
|||
This register only changes if an SPI transfer is triggered by the MMIO
|
||||
registers. SPI transfers by other masters will not affect this register.
|
||||
buffer."""),
|
||||
Descr("dac_send_buf, 24, "read-write", """\
|
||||
Descr("dac_send_buf", 24, "read-write", 8, """\
|
||||
DAC master send buffer.
|
||||
|
||||
Fill this buffer with a 24 bit Analog Devices DAC command. Updating
|
||||
|
@ -158,7 +157,7 @@ registers = [
|
|||
Modifying this buffer during a transfer does not disrupt an in-process
|
||||
transfer."""),
|
||||
|
||||
Descr("cl_assert_change", 1, "read-write", """\
|
||||
Descr("cl_assert_change", 1, "read-write", 1, """\
|
||||
Flush parameter changes to control loop.
|
||||
|
||||
When this bit is raised from low to high, this signals the control
|
||||
|
@ -168,21 +167,23 @@ registers = [
|
|||
|
||||
When this bit is raised from high to low before ``cl_change_made``
|
||||
is asserted by the control loop, nothing happens."""),
|
||||
Descr("cl_change_made", 1, "read-only", """\
|
||||
Descr("cl_change_made", 1, "read-only", 1, """\
|
||||
Signal from the control loop that the parameters have been applied.
|
||||
|
||||
This signal goes high only while ``cl_assert_change`` is high. No
|
||||
change will be applied afterwards while both are high."""),
|
||||
|
||||
Descr("cl_in_loop_in", 1, "read-only", """\
|
||||
Descr("cl_in_loop", 1, "read-only", 1, """\
|
||||
This bit is high if the control loop is running."""),
|
||||
Descr("cl_setpt_in", 18, "read-write", """\
|
||||
Descr("cl_run_loop_in", 1, "read-write", 1, """\
|
||||
Set this bit high to start the control loop."""),
|
||||
Descr("cl_setpt_in", 18, "read-write", 1, """\
|
||||
Setpoint of the control loop.
|
||||
|
||||
This is a twos-complement number in ADC units.
|
||||
|
||||
This is a parameter: see ``cl_assert_change``."""),
|
||||
Descr("cl_P_in", 64, "read-write", """\
|
||||
Descr("cl_P_in", 64, "read-write", 1, """\
|
||||
Proportional parameter of the control loop.
|
||||
|
||||
This is a twos-complement fixed point number with 21 whole
|
||||
|
@ -190,7 +191,7 @@ registers = [
|
|||
in DAC units.
|
||||
|
||||
This is a parameter: see ``cl_assert_change``."""),
|
||||
Descr("cl_I_in", 64, "read-write", """\
|
||||
Descr("cl_I_in", 64, "read-write", 1, """\
|
||||
Integral parameter of the control loop.
|
||||
|
||||
This is a twos-complement fixed point number with 21 whole
|
||||
|
@ -198,7 +199,7 @@ registers = [
|
|||
in DAC units.
|
||||
|
||||
This is a parameter: see ``cl_assert_change``."""),
|
||||
Descr("cl_delay_in", 16, "read-write", """\
|
||||
Descr("cl_delay_in", 16, "read-write", 1, """\
|
||||
Delay parameter of the loop.
|
||||
|
||||
This is an unsigned number denoting the number of cycles
|
||||
|
@ -206,15 +207,15 @@ registers = [
|
|||
|
||||
This is a parameter: see ``cl_assert_change``."""),
|
||||
|
||||
Descr("cl_cycle_count", 18, "read-only", """\
|
||||
Descr("cl_cycle_count", 18, "read-only", 1, """\
|
||||
Delay parameter of the loop.
|
||||
|
||||
This is an unsigned number denoting the number of cycles
|
||||
the loop should wait between loop executions."""),
|
||||
Descr("cl_z_pos", 20, "read-only", """\
|
||||
Descr("cl_z_pos", 20, "read-only", 1, """\
|
||||
Control loop DAC Z position.
|
||||
"""),
|
||||
Descr("cl_z_measured", 18, "read-only", """\
|
||||
Descr("cl_z_measured", 18, "read-only", 1, """\
|
||||
Control loop ADC Z position.
|
||||
"""),
|
||||
]
|
||||
|
|
|
@ -292,6 +292,7 @@ m4_define(CL_DATA_WID, CL_CONSTS_WID)
|
|||
|
||||
input cl_assert_change,
|
||||
output cl_change_made,
|
||||
output cl_in_loop,
|
||||
|
||||
input cl_run_loop_in,
|
||||
input [ADC_TYPE1_WID-1:0] cl_setpt_in,
|
||||
|
@ -299,9 +300,9 @@ m4_define(CL_DATA_WID, CL_CONSTS_WID)
|
|||
input [CL_DATA_WID-1:0] cl_I_in,
|
||||
input [CL_DELAY_WID-1:0] cl_delay_in,
|
||||
|
||||
output [CYCLE_COUNT_WID-1:0] cl_cycle_count,
|
||||
output [CL_CYCLE_COUNT_WID-1:0] cl_cycle_count,
|
||||
output [DAC_DATA_WID-1:0] cl_z_pos,
|
||||
output [ADC_WID-1:0] cl_z_measured
|
||||
output [ADC_TYPE1_WID-1:0] cl_z_measured
|
||||
);
|
||||
|
||||
assign set_low = 0;
|
||||
|
|
|
@ -144,7 +144,7 @@ class Base(Module, AutoCSR):
|
|||
if num is not None:
|
||||
name = f"{name}_{num}"
|
||||
|
||||
if self.ro == "read-only":
|
||||
if reg.rwperm == "read-only":
|
||||
csrclass = CSRStatus
|
||||
else:
|
||||
csrclass = CSRStorage
|
||||
|
|
Loading…
Reference in New Issue