1 | |
---|
2 | __doc__ = ''' |
---|
3 | This file is a Cluster library. It contains classes implementing the |
---|
4 | netlist of a cluster, for different tsar versions. |
---|
5 | ''' |
---|
6 | |
---|
7 | class Cluster: |
---|
8 | ''' |
---|
9 | A generic netlist of a cluster, which must be subclassed to |
---|
10 | implement caches&dma instanciation |
---|
11 | ''' |
---|
12 | |
---|
13 | def __init__(self, pf, ringp, ringc, mtp, mtc, mtx, proc_count, cluster_no, cluster_base): |
---|
14 | self.pf = pf |
---|
15 | self.ringp = ringp |
---|
16 | self.ringc = ringc |
---|
17 | self.mtp = mtp |
---|
18 | self.mtc = mtc |
---|
19 | self.mtx = mtx |
---|
20 | self.cluster_no = cluster_no |
---|
21 | |
---|
22 | self.generate(proc_count, cluster_base) |
---|
23 | |
---|
24 | def generate(self, proc_count, cluster_base): |
---|
25 | ''' |
---|
26 | The core netlist, where caches and components are created |
---|
27 | ''' |
---|
28 | self.cpu = [] |
---|
29 | for i in range(proc_count): |
---|
30 | c = self.create_cpu(i, |
---|
31 | cluster_base |
---|
32 | + 0x10200000 |
---|
33 | + 0x01000000 * (i+1) |
---|
34 | ) |
---|
35 | self.cpu.append(c) |
---|
36 | |
---|
37 | memc, xram = self.create_memcache( segments = [(cluster_base, 0x02000000)] ) |
---|
38 | rom = self.create_rom( segments = [(0xbfc00000, 0x00400000)], memc = memc ) |
---|
39 | tty = self.create_tty( addr = 0xd0200000 ) |
---|
40 | dma = self.create_dma( addr = 0xd1200000 ) |
---|
41 | xicu = self.create_xicu( addr = 0xd2200000, hwi_count = 3, cpu_count = proc_count ) |
---|
42 | |
---|
43 | xicu.hwi[0] // tty.irq[0] |
---|
44 | xicu.hwi[1] // dma.irq |
---|
45 | |
---|
46 | for p, cpu in enumerate(self.cpu): |
---|
47 | for i in range(6): |
---|
48 | xicu.irq[i+p*6] // cpu.irq[i] |
---|
49 | |
---|
50 | def create_rom(self, segments, memc): |
---|
51 | name = 'rom%d'%self.cluster_no |
---|
52 | rom = self.pf.create('caba:vci_simple_ram', name, latency = 1) |
---|
53 | self.ringp.to_target.new() // rom.vci |
---|
54 | for addr, size in segments: |
---|
55 | rom.addSegment(name, address = addr, size = size, cacheable = True) |
---|
56 | return rom |
---|
57 | |
---|
58 | def create_tty(self, addr): |
---|
59 | name = 'tty%d'%self.cluster_no |
---|
60 | tty = self.pf.create('caba:vci_multi_tty', name, names = ['tty0']) |
---|
61 | self.ringp.to_target.new() // tty.vci |
---|
62 | tty.addSegment(name, address = addr, size = 0x10, cacheable = False) |
---|
63 | return tty |
---|
64 | |
---|
65 | def create_xicu(self, addr, hwi_count, cpu_count): |
---|
66 | name = 'xicu%d'%self.cluster_no |
---|
67 | xicu = self.pf.create('caba:vci_xicu', name, |
---|
68 | pti_count = cpu_count, |
---|
69 | hwi_count = hwi_count, |
---|
70 | wti_count = cpu_count, |
---|
71 | irq_count = 6*cpu_count, |
---|
72 | ) |
---|
73 | self.ringp.to_target.new() // xicu.vci |
---|
74 | xicu.addSegment(name, address = addr, size = 0x1000, cacheable = False) |
---|
75 | return xicu |
---|
76 | |
---|
77 | |
---|
78 | class ClusterV3(Cluster): |
---|
79 | ''' |
---|
80 | A TsarV3 implementation, using vci_cc_vcache_wrapper2_v1, |
---|
81 | vci_mem_cache_v3 and vci_dma_tsar_v2. |
---|
82 | ''' |
---|
83 | |
---|
84 | def create_rom(self, segments, memc): |
---|
85 | # Here is a hack needed for TsarV3: |
---|
86 | # |
---|
87 | # memcache must have segments corresponding to the rom in |
---|
88 | # order to handle cleanup messages emitted by the L1 caches on |
---|
89 | # the coherency network (else, they could be routed to wrong |
---|
90 | # places) |
---|
91 | name = 'rom%d'%self.cluster_no |
---|
92 | for addr, size in segments: |
---|
93 | memc.addSegment(name+'_c', address = addr, size = size, cacheable = True, mt = self.mtc) |
---|
94 | return Cluster.create_rom(self, segments, memc) |
---|
95 | |
---|
96 | def create_cpu(self, cpuid, addr): |
---|
97 | c = self.pf.create( |
---|
98 | 'caba:vci_cc_vcache_wrapper2_v1', |
---|
99 | 'proc_%d_%d' % (self.cluster_no, cpuid), |
---|
100 | iss_t = "common:mips32el", |
---|
101 | proc_id = cpuid, |
---|
102 | icache_ways = 4, |
---|
103 | icache_sets = 64, |
---|
104 | icache_words = 16, |
---|
105 | itlb_ways = 4, |
---|
106 | itlb_sets = 16, |
---|
107 | dcache_ways = 4, |
---|
108 | dcache_sets = 64, |
---|
109 | dcache_words = 16, |
---|
110 | dtlb_ways = 4, |
---|
111 | dtlb_sets = 16, |
---|
112 | write_buf_size = 16, |
---|
113 | ) |
---|
114 | self.ringc.to_initiator.new() // c.vci_ini_c |
---|
115 | self.ringc.to_target.new() // c.vci_tgt |
---|
116 | self.ringp.to_initiator.new() // c.vci_ini_rw |
---|
117 | |
---|
118 | c.addSegment('proc_%d_%d' % (self.cluster_no, cpuid), |
---|
119 | address = addr, |
---|
120 | size = 0x10, |
---|
121 | cacheable = False, |
---|
122 | ) |
---|
123 | |
---|
124 | return c |
---|
125 | |
---|
126 | def create_memcache(self, segments): |
---|
127 | memc = self.pf.create('caba:vci_mem_cache_v3', 'memc', |
---|
128 | mtx = self.mtx, |
---|
129 | vci_ixr_index = (self.cluster_no,), |
---|
130 | nways = 16, |
---|
131 | nsets = 256, |
---|
132 | nwords = 16, |
---|
133 | heap_size = 1024 |
---|
134 | ) |
---|
135 | self.ringc.to_target.new() // memc.vci_tgt_cleanup |
---|
136 | self.ringp.to_target.new() // memc.vci_tgt |
---|
137 | self.ringc.to_initiator.new() // memc.vci_ini |
---|
138 | |
---|
139 | xram = self.pf.create('caba:vci_simple_ram', 'xram', |
---|
140 | mt = self.mtx, |
---|
141 | ident = (self.cluster_no,), |
---|
142 | latency = 1, |
---|
143 | ) |
---|
144 | memc.vci_ixr // xram.vci |
---|
145 | |
---|
146 | for addr, size in segments: |
---|
147 | # Here DSX knows the only way to address xram is through its |
---|
148 | # vci port. It also knows the only associated mapping_table. |
---|
149 | xram.addSegment('ram_x', address = addr, size = size, cacheable = True) |
---|
150 | |
---|
151 | # For these segments, there is ambiguity for the mapping_table |
---|
152 | # we are talking about, so we specify mt = ... |
---|
153 | memc.addSegment('ram_p', address = addr, size = size, cacheable = True, mt = self.mtp) |
---|
154 | memc.addSegment('ram_c', address = addr, size = size, cacheable = True, mt = self.mtc) |
---|
155 | return memc, xram |
---|
156 | |
---|
157 | def create_dma(self, addr): |
---|
158 | name = 'dma%d'%self.cluster_no |
---|
159 | dma = self.pf.create('caba:vci_dma_tsar_v2', name, burst_size = 64) |
---|
160 | self.ringp.to_target.new() // dma.vci_target |
---|
161 | self.ringp.to_initiator.new() // dma.vci_initiator |
---|
162 | dma.addSegment(name, address = addr, size = 0x14, cacheable = False) |
---|
163 | return dma |
---|