#!/usr/bin/env python2.7 """This file contains a mapping generator for the tsar_generic_iob platform""" from math import log from mapping import Mapping ################################################################################ # file : arch.py (for the tsar_generic_iob architecture) # date : may 2014 # author : Alain Greiner # # modified by: # Cesar Fuguet # - Adding distributed ROMs used by the distributed reconfiguration # procedure # ################################################################################ # This platform includes 6 external peripherals, accessible through two # IO_Bridge components located in cluster [0,0] and cluster [x_size-1, # y_size-1]. Available peripherals are: TTY, BDV, FBF, ROM, NIC, CMA. # # The "constructor" parameters are: # - x_size : number of clusters in a row # - y_size : number of clusters in a column # - nb_procs : number of processors per cluster # - nb_ttys : number of TTY channels # - fbf_width : frame_buffer width = frame_buffer heigth # # The "hidden" parameters (defined below) are: # - NB_NICS : number of NIC channels # - X_IO : cluster_io x coordinate # - Y_IO : cluster_io y coordinate # - X_WIDTH : number of bits for x coordinate # - Y_WIDTH : number of bits for y coordinate # - P_WIDTH : number of bits for processor local id field # - PADDR_WIDTH : number of bits for physical address # - IRQ_PER_PROC : number of input IRQs per processor # - USE_RAMDISK : use a ramdisk when True # - PERI_INCREMENT : virtual address increment for replicated peripherals # - PTAB_INCREMENT : virtual address increment for replicated page tables # - SCHED_INCREMENT: virtual address increment for replicated schedulers ################################################################################ # define architecture constants PADDR_WIDTH = 40 NB_NICS = 2 FBF_WIDTH = 128 X_WIDTH = 4 Y_WIDTH = 4 P_WIDTH = 2 X_IO = 0 Y_IO = 0 IRQ_PER_PROC = 4 USE_RAMDISK = False USE_NIC = False # virtual address increment for distributed memory segments in the GietVM OS PERI_INCREMENT = 0x10000 PTAB_INCREMENT = 0x200000 SCHED_INCREMENT = 0x10000 def pmsb(x, y): """This function returns the physical most signicant bits for the cluster(x,y)""" return (x << Y_WIDTH) | y def arch(x_size=2, y_size=2, nb_procs=4, nb_ttys=1, fbf_width=FBF_WIDTH, ioc_type='BDV'): """This function describes the tsar_generic_iob platform and defines its parameters""" # parameters checking assert (nb_procs <= (1 << P_WIDTH)) assert ((x_size >= 1) and (x_size <= (1 << X_WIDTH))) assert ((y_size >= 1) and (y_size <= (1 << Y_WIDTH))) assert ((nb_ttys >= 1) and (nb_ttys <= 16)) assert (((X_IO == 0) and (Y_IO == 0)) or ((X_IO == (x_size - 1)) and (Y_IO == (y_size - 1)))) platform_name = 'reconf-tsar_iob_%d_%d_%d' % (x_size, y_size, nb_procs) # define physical segments ram_base = 0x0000000000 ram_size = 0x4000000 / (x_size * y_size) xcu_base = 0x00B0000000 xcu_size = 0x1000 # 4 Kbytes dma_base = 0x00B1000000 dma_size = 0x1000 * nb_procs # 4 Kbytes * nb_procs mmc_base = 0x00B2000000 mmc_size = 0x1000 # 4 Kbytes drom_base = 0x00BFC00000 drom_size = 0x8000 # 32 Kbytes offset_io = pmsb(X_IO, Y_IO) << (PADDR_WIDTH - X_WIDTH - Y_WIDTH) bdv_base = 0x00B3000000 + offset_io bdv_size = 0x1000 # 4 kbytes tty_base = 0x00B4000000 + offset_io tty_size = 0x1000 # 4 Kbytes nic_base = 0x00B5000000 + offset_io nic_size = 0x80000 # 512 kbytes cma_base = 0x00B6000000 + offset_io cma_size = 0x1000 * 2 * NB_NICS # 4 kbytes * 2 * NB_NICS fbf_base = 0x00B7000000 + offset_io fbf_size = fbf_width * fbf_width # fbf_width * fbf_width bytes pic_base = 0x00B8000000 + offset_io pic_size = 0x1000 # 4 Kbytes sim_base = 0x00B9000000 + offset_io sim_size = 0x1000 # 4 kbytes iob_base = 0x00BE000000 + offset_io iob_size = 0x1000 # 4 kbytes rom_base = 0x00BA000000 rom_size = 0x8000 # 32 Kbytes # create mapping mapping = Mapping(name=platform_name, x_size=x_size, y_size=y_size, nprocs=nb_procs, x_width=X_WIDTH, y_width=Y_WIDTH, p_width=P_WIDTH, paddr_width=PADDR_WIDTH, coherence=True, irq_per_proc=IRQ_PER_PROC, use_ramdisk=USE_RAMDISK, x_io=X_IO, y_io=Y_IO, peri_increment=PERI_INCREMENT, ram_base=ram_base, ram_size=ram_size) # external peripherals (accessible in cluster[0,0] only for this mapping) pic = mapping.addPeriph('PIC', base=pic_base, size=pic_size, ptype='PIC', channels=32) mapping.addPeriph('IOB', base=iob_base, size=iob_size, ptype='IOB') bdv = mapping.addPeriph('BDV', base=bdv_base, size=bdv_size, ptype='IOC', subtype='BDV') mapping.addIrq(pic, index=8, src=bdv, isrtype='ISR_BDV', channel=0) tty = mapping.addPeriph('TTY', base=tty_base, size=tty_size, ptype='TTY', channels=nb_ttys) for i in xrange(nb_ttys): mapping.addIrq(pic, index=16+i, src=tty, isrtype='ISR_TTY_RX', channel=i) if USE_NIC: nic = mapping.addPeriph('NIC', base=nic_base, size=nic_size, ptype='NIC', channels=NB_NICS) mapping.addIrq(pic, index=0, src=nic, isrtype='ISR_NIC_RX', channel=0) mapping.addIrq(pic, index=1, src=nic, isrtype='ISR_NIC_RX', channel=1) mapping.addIrq(pic, index=2, src=nic, isrtype='ISR_NIC_TX', channel=0) mapping.addIrq(pic, index=3, src=nic, isrtype='ISR_NIC_TX', channel=1) cma = mapping.addPeriph('CMA', base=cma_base, size=cma_size, ptype='CMA', channels=2*NB_NICS) mapping.addIrq(pic, index=4, src=cma, isrtype='ISR_CMA', channel=0) mapping.addIrq(pic, index=5, src=cma, isrtype='ISR_CMA', channel=1) mapping.addIrq(pic, index=6, src=cma, isrtype='ISR_CMA', channel=2) mapping.addIrq(pic, index=7, src=cma, isrtype='ISR_CMA', channel=3) mapping.addPeriph('FBF', base=fbf_base, size=fbf_size, ptype='FBF', arg0=fbf_width, arg1=fbf_width) mapping.addPeriph('SIM', base=sim_base, size=sim_size, ptype='SIM') mapping.addPeriph('ROM', base=rom_base, size=rom_size, ptype='ROM') # hardware components replicated in all clusters for x in xrange(x_size): for y in xrange(y_size): offset = pmsb(x, y) << (PADDR_WIDTH - X_WIDTH - Y_WIDTH) mapping.addRam('RAM', base=ram_base + offset, size=ram_size) mapping.addPeriph('DROM', base=drom_base + offset, size=drom_size, ptype='DROM') mmc = mapping.addPeriph('MMC', base=mmc_base + offset, size=mmc_size, ptype='MMC') dma = mapping.addPeriph('DMA', base=dma_base + offset, size=dma_size, ptype='DMA', channels=nb_procs) xcu = mapping.addPeriph('XCU', base=xcu_base + offset, size=xcu_size, ptype='XCU', channels=nb_procs * IRQ_PER_PROC, arg0=16, arg1=16, arg2=16) # MMC IRQ replicated in all clusters mapping.addIrq(xcu, index=0, src=mmc, isrtype='ISR_MMC') # DMA IRQ replicated in all clusters for i in xrange(dma.channels): mapping.addIrq(xcu, index=1+i, src=dma, isrtype='ISR_DMA', channel=i) # processors for p in xrange(nb_procs): mapping.addProc(x, y, p) ############################################################################ # GIET_VM specifics # define bootloader vsegs base addresses bmapping_vbase = 0x00001000 # ident bmapping_size = 0x0007F000 # 508 Kbytes bcode_vbase = 0x00080000 # ident bcode_size = 0x00040000 # 256 Kbytes bdata_vbase = 0x000C0000 # ident bdata_size = 0x00080000 # 512 Kbytes bstack_vbase = 0x00140000 # ident bstack_size = 0x00050000 # 320 Kbytes # define kernel vsegs base addresses and sizes kcode_vbase = 0x80000000 kcode_size = 0x00080000 # 512 Kbytes kdata_vbase = 0x80100000 kdata_size = 0x00080000 # 512 Kbytes kinit_vbase = 0x80800000 kinit_size = 0x00080000 # 512 Kbytes kuncdata_vbase = 0x80180000 kuncdata_size = 0x00001000 # 4 Kbytes kptab_vbase = 0xC0000000 kptab_size = 0x00200000 # 512 Kbytes ksched_vbase = 0xF0000000 # distributed in all clusters ksched_size = 0x2000 * nb_procs # 8 kbytes per processor # global vsegs for boot_loader / identity mapping mapping.addGlobal('seg_boot_mapping', bmapping_vbase, bmapping_size, 'CXW_', vtype='BLOB', x=0, y=0, pseg='RAM', identity=True, local=False, big=True) mapping.addGlobal('seg_boot_code', bcode_vbase, bcode_size, 'CXW_', vtype='BUFFER', x=0, y=0, pseg='RAM', identity=True, local=False, big=True) mapping.addGlobal('seg_boot_data', bdata_vbase, bdata_size, 'CXW_', vtype='BUFFER', x=0, y=0, pseg='RAM', identity=True, local=False, big=True) mapping.addGlobal('seg_boot_stack', bstack_vbase, bstack_size, 'CXW_', vtype='BUFFER', x=0, y=0, pseg='RAM', identity=True, local=False, big=True) # the code global vsegs for kernel can be replicated in all clusters # if the page tables are distributed in all clusters. for x in xrange(x_size): for y in xrange(y_size): mapping.addGlobal('seg_kernel_code', kcode_vbase, kcode_size, 'CXW_', vtype='ELF', x=x, y=y, pseg='RAM', binpath='bin/kernel/kernel.elf', local=True, big=True) mapping.addGlobal('seg_kernel_init', kinit_vbase, kinit_size, 'CXW_', vtype='ELF', x=x, y=y, pseg='RAM', binpath='bin/kernel/kernel.elf', local=True, big=True) offset = pmsb(x, y) * PTAB_INCREMENT mapping.addGlobal('seg_kernel_ptab_%d_%d' % (x, y), kptab_vbase + offset, kptab_size, 'C_W_', vtype='PTAB', x=x, y=y, pseg='RAM', local=False, big=True) offset = pmsb(x, y) * SCHED_INCREMENT mapping.addGlobal('seg_kernel_sched_%d_%d' % (x, y), ksched_vbase + offset, ksched_size, 'C_W_', vtype='SCHED', x=x, y=y, pseg='RAM', local=False, big=False) # shared global vsegs for kernel mapping.addGlobal('seg_kernel_data', kdata_vbase, kdata_size, 'CXW_', vtype='ELF', x=0, y=0, pseg='RAM', binpath='bin/kernel/kernel.elf', local=False, big=True) mapping.addGlobal('seg_kernel_uncdata', kuncdata_vbase, kuncdata_size, 'CXW_', vtype='ELF', x=0, y=0, pseg='RAM', binpath='bin/kernel/kernel.elf', local=False, big=True) # global vsegs for external peripherals / identity mapping mapping.addGlobal('seg_iob', iob_base, iob_size, '__W_', vtype='PERI', x=X_IO, y=Y_IO, pseg='IOB', local=False, big=False) mapping.addGlobal('seg_bdv', bdv_base, bdv_size, '__W_', vtype='PERI', x=X_IO, y=Y_IO, pseg='BDV', local=False, big=False) mapping.addGlobal('seg_tty', tty_base, tty_size, '__W_', vtype='PERI', x=X_IO, y=Y_IO, pseg='TTY', local=False, big=False) mapping.addGlobal('seg_nic', nic_base, nic_size, '__W_', vtype='PERI', x=X_IO, y=Y_IO, pseg='NIC', local=False, big=False) mapping.addGlobal('seg_cma', cma_base, cma_size, '__W_', vtype='PERI', x=X_IO, y=Y_IO, pseg='CMA', local=False, big=False) mapping.addGlobal('seg_fbf', fbf_base, fbf_size, '__W_', vtype='PERI', x=X_IO, y=Y_IO, pseg='FBF', local=False, big=True) mapping.addGlobal('seg_pic', pic_base, pic_size, '__W_', vtype='PERI', x=X_IO, y=Y_IO, pseg='PIC', local=False, big=False) mapping.addGlobal('seg_sim', sim_base, sim_size, '__W_', vtype='PERI', x=X_IO, y=Y_IO, pseg='SIM', local=False, big=False) # for the Giet-VM is not necessary to map the replicated ROMs mapping.addGlobal('seg_rom', drom_base, drom_size, 'CX__', vtype='PERI', x=X_IO, y=Y_IO, pseg='ROM', local=False, big=True) # global vsegs for internal peripherals for x in xrange(x_size): for y in xrange(y_size): offset = pmsb(x, y) * PERI_INCREMENT mapping.addGlobal('seg_xcu_%d_%d' % (x, y), xcu_base + offset, xcu_size, '__W_', vtype='PERI', x=x, y=y, pseg='XCU', local=False, big=False) mapping.addGlobal('seg_dma_%d_%d' % (x, y), dma_base + offset, dma_size, '__W_', vtype='PERI', x=x, y=y, pseg='DMA', local=False, big=False) mapping.addGlobal('seg_mmc_%d_%d' % (x, y), mmc_base + offset, mmc_size, '__W_', vtype='PERI', x=x, y=y, pseg='MMC', local=False, big=False) return mapping def main(x, y, p, hard_path, xml_path, dts_path): """main function: it generates the map.xml and the hard_config.h file based on the Mapping object returned by arch()""" mapping = arch(x_size=x, y_size=y, nb_procs=p) with open(xml_path, "w") as map_xml: map_xml.write(mapping.xml()) with open(hard_path, "w") as hard_config: hard_config.write(mapping.hard_config()) if dts_path != None: with open(dts_path, "w") as linux_dts: linux_dts.write(mapping.linux_dts()) ################################# platform test ################################ import sys if __name__ == '__main__': main(x=int(sys.argv[1]), y=int(sys.argv[2]), p=int(sys.argv[3]), hard_path="hard_config.test.h", xml_path="map.test.xml", dts_path="linux.dts") # Local Variables: # tab-width: 4; # c-basic-offset: 4; # c-file-offsets:((innamespace . 0)(inline-open . 0)); # indent-tabs-mode: nil; # End: # # vim: filetype=python:expandtab:shiftwidth=4:tabstop=4:softtabstop=4