| 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 | + 0x01200000 |
|---|
| 33 | + 0x01000000 * i |
|---|
| 34 | ) |
|---|
| 35 | self.cpu.append(c) |
|---|
| 36 | |
|---|
| 37 | memc, xram = self.create_memcache( segments = [ |
|---|
| 38 | ('reset', 0xbfc00000, 0x00010000), |
|---|
| 39 | ('excep', 0x80000000, 0x00010000), |
|---|
| 40 | ('text', 0x00400000, 0x00050000), |
|---|
| 41 | ('data', 0x10000000, 0x00100000), |
|---|
| 42 | ] ) |
|---|
| 43 | tty = self.create_tty( addr = 0xc0200000, tty_count = 1 ) |
|---|
| 44 | xicu = self.create_xicu( addr = 0xd2200000, pti_count = 1, |
|---|
| 45 | hwi_count = 3, |
|---|
| 46 | wti_count = 4, |
|---|
| 47 | irq_count = 4) |
|---|
| 48 | dma = self.create_dma( addr = 0xd1200000, burst_size = 64) |
|---|
| 49 | fb = self.create_fb( addr = 0xe2200000, width = 320, |
|---|
| 50 | height = 200, |
|---|
| 51 | subsampling = 422) |
|---|
| 52 | |
|---|
| 53 | tty.irq[0] // xicu.hwi[0] |
|---|
| 54 | for i in range(proc_count): |
|---|
| 55 | self.cpu[i].irq[0] // xicu.irq[i] |
|---|
| 56 | dma.irq // xicu.hwi[1] |
|---|
| 57 | |
|---|
| 58 | |
|---|
| 59 | def create_dma(self, addr, burst_size): |
|---|
| 60 | name = 'dma%d'%self.cluster_no |
|---|
| 61 | dma = self.pf.create('caba:vci_dma_vhdl', name, burst_size = burst_size) |
|---|
| 62 | self.ringp.to_target.new() // dma.vci_target |
|---|
| 63 | self.ringp.to_initiator.new() // dma.vci_initiator |
|---|
| 64 | dma.addSegment(name, address = addr, size = 0x1000, cacheable = False) |
|---|
| 65 | return dma |
|---|
| 66 | |
|---|
| 67 | def create_fb(self, addr, width, height, subsampling): |
|---|
| 68 | name = 'fb%d'%self.cluster_no |
|---|
| 69 | fb = self.pf.create('caba:vci_framebuffer', name, width = width, |
|---|
| 70 | height = height, |
|---|
| 71 | subsampling = subsampling) |
|---|
| 72 | self.ringp.to_target.new() // fb.vci |
|---|
| 73 | fb.addSegment(name, address = addr, size = width * height * 2, cacheable = False) |
|---|
| 74 | return fb |
|---|
| 75 | |
|---|
| 76 | def create_tty(self, addr, tty_count = 1): |
|---|
| 77 | names = map(lambda x:'tty%d'%x, range(tty_count)) |
|---|
| 78 | name = 'tty%d'%self.cluster_no |
|---|
| 79 | tty = self.pf.create('caba:vci_multi_tty', name, names = names) |
|---|
| 80 | self.ringp.to_target.new() // tty.vci |
|---|
| 81 | tty.addSegment(name, address = addr, size = 0x1000, cacheable = False) |
|---|
| 82 | return tty |
|---|
| 83 | |
|---|
| 84 | def create_xicu(self, addr, pti_count, hwi_count, wti_count, irq_count): |
|---|
| 85 | name = 'xicu' |
|---|
| 86 | xicu = self.pf.create('caba:vci_xicu', name, pti_count = pti_count, |
|---|
| 87 | hwi_count = hwi_count, |
|---|
| 88 | wti_count = wti_count, |
|---|
| 89 | irq_count = irq_count) |
|---|
| 90 | self.ringp.to_target.new() // xicu.vci |
|---|
| 91 | xicu.addSegment(name, address = addr, size = 0x1000, cacheable = False) |
|---|
| 92 | return xicu |
|---|
| 93 | |
|---|
| 94 | |
|---|
| 95 | class ClusterV3(Cluster): |
|---|
| 96 | ''' |
|---|
| 97 | A TsarV3 implementation, using vci_cc_vcache_wrapper2_v1, |
|---|
| 98 | vci_mem_cache_v3 and vci_dma_tsar_v2. |
|---|
| 99 | ''' |
|---|
| 100 | |
|---|
| 101 | def create_cpu(self, cpuid, addr): |
|---|
| 102 | c = self.pf.create( |
|---|
| 103 | 'caba:vci_cc_xcache_wrapper_v1', |
|---|
| 104 | 'proc_%d_%d' % (self.cluster_no, cpuid), |
|---|
| 105 | iss_t = "common:mips32el", |
|---|
| 106 | proc_id = cpuid, |
|---|
| 107 | icache_ways = 4, |
|---|
| 108 | icache_sets = 64, |
|---|
| 109 | icache_words = 16, |
|---|
| 110 | dcache_ways = 4, |
|---|
| 111 | dcache_sets = 64, |
|---|
| 112 | dcache_words = 16, |
|---|
| 113 | write_buf_size = 16, |
|---|
| 114 | ) |
|---|
| 115 | self.ringc.to_initiator.new() // c.vci_ini_c |
|---|
| 116 | self.ringc.to_target.new() // c.vci_tgt |
|---|
| 117 | self.ringp.to_initiator.new() // c.vci_ini_rw |
|---|
| 118 | |
|---|
| 119 | c.addSegment('proc_%d_%d' % (self.cluster_no, cpuid), |
|---|
| 120 | address = addr, |
|---|
| 121 | size = 0x10, |
|---|
| 122 | cacheable = False, |
|---|
| 123 | ) |
|---|
| 124 | |
|---|
| 125 | return c |
|---|
| 126 | |
|---|
| 127 | def create_memcache(self, segments): |
|---|
| 128 | memc = self.pf.create('caba:vci_mem_cache_v1', 'memc', |
|---|
| 129 | mtx = self.mtx, |
|---|
| 130 | vci_ixr_index = (self.cluster_no,), |
|---|
| 131 | nways = 16, |
|---|
| 132 | nsets = 256, |
|---|
| 133 | nwords = 16, |
|---|
| 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 name, 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_'+name, 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_'+name, address = addr, size = size, cacheable = True, mt = self.mtp) |
|---|
| 154 | memc.addSegment('ram_c_'+name, address = addr, size = size, cacheable = True, mt = self.mtc) |
|---|
| 155 | return memc, xram |
|---|