add copies of get_input/output/etc to at least put in some prints
[pinmux.git] / src / spec / testing_stage1.py
1 #!/usr/bin/env python3
2 from nmigen.build.dsl import Resource, Subsignal, Pins
3 from nmigen.build.plat import TemplatedPlatform
4 from nmigen import Elaboratable, Signal, Module, Instance
5 from collections import OrderedDict
6
7 # Was thinking of using these functions, but skipped for simplicity for now
8 # XXX nope. the output from JSON file.
9 #from pinfunctions import (i2s, lpc, emmc, sdmmc, mspi, mquadspi, spi,
10 # quadspi, i2c, mi2c, jtag, uart, uartfull, rgbttl, ulpi, rgmii, flexbus1,
11 # flexbus2, sdram1, sdram2, sdram3, vss, vdd, sys, eint, pwm, gpio)
12
13 # File for stage 1 pinmux tested proposed by Luke,
14 # https://bugs.libre-soc.org/show_bug.cgi?id=50#c10
15
16
17 def dummy_pinset():
18 # sigh this needs to come from pinmux.
19 gpios = []
20 for i in range(16):
21 gpios.append("%d*" % i)
22 return {'uart': ['tx+', 'rx-'],
23 'gpio': gpios,
24 'i2c': ['sda*', 'scl+']}
25
26 """
27 a function is needed which turns the results of dummy_pinset()
28 into:
29
30 [UARTResource("uart", 0, tx=..., rx=..),
31 I2CResource("i2c", 0, scl=..., sda=...),
32 Resource("gpio", 0, Subsignal("i"...), Subsignal("o"...)
33 Resource("gpio", 1, Subsignal("i"...), Subsignal("o"...)
34 ...
35 ]
36 """
37
38
39 def create_resources(pinset):
40 resources = []
41 for periph, pins in pinset.items():
42 print(periph, pins)
43 if periph == 'i2c':
44 #print("I2C required!")
45 resources.append(I2CResource('i2c', 0, sda='sda', scl='scl'))
46 elif periph == 'uart':
47 #print("UART required!")
48 resources.append(UARTResource('uart', 0, tx='tx', rx='rx'))
49 elif periph == 'gpio':
50 #print("GPIO required!")
51 print ("GPIO is defined as '*' type, meaning i, o and oe needed")
52 ios = []
53 for pin in pins:
54 pname = "gpio"+pin[:-1] # strip "*" on end
55 pads = []
56 # urrrr... tristsate and io assume a single pin which is
57 # of course exactly what we don't want in an ASIC: we want
58 # *all three* pins but the damn port is not outputted
59 # as a triplet, it's a single Record named "io". sigh.
60 # therefore the only way to get a triplet of i/o/oe
61 # is to *actually* create explicit triple pins
62 pads.append(Subsignal("i",
63 Pins(pname+"_i", dir="i", assert_width=1)))
64 pads.append(Subsignal("o",
65 Pins(pname+"_o", dir="o", assert_width=1)))
66 pads.append(Subsignal("oe",
67 Pins(pname+"_oe", dir="oe", assert_width=1)))
68 ios.append(Resource.family(pname, 0, default_name=pname,
69 ios=pads))
70 resources.append(Resource.family(periph, 0, default_name="gpio",
71 ios=ios))
72
73 # add clock and reset
74 clk = Resource("clk", 0, Pins("sys_clk", dir="i"))
75 rst = Resource("rst", 0, Pins("sys_rst", dir="i"))
76 resources.append(clk)
77 resources.append(rst)
78 return resources
79
80
81 def UARTResource(*args, rx, tx):
82 io = []
83 io.append(Subsignal("rx", Pins(rx, dir="i", assert_width=1)))
84 io.append(Subsignal("tx", Pins(tx, dir="o", assert_width=1)))
85 return Resource.family(*args, default_name="uart", ios=io)
86
87
88 def I2CResource(*args, scl, sda):
89 io = []
90 io.append(Subsignal("scl", Pins(scl, dir="io", assert_width=1)))
91 io.append(Subsignal("sda", Pins(sda, dir="io", assert_width=1)))
92 return Resource.family(*args, default_name="i2c", ios=io)
93
94
95 # ridiculously-simple top-level module. doesn't even have a sync domain
96 # and can't have one until a clock has been established by DummyPlatform.
97 class Blinker(Elaboratable):
98 def __init__(self):
99 pass
100 def elaborate(self, platform):
101 m = Module()
102 count = Signal(5)
103 m.d.sync += count.eq(5)
104 print ("resources", platform.resources.items())
105 gpio = platform.request("gpio", 0)
106 print (gpio, gpio.layout, gpio.fields)
107 # get the GPIO bank, mess about with some of the pins
108 m.d.comb += gpio.gpio0.o.eq(1)
109 m.d.comb += gpio.gpio1.o.eq(gpio.gpio2.i)
110 m.d.comb += gpio.gpio1.oe.eq(count[4])
111 m.d.sync += count[0].eq(gpio.gpio1.i)
112 # get the UART resource, mess with the output tx
113 uart = platform.request("uart", 0)
114 print (uart, uart.fields)
115 m.d.comb += uart.tx.eq(1)
116 return m
117
118
119 '''
120 _trellis_command_templates = [
121 r"""
122 {{invoke_tool("yosys")}}
123 {{quiet("-q")}}
124 {{get_override("yosys_opts")|options}}
125 -l {{name}}.rpt
126 {{name}}.ys
127 """,
128 ]
129 '''
130
131 # sigh, have to create a dummy platform for now.
132 # TODO: investigate how the heck to get it to output ilang. or verilog.
133 # or, anything, really. but at least it doesn't barf
134 class DummyPlatform(TemplatedPlatform):
135 connectors = []
136 resources = OrderedDict()
137 required_tools = []
138 command_templates = ['/bin/true']
139 file_templates = {
140 **TemplatedPlatform.build_script_templates,
141 "{{name}}.il": r"""
142 # {{autogenerated}}
143 {{emit_rtlil()}}
144 """,
145 "{{name}}.debug.v": r"""
146 /* {{autogenerated}} */
147 {{emit_debug_verilog()}}
148 """,
149 }
150 toolchain = None
151 default_clk = "clk" # should be picked up / overridden by platform sys.clk
152 default_rst = "rst" # should be picked up / overridden by platform sys.rst
153 def __init__(self, resources):
154 super().__init__()
155 self.add_resources(resources)
156
157 # XXX these aren't strictly necessary right now but the next
158 # phase is to add JTAG Boundary Scan so it maaay be worth adding?
159 # at least for the print statements
160 def get_input(self, pin, port, attrs, invert):
161 self._check_feature("single-ended input", pin, attrs,
162 valid_xdrs=(0,), valid_attrs=None)
163
164 print (" get_input", pin, "port", port, port.layout)
165 m = Module()
166 m.d.comb += pin.i.eq(self._invert_if(invert, port))
167 return m
168
169 def get_output(self, pin, port, attrs, invert):
170 self._check_feature("single-ended output", pin, attrs,
171 valid_xdrs=(0,), valid_attrs=None)
172
173 print (" get_output", pin, "port", port, port.layout)
174 m = Module()
175 m.d.comb += port.eq(self._invert_if(invert, pin.o))
176 return m
177
178 def get_tristate(self, pin, port, attrs, invert):
179 self._check_feature("single-ended tristate", pin, attrs,
180 valid_xdrs=(0,), valid_attrs=None)
181
182 m = Module()
183 m.submodules += Instance("$tribuf",
184 p_WIDTH=pin.width,
185 i_EN=pin.oe,
186 i_A=self._invert_if(invert, pin.o),
187 o_Y=port,
188 )
189 return m
190
191 def get_input_output(self, pin, port, attrs, invert):
192 self._check_feature("single-ended input/output", pin, attrs,
193 valid_xdrs=(0,), valid_attrs=None)
194 print (" get_input_output", pin, "port", port, port.layout)
195 m = Module()
196 m.submodules += Instance("$tribuf",
197 p_WIDTH=pin.width,
198 i_EN=pin.oe,
199 i_A=self._invert_if(invert, pin.o),
200 o_Y=port,
201 )
202 m.d.comb += pin.i.eq(self._invert_if(invert, port))
203 return m
204
205
206 """
207 and to create a Platform instance with that list, and build
208 something random
209
210 p=Platform()
211 p.resources=listofstuff
212 p.build(Blinker())
213 """
214 pinset = dummy_pinset()
215 resources = create_resources(pinset)
216 print(pinset)
217 print(resources)
218 p = DummyPlatform (resources)
219 p.build(Blinker())
220