Browse Source

Add python project (WIP)

spi-hax
Konrad Beckmann 2 years ago
parent
commit
658e68b90f
9 changed files with 384 additions and 0 deletions
  1. +12
    -0
      LICENSE.txt
  2. +14
    -0
      README.md
  3. +6
    -0
      software/kilsyth/__init__.py
  4. +3
    -0
      software/kilsyth/__main__.py
  5. +22
    -0
      software/kilsyth/applets/__init__.py
  6. +44
    -0
      software/kilsyth/applets/blinky/__init__.py
  7. +21
    -0
      software/kilsyth/device/__init__.py
  8. +164
    -0
      software/kilsyth/device/rev_a/__init__.py
  9. +98
    -0
      software/kilsyth/kilsyth.py

+ 12
- 0
LICENSE.txt View File

@ -0,0 +1,12 @@
Copyright (C) 2019 konrad.beckmann@gmail.com
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

+ 14
- 0
README.md View File

@ -25,6 +25,20 @@ Ideas for RevB are still being collected. Feel free to suggest changes in an iss
- Add support for reversible USB-C connector using [PI5USB30213A](https://www.diodes.com/products/connectivity-and-timing/switches-mux/protocol-switches/usb-switches/part/PI5USB30213A).
## Software usage (TODO)
Requires a patched migen and a patched ftdi library.. Nasty, I know, sorry.
```
Help:
$ python -m software.kilsyth -h
Run blinky:
$ python -m software.kilsyth run blinky
```
# Contact
Reach out to [@kbeckmann](https://twitter.com/kbeckmann) on Twitter or IRC/Freenode.

+ 6
- 0
software/kilsyth/__init__.py View File

@ -0,0 +1,6 @@
from . import kilsyth
# Is this file even needed?
if __name__ == "__main__":
kilsyth.main()

+ 3
- 0
software/kilsyth/__main__.py View File

@ -0,0 +1,3 @@
from . import kilsyth
kilsyth.main()

+ 22
- 0
software/kilsyth/applets/__init__.py View File

@ -0,0 +1,22 @@
# This is based on https://github.com/whitequark/Glasgow/blob/master/software/glasgow/applet/__init__.py
from migen import *
class KilsythApplet(Module):
all = {}
def __init_subclass__(cls, name, **kwargs):
super().__init_subclass__(**kwargs)
if name in cls.all:
raise ValueError("Applet {!r} already exists".format(name))
cls.all[name] = cls
cls.name = name
help = "applet help missing"
description = "applet description missing"
def build(self, device):
raise NotImplementedError
from . import blinky

+ 44
- 0
software/kilsyth/applets/blinky/__init__.py View File

@ -0,0 +1,44 @@
from migen import *
import os, sys
from .. import KilsythApplet
class Blinky(KilsythApplet, name="blinky"):
description = "blinks some LEDs"
help = "Blinks some LEDs"
def __init__(self, device):
self.device = device
led = device.request('user_led')
self.div = Signal(23)
self.sync += self.div.eq(self.div + 1)
self.comb += led.eq(self.div[22])
def testbench(self):
assert (yield self.div[0]) == 0
yield
assert (yield self.div[0]) == 1
yield
assert (yield self.div[0]) == 0
yield
assert (yield self.div[0]) == 1
yield
def build(self):
print("woop")
# self.device.build(self, toolchain_path='/usr/share/trellis')
self.device.build(self, toolchain_path='/usr/share/trellis')
# def test(self, device):
# led = device.request('user_led')
# blinky = Blinky(led)
# if len(sys.argv) == 2 and sys.argv[1] == "test":
# run_simulation(blinky, blinky.testbench(), vcd_name="out.vcd")
# print("Passed")
# else:
# device.build(blinky, toolchain_path='/usr/share/trellis')
# if __name__ == '__main__':

+ 21
- 0
software/kilsyth/device/__init__.py View File

@ -0,0 +1,21 @@
from migen.build.lattice import LatticePlatform
class KilsythDevice(LatticePlatform):
all = {}
def __init_subclass__(cls, name, **kwargs):
super().__init_subclass__(**kwargs)
if name == None:
return
if name in cls.all:
raise ValueError("Device {!r} already exists".format(name))
cls.all[name] = cls
cls.name = name
help = "device help missing"
description = "device description missing"
from . import rev_a

+ 164
- 0
software/kilsyth/device/rev_a/__init__.py View File

@ -0,0 +1,164 @@
from migen.build.generic_platform import *
from migen.build.lattice import LatticePlatform
from .. import *
_io = [
("clk16", 0, Pins("G3"), IOStandard("LVCMOS33")),
# user_led 0 is actually connected to WIDE:33, but it's N/C.
# Place jumper between 33 and 31 to use user led 0
("user_led", 0, Pins("WIDE:31"), IOStandard("LVCMOS33")),
("user_led", 1, Pins("WIDE:34"), IOStandard("LVCMOS33")),
("user_led", 2, Pins("WIDE:35"), IOStandard("LVCMOS33")),
("user_led", 3, Pins("WIDE:36"), IOStandard("LVCMOS33")),
("user_led", 4, Pins("WIDE:37"), IOStandard("LVCMOS33")),
("user_led", 5, Pins("WIDE:38"), IOStandard("LVCMOS33")),
("user_led", 6, Pins("WIDE:39"), IOStandard("LVCMOS33")),
("user_led", 7, Pins("WIDE:40"), IOStandard("LVCMOS33")),
("ft600", 0,
Subsignal("clk", Pins("H2")),
Subsignal("data", Pins("P4 P3 P2 P1 N4 N3 N2 N1 M3 M1 L3 L2 L1 K4 K3 K2")),
Subsignal("be", Pins("K1 J5")),
Subsignal("rd_n", Pins("M4")),
Subsignal("wr_n", Pins("J1")),
Subsignal("gpio1", Pins("G5")),
Subsignal("txe_n", Pins("J4")),
Subsignal("rxf_n", Pins("J3")),
Subsignal("oe_n", Pins("H1")),
)
]
_connectors = [
("WIDE",
"None", # 0: No pin0
# Bank 7
"F3", # 1
"F2",
"E2",
"E1",
"C1",
"D1",
"A2",
"B1",
"C2",
"B2", # 10
"A3",
"D2",
"C3",
"B3",
"A4",
"D3",
"C4",
"B4",
"A5",
"E4", # 20
"C5",
"B5",
"A6",
"D5",
# Bank 0
"C6", # 25
"B6",
"C7",
"A7",
"B8",
"A8", # 30
"A9", # 31: LED 0 if jumper is placed
"C8",
"None", # 33: LED 0 (N/C)
"B9", # 34: LED 1
"B10", # 35: LED 2
"A10", # 36: LED 3
"A11", # 37: LED 4
"C10", # 38: LED 5
"B11", # 39: LED 6
"C11", # 40: LED 7
),
("PMOD0",
"None", # 0: N/C
"A12", # 1: PMOD1
"D12", # 2: PMOD2
"A13", # 3: PMOD3
"D13", # 4: PMOD4
"None", # 5: GND
"None", # 6: 3.3V
"B12", # 7: PMOD5
"C12", # 8: PMOD6
"B13", # 9: PMOD7
"C13", # 10: PMOD8
"None", # 11: GND
"None", # 12: 3.3v
),
("PMOD1",
"None", # 0: N/C
"A14", # 1: PMOD1
"B15", # 2: PMOD2
"C15", # 3: PMOD3
"B16", # 4: PMOD4
"None", # 5: GND
"None", # 6: 3.3V
"C14", # 7: PMOD5
"D15", # 8: PMOD6
"A16", # 9: PMOD7
"C16", # 10: PMOD8
"None", # 11: GND
"None", # 12: 3.3v
),
("PMOD2",
"None", # 0: N/C
"A17", # 1: PMOD1
"C17", # 2: PMOD2
"B18", # 3: PMOD3
"B20", # 4: PMOD4
"None", # 5: GND
"None", # 6: 3.3V
"B17", # 7: PMOD5
"A18", # 8: PMOD6
"A19", # 9: PMOD7
"B19", # 10: PMOD8
"None", # 11: GND
"None", # 12: 3.3v
),
]
class KilsythRevA(KilsythDevice, name=None):
help = "Kilsyth RevA"
description = "Kilsyth RevA"
# Super must set this
idcode = None
device = None
default_clk_name = "clk16"
default_clk_period = 62.5
def __init__(self, *args, **kwargs):
LatticePlatform.__init__(self, self.device, _io, _connectors,
toolchain='trellis', *args, **kwargs)
def build(self, *args, **kwargs):
KilsythDevice.build(self, idcode=self.idcode, *args, **kwargs)
class KilsythRevA12(KilsythRevA, name="rev_a_12"):
help = "Kilsyth RevA LFE5U-12F"
description = "Kilsyth RevA LFE5U-12F"
idcode = "0x21111043"
device = "LFE5U-25F-6BG381C"
class KilsythRevA25(KilsythRevA, name="rev_a_25"):
help = "Kilsyth RevA LFE5U-25F"
description = "Kilsyth RevA LFE5U-25F"
idcode = "0x41111043"
device = "LFE5U-25F-6BG381C"
class KilsythRevA45(KilsythRevA, name="rev_a_45"):
help = "Kilsyth RevA LFE5U-45F"
description = "Kilsyth RevA LFE5U-45F"
idcode = "0x41112043"
device = "LFE5U-45F-6BG381C"
class KilsythRevA85(KilsythRevA, name="rev_a_85"):
help = "Kilsyth RevA LFE5U-85F"
description = "Kilsyth RevA LFE5U-85F"
idcode = "0x41113043"
device = "LFE5U-85F-6BG381C"

+ 98
- 0
software/kilsyth/kilsyth.py View File

@ -0,0 +1,98 @@
# This is inspired by https://github.com/whitequark/Glasgow/blob/master/software/glasgow/__init__.py
import os
import sys
import logging
import argparse
import subprocess
from .applets import *
from .device import *
def build(args):
device_cls = KilsythDevice.all[args.device]
applet_cls = KilsythApplet.all[args.applet]
device = device_cls()
applet = applet_cls(device)
device.build(applet, toolchain_path='/usr/share/trellis')
def run(args):
device_cls = KilsythDevice.all[args.device]
applet_cls = KilsythApplet.all[args.applet]
device = device_cls()
applet = applet_cls(device)
device.build(applet, toolchain_path='/usr/share/trellis')
# TODO fix irmask. Move to device
script = "; ".join([
"jtag newtap device tap -expected-id %s -irlen 8 -irmask 0xFF -ircapture 0x1" % (device.idcode),
"transport select jtag",
"adapter_khz 10000",
"init",
"svf -tap device.tap -quiet -progress %s" % ("build/top.svf"),
"exit",
])
# TODO turn into an argument
openocd_interface = "interface/ftdi/dp_busblaster.cfg"
subprocess.call(["openocd", "-f", openocd_interface, "-c", script])
def main():
print("KILSYTH [WIP]")
parser = argparse.ArgumentParser()
parser.add_argument(
"-v", "--verbose", default=0, action="count",
help="increase logging verbosity")
parser.add_argument('--device',
choices=KilsythDevice.all.keys(),
help="which device to target",
default="rev_a_12") # todo fix this
subparsers = parser.add_subparsers(dest="action", metavar="COMMAND")
subparsers.required = True
p_run = subparsers.add_parser(
"run",
description="Builds and loads an applet bitstream",
help="builds and loads an applet bitstream")
p_run_applet = p_run.add_subparsers(dest="applet", metavar="APPLET")
for applet in KilsythApplet.all.values():
p_run_applet.add_parser(
applet.name,
description=applet.description,
help=applet.help)
p_build = subparsers.add_parser(
"build",
description="Builds an applet bitstream",
help="builds an applet bitstream")
p_build_applet = p_build.add_subparsers(dest="applet", metavar="APPLET")
for applet in KilsythApplet.all.values():
p_build_applet.add_parser(
applet.name,
description=applet.description,
help=applet.help)
p_test = subparsers.add_parser(
"test",
description="Tests an applet",
help="tests an applet")
p_test_applet = p_test.add_subparsers(dest="applet", metavar="APPLET")
for applet in KilsythApplet.all.values():
p_test_applet.add_parser(
applet.name,
description=applet.description,
help=applet.help)
args = parser.parse_args()
print(args)
if args.action == "run":
run(args)
elif args.action == "build":
build(args)
elif args.action == "test":
print("Not implemented.")

Loading…
Cancel
Save