1- using Revise
2- using Graphs
3- using FileIO
4- import DeviceLayout. Paths: RouteChannel, ChannelRouter, assign_channels!, assign_tracks!, visualize_router_state
1+ import DeviceLayout. Paths: RouteChannel
52
6- # @testset "Channels" begin
7- # ## Unit tests
8-
9- # ## Integration tests
3+ function test_single_channel_reversals (r, seg, sty)
4+ paths = test_single_channel (r, seg, sty;
5+ reverse_channel= false , reverse_paths= false )
6+ paths_revch = test_single_channel (r, seg, sty;
7+ reverse_channel= true , reverse_paths= false )
8+ paths_revp = test_single_channel (r, seg, sty;
9+ reverse_channel= false , reverse_paths= true )
10+ paths_rev_ch_p = test_single_channel (r, seg, sty;
11+ reverse_channel= true , reverse_paths= true )
12+ # Segments are approximately the same when channel is reversed
13+ for (pa1, pa2) in zip (paths, paths_revch)
14+ for (n1, n2) in zip (pa1, pa2)
15+ @test p0 (n1. seg) ≈ p0 (n2. seg) atol= 1 nm
16+ @test p1 (n1. seg) ≈ p1 (n2. seg) atol= 1 nm
17+ @test isapprox_angle (α0 (n1. seg), α0 (n2. seg), atol= 1e-6 )
18+ @test isapprox_angle (α1 (n1. seg), α1 (n2. seg), atol= 1e-6 )
19+ @test pathlength (n1. seg) ≈ pathlength (n2. seg) atol= 1 nm
20+ end
21+ end
22+ for (pa1, pa2) in zip (paths_revp, paths_rev_ch_p)
23+ for (n1, n2) in zip (pa1, pa2)
24+ @test p0 (n1. seg) ≈ p0 (n2. seg) atol= 1 nm
25+ @test p1 (n1. seg) ≈ p1 (n2. seg) atol= 1 nm
26+ @test isapprox_angle (α0 (n1. seg), α0 (n2. seg), atol= 1e-6 )
27+ @test isapprox_angle (α1 (n1. seg), α1 (n2. seg), atol= 1e-6 )
28+ @test pathlength (n1. seg) ≈ pathlength (n2. seg) atol= 1 nm
29+ end
30+ end
31+ # Segments are approximately reversed when paths are reversed
32+ for (pa1, pa2) in zip (paths, paths_revp)
33+ for (n1, n2) in zip (pa1, reverse (pa2. nodes))
34+ @test p0 (n1. seg) ≈ p1 (n2. seg) atol= 1 nm
35+ @test p1 (n1. seg) ≈ p0 (n2. seg) atol= 1 nm
36+ @test isapprox_angle (α0 (n1. seg), α1 (n2. seg) + 180 °, atol= 1e-6 )
37+ @test isapprox_angle (α1 (n1. seg), α0 (n2. seg) + 180 °, atol= 1e-6 )
38+ @test pathlength (n1. seg) ≈ pathlength (n2. seg) atol= 1 nm
39+ # Some reversed paths are visibly different with taper trace and auto_speed (1um length difference)
40+ # because the asymmetry causes speed optimization to find a different optimum
41+ # depending on which is t0 and which is t1. So we use manual speed
42+ # (also because it runs faster and we don't need to test auto further)
43+ end
44+ end
45+ return paths
46+ end
1047
11- # end
12- function test_single (transition_rule, channel_segment, channel_style; reverse_channel= false , reverse_paths= false )
48+ function test_single_channel (transition_rule, channel_segment, channel_style;
49+ reverse_channel= false , reverse_paths= false )
1350 channel = Path (0.0 μm, 0.0 μm)
1451 if channel_segment == Paths. Straight
1552 straight! (channel, 1 mm, channel_style)
@@ -54,29 +91,45 @@ function test_single(transition_rule, channel_segment, channel_style; reverse_ch
5491
5592 paths = [Path (p, α0= α0) for (p, α0) in zip (p0s, α0s)]
5693 tracks = reverse_channel ? reverse (eachindex (paths)) : eachindex (paths)
94+ styles = [Paths. Trace (2 μm); fill (Paths. CPW (2 μm, 2 μm), length (paths))]
5795
5896 rule = Paths. SingleChannelRouting (Paths. RouteChannel (channel), transition_rule, 50.0 μm)
5997 setindex! .(Ref (rule. segment_tracks), tracks, paths)
60- for (track, pa, p1, α1) in zip (tracks, paths, p1s, α1s)
98+ for (pa, p1, α1, sty ) in zip (paths, p1s, α1s, styles )
6199 route! (pa, p1, α1, rule, Paths. CPW (2 μm, 2 μm))
62100 end
63-
64- c = Cell (" test" , nm);
65- render! .(c, paths, GDSMeta (), atol= 1 μm);
66- render! (c, channel, GDSMeta (2 ));
67- save (" test.gds" , c)
101+ return paths
68102end
69- transition_rules = [
70- Paths. BSplineRouting (auto_speed= true , auto_curvature= true )
71- Paths. StraightAnd90 (min_bend_radius= 25 μm) # Can only be used with straight and trace if any paths enter from the sides, no curves or tapers
72- ]
73- channel_segments = [
74- Paths. Straight,
75- Paths. Turn,
76- Paths. BSpline,
77- Paths. CompoundSegment
78- ]
79- channel_styles = [
80- Paths. Trace (100 μm),
81- Paths. TaperTrace (100 μm, 50 μm)
82- ]
103+
104+ @testset " Channels" begin
105+ # ## Single-channel integration tests
106+ # # Geometry-level routing
107+ # StraightAnd90 only works with straight channel
108+ transition_rules = [
109+ Paths. StraightAnd90 (min_bend_radius= 25 μm) # Can only be used with straight and trace if any paths enter from the sides, no curves or tapers
110+ Paths. BSplineRouting (endpoints_speed= 150 μm, auto_curvature= true )
111+ ]
112+ channel_segments = [
113+ Paths. Straight,
114+ Paths. Turn,
115+ Paths. BSpline,
116+ Paths. CompoundSegment
117+ ]
118+ channel_styles = [
119+ Paths. Trace (100 μm),
120+ Paths. TaperTrace (100 μm, 50 μm)
121+ ]
122+ @testset " Straight" begin
123+ rule = transition_rules[1 ]
124+ paths = test_single_channel_reversals (rule, channel_segments[1 ], channel_styles[1 ])
125+ @test isempty (Intersect. intersections (paths... ))
126+ end
127+ rule = transition_rules[2 ] # BSpline rule for all-angle transitions
128+ for segtype in channel_segments[2 : end ]
129+ @testset " $segtype channel" begin
130+ for sty in channel_styles
131+ test_single_channel_reversals (rule, segtype, sty)
132+ end
133+ end
134+ end
135+ end
0 commit comments