1+ # SPDX-License-Identifier: BSD-2-Clause
2+ import os
3+ import tempfile
4+ import unittest
5+ from pathlib import Path
6+ from unittest import mock
7+
8+ from chipflow_lib .software .soft_gen import SoftwareGenerator
9+
10+
11+ class TestSoftwareGenerator (unittest .TestCase ):
12+ def setUp (self ):
13+ """Set up the test with a SoftwareGenerator instance"""
14+ self .rom_start = 0x10000000
15+ self .rom_size = 0x8000
16+ self .ram_start = 0x20000000
17+ self .ram_size = 0x4000
18+ self .generator = SoftwareGenerator (
19+ rom_start = self .rom_start ,
20+ rom_size = self .rom_size ,
21+ ram_start = self .ram_start ,
22+ ram_size = self .ram_size
23+ )
24+
25+ def test_initialization (self ):
26+ """Test that the SoftwareGenerator initializes correctly"""
27+ self .assertEqual (self .generator .rom_start , self .rom_start )
28+ self .assertEqual (self .generator .rom_size , self .rom_size )
29+ self .assertEqual (self .generator .ram_start , self .ram_start )
30+ self .assertEqual (self .generator .ram_size , self .ram_size )
31+ self .assertEqual (self .generator .defines , [])
32+ self .assertEqual (self .generator .periphs , [])
33+ self .assertEqual (self .generator .extra_init , [])
34+
35+ def test_add_periph (self ):
36+ """Test adding peripherals"""
37+ self .generator .add_periph ("uart" , "uart0" , 0x40000000 )
38+ self .generator .add_periph ("gpio" , "gpio0" , 0x40001000 )
39+
40+ self .assertEqual (len (self .generator .periphs ), 2 )
41+ self .assertEqual (self .generator .periphs [0 ], ("uart" , "uart0" , 0x40000000 ))
42+ self .assertEqual (self .generator .periphs [1 ], ("gpio" , "gpio0" , 0x40001000 ))
43+
44+ def test_add_extra_init (self ):
45+ """Test adding extra initialization code"""
46+ init_code = "# This is a test init code"
47+ self .generator .add_extra_init (init_code )
48+
49+ self .assertEqual (len (self .generator .extra_init ), 1 )
50+ self .assertEqual (self .generator .extra_init [0 ], init_code )
51+
52+ def test_soc_h_with_uart (self ):
53+ """Test soc.h generation with a UART peripheral"""
54+ self .generator .add_periph ("uart" , "uart0" , 0x40000000 )
55+
56+ soc_h = self .generator .soc_h
57+
58+ # Check that the UART header is included
59+ self .assertIn ('#include "drivers/uart.h"' , soc_h )
60+
61+ # Check that the UART is defined
62+ self .assertIn ('#define uart0 ((volatile uart_regs_t *const)0x40000000)' , soc_h )
63+
64+ # Check that putc, puts, and puthex are defined to use uart0
65+ self .assertIn ('#define putc(x) uart_putc(uart0, x)' , soc_h )
66+ self .assertIn ('#define puts(x) uart_puts(uart0, x)' , soc_h )
67+ self .assertIn ('#define puthex(x) uart_puthex(uart0, x)' , soc_h )
68+
69+ def test_soc_h_without_uart (self ):
70+ """Test soc.h generation without a UART peripheral"""
71+ self .generator .add_periph ("gpio" , "gpio0" , 0x40001000 )
72+
73+ soc_h = self .generator .soc_h
74+
75+ # Check that the GPIO header is included
76+ self .assertIn ('#include "drivers/gpio.h"' , soc_h )
77+
78+ # Check that the GPIO is defined
79+ self .assertIn ('#define gpio0 ((volatile gpio_regs_t *const)0x40001000)' , soc_h )
80+
81+ # Check that putc, puts, and puthex are defined as no-ops
82+ self .assertIn ('#define putc(x) do {{ (void)x; }} while(0)' , soc_h )
83+ self .assertIn ('#define puts(x) do {{ (void)x; }} while(0)' , soc_h )
84+ self .assertIn ('#define puthex(x) do {{ (void)x; }} while(0)' , soc_h )
85+
86+ def test_start_assembly (self ):
87+ """Test start.S generation"""
88+ init_code = "# Custom initialization"
89+ self .generator .add_extra_init (init_code )
90+
91+ start_code = self .generator .start
92+
93+ # Check that the stack pointer is set to the top of RAM
94+ self .assertIn (f"li x2, 0x{ self .ram_start + self .ram_size :08x} " , start_code )
95+
96+ # Check that our custom initialization code is included
97+ self .assertIn (init_code , start_code )
98+
99+ # Check essential parts of the startup code
100+ self .assertIn ("call main" , start_code )
101+ self .assertIn ("loop:" , start_code )
102+
103+ def test_linker_script (self ):
104+ """Test sections.lds generation"""
105+ lds = self .generator .lds
106+
107+ # Check memory regions
108+ self .assertIn (f"FLASH (rx) : ORIGIN = 0x{ self .rom_start :08x} , LENGTH = 0x{ self .rom_size :08x} " , lds )
109+ self .assertIn (f"RAM (xrw) : ORIGIN = 0x{ self .ram_start :08x} , LENGTH = 0x{ self .ram_size :08x} " , lds )
110+
111+ # Check essential sections
112+ self .assertIn (".text :" , lds )
113+ self .assertIn (".data :" , lds )
114+ self .assertIn (".bss :" , lds )
115+ self .assertIn (".heap :" , lds )
116+
117+ def test_generate (self ):
118+ """Test file generation"""
119+ with tempfile .TemporaryDirectory () as temp_dir :
120+ # Generate the files
121+ self .generator .generate (temp_dir )
122+
123+ # Check that the files were created
124+ self .assertTrue (os .path .exists (os .path .join (temp_dir , "start.S" )))
125+ self .assertTrue (os .path .exists (os .path .join (temp_dir , "sections.lds" )))
126+ self .assertTrue (os .path .exists (os .path .join (temp_dir , "soc.h" )))
127+
128+ # Verify the content of the files
129+ with open (os .path .join (temp_dir , "start.S" ), "r" ) as f :
130+ self .assertEqual (f .read (), self .generator .start )
131+
132+ with open (os .path .join (temp_dir , "sections.lds" ), "r" ) as f :
133+ self .assertEqual (f .read (), self .generator .lds )
134+
135+ with open (os .path .join (temp_dir , "soc.h" ), "r" ) as f :
136+ self .assertEqual (f .read (), self .generator .soc_h )
0 commit comments