Skip to content

Conversation

@lyakh
Copy link
Collaborator

@lyakh lyakh commented Jul 14, 2020

This is a very early proposal of what Topology v2.0 files could eventually look like. For review and commenting only for now.

Topology 2.0 file format is an extension of the ALSA configuration
language. It uses the same basic syntax of "key-value pairs" of the
language but adds features, required to be able to define complex objects
by re-using definitions of component objects with different attributes.
This replaces the SOF m4 topology macro library.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
@lyakh lyakh requested review from lgirdwood and plbossart July 14, 2020 14:59
@lyakh
Copy link
Collaborator Author

lyakh commented Jul 15, 2020

Forgot to add yesterday: a list of new ALSA configuration keywords (might be missing some)

array
availability { mandatory, optional, automatic }
default
enum
graph
max
min
pipelines
range
struct
subtree
template
type
# in general "DefineX" declares a block for "SectionX" except for "abstract"
# definitions like "Attribute," "Template," "Type"
DefineAttribute
DefineBE
DefineControlMixer
DefineHWConfig
DefinePCM
DefinePCMCapabilities
DefineTemplate
DefineType
DefineWidget

Copy link
Member

@lgirdwood lgirdwood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make the changes and share a pipeline like

Host0 --> buffer0 --> volume0 --> buffer1 --> SSP0

We will need to have a global attributes and per widget/component/section attributes that should be prefixed to avoid collisions.

# adding ".optional" or ".mandatory" to the array name

DefineType.format {
enum [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we name space this and use the "" here. e.g.

DefineType."pcm.format" {

Since "format" can be used for multiple items.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a type definition, not an attribute declaration. PCM and DAI formats are the same, aren't they?

]
}

DefineType.time_domain {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto "pipeline.time_domain"


DefineType.time_domain {
enum [
"dma"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use the # here to comment each field. i.e.
"dma" #pipeline is scheduled via DMA interrupts

type array.tuple
}

DefineAttribute.format {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This overlaps with DefineType. I much rather reduce the number of new keywords so

DefineAttribute."pcm.format" {
    type enum
    values [
        s16le
        s24le
   [
    default s16le
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but we will have several attributes of type "format." Without defining the type "format" we'll have to repeat the same enum every time. Even worse with much longer enums like widget types.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be global and in a global pcm.conf header. PCM format will be used in lots of places so why would we have to repeat. Can you provide an example ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lgirdwood Even in minimal examples we have two formats: a pipeline format and a DAI format, so we need at least two attributes of type "format" - see pipeline_format and dai_format in this PR

]
}

DefineAttribute.tokens {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dont need to define tokens - it's low level implementation detail only.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a "tokens" attribute for cases where higher level configuration files (e.g. machine level) pass their specific token arrays to lower level configuration files (pipelines). This is currently used for example to define pipelines:

dnl W_PIPELINE(stream, period, priority, core, initiator, platform)
							  ^^^^^^^^
define(`W_PIPELINE',
...
`SectionWidget."'N_PIPELINE($1)`" {'
...
`	data ['
`		"'N_PIPELINE($1)`_data"'
`		"'$6`"'
		^^^^^^
`	]'
`}')

which then is called as

W_PIPELINE(N_DAI_OUT, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_dai_schedule_plat)
											       ^^^^^^^^^^^^^^^^^^^^^^

and pipe_dai_schedule_plat is an array of tokens, defined in bxt.m4 or similar. So far I don't have a good idea how to avoid such token array passing. The only thing we can make easier is make arrays of word- and string-tokens a built-in type, without this defining them directly as a structure of an array of string tokens and an array of word tokens becomes really painful.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we are not using SectionWidget or token array directly - we abstract all tokens with Attributes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lgirdwood we do that where possible, yes. E.g. for volume, where it's known in advance which tokens must be supplied. But here it can be any tokens that the respective platform decides to apply. So I don't see how we can replace them with fixed attributes?


# A buffer block, most attributes inherited from "Widget"
DefineWidget."buffer" {
attributes [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we make these attribute mandatory and optional in the widget definition. Some widgets will only have mandatory but some will have both e.g. for buffer "size" is mandatory but "ignore_underrun" is optional and false by default.

"siggen"
"src"
]
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dont need this, it's low level and encoded in the CC.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we add new widget types from time to time? Do we really want to patch the compiler every time we do that?

default_hw_conf_id $id

# FIXME we need concatenation
hw_configs [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need to concat this ?

hw_configs [
    config1
    config2
]

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

those aren't multiple configurations, that's just one configuration, generated by concatenating those two strings:

`SectionBE."'$4`" {'
...
`	hw_configs ['
`		"'$1$2`"'
`	]'

}

# SectionHWConfig
DefineHWConfig {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DefineHWConfig."hw_cfg.ssp" etc would support per DAI type configs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand correctly what you mean. This is dai.conf, so this is a generic definition of a SectionHWConfig component. "hw_cfg." seems to be unneeded - it just repeats DefineHWConfig. As for "ssp" - that would mean, that we have to instantiate SectionHWConfig components in machine configuration files. In fact this is exactly what my latest version does. But then we also have to define them per DAI type - as you say. What do we gain that way? So far we don't seem to have to do that? But that can be done, I think, let's see if we need it.

@@ -0,0 +1,80 @@
# Instantiate a subtree - all the pipelines, connected to one DAI
subtree {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect the machine file to contain

DeclarePipeline."pipe-name1" {
}

DeclarePipeline."pipe-name2" {
}

DeclareDAI."dai-name1" {
}

It should be representing the same data as contained in the machine M4 today.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Declare" in your code above means instantiation? I use "new." for it now. But yes, that's also what I do.
As far as I understand, the whole DSP audio topology can be divided into "DAI groups." I.e. each DAI can have a group of pipelines associated with it, but different DAIs never link. This seems to be what I see in most pipelines ATM but in fact I suspect this isn't a general rule? There can be some pass-through paths from a DMIC to a playback DAI, right? Do we have any such examples or any other examples, where different DAIs link together?
Currently in my notation a "subtree" is such an isolated part of the topology graph and it can include several pipelines, but only one DAI. The difference to the current m4 situation, where machine files just contain collections of pipelines, DAIs, backends, etc. is, that to make that approach work our m4 files make a heavy use of string-matching, i.e. concatenation. That's how DAIs, their configurations, graphs and pipelines are matched. To avoid that and to make explicit separation of graph parts I use "subtrees." E.g. each such subtree defines global parameters like dai_format etc. Without separating subtrees this would be impossible.

@lyakh
Copy link
Collaborator Author

lyakh commented Jul 16, 2020

Can you make the changes and share a pipeline like

Host0 --> buffer0 --> volume0 --> buffer1 --> SSP0

We will need to have a global attributes and per widget/component/section attributes that should be prefixed to avoid collisions.

@lgirdwood you want SSP over HDA? I now have exactly that example, but with HDA because their configuration is easier, it doesn't include capture and some other extensions.

@dbaluta
Copy link
Collaborator

dbaluta commented Jul 16, 2020

@lyakh a short introduction and context for this PR would be useful to have a better feel of why we are doing topology 2.0

@plbossart
Copy link
Member

Can you make the changes and share a pipeline like

Host0 --> buffer0 --> volume0 --> buffer1 --> SSP0

That's precisely what I recommended we avoid last week!
Please pretty please only think of such cases for testing, this is not scalable for actual firmware graphs.

@lyakh
Copy link
Collaborator Author

lyakh commented Jul 17, 2020

Can you make the changes and share a pipeline like

Host0 --> buffer0 --> volume0 --> buffer1 --> SSP0

That's precisely what I recommended we avoid last week!
Please pretty please only think of such cases for testing, this is not scalable for actual firmware graphs.

@plbossart yes, this is testing so far, but at least an example graph of the kind you're thinking about would be helpful. You mentioned, that sof-byt-codec.m4 was a good example, which defines the topology as

# PCM0 -----> volume -------v
#                            low latency mixer ----> volume ---->  SSP2
# PCM1 -----> volume -------^
# PCM0 <---- Volume <---- SSP2

where pcm0->volume, pcm1->volume, mixer->volume->SSP2, and pcm0<-volume<-SSP2 are 4 pipelines. Is it really a goal to not have pipelines, containing both a PCM and a DAI? We will make this possible, but for now there might indeed be a slight implicit assumption, that one such pipeline exists in each "pipeline group," but sure, I'll make sure to remove that assumption.

@lyakh
Copy link
Collaborator Author

lyakh commented Jul 17, 2020

@lyakh a short introduction and context for this PR would be useful to have a better feel of why we are doing topology 2.0

@dbaluta this is a rather early stage yet: we still haven't quite converged even on a prototype of a language definition and I'm just starting very tentative coding.

The reason to try and replace the present SOF m4 topology library is the inconvenience of dealing with parameters. It's very difficult or impossible to verify macro parameters, which makes their use very error-prone. We want to fix those issues, make working with topology files more natural and add further compile-time topology checks. For this we propose to extend the present ALSA configuration language by adding primitives, that will allow us to define topology components and then to use those definitions to build specific topologies - similar to how this is done now with m4.

@lgirdwood
Copy link
Member

Can you make the changes and share a pipeline like

Host0 --> buffer0 --> volume0 --> buffer1 --> SSP0

That's precisely what I recommended we avoid last week!
Please pretty please only think of such cases for testing, this is not scalable for actual firmware graphs.

Can you link in your bug/pr for reference here to remind me. I cant remember if this was to resolve some driver issues (sorry not tracking these atm).

@dbaluta
Copy link
Collaborator

dbaluta commented Jul 20, 2020

@lyakh a short introduction and context for this PR would be useful to have a better feel of why we are doing topology 2.0

@dbaluta this is a rather early stage yet: we still haven't quite converged even on a prototype of a language definition and I'm just starting very tentative coding.

The reason to try and replace the present SOF m4 topology library is the inconvenience of dealing with parameters. It's very difficult or impossible to verify macro parameters, which makes their use very error-prone. We want to fix those issues, make working with topology files more natural and add further compile-time topology checks. For this we propose to extend the present ALSA configuration language by adding primitives, that will allow us to define topology components and then to use those definitions to build specific topologies - similar to how this is done now with m4.

@lyakh thanks for explanation. Make sure this is also present in commit messages / PR description.

@lyakh
Copy link
Collaborator Author

lyakh commented Jul 20, 2020

There is a problem with this proposal: in ALSA configuration language '.' is used to describe parent-child relationships. And in this PR constructs like "DefineWidget.pipeline" or "new.widget.pcm" don't really describe such relationships. Moreover, in a fragment like

new.widget.pipeline {
	format s16le
	new.widget.buffer {...}
}

the "pipeline" widget will have 2 children: "format" and "new" which doesn't seem to make good sense.

@lgirdwood
Copy link
Member

@lyakh please see #3211. This is what I'm looking for.

@@ -0,0 +1,162 @@
# "DefineTemplate" doesn't seem to be needed
Copy link
Collaborator

@ranj063 ranj063 Nov 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lyakh I think we should have DefineTemplate{}. Ideally we should have DefineTemplate{} follow all Define*{} for that kind. For example, DefineMixerControl{} should have a DefineTemplate.mixercontrol{}, with default values so that we can instantiate a mixercontrol with that template and modfied attributes (if needed) easily.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ranj063 #3211 is the one to look at.

@lgirdwood lgirdwood closed this Mar 28, 2021
@lgirdwood lgirdwood deleted the branch thesofproject:master March 28, 2021 13:44
@paulstelian97
Copy link
Collaborator

A new pull request was probably in order anyway, but now you have to do it because the base branch "master" is gone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants