changeset 256:225f444019b1

Added build and flash menu option
author Windel Bouwman
date Sun, 04 Aug 2013 18:32:04 +0200
parents 7416c923a02a
children 703321743e8a
files README.md python/astviewer.py python/codeedit.py python/codegenarm.py python/icons/info.png python/icons/warning.png python/ide.py python/ir/function.py python/stm32.py python/stm32f4/burn.c3 python/testir.py
diffstat 11 files changed, 144 insertions(+), 94 deletions(-) [+]
line wrap: on
line diff
--- a/README.md	Sun Aug 04 15:10:10 2013 +0200
+++ b/README.md	Sun Aug 04 18:32:04 2013 +0200
@@ -1,7 +1,7 @@
 
 # Project goals
-* To write a microkernel sort of OS.
-* Write the kernel in C ('cos')
+* To write a microkernel OS.
+* Write the kernel in C3 ('cos')
 * Write a kernel in oberon like language and be able to compile this with the ide.
 * Create python scripts that form the major part of the OS.
 * Make IDE in python that can compile the OS.
@@ -19,7 +19,12 @@
 # How to start the IDE
 
     cd python
-    python runide.py
+    python ide.py
+
+# Run unittests
+
+   cd python
+   python -m unittest
 
 [![Build Status](https://drone.io/bitbucket.org/windel/lcfos/status.png)](https://drone.io/bitbucket.org/windel/lcfos/latest)
 
--- a/python/astviewer.py	Sun Aug 04 15:10:10 2013 +0200
+++ b/python/astviewer.py	Sun Aug 04 18:32:04 2013 +0200
@@ -3,19 +3,22 @@
 from c3 import Visitor, astnodes
 
 class AstModelBuilder:
-   def __init__(self):
+    def __init__(self):
       self.functionIco = QIcon(QPixmap('icons/functionicon.png').scaled(32, 32))
       self.variableIco = QIcon(QPixmap('icons/variableicon.png').scaled(32, 32))
       self.model = QStandardItemModel()
       self.model.setHorizontalHeaderLabels(['Object', 'Type'])
-   def build(self, pkg):
-      #self.model.clear()
-      c = self.model.rowCount()
-      self.model.removeRows(0, c)
-      self.curItem = self.model.invisibleRootItem()
-      visitor = Visitor()
-      visitor.visit(pkg, self.p1, self.p2)
-   def p1(self, node):
+
+    def build(self, pkg):
+        #self.model.clear()
+        c = self.model.rowCount()
+        self.model.removeRows(0, c)
+        self.curItem = self.model.invisibleRootItem()
+        if pkg:
+            visitor = Visitor()
+            visitor.visit(pkg, self.p1, self.p2)
+
+    def p1(self, node):
       if type(node) is astnodes.Variable:
          i = QStandardItem(self.variableIco, str(node))
       elif type(node) is astnodes.Function:
@@ -30,25 +33,26 @@
       i.setData(node)
       self.curItem.appendRow([i, ti])
       self.curItem = i
-   def p2(self, node):
+
+    def p2(self, node):
       if type(node) in [astnodes.Variable, astnodes.Function, astnodes.Package]:
          self.curItem = self.curItem.parent()
 
 # The actual widget:
 class AstViewer(QTreeView):
-   sigNodeSelected = pyqtSignal(object)
-   def __init__(self, parent=None):
+    sigNodeSelected = pyqtSignal(object)
+    def __init__(self, parent=None):
       super(AstViewer, self).__init__(parent)
       self.clicked.connect(self.selectHandler)
       self.modelBuilder = AstModelBuilder()
       self.setModel(self.modelBuilder.model)
 
-   def setAst(self, ast):
-      """ Create a new model and add all ast elements to it """
-      self.modelBuilder.build(ast)
-      self.expandAll()
+    def setAst(self, ast):
+        """ Create a new model and add all ast elements to it """
+        self.modelBuilder.build(ast)
+        self.expandAll()
 
-   def selectHandler(self, index):
+    def selectHandler(self, index):
       if not index.isValid():
          return
       model = self.model()
--- a/python/codeedit.py	Sun Aug 04 15:10:10 2013 +0200
+++ b/python/codeedit.py	Sun Aug 04 18:32:04 2013 +0200
@@ -36,24 +36,24 @@
       self.t.start()
 
     def updateCursor(self):
-      self.blinkcursor = not self.blinkcursor
-      self.update()
-      #self.update(self.cursorX, self.cursorY, self.charWidth, self.charHeight)
+        self.blinkcursor = not self.blinkcursor
+        self.update()
+        #self.update(self.cursorX, self.cursorY, self.charWidth, self.charHeight)
 
     def setSource(self, src):
-      self.src = src
-      self.adjust()
+        self.src = src
+        self.adjust()
 
     def getSource(self):
-      return self.src
+        return self.src
 
     def setErrors(self, el):
-      self.errorlist = el
-      self.update()
+        self.errorlist = el
+        self.update()
 
     def setCursorPosition(self, c):
-      self.cursorPosition = clipVal(c, 0, len(self.src))
-      self.update()
+        self.cursorPosition = clipVal(c, 0, len(self.src))
+        self.update()
 
     CursorPosition = property(lambda self: self.cursorPosition, setCursorPosition)
 
@@ -95,42 +95,51 @@
 
     def showRow(self, r):
       self.scrollArea.ensureVisible(self.xposTXT, r * self.charHeight, 4, self.charHeight)
+
     # Annotations:
     def addAnnotation(self, row, col, ln, msg):
       pass
+
     # Text modification:
     def getChar(self, pos):
       pass
+
     def insertText(self, txt):
-      self.setSource(self.src[0:self.CursorPosition] + txt + self.src[self.CursorPosition:])
-      self.CursorPosition += len(txt)
-      self.textChanged.emit()
+        self.setSource(self.src[0:self.CursorPosition] + txt + self.src[self.CursorPosition:])
+        self.CursorPosition += len(txt)
+        self.textChanged.emit()
+
     def deleteChar(self):
-      self.setSource(self.src[0:self.CursorPosition] + self.src[self.CursorPosition+1:])
-      self.textChanged.emit()
+        self.setSource(self.src[0:self.CursorPosition] + self.src[self.CursorPosition+1:])
+        self.textChanged.emit()
+
     def GotoNextChar(self):
-      if self.src[self.CursorPosition] != '\n':
-         self.CursorPosition += 1
+        if self.src[self.CursorPosition] != '\n':
+            self.CursorPosition += 1
+
     def GotoPrevChar(self):
-      if self.src[self.CursorPosition - 1] != '\n':
-         self.CursorPosition -= 1
+        if self.src[self.CursorPosition - 1] != '\n':
+            self.CursorPosition -= 1
+
     def GotoNextLine(self):
-      curLine = self.CurrentLine
-      c = self.CursorCol - 1 # go to zero based
-      self.CursorPosition += len(curLine) - c + 1 # line break char!
-      curLine = self.CurrentLine
-      if len(curLine) < c:
-         self.CursorPosition += len(curLine)
-      else:
-         self.CursorPosition += c
-      self.showRow(self.CursorRow)
+        curLine = self.CurrentLine
+        c = self.CursorCol - 1 # go to zero based
+        self.CursorPosition += len(curLine) - c + 1 # line break char!
+        curLine = self.CurrentLine
+        if len(curLine) < c:
+            self.CursorPosition += len(curLine)
+        else:
+            self.CursorPosition += c
+        self.showRow(self.CursorRow)
+
     def GotoPrevLine(self):
-      c = self.CursorCol - 1 # go to zero based
-      self.CursorPosition -= c + 1 # line break char!
-      curLine = self.CurrentLine
-      if len(curLine) > c:
-         self.CursorPosition -= len(curLine) - c
-      self.showRow(self.CursorRow)
+        c = self.CursorCol - 1 # go to zero based
+        self.CursorPosition -= c + 1 # line break char!
+        curLine = self.CurrentLine
+        if len(curLine) > c:
+            self.CursorPosition -= len(curLine) - c
+        self.showRow(self.CursorRow)
+
     def paintEvent(self, event):
       # Helper variables:
       er = event.rect()
@@ -209,25 +218,26 @@
       self.update()
 
     def mousePressEvent(self, event):
-      pos = event.pos()
-      if pos.x() > self.xposTXT and pos.x():
-         c = round((pos.x() - self.xposTXT) / self.charWidth)
-         r = int(pos.y() / self.charHeight) + 1
-         self.setRowCol(r, c)
+        pos = event.pos()
+        if pos.x() > self.xposTXT and pos.x():
+            c = round((pos.x() - self.xposTXT) / self.charWidth)
+            r = int(pos.y() / self.charHeight) + 1
+            self.setRowCol(r, c)
+        super().mousePressEvent(event)
 
     def adjust(self):
-      metrics = self.fontMetrics()
-      self.charHeight = metrics.height()
-      self.charWidth = metrics.width('x')
-      self.charDescent = metrics.descent()
-      self.xposERR = GAP
-      self.xposLNA = self.xposERR + GAP + self.errorPixmap.width()
-      self.xposTXT = self.xposLNA + 4 * self.charWidth + GAP
-      self.xposEnd = self.xposTXT + self.charWidth * 80
-      self.setMinimumWidth(self.xposEnd)
-      txt = self.src.split('\n')
-      self.setMinimumHeight(self.charHeight * len(txt))
-      self.update()
+        metrics = self.fontMetrics()
+        self.charHeight = metrics.height()
+        self.charWidth = metrics.width('x')
+        self.charDescent = metrics.descent()
+        self.xposERR = GAP
+        self.xposLNA = self.xposERR + GAP + self.errorPixmap.width()
+        self.xposTXT = self.xposLNA + 4 * self.charWidth + GAP
+        self.xposEnd = self.xposTXT + self.charWidth * 80
+        self.setMinimumWidth(self.xposEnd)
+        txt = self.src.split('\n')
+        self.setMinimumHeight(self.charHeight * len(txt))
+        self.update()
 
 class CodeEdit(QScrollArea):
     def __init__(self):
@@ -248,6 +258,7 @@
 
     def setFocus(self):
         self.ic.setFocus()
+        super().setFocus()
 
     def setFileName(self, fn):
         self.filename = fn
--- a/python/codegenarm.py	Sun Aug 04 15:10:10 2013 +0200
+++ b/python/codegenarm.py	Sun Aug 04 18:32:04 2013 +0200
@@ -62,6 +62,8 @@
             self.align()
         self.outs.backpatch()
         self.outs.backpatch()
+        code = self.outs.getSection('code').to_bytes()
+        self.logger.info('Generated {} bytes code'.format(len(code)))
 
     def dcd(self, x):
         self.emit(arm.dcd_ins(Imm32(x)))
Binary file python/icons/info.png has changed
Binary file python/icons/warning.png has changed
--- a/python/ide.py	Sun Aug 04 15:10:10 2013 +0200
+++ b/python/ide.py	Sun Aug 04 18:32:04 2013 +0200
@@ -16,12 +16,13 @@
 import zcc
 import outstream
 
+logformat='%(asctime)s|%(levelname)s|%(name)s|%(msg)s'
 
 class BuildOutput(QTextEdit):
     """ Build output component """
     def __init__(self, parent=None):
         super(BuildOutput, self).__init__(parent)
-        fmt = logging.Formatter(fmt='%(asctime)s %(levelname)s %(name)s %(msg)s')
+        fmt = logging.Formatter(fmt=logformat)
         class MyHandler(logging.Handler):
             def emit(self2, x):
                 self.append(str(fmt.format(x)))
@@ -57,11 +58,11 @@
          self.model.appendRow([item, irow, icol])
 
     def itemSelected(self, index):
-      if not index.isValid():
-         return
-      item = self.model.itemFromIndex(index)
-      err = item.data()
-      self.sigErrorSelected.emit(err)
+        if not index.isValid():
+            return
+        item = self.model.itemFromIndex(index)
+        err = item.data()
+        self.sigErrorSelected.emit(err)
 
 
 class AboutDialog(QDialog):
@@ -87,7 +88,7 @@
 class Ide(QMainWindow):
     def __init__(self, parent=None):
         super(Ide, self).__init__(parent)
-
+        self.to_open_files = []
 
         self.setWindowTitle('LCFOS IDE')
         icon = QIcon('icons/logo.png')
@@ -103,6 +104,7 @@
         self.mdiArea = QMdiArea()
         self.mdiArea.setViewMode(QMdiArea.TabbedView)
         self.mdiArea.setTabsClosable(True)
+        self.mdiArea.setTabsMovable(True)
         self.setCentralWidget(self.mdiArea)
 
         # Create components:
@@ -147,6 +149,7 @@
         addMenuEntry("Open", self.fileMenu, self.openFile, shortcut=QKeySequence(QKeySequence.Open))
         addMenuEntry("Save", self.fileMenu, self.saveFile, shortcut=QKeySequence(QKeySequence.Save))
         addMenuEntry("Build", self.fileMenu, self.buildFile, shortcut=QKeySequence("F7"))
+        addMenuEntry("Build and flash", self.fileMenu, self.buildFileAndFlash, shortcut=QKeySequence("F8"))
 
         self.helpAction  = QAction('Help', self)
         self.helpAction.setShortcut(QKeySequence('F1'))
@@ -217,8 +220,13 @@
             self.restoreGeometry(self.settings.value('mainwindowgeometry'))
         if self.settings.contains('lastfiles'):
             lfs = self.settings.value('lastfiles')
-            for lf in lfs:
-                self.loadFile(lf)
+            self.to_open_files.extend(lfs)
+
+    def showEvent(self, ev):
+        super().showEvent(ev)
+        while self.to_open_files:
+            fn = self.to_open_files.pop(0)
+            self.loadFile(fn)
 
     def closeEvent(self, ev):
         self.settings.setValue('mainwindowstate', self.saveState())
@@ -282,6 +290,18 @@
             ce.setErrors(self.diag.diags)
             return
 
+    def buildFileAndFlash(self):
+        ce = self.activeMdiChild()
+        if not ce:
+            return
+        self.diag.clear()
+        outs = outstream.TextOutputStream()
+        if not zcc.zcc(ce.Source, outs, self.diag, do_optimize=True):
+            # Set errors:
+            self.builderrors.setErrorList(self.diag.diags)
+            ce.setErrors(self.diag.diags)
+            return
+
         code_s = outs.getSection('code')
         self.debugInfo = code_s.debugInfos()
         if self.ctrlToolbar.device:
@@ -291,10 +311,12 @@
             stl = self.ctrlToolbar.device.iface
             stl.reset()
             stl.halt()
+            stl.run()
         logging.info('Done!')
 
+
 if __name__ == '__main__':
-    logging.basicConfig(format='%(asctime)s %(levelname)s %(name)s %(message)s', level=logging.DEBUG)
+    logging.basicConfig(format=logformat, level=logging.DEBUG)
     app = QApplication(sys.argv)
     ide = Ide()
     ide.show()
--- a/python/ir/function.py	Sun Aug 04 15:10:10 2013 +0200
+++ b/python/ir/function.py	Sun Aug 04 18:32:04 2013 +0200
@@ -38,14 +38,12 @@
             bb.check()
 
     def call(self, *args):
-        print(args)
         varmap = {}
         bb = self.Entry
         ip = 0
         while True:
             i = bb.Instructions[ip]
             ip += 1
-            print(i)
             return
 
 
--- a/python/stm32.py	Sun Aug 04 15:10:10 2013 +0200
+++ b/python/stm32.py	Sun Aug 04 18:32:04 2013 +0200
@@ -1,4 +1,5 @@
 import time
+import logging
 from devices import Device, registerDevice, STLinkException, Interface
 import stlink
 
@@ -100,7 +101,7 @@
       self.unlockFlashIf()
       self.writeFlashCrPsiz(2) # writes are 32 bits aligned
       self.setFlashCrPg()
-      self.logger.info('writing {0} bytes'.format(len(content)), end='')
+      self.logger.info('writing {0} bytes'.format(len(content)))
       offset = 0
       t1 = time.time()
       while offset < len(content):
@@ -113,10 +114,10 @@
          # Use simple mem32 writes:
          self.iface.write_mem32(address + offset, chunk)
          offset += size
-         print('.', end='', flush=True)
+         self.logger.info('.')
       t2 = time.time()
-      print('Done!')
-      print('Speed: {0} bytes/second'.format(len(content)/(t2-t1)))
+      self.logger.info('Done!')
+      self.logger.info('Speed: {0} bytes/second'.format(len(content)/(t2-t1)))
       self.lockFlash()
       # verfify program:
       self.verifyFlash(address, content)
@@ -135,12 +136,14 @@
       self.waitFlashBusy()
       self.clearFlashCrMer()
       self.lockFlash()
+
    def verifyFlash(self, address, content):
       device_content = self.readFlash(address, len(content))
       ok = content == device_content
-      print('Verify:', ok)
+      self.logger.info('Verify: {}'.format(ok))
+
    def readFlash(self, address, size):
-      print('Reading {1} bytes from 0x{0:X}'.format(address, size), end='')
+      self.logger.info('Reading {1} bytes from 0x{0:X}'.format(address, size))
       offset = 0
       tmp_size = 0x1800
       t1 = time.time()
@@ -159,14 +162,14 @@
          image += mem[:tmp_size]
 
          # indicate progress:
-         print('.', end='', flush=True)
+         self.logger.info('.')
 
          # increase for next piece:
          offset += tmp_size
       t2 = time.time()
       assert size == len(image)
-      print('Done!')
-      print('Speed: {0} bytes/second'.format(size/(t2-t1)))
+      self.logger.info('Done!')
+      self.logger.info('Speed: {0} bytes/second'.format(size/(t2-t1)))
       return image
 
    def waitFlashBusy(self):
--- a/python/stm32f4/burn.c3	Sun Aug 04 15:10:10 2013 +0200
+++ b/python/stm32f4/burn.c3	Sun Aug 04 18:32:04 2013 +0200
@@ -10,9 +10,11 @@
 
 import stm32f4xx;
 
+/*
 function void init()
 {
 }
+*/
 
 function void main()
 {
--- a/python/testir.py	Sun Aug 04 15:10:10 2013 +0200
+++ b/python/testir.py	Sun Aug 04 18:32:04 2013 +0200
@@ -1,6 +1,9 @@
 import unittest, os
 import sys
-import c3, ppci, ir, x86, transform
+import c3
+import ppci
+import ir, x86, transform
+import optimize
 
 class IrCodeTestCase(unittest.TestCase):
     def setUp(self):
@@ -117,7 +120,7 @@
     diag.printErrors(testsrc)
     ir.check()
     ir.dump()
-    transform.optimize(ir)
+    optimize.optimize(ir)
     print('dump IR')
     print('dump IR')
     print('dump IR')