Skip to content

Commit 660a511

Browse files
committed
24.23 support on AM, updated driver name, etc (#54)
* 24.23 support on AM, updated driver name, etc AD1939 sending 24.23 format is supported on Audiomini Driver path in sysfs is now /sys/class/fe_devicename/fe_devicenameminor#/, where minor# is generally going to be 0 Registers no longer are assumed to have register_control in front of them, so register names in model must match model.json instead of register_control_regname In progress on support for avalon wrapper handling registers that are outputs rather than inputs Fixed issues with regenerating a model that has an existing project but on a new target * Updated device driver generation to no longer use fe prefix as well as no longer hardcoding prefix everywhere * Fixed {Driver_Prefix} not being substituted out on the generated file * 0 register support, slave address size being inconsistent fixed, and baseAddr updated to 0x40 Slave address was being calculated with log 10 instead of log2 in dataplane_config.py After fixing slave address issue and attempting to generate sound_effects model, Platform Designer insisted that the base address be 0x00 or 0x40 instead of 0x20.
1 parent 54b8fe2 commit 660a511

11 files changed

+371
-349
lines changed

device_drivers/device.py

Lines changed: 77 additions & 75 deletions
Large diffs are not rendered by default.

device_drivers/device_attributes.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# Bozeman, MT 59718
2121
2222

23-
from device_drivers.device import DeviceType
23+
from device_drivers.device import DeviceType, DRIVER_PREFIX
2424

2525
class DataType:
2626
"""Represent a fixed point number."""
@@ -137,7 +137,7 @@ def create_read_func(self, device_name):
137137
Returns C function definition for reading the attribute value
138138
"""
139139
c_code = "static ssize_t " + self.name + "_read(struct device *dev, struct device_attribute *attr, char *buf) {\n"
140-
c_code += " fe_" + device_name + "_dev_t * devp = (fe_" + device_name + "_dev_t *)dev_get_drvdata(dev);\n"
140+
c_code += f" {DRIVER_PREFIX}_{device_name}_dev_t * devp = ({DRIVER_PREFIX}_{device_name}_dev_t *)dev_get_drvdata(dev);\n"
141141
if self.data_type.name == "string":
142142
c_code += self._read_string()
143143
else:
@@ -244,7 +244,7 @@ def create_write_func(self, device_name):
244244
c_code += " char substring[80];\n"
245245
c_code += " int substring_count = 0;\n"
246246
c_code += " int i;\n"
247-
c_code += " fe_" + device_name + "_dev_t *devp = (fe_" + device_name + \
247+
c_code += f" {DRIVER_PREFIX}_{device_name}_dev_t *devp = ({DRIVER_PREFIX}_" + device_name + \
248248
"_dev_t *)dev_get_drvdata(dev);\n"
249249
c_code += " for (i = 0; i < count; i++) {\n"
250250
c_code += " if ((buf[i] != ',') && (buf[i] != ' ') && (buf[i] != '\\0') && (buf[i] != '\\r') && (buf[i] != '\\n')) {\n"
@@ -329,7 +329,7 @@ def create_write_func(self, device_name, device_name_abbrev):
329329
c_code += ","
330330
c_code += "};\n"
331331
c_code += " uint8_t code = 0x00;\n"
332-
c_code += " fe_" + device_name + "_dev_t * devp = (fe_" + device_name + \
332+
c_code += f" {DRIVER_PREFIX}_{device_name}_dev_t * devp = ({DRIVER_PREFIX}_" + device_name + \
333333
"_dev_t *) dev_get_drvdata(dev);\n"
334334
c_code += " for (i = 0; i < count; i++) {\n"
335335
c_code += " if ((buf[i] != ',') && (buf[i] != ' ') && (buf[i] != '\\0') && (buf[i] != '\\r') && (buf[i] != '\\n')) {\n"
@@ -399,7 +399,7 @@ def create_write_func(self, device_name, device_name_abbrev):
399399
c_code += ","
400400
c_code += "};\n"
401401
c_code += " uint8_t code = 0x00;\n"
402-
c_code += " fe_" + device_name + "_dev_t * devp = (fe_" + device_name + \
402+
c_code += f" {DRIVER_PREFIX}_{device_name}_dev_t * devp = ({DRIVER_PREFIX}_" + device_name + \
403403
"_dev_t *) dev_get_drvdata(dev);\n"
404404
c_code += " for (i = 0; i < count; i++) {\n"
405405
c_code += " if ((buf[i] != ',') && (buf[i] != ' ') && (buf[i] != '\\0') && (buf[i] != '\\r') && (buf[i] != '\\n')) {\n"

ipcore/avalon_config.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,16 @@ def parse_json(config_filepath):
6161
json_registers = modeljson['devices'][0]["registers"]
6262
registers = []
6363
for reg in json_registers:
64+
direction = reg.get("direction") or "in"
6465
registers.append(Register(
6566
reg["name"],
6667
DataType(
6768
reg["dataType"]["wordLength"],
6869
reg["dataType"]["fractionLength"],
6970
reg["dataType"]["signed"]
7071
),
71-
reg["defaultValue"]
72+
reg["defaultValue"],
73+
direction
7274
))
7375
entity_name = modeljson['devices'][0]["name"] + "_dataplane"
7476
is_sample_based = modeljson['system']['processing'].lower() == "sample"

ipcore/avalon_wrapper.py

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,28 +39,28 @@ def generate_avalon_wrapper(registers, audio_in, audio_out, entity_name, working
3939
working_dir : str, optional
4040
Directory to output avalon wrapper to, by default "" which is the current directory
4141
"""
42-
avalon_in_data_type = AD1939_DATA_TYPE
43-
avalon_out_data_type = AD1939_DATA_TYPE
42+
avalon_in_data_type = audio_in.data_type
43+
avalon_out_data_type = audio_out.data_type
4444
if len(registers) == 0:
4545
addr_width = 0
4646
else:
4747
addr_width = int(ceil(log(len(registers), 2)))
4848
if addr_width == 0 and len(registers) == 1:
4949
addr_width = 1
5050
channel_in_width = int(ceil(log(audio_in.channel_count, 2)))
51-
print(channel_in_width)
51+
5252
channel_out_width = int(ceil(log(audio_out.channel_count, 2)))
5353

5454
avalon_entity_ports = [
5555
Port(PortDir.In, Signal("clk")),
5656
Port(PortDir.In, Signal("reset")),
5757
Port(PortDir.In, Signal("avalon_sink_valid")),
58-
Port(PortDir.In, Signal("avalon_sink_data", 32,
58+
Port(PortDir.In, Signal("avalon_sink_data", audio_in.data_type.word_len,
5959
None, "std_logic_vector", avalon_in_data_type)),
6060
Port(PortDir.In, Signal("avalon_sink_channel", channel_in_width, None, "std_logic_vector")),
6161
Port(PortDir.In, Signal("avalon_sink_error", 2)),
6262
Port(PortDir.Out, Signal("avalon_source_valid")),
63-
Port(PortDir.Out, Signal("avalon_source_data", 32,
63+
Port(PortDir.Out, Signal("avalon_source_data", audio_out.data_type.word_len,
6464
None, "std_logic_vector", avalon_out_data_type)),
6565
Port(PortDir.Out, Signal("avalon_source_channel", channel_out_width, None, "std_logic_vector")),
6666
Port(PortDir.Out, Signal("avalon_source_error", 2)),
@@ -93,12 +93,11 @@ def generate_avalon_wrapper(registers, audio_in, audio_out, entity_name, working
9393
for reg in registers]
9494
dataplane_signals = create_dataplane_signals(
9595
audio_in, audio_out, is_sample_based)
96-
register_prefix = "register_control_"
9796
register_ports = [
9897
Port(
99-
PortDir.In,
98+
PortDir.Out if reg.direction == "out" else PortDir.In,
10099
Signal(
101-
register_prefix + reg.name,
100+
reg.name.replace(" ", "_"),
102101
reg.data_type.word_len,
103102
None,
104103
"std_logic" if reg.data_type.word_len == 1 else "std_logic_vector",
@@ -214,7 +213,7 @@ def create_dataplane_port_map(dataplane, entity, registers, register_signals, ar
214213
reg_signal = next(
215214
port for port in register_signals if port.name == reg.name)
216215
port_map[dataplane.get_port(
217-
f"register_control_{reg.name}")] = reg_signal
216+
reg.name)] = reg_signal
218217
return PortMap(f"u_{dataplane.name}", port_map, dataplane)
219218

220219

@@ -277,8 +276,10 @@ def create_bus_read_logic(register_signals, avalon_slave_readdata_signal):
277276
logic_string += tab() + \
278277
f"if rising_edge(clk) and {read_enable} = '1' then \n"
279278
logic_string += tab(2) + f"case {avalon_slave_address} is\n"
280-
281-
addr_width = int(ceil(log(len(register_signals), 2)))
279+
try:
280+
addr_width = int(ceil(log(len(register_signals), 2)))
281+
except ValueError:
282+
addr_width = 0
282283
for idx, reg in enumerate(register_signals):
283284
addr = "{0:0{1}b}".format(idx, addr_width)
284285
assignment = data_out.generate_assignment(reg)
@@ -291,13 +292,13 @@ def create_bus_read_logic(register_signals, avalon_slave_readdata_signal):
291292
return logic_string
292293

293294

294-
def create_bus_write_logic(register_signals, avalon_slave_writedata_signal):
295+
def create_bus_write_logic(register_ports, avalon_slave_writedata_signal):
295296
"""Create VHDL logic to write to dataplane registers.
296297
297298
Parameters
298299
----------
299-
register_signals : list of Signal
300-
Signals connected to dataplane registers
300+
register_ports : list of Port
301+
Ports connected to dataplane registers
301302
avalon_slave_writedata_signal : Signal
302303
Signal that the avalon writes data to
303304
@@ -312,7 +313,7 @@ def create_bus_write_logic(register_signals, avalon_slave_writedata_signal):
312313

313314
logic_string = ""
314315
logic_string += tab() + f"if reset = '1' then \n"
315-
for reg in register_signals:
316+
for reg in register_ports:
316317
data_type = reg.underlying_data_type
317318
default_bit_string = num_to_bitstring(
318319
reg.default_value, data_type.word_len, data_type.frac_len)
@@ -323,8 +324,13 @@ def create_bus_write_logic(register_signals, avalon_slave_writedata_signal):
323324
f"elsif rising_edge(clk) and {write_enable} = '1' then\n"
324325
logic_string += tab(2) + f"case {avalon_slave_address} is\n"
325326

326-
addr_width = int(ceil(log(len(register_signals), 2)))
327-
for idx, reg in enumerate(register_signals):
327+
try:
328+
addr_width = int(ceil(log(len(register_ports), 2)))
329+
except ValueError:
330+
addr_width = 0
331+
for idx, reg in enumerate(register_ports):
332+
# if(reg.direction == PortDir.Out):
333+
# continue
328334
addr = "{0:0{1}b}".format(idx, addr_width)
329335
assignment = reg.generate_assignment(data_in)
330336
logic_string += tab(3) + f"when \"{addr}\" => {assignment}"

ipcore/dataplane_config.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ def __init__(self):
2121

2222
self.sink_max_channel = 0
2323
self.source_max_channel = 0
24+
self.sink_bits_per_symbol = 24
25+
self.source_bits_per_symbol = 24
2426

2527
def populate_additional_filesets(self, additionalFilesetAbsDir, sourceFilePatterns):
2628
for pattern in sourceFilePatterns:
@@ -53,10 +55,12 @@ def parse_json(inputFilename, deviceIndex=0):
5355
if len(model.devices[deviceIndex].registers) > 0:
5456
config.has_avalon_mm_slave_signal = True
5557
config.address_bus_size = int(
56-
ceil(log(len(model.devices[deviceIndex].registers))))
58+
ceil(log(len(model.devices[deviceIndex].registers), 2)))
5759

5860
config.sink_max_channel = model.system.audioIn.numberOfChannels - 1
5961
config.source_max_channel = model.system.audioOut.numberOfChannels - 1
62+
config.sink_bits_per_symbol = model.system.audioIn.wordLength
63+
config.source_bits_per_symbol = model.system.audioOut.wordLength
6064
return config
6165

6266

ipcore/hw_tcl_generator.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ def __init__(self, dataplane_config):
2020
self.sink_max_channel = dataplane_config.sink_max_channel
2121
self.source_max_channel = dataplane_config.source_max_channel
2222

23+
self.sink_bits_per_symbol = dataplane_config.sink_bits_per_symbol
24+
self.source_bits_per_symbol = dataplane_config.source_bits_per_symbol
25+
2326
def write_tcl(self, outputFilename):
2427
with open(outputFilename, "w") as out_file:
2528
out_file.write(self.generate())
@@ -128,8 +131,9 @@ def create_connection_point_reset(self):
128131

129132

130133
def create_mm_connection_point(self):
131-
if not self.has_avalon_mm_slave_signal:
132-
return ""
134+
# Even if no memory, the interface is still needed
135+
#if not self.has_avalon_mm_slave_signal:
136+
# return ""
133137
tcl = ""
134138
memory_slave = 'avalon_slave'
135139
tcl += "add_interface " + memory_slave + " avalon end\n"
@@ -189,7 +193,7 @@ def create_sink_connection_point(self):
189193
tcl += "set_interface_property " + sink + " associatedClock clock\n"
190194
tcl += "set_interface_property " + sink + " associatedReset reset\n"
191195
tcl += "set_interface_property " + sink + \
192-
" dataBitsPerSymbol " + str(self.data_bus_size) + "\n"
196+
" dataBitsPerSymbol " + str(self.sink_bits_per_symbol) + "\n"
193197
tcl += "set_interface_property " + sink + " errorDescriptor \"\"\n"
194198
tcl += "set_interface_property " + \
195199
sink + " firstSymbolInHighOrderBits true\n"
@@ -203,7 +207,7 @@ def create_sink_connection_point(self):
203207
sink + " CMSIS_SVD_VARIABLES \"\"\n"
204208
tcl += "set_interface_property " + sink + " SVD_ADDRESS_GROUP \"\"\n"
205209
tcl += "add_interface_port " + sink + " avalon_sink_valid valid Input 1\n"
206-
tcl += "add_interface_port " + sink + " avalon_sink_data data Input 32\n"
210+
tcl += f"add_interface_port {sink} avalon_sink_data data Input {self.sink_bits_per_symbol}\n"
207211
tcl += f"add_interface_port {sink} avalon_sink_channel channel Input {int(ceil(log(self.sink_max_channel + 1, 2))) or 1}\n"
208212
tcl += "add_interface_port " + sink + " avalon_sink_error error Input 2\n"
209213
tcl += "\n\n\n"
@@ -217,7 +221,7 @@ def create_source_connection_point(self):
217221
tcl += "set_interface_property " + source + " associatedClock clock\n"
218222
tcl += "set_interface_property " + source + " associatedReset reset\n"
219223
tcl += "set_interface_property " + source + \
220-
" dataBitsPerSymbol " + str(self.data_bus_size) + "\n"
224+
" dataBitsPerSymbol " + str(self.source_bits_per_symbol) + "\n"
221225
tcl += "set_interface_property " + source + " errorDescriptor \"\"\n"
222226
tcl += "set_interface_property " + \
223227
source + " firstSymbolInHighOrderBits true\n"
@@ -232,7 +236,7 @@ def create_source_connection_point(self):
232236
tcl += "set_interface_property " + source + " SVD_ADDRESS_GROUP \"\"\n"
233237

234238
tcl += "add_interface_port " + source + " avalon_source_valid valid Output 1\n"
235-
tcl += "add_interface_port " + source + " avalon_source_data data Output 32\n"
239+
tcl += f"add_interface_port {source} avalon_source_data data Output {self.source_bits_per_symbol}\n"
236240
tcl += f"add_interface_port {source} avalon_source_channel channel Output {int(ceil(log(self.source_max_channel + 1, 2))) or 1}\n"
237241
tcl += "add_interface_port " + source + " avalon_source_error error Output 2\n"
238242
tcl += "\n\n\n"

ipcore/util.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from math import fabs
22
import collections
33

4-
Register = collections.namedtuple('Register', ['name', 'data_type', 'default'])
4+
Register = collections.namedtuple('Register', ['name', 'data_type', 'default', 'direction'])
55
Audio = collections.namedtuple('Audio', ['data_type', 'channel_count', 'dual'])
66
DataType = collections.namedtuple(
77
'DataType', ['word_len', 'frac_len', 'signed'])

quartus/quartus_templates.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
load_package flow
2828
2929
if [project_exists $project] {
30-
project_open $project
31-
create_revision $revision
30+
project_open -force -current_revision $project
31+
create_revision -set_current $revision
3232
} else {
3333
project_new $project -revision ${revision} -overwrite
3434
}
@@ -60,7 +60,7 @@
6060
class QuartusTemplates:
6161
"""Generate templates for Quartus workflow."""
6262

63-
def __init__(self, num_custom_components, baseAddress=20):
63+
def __init__(self, num_custom_components, baseAddress=40):
6464
"""Initialize QuartusTemplates.
6565
6666
Parameters

0 commit comments

Comments
 (0)