@@ -22,26 +22,41 @@ def _camelcase(value: str) -> str:
2222 return "" .join (word .capitalize () for word in words )
2323
2424
25- def run (root_node : node .AddrmapNode , out_dir : Path ) -> None :
26- """Export RDL to opentitan RTL."""
25+ def run (root_node : node .AddrmapNode , out_dir : Path , is_soc : bool = False ) -> None :
26+ """Export RDL to opentitan RTL.
27+
28+ IS_SOC: True if the root node represents an soc with address maps representing peripherals/devices.
29+ """
2730 factory = OtInterfaceBuilder ()
28- data = factory .parse_root (root_node )
31+ if is_soc :
32+ data = factory .parse_soc (root_node )
33+ else :
34+ data = factory .parse_ip_block (root_node )
2935
3036 Path (out_dir / "rdl.json" ).write_text (json .dumps (data , indent = 2 ), encoding = "utf-8" )
3137
38+ if not is_soc :
39+ _export (data , out_dir )
40+ return
41+
42+ for ip_block in data ["devices" ]:
43+ _export (ip_block , out_dir )
44+
45+
46+ def _export (ip_block : dict , out_dir : Path ) -> None :
3247 file_loader = FileSystemLoader (TEMPLATES_DIR )
3348 env = Environment (loader = file_loader )
3449 env .filters ["camelcase" ] = _camelcase
3550
36- ip_name = data ["ip_name" ]
51+ ip_name = ip_block ["ip_name" ]. lower ()
3752 reg_pkg_tpl = env .get_template ("reg_pkg.sv.tpl" )
38- stream = reg_pkg_tpl .render (data )
53+ stream = reg_pkg_tpl .render (ip_block )
3954 path = out_dir / f"{ ip_name } _reg_pkg.sv"
4055 path .open ("w" ).write (stream )
4156 print (f"Generated { path } ." )
4257
4358 reg_top_tpl = env .get_template ("reg_top.sv.tpl" )
44- for interface in data ["interfaces" ]:
59+ for interface in ip_block ["interfaces" ]:
4560 name = "_{}" .format (interface ["name" ].lower ()) if "name" in interface else ""
4661 data_ = {"ip_name" : ip_name , "interface" : interface }
4762 stream = reg_top_tpl .render (data_ ).replace (" \n " , "\n " )
@@ -193,14 +208,10 @@ def get_interface(self, addrmap: node.AddrmapNode, defalt_name: None | str = Non
193208 self .any_shadowed_reg = False
194209 self .async_registers .clear ()
195210
196- if addrmap .is_array :
197- print (f"WARNING: Unsupported array type: { type (addrmap )} , skiping..." )
198-
199211 interface = {}
200212 if defalt_name :
201213 interface ["name" ] = addrmap .inst_name or defalt_name
202214
203- interface ["offset" ] = addrmap .address_offset
204215 interface ["regs" ] = []
205216 interface ["windows" ] = []
206217 for child in addrmap .children ():
@@ -247,25 +258,26 @@ def get_interface(self, addrmap: node.AddrmapNode, defalt_name: None | str = Non
247258 ]
248259 return interface
249260
250- def parse_root (self , root : node .AddrmapNode ) -> dict :
251- """Parse the root node and return a dictionary representing a window."""
252- if root .is_array :
253- print ("Error: Unsupported array type on the top" )
254- raise RuntimeError
255- if not isinstance (root , node .AddrmapNode ):
256- print ("Error: Top level must be an addrmap" )
257- raise TypeError
258-
261+ def parse_ip_block (self , ip_block : node .AddrmapNode ) -> dict :
262+ """Parse the ip_block node of an IP block and return a dictionary."""
259263 obj = {}
260- params = self .get_paramesters (root )
264+ params = self .get_paramesters (ip_block )
261265 if params :
262266 obj ["parameters" ] = params
263- obj ["ip_name" ] = root .inst_name
264- obj ["offset" ] = root .address_offset
267+ obj ["ip_name" ] = ip_block .inst_name
268+
269+ obj ["offsets" ] = []
270+ if ip_block .is_array :
271+ offset = ip_block .raw_address_offset
272+ for _idx in range (ip_block .array_dimensions [0 ]):
273+ obj ["offsets" ].append (offset )
274+ offset += ip_block .array_stride
275+ else :
276+ obj ["offsets" ].append (ip_block .address_offset )
265277
266278 obj ["interfaces" ] = []
267279 obj ["alerts" ] = []
268- for child in root .children ():
280+ for child in ip_block .children ():
269281 if isinstance (child , node .AddrmapNode ):
270282 child_obj = self .get_interface (child , DEFAULT_INTERFACE_NAME )
271283 obj ["interfaces" ].append (child_obj )
@@ -279,10 +291,25 @@ def parse_root(self, root: node.AddrmapNode) -> dict:
279291 )
280292 raise TypeError
281293
282- # If the root contain imediate registers, use a default interface name
283- if len (root .registers ()) > 0 :
284- interface = self .get_interface (root )
294+ # If the ip_block contain imediate registers, use a default interface name
295+ if len (ip_block .registers ()) > 0 :
296+ interface = self .get_interface (ip_block )
285297 obj ["interfaces" ].append (interface )
286298 obj ["alerts" ].extend (interface ["alerts" ])
287299
288300 return obj
301+
302+ def parse_soc (self , root : node .AddrmapNode ) -> dict :
303+ """Parse the SoC root node and return a dictionary."""
304+ if root .is_array :
305+ print ("Error: Unsupported array type on the top" )
306+ raise RuntimeError
307+ if not isinstance (root , node .AddrmapNode ):
308+ print ("Error: Top level must be an addrmap" )
309+ raise TypeError
310+
311+ obj = {"devices" : []}
312+ for child in root .children ():
313+ obj ["devices" ].append (self .parse_ip_block (child ))
314+ return obj
315+
0 commit comments