mirror of
https://github.com/saymrwulf/pulp-runtime.git
synced 2026-05-14 20:48:09 +00:00
Add support for running from flash
* Add possibility to supply additional vsim flags with run target * Now the user can supply the bootmode=<spi|flash|fast_debug|jtag> variable with the run target to choose the desired boot mode.
This commit is contained in:
parent
3903c87478
commit
277d7ac330
4 changed files with 624 additions and 4 deletions
469
bin/plp_flash_stimuli.py
Executable file
469
bin/plp_flash_stimuli.py
Executable file
|
|
@ -0,0 +1,469 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright (C) 2015 ETH Zurich and University of Bologna
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# This software may be modified and distributed under the terms
|
||||||
|
# of the BSD license. See the LICENSE file for details.
|
||||||
|
#
|
||||||
|
# Authors: Germain Haugou (germain.haugou@gmail.com)
|
||||||
|
#
|
||||||
|
|
||||||
|
#file extracted from pulp sdk : https://github.com/pulp-platform/pulp-sdk.git
|
||||||
|
#to be used in marsellus project
|
||||||
|
|
||||||
|
import os
|
||||||
|
import struct
|
||||||
|
from elftools.elf.elffile import ELFFile
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def dumpByteToSlm(file, addr, value):
|
||||||
|
file.write("@%08X %02X\n" % (addr, value))
|
||||||
|
|
||||||
|
def dumpShortToSlm(file, addr, value):
|
||||||
|
file.write("@%08X %04X\n" % (addr, value))
|
||||||
|
|
||||||
|
def dumpWordToSlm(file, addr, value):
|
||||||
|
file.write("@%08X %08X\n" % (addr, value))
|
||||||
|
|
||||||
|
def dumpLongToSlm(file, addr, value):
|
||||||
|
file.write("@%08X %016X\n" % (addr, value))
|
||||||
|
|
||||||
|
def dump_word( filetoprint, addr, data_s):
|
||||||
|
for i in xrange(0,4,1):
|
||||||
|
filetoprint.write("@%08X %s\n" % ( addr+i, data_s[i*2:(i+1)*2] ))
|
||||||
|
return 4
|
||||||
|
|
||||||
|
class Comp(object):
|
||||||
|
|
||||||
|
def __init__(self, dirpath, name):
|
||||||
|
self.path = os.path.join(dirpath, name)
|
||||||
|
self.name = name
|
||||||
|
self.size = os.path.getsize(self.path)
|
||||||
|
|
||||||
|
def dump(self):
|
||||||
|
print (self.name)
|
||||||
|
print ('Path: ' + self.path)
|
||||||
|
print ('Flash addr: ' + str(self.flashAddr))
|
||||||
|
print ('Size: ' + str(self.size))
|
||||||
|
print ('')
|
||||||
|
|
||||||
|
class BinarySegment(object):
|
||||||
|
|
||||||
|
def __init__(self, base, data):
|
||||||
|
self.base = base
|
||||||
|
self.data = data
|
||||||
|
self.size = len(data)
|
||||||
|
|
||||||
|
class Binary(object):
|
||||||
|
|
||||||
|
def __init__(self, elf=None):
|
||||||
|
self.segments = []
|
||||||
|
|
||||||
|
if elf != None:
|
||||||
|
|
||||||
|
with open(elf, 'rb') as file:
|
||||||
|
elffile = ELFFile(file)
|
||||||
|
|
||||||
|
self.entry = elffile['e_entry']
|
||||||
|
|
||||||
|
for segment in elffile.iter_segments():
|
||||||
|
if segment['p_type'] == 'PT_LOAD':
|
||||||
|
self.segments.append(BinarySegment(segment['p_paddr'], segment.data()))
|
||||||
|
|
||||||
|
|
||||||
|
class FlashImage(object):
|
||||||
|
|
||||||
|
def __init__(self, raw=None, stimuli=None, verbose=True, archi=None, encrypt=False, aesKey=None, aesIv=None, flashType='spi', qpi=True):
|
||||||
|
|
||||||
|
self.bootBinary = None
|
||||||
|
self.raw = raw
|
||||||
|
self.stimuli = stimuli
|
||||||
|
self.compList = []
|
||||||
|
self.buff = []
|
||||||
|
self.flashOffset = 0
|
||||||
|
if flashType == 'hyper': self.blockSize = 1024
|
||||||
|
else: self.blockSize = 4096
|
||||||
|
self.bootaddr = 0x1c000000
|
||||||
|
self.verbose = verbose
|
||||||
|
self.archi = archi
|
||||||
|
self.encrypt = encrypt
|
||||||
|
self.aesKey = aesKey
|
||||||
|
self.aesIv = aesIv
|
||||||
|
self.flashType = flashType
|
||||||
|
self.qpi = qpi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def appendBootBinary(self, elf=None):
|
||||||
|
self.bootBinary = Binary(elf=elf)
|
||||||
|
|
||||||
|
def appendComponent(self, dirname, name):
|
||||||
|
|
||||||
|
self.compList.append(Comp(dirname, name))
|
||||||
|
|
||||||
|
def __roundToNextBlock(self):
|
||||||
|
nextOffset = (int)((self.flashOffset + self.blockSize - 1) / self.blockSize) * self.blockSize
|
||||||
|
padding = nextOffset - self.flashOffset
|
||||||
|
self.flashOffset = nextOffset
|
||||||
|
for i in range(0, padding):
|
||||||
|
self.buff.append(0)
|
||||||
|
|
||||||
|
def __padBlock(self, size):
|
||||||
|
padsize = (int)((size + self.blockSize - 1) / self.blockSize) * self.blockSize - size
|
||||||
|
self.flashOffset += padsize
|
||||||
|
for i in range(0, padsize):
|
||||||
|
self.buff.append(0)
|
||||||
|
|
||||||
|
def __pad(self, padsize, buff=None):
|
||||||
|
if buff is None:
|
||||||
|
self.flashOffset += padsize
|
||||||
|
for i in range(0, padsize):
|
||||||
|
self.buff.append(0)
|
||||||
|
else:
|
||||||
|
for i in range(0, padsize):
|
||||||
|
buff = self.__appendByte(0, buff=buff)
|
||||||
|
return buff
|
||||||
|
|
||||||
|
def __appendInt(self, value, newBlock=False, buff=None):
|
||||||
|
if buff is None:
|
||||||
|
#if newBlock: self.__roundToNextBlock()
|
||||||
|
self.buff += struct.pack("I", value)
|
||||||
|
self.flashOffset += 4
|
||||||
|
else:
|
||||||
|
buff += struct.pack("I", value)
|
||||||
|
return buff
|
||||||
|
|
||||||
|
def __appendLongInt(self, value, newBlock=False, buff=None):
|
||||||
|
if buff is None:
|
||||||
|
#if newBlock: self.__roundToNextBlock()
|
||||||
|
self.buff += struct.pack("Q", value)
|
||||||
|
self.flashOffset += 8
|
||||||
|
else:
|
||||||
|
buff += struct.pack("Q", value)
|
||||||
|
return buff
|
||||||
|
|
||||||
|
def __appendByte(self, value, newBlock=False, buff=None):
|
||||||
|
if buff is None:
|
||||||
|
#if newBlock: self.__roundToNextBlock()
|
||||||
|
self.buff += struct.pack("B", value)
|
||||||
|
self.flashOffset += 1
|
||||||
|
else:
|
||||||
|
buff += struct.pack("B", value)
|
||||||
|
return buff
|
||||||
|
|
||||||
|
|
||||||
|
def get_crc(self, buff):
|
||||||
|
crc = 0xffffffff
|
||||||
|
for data in buff:
|
||||||
|
crc = crc ^ data
|
||||||
|
for i in range(7, -1, -1):
|
||||||
|
if crc & 1 == 1:
|
||||||
|
mask = 0xffffffff
|
||||||
|
else:
|
||||||
|
mask = 0
|
||||||
|
crc2 = crc >> 1
|
||||||
|
crc = (crc >> 1) ^ (0xEDB88320 & mask)
|
||||||
|
|
||||||
|
return (crc ^ 0xffffffff)
|
||||||
|
|
||||||
|
|
||||||
|
def __appendBuffer(self, buffer, newBlock=False, pad=False, encrypt=False, padToOffset=None):
|
||||||
|
#if newBlock: self.__roundToNextBlock()
|
||||||
|
if self.encrypt:
|
||||||
|
cmd = 'aes_encode %s %s' % (self.aesKey, self.aesIv)
|
||||||
|
|
||||||
|
crc = self.get_crc(buffer)
|
||||||
|
buffer += struct.pack("I", crc)
|
||||||
|
|
||||||
|
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
|
||||||
|
out, err = p.communicate(buffer)
|
||||||
|
if p.returncode != 0:
|
||||||
|
raise Exception('Error when executing aes_encore to encrypt binary, probably this tool is not available')
|
||||||
|
buffer = out
|
||||||
|
|
||||||
|
if padToOffset != None:
|
||||||
|
self.__pad(padToOffset - self.flashOffset)
|
||||||
|
|
||||||
|
self.buff += buffer
|
||||||
|
self.flashOffset += len(buffer)
|
||||||
|
if pad:
|
||||||
|
self.__padBlock(len(buffer))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def __dumpToBuff(self):
|
||||||
|
self.__dumpBootBinaryToBuff()
|
||||||
|
self.__dumpCompsToBuff()
|
||||||
|
|
||||||
|
def __dumpFlashHeader_v1(self):
|
||||||
|
|
||||||
|
if self.verbose:
|
||||||
|
print ("Generating boot binary")
|
||||||
|
|
||||||
|
index = 0
|
||||||
|
print ("Merging following segments:")
|
||||||
|
for segment in self.bootBinary.segments:
|
||||||
|
if self.verbose: print (" Area %d: base: 0x%x, size: 0x%x" % (index, segment.base, segment.size))
|
||||||
|
index = index + 1
|
||||||
|
|
||||||
|
l1Area = BinarySegment(0x10000000, [])
|
||||||
|
l2Area = BinarySegment(0x1c000000, [])
|
||||||
|
|
||||||
|
self.bootBinary.mergedSegments = [l2Area, l1Area]
|
||||||
|
|
||||||
|
for segment in self.bootBinary.segments:
|
||||||
|
if segment.base < 0x1c000000: area = l1Area
|
||||||
|
else: area = l2Area
|
||||||
|
if segment.base > area.base + area.size:
|
||||||
|
diff = segment.base - (area.base + area.size)
|
||||||
|
area.size += diff
|
||||||
|
for i in range(0, diff):
|
||||||
|
area.data.append(0)
|
||||||
|
|
||||||
|
area.data += segment.data
|
||||||
|
area.size += segment.size
|
||||||
|
|
||||||
|
# First compute areas flash information
|
||||||
|
flashOffset = 0
|
||||||
|
flashOffset += 4*4*2
|
||||||
|
|
||||||
|
print ("Merged into:")
|
||||||
|
index = 0
|
||||||
|
for segment in self.bootBinary.mergedSegments:
|
||||||
|
segment.nbBlocks = int((segment.size + self.blockSize - 1) / self.blockSize)
|
||||||
|
segment.offset = flashOffset
|
||||||
|
flashOffset += segment.nbBlocks * self.blockSize
|
||||||
|
if self.verbose: print (" Area %d: offset: 0x%x, base: 0x%x, size: 0x%x, nbBlocks: %d" % (index, segment.offset, segment.base, segment.size, segment.nbBlocks))
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
# Then write the header containing memory areas declaration
|
||||||
|
self.__appendInt(l2Area.offset)
|
||||||
|
self.__appendInt(l2Area.base)
|
||||||
|
self.__appendInt(l2Area.size)
|
||||||
|
self.__appendInt(l2Area.nbBlocks)
|
||||||
|
|
||||||
|
self.__appendInt(l1Area.offset)
|
||||||
|
self.__appendInt(l1Area.base)
|
||||||
|
self.__appendInt(l1Area.size)
|
||||||
|
self.__appendInt(l1Area.nbBlocks)
|
||||||
|
|
||||||
|
# Finally write the data
|
||||||
|
for area in self.bootBinary.mergedSegments:
|
||||||
|
self.__appendBuffer(area.data, pad=True, encrypt=self.encrypt)
|
||||||
|
|
||||||
|
def __dumpFlashHeader_v2(self):
|
||||||
|
|
||||||
|
if self.verbose:
|
||||||
|
print ("Generating boot binary")
|
||||||
|
print (" Nb areas: %d" % len(self.bootBinary.segments))
|
||||||
|
|
||||||
|
# First compute areas flash information
|
||||||
|
flashOffset = 0
|
||||||
|
flashOffset += 4 + 4 + 4 + 4 + 16 * 4 * len(self.bootBinary.segments)
|
||||||
|
|
||||||
|
crc_offset = flashOffset
|
||||||
|
flashOffset += 4
|
||||||
|
|
||||||
|
flashOffset = (flashOffset + self.blockSize - 1) & ~(self.blockSize - 1)
|
||||||
|
|
||||||
|
if self.encrypt:
|
||||||
|
for segment in self.bootBinary.segments:
|
||||||
|
segment.size += 4
|
||||||
|
|
||||||
|
index = 0
|
||||||
|
for segment in self.bootBinary.segments:
|
||||||
|
segment.nbBlocks = int((segment.size + self.blockSize - 1) / self.blockSize)
|
||||||
|
segment.offset = flashOffset
|
||||||
|
flashOffset += segment.nbBlocks * self.blockSize
|
||||||
|
if self.verbose: print (" Area %d: offset: 0x%x, base: 0x%x, size: 0x%x, nbBlocks: %d" % (index, segment.offset, segment.base, segment.size, segment.nbBlocks))
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Then write the header containing memory areas declaration
|
||||||
|
flashOffset = (flashOffset + 7) & ~7
|
||||||
|
self.fsOffset = flashOffset
|
||||||
|
|
||||||
|
header_buff = bytes([])
|
||||||
|
header_buff = self.__appendInt(flashOffset, buff=header_buff)
|
||||||
|
header_buff = self.__appendInt(len(self.bootBinary.segments), buff=header_buff)
|
||||||
|
#self.__appendInt(self.bootBinary.entry)
|
||||||
|
header_buff = self.__appendInt(self.bootBinary.entry, buff=header_buff)
|
||||||
|
header_buff = self.__appendInt(self.bootaddr, buff=header_buff)
|
||||||
|
|
||||||
|
for area in self.bootBinary.segments:
|
||||||
|
header_buff = self.__appendInt(area.offset, buff=header_buff)
|
||||||
|
header_buff = self.__appendInt(area.base, buff=header_buff)
|
||||||
|
header_buff = self.__appendInt(area.size, buff=header_buff)
|
||||||
|
header_buff = self.__appendInt(area.nbBlocks, buff=header_buff)
|
||||||
|
|
||||||
|
header_buff = self.__pad(crc_offset - self.flashOffset - len(header_buff), buff=header_buff)
|
||||||
|
crc = self.get_crc(header_buff)
|
||||||
|
header_buff = self.__appendInt(crc, buff=header_buff)
|
||||||
|
self.__appendBuffer(header_buff, encrypt=self.encrypt)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Finally write the data
|
||||||
|
for area in self.bootBinary.segments:
|
||||||
|
self.__appendBuffer(area.data, padToOffset=area.offset, encrypt=self.encrypt)
|
||||||
|
|
||||||
|
self.__pad(self.fsOffset - self.flashOffset)
|
||||||
|
|
||||||
|
def __dumpBootBinaryToBuff(self):
|
||||||
|
if self.bootBinary != None:
|
||||||
|
|
||||||
|
if self.archi == 'vivosoc2' or self.archi == 'fulmine':
|
||||||
|
self.__dumpFlashHeader_v1()
|
||||||
|
else:
|
||||||
|
self.__dumpFlashHeader_v2()
|
||||||
|
|
||||||
|
else:
|
||||||
|
# In case no boot binary is there, we must have at least the first word telling where starts the next descriptor
|
||||||
|
self.__appendLongInt(8)
|
||||||
|
|
||||||
|
|
||||||
|
def __dumpCompsToBuff(self):
|
||||||
|
|
||||||
|
#
|
||||||
|
# Flash address computation
|
||||||
|
#
|
||||||
|
|
||||||
|
if self.verbose: print ('Generating files (header offset: 0x%x)' % self.flashOffset)
|
||||||
|
|
||||||
|
flashAddr = self.flashOffset
|
||||||
|
headerSize = 0
|
||||||
|
|
||||||
|
# Compute the header size
|
||||||
|
headerSize += 12 # Header size and number of components
|
||||||
|
|
||||||
|
for comp in self.compList:
|
||||||
|
headerSize += 12 # Flash address, size and path length
|
||||||
|
headerSize += len(comp.name)+1 # Path
|
||||||
|
|
||||||
|
flashAddr += headerSize
|
||||||
|
|
||||||
|
# Now set the flash address for each component
|
||||||
|
for comp in self.compList:
|
||||||
|
comp.flashAddr = (flashAddr + 3) & ~3
|
||||||
|
if self. verbose:
|
||||||
|
print (' Adding component (name: %s, flashOffset: 0x%x)' % (comp.name, comp.flashAddr))
|
||||||
|
flashAddr = comp.flashAddr + comp.size
|
||||||
|
|
||||||
|
|
||||||
|
# Now create the raw image as a byte array
|
||||||
|
|
||||||
|
# First header size
|
||||||
|
self.__appendLongInt(headerSize)
|
||||||
|
|
||||||
|
# Number of components
|
||||||
|
self.__appendInt(len(self.compList))
|
||||||
|
|
||||||
|
# Then for each component
|
||||||
|
for comp in self.compList:
|
||||||
|
# The flash address
|
||||||
|
self.__appendInt(comp.flashAddr)
|
||||||
|
|
||||||
|
# Binary size
|
||||||
|
self.__appendInt(comp.size)
|
||||||
|
|
||||||
|
# The path length
|
||||||
|
self.__appendInt(len(comp.name)+1)
|
||||||
|
|
||||||
|
# And the path
|
||||||
|
self.__appendBuffer(comp.name.encode('utf-8'))
|
||||||
|
self.__appendByte(0)
|
||||||
|
|
||||||
|
# Then dump all components
|
||||||
|
for comp in self.compList:
|
||||||
|
with open(comp.path, 'rb') as file:
|
||||||
|
self.__appendBuffer(file.read(), padToOffset=comp.flashAddr)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def generate(self):
|
||||||
|
|
||||||
|
self.__dumpToBuff()
|
||||||
|
|
||||||
|
if self.raw != None:
|
||||||
|
try:
|
||||||
|
os.makedirs(os.path.dirname(self.raw))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with open(self.raw, 'wb') as file:
|
||||||
|
file.write(bytes(self.buff))
|
||||||
|
|
||||||
|
if self.stimuli != None:
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.makedirs(os.path.dirname(self.stimuli))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with open(self.stimuli, 'w') as file:
|
||||||
|
if self.flashType == 'mram':
|
||||||
|
last_bytes = len(self.buff) & 0x7
|
||||||
|
for i in range(0, 8 - last_bytes):
|
||||||
|
self.__appendByte(0)
|
||||||
|
for i in range(0, len(self.buff)>>3):
|
||||||
|
value = (self.buff[i*8+7] << 56) + (self.buff[i*8+6] << 48) + (self.buff[i*8+5] << 40) + (self.buff[i*8+4] << 32) + (self.buff[i*8+3] << 24) + (self.buff[i*8+2] << 16) + (self.buff[i*8+1] << 8) + self.buff[i*8]
|
||||||
|
dumpLongToSlm(file, i, value)
|
||||||
|
elif self.flashType == 'hyper':
|
||||||
|
if len(self.buff) & 1 != 0:
|
||||||
|
self.__appendByte(0)
|
||||||
|
for i in range(0, len(self.buff)>>1):
|
||||||
|
value = (self.buff[i*2+1] << 8) + self.buff[i*2]
|
||||||
|
dumpShortToSlm(file, i, value)
|
||||||
|
elif self.archi == 'vivosoc2' or self.archi == 'fulmine':
|
||||||
|
if len(self.buff) % 4 != 0:
|
||||||
|
for i in range(0, 4 - (len(self.buff)%4)):
|
||||||
|
self.buff.append(0)
|
||||||
|
for i in range(0, len(self.buff), 4):
|
||||||
|
dumpByteToSlm(file, i, self.buff[i+3])
|
||||||
|
dumpByteToSlm(file, i+1, self.buff[i+2])
|
||||||
|
dumpByteToSlm(file, i+2, self.buff[i+1])
|
||||||
|
dumpByteToSlm(file, i+3, self.buff[i+0])
|
||||||
|
else:
|
||||||
|
for i in range(0, len(self.buff)):
|
||||||
|
dumpByteToSlm(file, i, self.buff[i])
|
||||||
|
|
||||||
|
|
||||||
|
def genFlashImage(slmStim=None, raw_stim=None, bootBinary=None, comps=[], verbose=False, archi=None, encrypt=False, aesKey=None, aesIv=None, flashType='spi', qpi=True):
|
||||||
|
print('gen flash image')
|
||||||
|
saved_args = locals()
|
||||||
|
print("saved_args is", saved_args)
|
||||||
|
if bootBinary != None or len(comps) != 0:
|
||||||
|
if slmStim != None or raw_stim is not None:
|
||||||
|
compsList = ''
|
||||||
|
romBoot = ''
|
||||||
|
|
||||||
|
if bootBinary != None:
|
||||||
|
romBoot = ' --flash-boot-binary=%s' % bootBinary
|
||||||
|
|
||||||
|
for comp in comps:
|
||||||
|
compsList += ' --comp=%s' % comp
|
||||||
|
|
||||||
|
if slmStim is not None:
|
||||||
|
cmd = "plp_mkflash %s %s --stimuli=%s --flash-type=%s" % (romBoot, compsList, slmStim, flashType)
|
||||||
|
else:
|
||||||
|
cmd = "plp_mkflash %s %s --raw=%s --flash-type=%s" % (romBoot, compsList, raw_stim, flashType)
|
||||||
|
|
||||||
|
if qpi: cmd+= ' --qpi'
|
||||||
|
|
||||||
|
if encrypt: cmd += ' --encrypt --aes-key=%s --aes-iv=%s' % (aesKey, aesIv)
|
||||||
|
|
||||||
|
if verbose: cmd += ' --verbose'
|
||||||
|
if archi != None: cmd += ' --archi=%s' % archi
|
||||||
|
if not verbose:
|
||||||
|
print ('Building flash stimuli with command:')
|
||||||
|
print (cmd)
|
||||||
|
if os.system(cmd) != 0:
|
||||||
|
raise Exception('Error while generating flash image')
|
||||||
|
|
||||||
|
|
||||||
|
return 0
|
||||||
89
bin/plp_mkflash
Executable file
89
bin/plp_mkflash
Executable file
|
|
@ -0,0 +1,89 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
#file extracted from pulp sdk : https://github.com/pulp-platform/pulp-sdk.git
|
||||||
|
#to be used in marsellus project
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
from os import listdir
|
||||||
|
from os.path import isfile, join, isdir
|
||||||
|
import struct
|
||||||
|
import plp_flash_stimuli as plp_flash_stimuli
|
||||||
|
|
||||||
|
class bcolors:
|
||||||
|
HEADER = '\033[95m'
|
||||||
|
OKBLUE = '\033[94m'
|
||||||
|
OKGREEN = '\033[92m'
|
||||||
|
WARNING = '\033[93m'
|
||||||
|
FAIL = '\033[91m'
|
||||||
|
ENDC = '\033[0m'
|
||||||
|
BOLD = '\033[1m'
|
||||||
|
UNDERLINE = '\033[4m'
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='Build flash image for Pulp')
|
||||||
|
|
||||||
|
parser.add_argument("--flash-boot-binary", dest="flashBootBinary", default=None, help="Boot from flash")
|
||||||
|
parser.add_argument("--elf-loader", dest="elfLoader", default=None, help="Boot using the specified ELF loader")
|
||||||
|
parser.add_argument("--binary", dest="binary", default=None, help="Resident binary")
|
||||||
|
parser.add_argument("--flash-type", dest="flashType", default='spi', help="Flash type")
|
||||||
|
parser.add_argument("--comp-dir", dest="compDir", default=[], action="append", help="Component directory")
|
||||||
|
parser.add_argument("--comp-dir-rec", dest="compDirRec", default=[], action="append", help="Recursive component directory")
|
||||||
|
parser.add_argument("--comp", dest="comp", default=[], action="append", help="Component")
|
||||||
|
parser.add_argument("--stimuli", dest="stimuli", default=None, help="Generate stimuli")
|
||||||
|
parser.add_argument("--raw", dest="raw", default=None, help="Generate raw image")
|
||||||
|
parser.add_argument("--archi", dest="archi", default=None, help="Architecture")
|
||||||
|
parser.add_argument("--verbose", dest="verbose", action="store_true", help="Verbose mode")
|
||||||
|
parser.add_argument("--encrypt", dest="encrypt", action="store_true", help="Encrypt binary")
|
||||||
|
parser.add_argument("--qpi", dest="qpi", action="store_true", help="Use QPI")
|
||||||
|
parser.add_argument("--aes-key", dest="aesKey", default=None, help="AES key for encryption")
|
||||||
|
parser.add_argument("--aes-iv", dest="aesIv", default=None, help="AES init vector for encryption")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def getFilesFromDir(path, rec=False, incDirInName=True):
|
||||||
|
files = []
|
||||||
|
for file in listdir(path):
|
||||||
|
fullPath = os.path.join(path, file)
|
||||||
|
if isfile(fullPath): files.append(Comp(path, file))
|
||||||
|
elif rec and isdir(fullPath): files += getFilesFromDir(fullPath, True)
|
||||||
|
return files
|
||||||
|
|
||||||
|
|
||||||
|
flashImage = plp_flash_stimuli.FlashImage(raw=args.raw, stimuli=args.stimuli, verbose=args.verbose, archi=args.archi, encrypt=args.encrypt, aesKey=args.aesKey, aesIv=args.aesIv, flashType=args.flashType, qpi=args.qpi)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Boot binary
|
||||||
|
#
|
||||||
|
|
||||||
|
# In case the chip is booting from ROM, the flash contains first the binary to be loaded into the chip by the ROM
|
||||||
|
|
||||||
|
bootBinary = args.flashBootBinary
|
||||||
|
if bootBinary != None:
|
||||||
|
|
||||||
|
flashImage.appendBootBinary(elf=bootBinary)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Collect files from options
|
||||||
|
#
|
||||||
|
|
||||||
|
for comp in args.comp:
|
||||||
|
flashImage.appendComponent(os.path.dirname(comp), os.path.basename(comp))
|
||||||
|
|
||||||
|
for compDir in args.compDir:
|
||||||
|
for dirname, name in getFilesFromDir(compDir, incDirInName=False):
|
||||||
|
flashImage.appendComponent(dirname, name)
|
||||||
|
|
||||||
|
for compDir in args.compDirRec:
|
||||||
|
for dirname, name in getFilesFromDir(compDir, True, incDirInName=False):
|
||||||
|
flashImage.appendComponent(dirname, name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Finally generate the image
|
||||||
|
#
|
||||||
|
|
||||||
|
flashImage.generate()
|
||||||
30
bin/slm_hyper.py
Executable file
30
bin/slm_hyper.py
Executable file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
#Written by ABA to update the format of the slm file to be compliant with hyperflash model used in testbench
|
||||||
|
import numpy as np
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='Generate hyper memory image file from slm')
|
||||||
|
|
||||||
|
parser.add_argument("--input", dest="input_file", default=None, help="Specify input file (ex. ./build/pulpissimo/slm_files/flash_stim.slm)")
|
||||||
|
parser.add_argument("--output", dest="output_file", default=None, help="Specify output file (ex. ./build/pulpissimo/slm_files/hyper_flash_stim.slm)")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.input_file is None:
|
||||||
|
raise Exception('Specify the input file with --input=<path> (ex. --input=./build/pulpissimo/slm_files/flash_stim.slm)')
|
||||||
|
|
||||||
|
if args.output_file is None:
|
||||||
|
raise Exception('Specify the output file with --output=<path> (ex. --output=./build/pulpissimo/slm_files/hyper_flash_stim.slm')
|
||||||
|
|
||||||
|
delimiter=" "
|
||||||
|
with open(args.input_file, "rU") as fi:
|
||||||
|
data = list(map(lambda x:x.split(delimiter), fi.read().strip().split("\n")))
|
||||||
|
fo=open(args.output_file, "w")
|
||||||
|
A=np.array(data)
|
||||||
|
fo.write('@000000\n')
|
||||||
|
for i in range(0, A.shape[0],2):
|
||||||
|
fo.write('%s%s\n' %(A[i+1][1],A[i][1]))
|
||||||
|
|
@ -138,6 +138,35 @@ override runner_args += --config-user=$(RUNNER_CONFIG)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# VSIM Flags
|
||||||
|
#
|
||||||
|
vsim_flags ?= +ENTRY_POINT=0x1c008080 -dpicpppath /usr/bin/g++ -permit_unmatched_virtual_intf -gBAUDRATE=115200
|
||||||
|
ifdef bootmode
|
||||||
|
ifeq ($(bootmode), spi)
|
||||||
|
vsim_flags += -gSTIM_FROM=SPI_FLASH -gLOAD_L2=STANDALONE -gUSE_S25FS256S_MODEL=1
|
||||||
|
else
|
||||||
|
ifeq ($(bootmode), hyperflash)
|
||||||
|
vsim_flags += -gSTIM_FROM=HYPER_FLASH -gLOAD_L2=STANDALONE -gUSE_HYPER_MODELS=1
|
||||||
|
else
|
||||||
|
ifeq ($(bootmode), fast_debug)
|
||||||
|
vsim_flags += -gLOAD_L2=FAST_DEBUG_PRELOAD
|
||||||
|
else
|
||||||
|
ifeq ($(bootmode), jtag)
|
||||||
|
vsim_flags += -gLOAD_L2=JTAG
|
||||||
|
else
|
||||||
|
$(error Illegal value supplied for bootmode. Legal values are 'spi', 'hyperflash', 'fast_debug' and 'jtag')
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
vsim_flags += -gLOAD_L2=JTAG
|
||||||
|
endif
|
||||||
|
ifdef vsim_additional_flags
|
||||||
|
vsim_flags += $(vsim_additional_flags)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# PULP_APPS
|
# PULP_APPS
|
||||||
|
|
@ -245,17 +274,20 @@ $(TARGET_BUILD_DIR)/stdout:
|
||||||
$(TARGET_BUILD_DIR)/fs:
|
$(TARGET_BUILD_DIR)/fs:
|
||||||
mkdir -p $@
|
mkdir -p $@
|
||||||
|
|
||||||
run: $(TARGET_BUILD_DIR)/modelsim.ini $(TARGET_BUILD_DIR)/boot $(TARGET_BUILD_DIR)/tcl_files \
|
|
||||||
$(TARGET_BUILD_DIR)/stdout $(TARGET_BUILD_DIR)/fs $(TARGET_BUILD_DIR)/waves
|
run: $(TARGET_BUILD_DIR)/modelsim.ini $(TARGET_BUILD_DIR)/boot $(TARGET_BUILD_DIR)/tcl_files $(TARGET_BUILD_DIR)/stdout $(TARGET_BUILD_DIR)/fs $(TARGET_BUILD_DIR)/waves
|
||||||
$(PULPRT_HOME)/bin/stim_utils.py --binary=$(TARGETS) --vectors=$(TARGET_BUILD_DIR)/vectors/stim.txt
|
$(PULPRT_HOME)/bin/stim_utils.py --binary=$(TARGETS) --vectors=$(TARGET_BUILD_DIR)/vectors/stim.txt
|
||||||
|
$(PULPRT_HOME)/bin/plp_mkflash --flash-boot-binary=$(TARGETS) --stimuli=$(TARGET_BUILD_DIR)/vectors/qspi_stim.slm --flash-type=spi --qpi
|
||||||
|
$(PULPRT_HOME)/bin/slm_hyper.py --input=$(TARGET_BUILD_DIR)/vectors/qspi_stim.slm --output=$(TARGET_BUILD_DIR)/vectors/hyper_stim.slm
|
||||||
ifndef VSIM_PATH
|
ifndef VSIM_PATH
|
||||||
$(error "VSIM_PATH is undefined. Either call \
|
$(error "VSIM_PATH is undefined. Either call \
|
||||||
'source $$YOUR_HW_DIR/setup/vsim.sh' or set it manually.")
|
'source $$YOUR_HW_DIR/setup/vsim.sh' or set it manually.")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef gui
|
ifdef gui
|
||||||
cd $(TARGET_BUILD_DIR) && export VSIM_RUNNER_FLAGS="+ENTRY_POINT=0x1c008080 -gLOAD_L2=JTAG -dpicpppath /usr/bin/g++ -permit_unmatched_virtual_intf -gBAUDRATE=115200" && export VOPT_ACC_ENA="YES" && vsim -64 -do 'source $(VSIM_PATH)/tcl_files/config/run_and_exit.tcl' -do 'source $(VSIM_PATH)/tcl_files/run.tcl; '
|
cd $(TARGET_BUILD_DIR) && export VSIM_RUNNER_FLAGS='$(vsim_flags)' && export VOPT_ACC_ENA="YES" && vsim -64 -do 'source $(VSIM_PATH)/tcl_files/config/run_and_exit.tcl' -do 'source $(VSIM_PATH)/tcl_files/run.tcl; '
|
||||||
else
|
else
|
||||||
cd $(TARGET_BUILD_DIR) && export VSIM_RUNNER_FLAGS="+ENTRY_POINT=0x1c008080 -gLOAD_L2=JTAG -dpicpppath /usr/bin/g++ -permit_unmatched_virtual_intf -gBAUDRATE=115200" && vsim -64 -c -do 'source $(VSIM_PATH)/tcl_files/config/run_and_exit.tcl' -do 'source $(VSIM_PATH)/tcl_files/run.tcl; run_and_exit;'
|
cd $(TARGET_BUILD_DIR) && export VSIM_RUNNER_FLAGS='$(vsim_flags)' && vsim -64 -c -do 'source $(VSIM_PATH)/tcl_files/config/run_and_exit.tcl' -do 'source $(VSIM_PATH)/tcl_files/run.tcl; run_and_exit;'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue