2 from ..hdl
.rec
import *
4 from ..build
.dsl
import *
5 from ..build
.res
import *
9 class ResourceManagerTestCase(FHDLTestCase
):
12 Resource("clk100", 0, DiffPairs("H1", "H2", dir="i"), Clock(100e6
)),
13 Resource("clk50", 0, Pins("K1"), Clock(50e6
)),
14 Resource("user_led", 0, Pins("A0", dir="o")),
16 Subsignal("scl", Pins("N10", dir="o")),
17 Subsignal("sda", Pins("N11"))
21 Connector("pmod", 0, "B0 B1 B2 B3 - -"),
23 self
.cm
= ResourceManager(self
.resources
, self
.connectors
)
26 self
.cm
= ResourceManager(self
.resources
, self
.connectors
)
27 self
.assertEqual(self
.cm
.resources
, {
28 ("clk100", 0): self
.resources
[0],
29 ("clk50", 0): self
.resources
[1],
30 ("user_led", 0): self
.resources
[2],
31 ("i2c", 0): self
.resources
[3]
33 self
.assertEqual(self
.cm
.connectors
, {
34 ("pmod", 0): self
.connectors
[0],
37 def test_add_resources(self
):
39 Resource("user_led", 1, Pins("A1", dir="o"))
41 self
.cm
.add_resources(new_resources
)
42 self
.assertEqual(self
.cm
.resources
, {
43 ("clk100", 0): self
.resources
[0],
44 ("clk50", 0): self
.resources
[1],
45 ("user_led", 0): self
.resources
[2],
46 ("i2c", 0): self
.resources
[3],
47 ("user_led", 1): new_resources
[0]
50 def test_lookup(self
):
51 r
= self
.cm
.lookup("user_led", 0)
52 self
.assertIs(r
, self
.cm
.resources
["user_led", 0])
54 def test_request_basic(self
):
55 r
= self
.cm
.lookup("user_led", 0)
56 user_led
= self
.cm
.request("user_led", 0)
58 self
.assertIsInstance(user_led
, Pin
)
59 self
.assertEqual(user_led
.name
, "user_led_0")
60 self
.assertEqual(user_led
.width
, 1)
61 self
.assertEqual(user_led
.dir, "o")
63 ports
= list(self
.cm
.iter_ports())
64 self
.assertEqual(len(ports
), 1)
66 self
.assertEqual(list(self
.cm
.iter_port_constraints()), [
67 ("user_led_0__io", ["A0"], {})
70 def test_request_with_dir(self
):
71 i2c
= self
.cm
.request("i2c", 0, dir={"sda": "o"})
72 self
.assertIsInstance(i2c
, Record
)
73 self
.assertIsInstance(i2c
.sda
, Pin
)
74 self
.assertEqual(i2c
.sda
.dir, "o")
76 def test_request_tristate(self
):
77 i2c
= self
.cm
.request("i2c", 0)
78 self
.assertEqual(i2c
.sda
.dir, "io")
80 ports
= list(self
.cm
.iter_ports())
81 self
.assertEqual(len(ports
), 2)
83 self
.assertEqual(ports
[1].name
, "i2c_0__sda__io")
84 self
.assertEqual(ports
[1].width
, 1)
86 self
.assertEqual(list(self
.cm
.iter_single_ended_pins()), [
87 (i2c
.scl
, scl
, {}, False),
88 (i2c
.sda
, sda
, {}, False),
90 self
.assertEqual(list(self
.cm
.iter_port_constraints()), [
91 ("i2c_0__scl__io", ["N10"], {}),
92 ("i2c_0__sda__io", ["N11"], {})
95 def test_request_diffpairs(self
):
96 clk100
= self
.cm
.request("clk100", 0)
97 self
.assertIsInstance(clk100
, Pin
)
98 self
.assertEqual(clk100
.dir, "i")
99 self
.assertEqual(clk100
.width
, 1)
101 ports
= list(self
.cm
.iter_ports())
102 self
.assertEqual(len(ports
), 2)
104 self
.assertEqual(p
.name
, "clk100_0__p")
105 self
.assertEqual(p
.width
, clk100
.width
)
106 self
.assertEqual(n
.name
, "clk100_0__n")
107 self
.assertEqual(n
.width
, clk100
.width
)
109 self
.assertEqual(list(self
.cm
.iter_differential_pins()), [
110 (clk100
, p
, n
, {}, False),
112 self
.assertEqual(list(self
.cm
.iter_port_constraints()), [
113 ("clk100_0__p", ["H1"], {}),
114 ("clk100_0__n", ["H2"], {}),
117 def test_request_inverted(self
):
119 Resource("cs", 0, PinsN("X0")),
120 Resource("clk", 0, DiffPairsN("Y0", "Y1")),
122 self
.cm
.add_resources(new_resources
)
124 sig_cs
= self
.cm
.request("cs")
125 sig_clk
= self
.cm
.request("clk")
126 port_cs
, port_clk_p
, port_clk_n
= self
.cm
.iter_ports()
127 self
.assertEqual(list(self
.cm
.iter_single_ended_pins()), [
128 (sig_cs
, port_cs
, {}, True),
130 self
.assertEqual(list(self
.cm
.iter_differential_pins()), [
131 (sig_clk
, port_clk_p
, port_clk_n
, {}, True),
134 def test_request_raw(self
):
135 clk50
= self
.cm
.request("clk50", 0, dir="-")
136 self
.assertIsInstance(clk50
, Record
)
137 self
.assertIsInstance(clk50
.io
, Signal
)
139 ports
= list(self
.cm
.iter_ports())
140 self
.assertEqual(len(ports
), 1)
141 self
.assertIs(ports
[0], clk50
.io
)
143 def test_request_raw_diffpairs(self
):
144 clk100
= self
.cm
.request("clk100", 0, dir="-")
145 self
.assertIsInstance(clk100
, Record
)
146 self
.assertIsInstance(clk100
.p
, Signal
)
147 self
.assertIsInstance(clk100
.n
, Signal
)
149 ports
= list(self
.cm
.iter_ports())
150 self
.assertEqual(len(ports
), 2)
151 self
.assertIs(ports
[0], clk100
.p
)
152 self
.assertIs(ports
[1], clk100
.n
)
154 def test_request_via_connector(self
):
155 self
.cm
.add_resources([
157 Subsignal("ss", Pins("1", conn
=("pmod", 0))),
158 Subsignal("clk", Pins("2", conn
=("pmod", 0))),
159 Subsignal("miso", Pins("3", conn
=("pmod", 0))),
160 Subsignal("mosi", Pins("4", conn
=("pmod", 0))),
163 spi0
= self
.cm
.request("spi", 0)
164 self
.assertEqual(list(self
.cm
.iter_port_constraints()), [
165 ("spi_0__ss__io", ["B0"], {}),
166 ("spi_0__clk__io", ["B1"], {}),
167 ("spi_0__miso__io", ["B2"], {}),
168 ("spi_0__mosi__io", ["B3"], {}),
171 def test_request_via_nested_connector(self
):
173 Connector("pmod_extension", 0, "1 2 3 4 - -", conn
=("pmod", 0)),
175 self
.cm
.add_connectors(new_connectors
)
176 self
.cm
.add_resources([
178 Subsignal("ss", Pins("1", conn
=("pmod_extension", 0))),
179 Subsignal("clk", Pins("2", conn
=("pmod_extension", 0))),
180 Subsignal("miso", Pins("3", conn
=("pmod_extension", 0))),
181 Subsignal("mosi", Pins("4", conn
=("pmod_extension", 0))),
184 spi0
= self
.cm
.request("spi", 0)
185 self
.assertEqual(list(self
.cm
.iter_port_constraints()), [
186 ("spi_0__ss__io", ["B0"], {}),
187 ("spi_0__clk__io", ["B1"], {}),
188 ("spi_0__miso__io", ["B2"], {}),
189 ("spi_0__mosi__io", ["B3"], {}),
192 def test_request_clock(self
):
193 clk100
= self
.cm
.request("clk100", 0)
194 clk50
= self
.cm
.request("clk50", 0, dir="i")
195 clk100_port_p
, clk100_port_n
, clk50_port
= self
.cm
.iter_ports()
196 self
.assertEqual(list(self
.cm
.iter_clock_constraints()), [
197 (clk100_port_p
, 100e6
),
201 def test_add_clock(self
):
202 i2c
= self
.cm
.request("i2c")
203 self
.cm
.add_clock_constraint(i2c
.scl
, 100e3
)
204 scl_port
, sda_port
= self
.cm
.iter_ports()
205 self
.assertEqual(list(self
.cm
.iter_clock_constraints()), [
209 def test_get_clock(self
):
210 clk100
= self
.cm
.request("clk100", 0)
211 self
.assertEqual(self
.cm
.get_clock_constraint(clk100
), 100e6
)
212 with self
.assertRaises(KeyError):
213 self
.cm
.get_clock_constraint(Signal())
215 def test_wrong_resources(self
):
216 with self
.assertRaises(TypeError, msg
="Object 'wrong' is not a Resource"):
217 self
.cm
.add_resources(['wrong'])
219 def test_wrong_resources_duplicate(self
):
220 with self
.assertRaises(NameError,
221 msg
="Trying to add (resource user_led 0 (pins o A1)), but "
222 "(resource user_led 0 (pins o A0)) has the same name and number"):
223 self
.cm
.add_resources([Resource("user_led", 0, Pins("A1", dir="o"))])
225 def test_wrong_connectors(self
):
226 with self
.assertRaises(TypeError, msg
="Object 'wrong' is not a Connector"):
227 self
.cm
.add_connectors(['wrong'])
229 def test_wrong_connectors_duplicate(self
):
230 with self
.assertRaises(NameError,
231 msg
="Trying to add (connector pmod 0 1=>1 2=>2), but "
232 "(connector pmod 0 1=>B0 2=>B1 3=>B2 4=>B3) has the same name and number"):
233 self
.cm
.add_connectors([Connector("pmod", 0, "1 2")])
235 def test_wrong_lookup(self
):
236 with self
.assertRaises(ResourceError
,
237 msg
="Resource user_led#1 does not exist"):
238 r
= self
.cm
.lookup("user_led", 1)
240 def test_wrong_clock_signal(self
):
241 with self
.assertRaises(TypeError,
242 msg
="Object None is not a Signal or Pin"):
243 self
.cm
.add_clock_constraint(None, 10e6
)
245 def test_wrong_clock_frequency(self
):
246 with self
.assertRaises(TypeError,
247 msg
="Frequency must be a number, not None"):
248 self
.cm
.add_clock_constraint(Signal(), None)
250 def test_wrong_clock_pin(self
):
251 with self
.assertRaises(ValueError,
252 msg
="The Pin object (rec <unnamed> i), which is not a previously requested "
253 "resource, cannot be used to desigate a clock"):
254 self
.cm
.add_clock_constraint(Pin(1, dir="i"), 1e6
)
256 def test_wrong_request_duplicate(self
):
257 with self
.assertRaises(ResourceError
,
258 msg
="Resource user_led#0 has already been requested"):
259 self
.cm
.request("user_led", 0)
260 self
.cm
.request("user_led", 0)
262 def test_wrong_request_duplicate_physical(self
):
263 self
.cm
.add_resources([
264 Resource("clk20", 0, Pins("H1", dir="i")),
266 self
.cm
.request("clk100", 0)
267 with self
.assertRaises(ResourceError
,
268 msg
="Resource component clk20_0 uses physical pin H1, but it is already "
269 "used by resource component clk100_0 that was requested earlier"):
270 self
.cm
.request("clk20", 0)
272 def test_wrong_request_with_dir(self
):
273 with self
.assertRaises(TypeError,
274 msg
="Direction must be one of \"i\", \"o\", \"oe\", \"io\", or \"-\", "
276 user_led
= self
.cm
.request("user_led", 0, dir="wrong")
278 def test_wrong_request_with_dir_io(self
):
279 with self
.assertRaises(ValueError,
280 msg
="Direction of (pins o A0) cannot be changed from \"o\" to \"i\"; direction "
281 "can be changed from \"io\" to \"i\", \"o\", or \"oe\", or from anything "
283 user_led
= self
.cm
.request("user_led", 0, dir="i")
285 def test_wrong_request_with_dir_dict(self
):
286 with self
.assertRaises(TypeError,
287 msg
="Directions must be a dict, not 'i', because (resource i2c 0 (subsignal scl "
288 "(pins o N10)) (subsignal sda (pins io N11))) "
290 i2c
= self
.cm
.request("i2c", 0, dir="i")
292 def test_wrong_request_with_wrong_xdr(self
):
293 with self
.assertRaises(ValueError,
294 msg
="Data rate of (pins o A0) must be a non-negative integer, not -1"):
295 user_led
= self
.cm
.request("user_led", 0, xdr
=-1)
297 def test_wrong_request_with_xdr_dict(self
):
298 with self
.assertRaises(TypeError,
299 msg
="Data rate must be a dict, not 2, because (resource i2c 0 (subsignal scl "
300 "(pins o N10)) (subsignal sda (pins io N11))) "
302 i2c
= self
.cm
.request("i2c", 0, xdr
=2)
304 def test_wrong_clock_constraint_twice(self
):
305 clk100
= self
.cm
.request("clk100")
306 with self
.assertRaises(ValueError,
307 msg
="Cannot add clock constraint on (sig clk100_0__p), which is already "
308 "constrained to 100000000.0 Hz"):
309 self
.cm
.add_clock_constraint(clk100
, 1e6
)