changeset 237:81752b0f85a5

Added burn led test program
author Windel Bouwman
date Wed, 17 Jul 2013 22:31:54 +0200
parents 8786811a5a59
children 90637d1bbfad
files python/c3/examples/types.c3 python/codegenarm.py python/cortexm3.py python/outstream.py python/stm32f4/burn.c3 python/testasm.py python/testir.py python/testzcc.py python/transform.py python/zcc.py
diffstat 10 files changed, 277 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/c3/examples/types.c3	Wed Jul 17 22:31:54 2013 +0200
@@ -0,0 +1,40 @@
+
+/*
+ Demo of how to define types
+*/
+
+package typedemo;
+
+type int A;
+type int B;
+type struct {
+  int x, y;
+  A z;
+} C;
+type struct {
+  C x;
+  B y;
+  int z;
+} D;
+
+type D* E;
+
+function int testcast()
+{
+    var A a;
+    var B b;
+    a = 3;
+    b = a;
+    var C c;
+    c.x = a;
+    c.z = c.y;
+    var D d;
+    var E e;
+    var D* e2;
+    e = &d;
+    e2 = e;
+    e2->x.x = 22;
+    
+    return 0;
+}
+
--- a/python/codegenarm.py	Mon Jul 15 20:15:31 2013 +0200
+++ b/python/codegenarm.py	Wed Jul 17 22:31:54 2013 +0200
@@ -28,8 +28,11 @@
 
         # Manually inserted startup code:
         self.dcd(0x20000678) # initial stack ptr
-        self.dcd(0x08000401) # reset vector
+        # TODO: use label here:
+        #self.emit(arm.dcd_ins(LabelRef('reset'))) # reset vector
+        self.dcd(0x08000009) # reset vector, lsb indicates thumb mode
 
+        self.emit(Label('reset'))
         for f in ircode.Functions:
             # Add global variable addresses to immediate list:
             for gvar in ircode.Variables:
@@ -50,6 +53,8 @@
                 self.emit(Label(l))
                 self.dcd(v)
             self.align()
+        self.outs.backpatch()
+        self.outs.backpatch()
 
     def dcd(self, x):
         self.emit(arm.dcd_ins(Imm32(x)))
@@ -74,8 +79,8 @@
     def generateInstruction(self, ins):
         self.comment(str(ins))
         if type(ins) is ir.Branch:
-            tgt = Label(ins.target.name)
-            self.emit(arm.jmp_ins(tgt))
+            tgt = LabelRef(ins.target.name)
+            self.emit(arm.b_ins(tgt))
         elif type(ins) is ir.ImmLoad:
             lname = ins.target.name + '_ivalue'
             self.emit(arm.ldr_pcrel(arm.r0, LabelRef(lname)))
@@ -108,7 +113,7 @@
             elif ins.operation == '|':
                 self.emit(arm.orrregs_ins(arm.r0, arm.r1))
             else:
-                print('operation not implemented', ins.operation)
+                raise NotImplementedError('operation {} not implemented'.format(ins.operation))
             # Store value back:
             self.emit(arm.str_sprel(arm.r0, arm.MemSpRel(self.addStack(ins.result))))
         elif type(ins) is ir.Return:
@@ -121,13 +126,13 @@
             if ins.cond == '==':
                 self.emit(arm.beq_ins(tgt_yes))
             else:
-                print('TODO', ins.cond)
+                raise NotImplementedError('"{}" not covered'.format(ins.cond))
             tgt_no = Label(ins.lab2.name)
             self.emit(arm.jmp_ins(tgt_no))
         elif type(ins) is ir.Alloc:
             # Local variables are added to stack
             self.addStack(ins.value)
         else:
-            raise CompilerError('IR "{}" not covered'.format(ins))
+            raise NotImplementedError('IR "{}" not covered'.format(ins))
 
 
--- a/python/cortexm3.py	Mon Jul 15 20:15:31 2013 +0200
+++ b/python/cortexm3.py	Wed Jul 17 22:31:54 2013 +0200
@@ -201,8 +201,18 @@
     mnemonic = 'dcd'
     operands = (Imm32,)
     def __init__(self, expr):
-        assert isinstance(expr, Imm32)
-        self.expr = expr.imm
+        if isinstance(expr, Imm32):
+            self.expr = expr.imm
+            self.label = None
+        elif isinstance(expr, LabelRef):
+            self.expr = 0
+            self.label = expr
+        else:
+            raise NotImplementedError()
+
+    def resolve(self, f):
+        if self.label:
+            self.expr = f(self.label.name)
 
     def encode(self):
         return u32(self.expr)
@@ -451,35 +461,48 @@
 
 # Jumping:
 
-@armtarget.instruction
-class jmp_ins(ArmInstruction):
-    operands = (Label,)
-    mnemonic = 'jmp'
+class jumpBase_ins(ArmInstruction):
+    operands = (LabelRef,)
     def __init__(self, target_label):
-        assert type(target_label) is Label
+        assert type(target_label) is LabelRef
         self.target = target_label
-    def fixUp(self):
-        pass
-    def encode(self):
-        h = 0 # TODO
-        return u16(h)
+        self.offset = 0
+
+    def resolve(self, f):
+        la = f(self.target.name)
+        sa = self.address
+        self.offset = (la - sa)
+        if self.offset < 0:
+            # TODO: handle negative jump
+            self.offset = 0
+
     def __repr__(self):
-        return 'B {0}'.format(self.target.name)
+        return '{} {}'.format(self.mnemonic, self.target.name)
 
 @armtarget.instruction
-class beq_ins(ArmInstruction):
-    operands = (Label,)
+class b_ins(jumpBase_ins):
+    mnemonic = 'B'
+
+    def encode(self):
+        imm11 = self.offset >> 1
+        h = (0b11100 << 11) | imm11 | 1 # 1 to enable thumb mode
+        return u16(h)
+
+class cond_base_ins(jumpBase_ins):
+    def encode(self):
+        imm8 = 0
+        h = (0b1101 << 12) | (self.cond << 8) | imm8
+        return u16(h)
+
+@armtarget.instruction
+class beq_ins(cond_base_ins):
     mnemonic = 'beq'
-    def __init__(self, target_label):
-        assert type(target_label) is Label
-        self.target = target_label
-    def fixUp(self):
-        pass
-    def encode(self):
-        h = 0 # TODO
-        return u16(h)
-    def __repr__(self):
-        return 'BEQ {0}'.format(self.target.name)
+    cond = 0
+
+@armtarget.instruction
+class beq_ins(cond_base_ins):
+    mnemonic = 'bne'
+    cond = 1
 
 @armtarget.instruction
 class push_ins(ArmInstruction):
--- a/python/outstream.py	Mon Jul 15 20:15:31 2013 +0200
+++ b/python/outstream.py	Wed Jul 17 22:31:54 2013 +0200
@@ -7,24 +7,41 @@
 """
 
 
+class Section:
+    def __init__(self):
+        self.instructions = []
+
+    def emit(self, item):
+        assert isinstance(item, Instruction)
+        self.instructions.append(item)
+
+    def to_bytes(self):
+        d = bytearray()
+        for i in self.instructions:
+            addr = i.address
+            insword = i.encode()
+            assert type(insword) is bytes
+            d.extend(insword)
+        return bytes(d)
+
 class OutputStream:
     def __init__(self):
         self.sections = {}
         self.currentSection = None
 
     def emit(self, item):
-        assert isinstance(item, Instruction)
-        self.sections[self.currentSection].append(item)
+        assert self.currentSection
+        self.sections[self.currentSection].emit(item)
 
     def selectSection(self, s):
         self.currentSection = s
         if not s in self.sections:
-            self.sections[s] = []
+            self.sections[s] = Section()
 
     def getLabelAddress(self, lname):
         assert isinstance(lname, str)
         for s in self.sections.values():
-            for i in s:
+            for i in s.instructions:
                 if type(i) is Label:
                     if i.name == lname:
                         return i.address
@@ -40,7 +57,8 @@
                 address = 0x02000000
             else:
                 address = 0x0
-            for i in self.sections[s]:
+
+            for i in self.sections[s].instructions:
                 i.address = address
                 i.resolve(self.getLabelAddress)
                 bts = i.encode()
@@ -53,8 +71,8 @@
             self.dumpSection(s)
 
     def dumpSection(self, s):
-        print('.section '+s)
-        for i in self.sections[s]:
+        print('.section '+ s)
+        for i in self.sections[s].instructions:
             addr = i.address
             insword = i.encode()
             assert type(insword) is bytes
@@ -69,8 +87,6 @@
     pass
 
 class BinOutputStream(OutputStream):
-    def dump(self):
-        pass
 
     @property
     def Data(self):
@@ -80,15 +96,7 @@
     def dump(self):
         self.backpatch()
         self.backpatch()
-        section = list(self.sections.keys())[0]
-        return self.dumpSection(section)
+        section = self.sections[list(self.sections.keys())[0]]
+        return section.to_bytes()
 
-    def dumpSection(self, s):
-        d = bytearray()
-        for i in self.sections[s]:
-            addr = i.address
-            insword = i.encode()
-            assert type(insword) is bytes
-            d.extend(insword)
-        return d
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/stm32f4/burn.c3	Wed Jul 17 22:31:54 2013 +0200
@@ -0,0 +1,60 @@
+/* 
+
+This file blinks a LED on the STM32F4 discovery board.
+
+the board has 4 leds on PD12, PD13, PD14 and PD15
+
+*/
+
+package blink;
+
+type struct {
+    int MODER;
+    int OTYPER;
+    int OSPEEDR;
+    int PUPDR;
+    int IDR;
+    int ODR;
+}* GPIO_Type;
+
+type struct {
+    int CR;
+    int PLLCFGR;
+    int CFGR;
+    int CIR;
+    int AHB1RSTR;
+    int AHB2RSTR;
+    int AHB3RSTR;
+    int reserved0;
+    int APB1RSTR;
+    int APB2RSTR;
+    int reserved1a, reserved1b;
+    int AHB1ENR;
+    int AHB2ENR;
+    int AHB3ENR;
+    int reserved2;
+    int APB1ENR, APB2ENR;
+}* RCC_Type;
+
+
+// Functions:
+function void main()
+{
+    // Memory mapped control registers:
+    var GPIO_Type GPIOD;
+    GPIOD = cast<GPIO_Type>(0x40020C00);
+    var RCC_Type RCC;
+    RCC = cast<RCC_Type>(0x40023800);
+
+    // Enable the clock to port D:
+    RCC->AHB1ENR = RCC->AHB1ENR | (1 << 3);
+
+    var int pin;
+    pin = 13;
+    // PD13 == output (01)
+    GPIOD->MODER = (1 << (pin << 1));
+    GPIOD->ODR = (1 << pin);
+
+    while(true) {}
+}
+
--- a/python/testasm.py	Mon Jul 15 20:15:31 2013 +0200
+++ b/python/testasm.py	Wed Jul 17 22:31:54 2013 +0200
@@ -212,11 +212,36 @@
         self.check('0190')
 
     def testLdrPcRel(self):
+        self.feed('ldr r7, henkie')
+        self.feed('ldr r6, henkie')
         self.feed('ldr r1, henkie')
         self.feed('align 4')
         self.feed('dcd 1')
         self.feed('henkie: dcd 2')
-        self.check('014900000100000002000000')
+        self.check('024F024E 01490000 01000000 02000000')
+
+    def testBranch(self):
+        self.feed('start: b henkie')
+        self.feed('beq henkie')
+        self.feed('bne henkie')
+        self.feed('henkie: b start')
+        self.feed('eof: b eof')
+        self.check('01e000d0 ffd1fbe7 fee7')
+
+    def testBoff(self):
+        self.feed('b henkie')
+        self.feed('b henkie')
+        self.feed('b henkie')
+        self.feed('b henkie')
+        self.feed('b henkie')
+        self.feed('b henkie')
+        self.feed('b henkie')
+        self.feed('henkie:')
+        self.feed('b henkie')
+        self.feed('b henkie')
+        self.feed('b henkie')
+        self.feed('b henkie')
+        self.check('05e004e0 03e002e0 01e000e0 ffe7fee7 fde7fce7 fbe7')
 
     def testCmpRegReg(self):
         self.feed('cmp r0, r1')
--- a/python/testir.py	Mon Jul 15 20:15:31 2013 +0200
+++ b/python/testir.py	Wed Jul 17 22:31:54 2013 +0200
@@ -5,10 +5,10 @@
     def setUp(self):
         self.b = ir.Builder()
         self.cf = transform.ConstantFolder()
+        self.m = ir.Module('test')
+        self.b.setModule(self.m)
 
     def testBuilder(self):
-        m = ir.Module('test')
-        self.b.setModule(m)
         f = self.b.newFunction('test')
         self.b.setFunction(f)
         bb = self.b.newBB()
@@ -19,11 +19,22 @@
         self.b.addIns(ir.ImmLoad(v1, 5))
         self.b.addIns(ir.ImmLoad(v2, 7))
         self.b.addIns(ir.BinaryOperator(v3, '+', v1, v2))
-        self.assertEqual(3, len(m.Instructions))
-        self.cf.run(m)
-        self.assertEqual(3, len(m.Instructions))
-        self.assertIsInstance(m.Instructions[-1], ir.ImmLoad)
-        self.assertEqual(12, m.Instructions[-1].value)
+        self.assertEqual(3, len(self.m.Instructions))
+        self.cf.run(self.m)
+        self.assertEqual(3, len(self.m.Instructions))
+        self.assertIsInstance(self.m.Instructions[-1], ir.ImmLoad)
+        self.assertEqual(12, self.m.Instructions[-1].value)
+
+    def testAdd0(self):
+        f = self.b.newFunction('test')
+        self.b.setFunction(f)
+        bb = self.b.newBB()
+        self.b.setBB(bb)
+        v1 = self.b.newTmp('t')
+        v2 = self.b.newTmp('t')
+        v3 = self.b.newTmp('t')
+        self.b.addIns(ir.ImmLoad(v2, 0))
+        self.b.addIns(ir.BinaryOperator(v3, '+', v1, v2))
 
 
 testsrc = """
@@ -75,8 +86,8 @@
 """
 
 if __name__ == '__main__':
-   unittest.main()
-   sys.exit()
+   #unittest.main()
+   #sys.exit()
    diag = ppci.DiagnosticsManager()
    builder = c3.Builder(diag)
    cgenx86 = x86.X86CodeGenSimple(diag)
--- a/python/testzcc.py	Mon Jul 15 20:15:31 2013 +0200
+++ b/python/testzcc.py	Wed Jul 17 22:31:54 2013 +0200
@@ -1,15 +1,22 @@
 import unittest
+import glob
 import zcc
 
 class ZccTestCase(unittest.TestCase):
     """ Tests the compiler driver """
 
-    def testBlinkDemo(self):
+    def do(self, fn):
         """ Compile blink.c3 """
         #args = zcc.parser.parse_args(['-d', 'stm32f4/blink.c3'])
-        args = zcc.parser.parse_args(['stm32f4/blink.c3'])
+        args = zcc.parser.parse_args([fn])
         zcc.main(args)
 
+    def testExamples(self):
+        """ Test all examples in the c3/examples directory """
+        example_filenames = glob.glob('./stm32f4/*.c3')
+        for filename in example_filenames:
+            self.do(filename)
+
 if __name__ == '__main__':
     unittest.main()
 
--- a/python/transform.py	Mon Jul 15 20:15:31 2013 +0200
+++ b/python/transform.py	Wed Jul 17 22:31:54 2013 +0200
@@ -54,6 +54,37 @@
             i2 = ImmLoad(i.result, vr)
             i.Parent.replaceInstruction(i, i2)
 
+
+class ConstantMerge(InstructionPass):
+    def prepare(self):
+        self.constMap = {}
+    def onInstruction(self, i):
+        if type(i) is ImmLoad:
+            v = i.value
+            if v in self.constMap:
+                # v is already defined, re-use the imm-load from elsewhere
+                pass
+            else:
+                self.constMap[v] = i
+        elif type(i) is BinaryOperator:
+         if i.value1 in self.constMap and i.value2 in self.constMap:
+            op = i.operation
+            va = self.constMap[i.value1]
+            vb = self.constMap[i.value2]
+            if op == '+':
+               vr = va + vb
+            elif op == '*':
+               vr = va * vb
+            elif op == '-':
+               vr = va - vb
+            else:
+               vr = None
+               return
+            self.constMap[i.result] = vr
+            i2 = ImmLoad(i.result, vr)
+            i.Parent.replaceInstruction(i, i2)
+
+
 class DeadCodeDeleter(BasicBlockPass):
    def onBasicBlock(self, bb):
       def instructionUsed(ins):
--- a/python/zcc.py	Mon Jul 15 20:15:31 2013 +0200
+++ b/python/zcc.py	Wed Jul 17 22:31:54 2013 +0200
@@ -41,12 +41,14 @@
     if args.dumpir:
         outs.dump()
 
+    code_bytes = outs.sections['code'].to_bytes()
+    print('bytes:', code_bytes)
     if args.output:
         output_filename = args.output
     else:
-        output_filename = 'lc.output'
-
-    # TODO: store data
+        output_filename = 'b.output'
+    with open(output_filename, 'wb') as f:
+        f.write(code_bytes)
 
 if __name__ == '__main__':
     arguments = parser.parse_args()