# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
# OF THE POSSIBILITY OF SUCH DAMAGE
#
+# Copyright (c) 2006-2007 Intel Corporation
+# All rights reserved.
+#
+# This file is distributed under the terms in the attached INTEL-LICENSE
+# file. If you do not find these files, copies can be found by writing to
+# Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
+# 94704. Attention: Intel License Inquiry.
+
# @author Jonathan Hui <jhui@archedrock.com>
+# @author David Gay
+# @author Kevin Klues <klueska@cs.stanford.edu>
+# @author R. Steve McKown <rsmckown@gmail.com>
#
# $Revision$
# $Date$
#
+from __future__ import with_statement # Does this require too new a python?
+
+import os
+import re
from re import match
from sys import *
-from xml.dom import minidom
+from xml.dom import *
+from xml.dom.minidom import *
+from subprocess import Popen, PIPE
+
+from getopt import *
+import string
+import commands
+#New way of handling arguments........
+try:
+ opts, args = getopt(argv[1:], "t", [])
+except GetoptError, err:
+ print str(err) # will print something like "option -a not recognized"
+ stderr.write( "Usage: tos-storage-stm25p [-t] <platform directory>\n" )
+
+if len( args ) == 1:
+ platformdir = args[0]
+ platform = os.path.basename(platformdir)
+ # In case platformdir was specified with a trailing path separator
+ if not platform:
+ platformdir = os.path.dirname(platformdir)
+ platform = os.path.basename(platformdir)
+ familydir = os.path.dirname(platformdir)
+ if familydir and not os.path.isfile(os.path.join(familydir, '.family')):
+ familydir = ""
+elif len( args ) == 0:
+ platformdir = ""
+ platform = ""
+ familydir = ""
+else:
+ stderr.write( "Usage: tos-storage-stm25p [-t] <platform directory>\n" )
+
+cthreads = False
+for o, a in opts:
+ if o == "-t":
+ cthreads = True
+ else:
+ assert False, "unhandled option"
+
+def error_exit( s ):
+ stderr.write( "ERROR: " + s + "\n" )
+ exit( 2 )
+
+def expand_path( path ):
+ substrs = path.split( "%" )
+ path = substrs[0]
+ i = 1
+ while i < len( substrs ):
+ if substrs[i] == "":
+ # There was a %%, leading to a blank substring, and the next string
+ # should just be appended
+ path += "%"
+ i = i + 1
+ if i < len( substrs ):
+ path += substrs[i]
+ else:
+ # The first character of the string is the one that followed %
+ c = substrs[i][0]
+ if c == 'p':
+ sub = platform
+ elif c == 'P':
+ sub = platformdir
+ elif c == 'F':
+ if not familydir:
+ nfail( "invalid include-path substitution character " + c + "; " + \
+ platform + " not in a family" )
+ sub = familydir
+ elif c == 'T':
+ sub = Popen( ["ncc", "-print-tosdir"], stdout=PIPE ).communicate( )[0]
+ sub = sub[:-1] # remove newline
+ else:
+ nfail( "unknown include-path substitution character " + c )
+ path += sub
+ path += substrs[i][1:]
+ i = i + 1
+ return path
-NUM_SECTORS = 16
-SECTOR_SIZE = 65536
+
+HEADER_FILE = 'Stm25p.h'
+NUM_SECTORS = 0
+SECTOR_SIZE = 0
+
+def parseHeader( dotfile ):
+ """ Return an ordered list of paths from the dotfile """
+ paths = []
+ inArray = False
+ p = re.compile('push\s*\(\s*@includes,\s*qw\s*\(');
+ q = re.compile('\)\s*\)\s*;');
+ try:
+ with open(dotfile, 'r') as file:
+ for line in file:
+ path = line.strip()
+ if path:
+ if p.match(path):
+ inArray = True
+ elif q.match(path):
+ inArray = False
+ elif inArray == True:
+ paths.append(path)
+ return paths
+ except:
+ return []
+
+def findFile( paths, filename ):
+ """ Find the first occurrence of 'filename' in the list of paths given. """
+ for path in paths:
+ rpath = expand_path(path)
+ try:
+ for file in os.listdir(rpath):
+ if file == filename:
+ return rpath + '/' + filename
+ except OSError:
+ None
+ return None
+
+def findVars( path, vars ):
+ """ Finds values for the variables already present in vars from path """
+ inEnum = False
+ p = re.compile('enum\s.*{');
+ q = re.compile('}s*;');
+ r = re.compile('^\s*([A-Z0-9_]*)\s*=\s*([^,]*)');
+ with open(path, 'r') as file:
+ for line in file:
+ line = line.strip()
+ if line:
+ if p.match(line):
+ inEnum = True
+ elif q.match(line):
+ inEnum = False
+ elif inEnum == True:
+ m = r.search(line)
+ if vars.has_key(m.group(1)):
+ vars[m.group(1)] = m.group(2)
+
+paths = parseHeader(os.path.join(familydir, '.family')) + \
+ parseHeader(os.path.join(platformdir, '.platform'))
+if paths:
+ path = findFile(paths, HEADER_FILE)
+ if path:
+ enums = {}
+ enums["STM25P_NUM_SECTORS"] = 0
+ enums["STM25P_SECTOR_SIZE_LOG2"] = 0
+ findVars(path, enums)
+ NUM_SECTORS = int(enums["STM25P_NUM_SECTORS"])
+ SECTOR_SIZE = 2**int(enums["STM25P_SECTOR_SIZE_LOG2"])
+if NUM_SECTORS == 0 or SECTOR_SIZE == 0:
+ stderr.write( "tos-storage-stm25p: no valid Stm25p.h found.\n\t"
+ "Check @includes in the platform's .platform file\n" )
+ exit(2)
volumes = {}
volumeNames = []
volumeSizes = []
volumeOffsets = []
+volumeTypes = dict()
+volumeOptions = dict()
freeSectors = NUM_SECTORS*[ True ]
-def error_exit( s ):
- stderr.write( "ERROR: " + s + "\n" )
- exit( 2 )
+def volumeparse( file, fname, depth ):
+ if depth > 10:
+ error_exit( "include nesting too deep - check for cycles" )
+ try:
+ dom = parse( file )
+ except xml.parsers.expat.ExpatError:
+ error_exit( fname + " is not a valid input file" )
+ except IOError:
+ error_exit( "couldn't open file " + fname )
-try:
- dom = minidom.parse( stdin )
-except xml.parsers.expat.ExpatError:
- error_exit( "input invalid" )
-
-# extract information
-for volume in dom.documentElement.getElementsByTagName( "volume" ):
- name = volume.getAttribute( "name" )
- size = volume.getAttribute( "size" )
- base = volume.getAttribute( "base" )
- if name == "":
- error_exit( "volume has no name" )
- elif not match( "^[a-zA-Z0-9_]+$", name ):
- error_exit( "volume has invalid name '%s'" % name )
- elif volumes.has_key( name ):
- error_exit( "duplicate volume definition '%s'" % name )
- else:
- volumes[ name ] = "blah"
-
- if size == "":
- error_exit( "volume '%s' has no size" % name )
- try:
- size = int( size )
- except ValueError:
- error_exit( "volume '%s' has invalid size" % name )
- if base != "":
- try:
- base = int( base )
- except ValueError:
- error_exit( "volume '%s' has invalid base" % name )
- if ( size & ( SECTOR_SIZE - 1 ) ) != 0:
- error_exit( "size of volume '%s' is not a multiple of %d" % \
- ( name, SECTOR_SIZE ) )
- if base != "" and ( base & ( SECTOR_SIZE - 1 ) ) != 0:
- error_exit( "base of volume '%s' is not a multiple of %d" % \
- ( name, SECTOR_SIZE ) )
-
- volumeNames.append( "VOLUME_" + name )
- volumeSizes.append( size / SECTOR_SIZE )
- if base == "":
- volumeOffsets.append( -1 )
+ # extract information
+ for volume in dom.documentElement.getElementsByTagName( "volume" ):
+ name = volume.getAttribute( "name" )
+ size = volume.getAttribute( "size" )
+ base = volume.getAttribute( "base" )
+ type = string.lower(volume.getAttribute("type"))
+ isCircular = string.upper(volume.getAttribute("circular"))
+ if isCircular == "":
+ isCircular = "FALSE"
+
+ if name == "":
+ error_exit( "volume has no name" )
+ elif not match( "^[a-zA-Z0-9_]+$", name ):
+ error_exit( "volume has invalid name '%s'" % name )
+ elif volumes.has_key( name ):
+ error_exit( "duplicate volume definition '%s'" % name )
+ else:
+ volumes[ name ] = "blah"
+
+ if size == "":
+ error_exit( "volume '%s' has no size" % name )
+ try:
+ size = int( size )
+ except ValueError:
+ error_exit( "volume '%s' has invalid size" % name )
+ if base != "":
+ try:
+ base = int( base )
+ except ValueError:
+ error_exit( "volume '%s' has invalid base" % name )
+ if ( size & ( SECTOR_SIZE - 1 ) ) != 0:
+ error_exit( "size of volume '%s' is not a multiple of %d" % \
+ ( name, SECTOR_SIZE ) )
+ if base != "" and ( base & ( SECTOR_SIZE - 1 ) ) != 0:
+ error_exit( "base of volume '%s' is not a multiple of %d" % \
+ ( name, SECTOR_SIZE ) )
+
+ volumeNames.append( "VOLUME_" + name )
+ volumeSizes.append( size / SECTOR_SIZE )
+ volumeTypes["VOLUME_" + name] = type
+ volumeOptions["VOLUME_" + name] = isCircular
+
+ if base == "":
+ volumeOffsets.append( -1 )
+ else:
+ base = base / SECTOR_SIZE
+ size = size / SECTOR_SIZE
+ volumeOffsets.append( base )
+ for i in range( size ):
+ freeSectors[ i + base ] = False
+
+ for include in dom.documentElement.getElementsByTagName( "include" ):
+ included = include.firstChild
+ if included != None and included.nodeType == included.TEXT_NODE:
+ included = expand_path( included.data )
+ volumeparse( included, "(file %s)" % included, depth + 1 )
else:
- base = base / SECTOR_SIZE
- volumeOffsets.append( base )
- for i in range( size ):
- freeSectors[ i + base ] = False
+ error_exit( "invalid include directive " + fname )
+ dom.unlink( )
+
+volumeparse( stdin, "(standard input)", 0 )
# allocate with first fit policy
for i in range( len( volumeOffsets ) ):
print ""
print "#endif"
+
+# output nc file for threads
+if cthreads == True:
+ outFile = open(commands.getstatusoutput("pwd")[1] + "/VolumeMapC.nc", "w")
+ outFile.write("#include \"StorageVolumes.h\" \n")
+ outFile.write("\n")
+ outFile.write("configuration VolumeMapC { \n")
+ outFile.write(" provides { \n")
+ outFile.write(" interface BlockRead[uint8_t volume_id]; \n")
+ outFile.write(" interface BlockWrite[uint8_t volume_id]; \n")
+ outFile.write(" interface LogRead[uint8_t volumeId]; \n")
+ outFile.write(" interface LogWrite[uint8_t volumeId]; \n")
+ outFile.write(" interface Mount[uint8_t volumeId]; \n")
+ outFile.write(" interface ConfigStorage[uint8_t volumeId]; \n")
+ outFile.write(" } \n")
+ outFile.write("} \n")
+ outFile.write("\n")
+ outFile.write("implementation { \n")
+ outFile.write(" components VolumeMapP; \n")
+ outFile.write("\n")
+ outFile.write(" BlockRead = VolumeMapP; \n")
+ outFile.write(" BlockWrite = VolumeMapP; \n")
+ outFile.write(" LogRead = VolumeMapP; \n")
+ outFile.write(" LogWrite = VolumeMapP; \n")
+ outFile.write(" Mount = VolumeMapP; \n")
+ outFile.write(" ConfigStorage = VolumeMapP; \n")
+
+ for i in range(len(volumeNames)):
+ if volumeTypes[volumeNames[i]] == "block":
+ outFile.write("\n")
+ outFile.write(" components new BlockStorageC(" + volumeNames[i] + ") as BlockStorageC_" + volumeNames[i] + "; \n")
+ outFile.write(" VolumeMapP.SubBlockRead[" + volumeNames[i] + "] -> BlockStorageC_" + volumeNames[i] + "; \n")
+ outFile.write(" VolumeMapP.SubBlockWrite[" + volumeNames[i] + "] -> BlockStorageC_" + volumeNames[i] + "; \n")
+ outFile.write("\n")
+
+ elif volumeTypes[volumeNames[i]] == "log":
+ outFile.write("\n")
+ outFile.write(" components new LogStorageC(" + volumeNames[i] + ", " + volumeOptions[volumeNames[i]] + ") as LogStorageC_" + volumeNames[i] + "; \n")
+ outFile.write(" VolumeMapP.SubLogRead[" + volumeNames[i] + "] -> LogStorageC_" + volumeNames[i] + "; \n")
+ outFile.write(" VolumeMapP.SubLogWrite[" + volumeNames[i] + "] -> LogStorageC_" + volumeNames[i] + "; \n")
+ outFile.write("\n")
+
+ elif volumeTypes[volumeNames[i]] == "config":
+ outFile.write(" components new ConfigStorageC(" + volumeNames[i] + ") as ConfigStorageC_" + volumeNames[i] + "; \n")
+ outFile.write(" Mount[" + volumeNames[i] + "] = ConfigStorageC_" + volumeNames[i] + "; \n")
+ outFile.write(" ConfigStorage[" + volumeNames[i] + "] = ConfigStorageC_" + volumeNames[i] + "; \n")
+ outFile.write("} \n")