]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tools/tinyos/misc/tos-storage-stm25p.in
tos-storage-stm25p: fix family support
[tinyos-2.x.git] / tools / tinyos / misc / tos-storage-stm25p.in
index c26793be078dd0d3429101d86cf787fa8b905f99..9ef1428f4094f257550b3f239fd7ff8530f2c1c0 100644 (file)
 # 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 ) ):
@@ -139,3 +321,50 @@ print "};"
 
 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")