ceb3663c021c6a5e2365f6470f0983282cbecbc8
6 from nmigen
import tracer
7 from nmigen_soc
.memory
import MemoryMap
8 from nmigen
.build
.run
import *
10 from .. import __version__
, software
11 from ..periph
import Peripheral
14 __all__
= ["socproperty", "SoC", "ConfigBuilder"]
17 def socproperty(cls
, *, weak
=False, src_loc_at
=0):
18 name
= tracer
.get_var_name(depth
=2 + src_loc_at
)
19 __name
= "__{}".format(name
)
22 assert isinstance(self
, SoC
)
23 attr
= getattr(self
, __name
, None)
24 if attr
is None and not weak
:
25 raise NotImplementedError("SoC {!r} does not have a {}"
29 def setter(self
, value
):
30 assert isinstance(self
, SoC
)
31 if not isinstance(value
, cls
):
32 raise TypeError("{} must be an instance of {}, not {!r}"
33 .format(name
, cls
.__name
__, value
))
34 setattr(self
, __name
, value
)
36 return property(getter
, setter
)
40 memory_map
= socproperty(MemoryMap
)
42 def build(self
, build_dir
="build/soc", do_build
=True, name
=None):
43 plan
= ConfigBuilder().prepare(self
, build_dir
, name
)
47 products
= plan
.execute_local(build_dir
)
53 "build_{{name}}.sh": r
"""
58 "{{name}}_resources.csv": r
"""
60 # <resource name>, <start address>, <end address>, <access width>
61 {% for resource, (start, end, width) in soc.memory_map.all_resources() -%}
62 {{resource.name}}, {{hex(start)}}, {{hex(end)}}, {{width}}
66 command_templates
= []
68 def prepare(self
, soc
, build_dir
, name
):
69 name
= name
or type(soc
).__name
__.lower()
71 autogenerated
= "Automatically generated by LambdaSoC {}. Do not edit.".format(__version__
)
73 def periph_addr(periph
):
74 assert isinstance(periph
, Peripheral
)
75 periph_map
= periph
.bus
.memory_map
76 for window
, (start
, end
, ratio
) in soc
.memory_map
.windows():
77 if periph_map
is window
:
79 raise KeyError(periph
)
81 def periph_csrs(periph
):
82 assert isinstance(periph
, Peripheral
)
83 periph_map
= periph
.bus
.memory_map
84 for resource
, (start
, end
, width
) in periph_map
.all_resources():
85 if isinstance(resource
, csr
.Element
):
86 yield resource
, (start
, end
, width
)
90 for index
, command_tpl
in enumerate(self
.command_templates
):
91 command
= render(command_tpl
, origin
="<command#{}>".format(index
+ 1))
92 command
= re
.sub(r
"\s+", " ", command
)
93 commands
.append(command
)
94 return "\n".join(commands
)
96 def render(source
, origin
):
98 source
= textwrap
.dedent(source
).strip()
99 compiled
= jinja2
.Template(source
, trim_blocks
=True, lstrip_blocks
=True)
100 except jinja2
.TemplateSyntaxError
as e
:
101 e
.args
= ("{} (at {}:{})".format(e
.message
, origin
, e
.lineno
),)
103 return compiled
.render({
104 "autogenerated": autogenerated
,
105 "build_dir": os
.path
.abspath(build_dir
),
106 "emit_commands": emit_commands
,
109 "periph_addr": periph_addr
,
110 "periph_csrs": periph_csrs
,
112 "software_dir": os
.path
.dirname(software
.__file
__),
115 plan
= BuildPlan(script
="build_{}".format(name
))
116 for filename_tpl
, content_tpl
in self
.file_templates
.items():
117 plan
.add_file(render(filename_tpl
, origin
=filename_tpl
),
118 render(content_tpl
, origin
=content_tpl
))