Revert Microwatt workaround
[soc.git] / src / soc / bus / external_core.py
1 #!/usr/bin/env python3
2 #
3 # SPDX-License-Identifier: LGPLv3+
4 # Copyright (C) 2022 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
5 # Sponsored by NLnet and NGI POINTER under EU Grants 871528 and 957073
6 # Part of the Libre-SOC Project.
7 #
8 # this is a wrapper around the external_core_top.v verilog module
9 # which allows for faster development iteration (oh and microwatt or
10 # other core to be dropped into a peripheral fabric)
11
12 from nmigen import (Elaboratable, Cat, Module, Signal, ClockSignal, Instance,
13 ResetSignal, Const)
14 from nmigen.cli import rtlil, verilog
15
16 from soc.debug.dmi import DMIInterface
17 from nmigen_soc.wishbone.bus import Interface
18 import os
19
20 __all__ = ["ExternalCore"]
21
22
23 class ExternalCore(Elaboratable):
24 """External Core verilog wrapper for microwatt and libre-soc
25 (actually, anything prepared to map to the Signals defined below)
26 remember to call ExternalCore.add_verilog_source
27 """
28
29 def __init__(self, ibus=None, dbus=None, features=None, name=None):
30
31 # set up the icache wishbone bus
32 if features is None:
33 features = frozenset(("stall",))
34 if ibus is None:
35 ibus = Interface(addr_width=32,
36 data_width=64,
37 features=features,
38 granularity=8,
39 name="core_ibus")
40 if dbus is None:
41 dbus = Interface(addr_width=32,
42 data_width=64,
43 features=features,
44 granularity=8,
45 name="core_dbus")
46 self.dmi = DMIInterface(name="dmi")
47 self.ibus = ibus
48 self.dbus = dbus
49
50 assert len(self.ibus.dat_r) == 64, "bus width must be 64"
51 assert len(self.dbus.dat_r) == 64, "bus width must be 64"
52
53 # IRQ for data buffer receive/xmit
54 self.irq = Signal()
55
56 # debug monitoring signals
57 self.nia = Signal(64)
58 self.nia_req = Signal()
59 self.msr = Signal(64)
60 self.ldst_addr = Signal(64)
61 self.ldst_req = Signal()
62
63 # alternative reset and termination indicator
64 self.alt_reset = Signal()
65 self.terminated_o = Signal()
66
67 @classmethod
68 def add_verilog_source(cls, verilog_src_dir, platform):
69 # add each of the verilog sources, needed for when doing platform.build
70 for fname in ['external_core_top.v',
71 ]:
72 # prepend the src directory to each filename, add its contents
73 fullname = os.path.join(verilog_src_dir, fname)
74 with open(fullname) as f:
75 platform.add_file(fullname, f)
76
77 def elaborate(self, platform):
78 m = Module()
79 comb = m.d.comb
80
81 # create definition of external core here, so that
82 # nmigen understands I/O directions (defined by i_ and o_ prefixes)
83 ibus, dbus, dmi = self.ibus, self.dbus, self.dmi
84
85 ibus_adr = Signal(32)
86 dbus_adr = Signal(32)
87 m.d.comb += ibus.adr.eq(ibus_adr)
88 m.d.comb += dbus.adr.eq(dbus_adr)
89
90 kwargs = {
91 # clock/reset signals
92 'i_clk': ClockSignal(),
93 'i_rst': ResetSignal(),
94 # DMI interface
95 'i_dmi_addr': dmi.addr_i,
96 'i_dmi_req': dmi.req_i,
97 'i_dmi_wr': dmi.we_i,
98 'i_dmi_din': dmi.din,
99 'o_dmi_dout': dmi.dout,
100 'o_dmi_ack': dmi.ack_o,
101 # debug/monitor signals
102 'o_nia': self.nia,
103 'o_nia_req': self.nia_req,
104 'o_msr_o': self.msr,
105 'o_ldst_addr': self.ldst_addr,
106 'o_ldst_req': self.ldst_req,
107 'i_alt_reset': self.alt_reset,
108 'o_terminated_out': self.terminated_o,
109 # wishbone instruction bus
110 'o_wishbone_insn_out.adr': ibus_adr,
111 'o_wishbone_insn_out.dat': ibus.dat_w,
112 'o_wishbone_insn_out.sel': ibus.sel,
113 'o_wishbone_insn_out.cyc': ibus.cyc,
114 'o_wishbone_insn_out.stb': ibus.stb,
115 'o_wishbone_insn_out.we': ibus.we,
116 'i_wishbone_insn_in.dat': ibus.dat_r,
117 'i_wishbone_insn_in.ack': ibus.ack,
118 'i_wishbone_insn_in.stall': ibus.stall,
119 # wishbone data bus
120 'o_wishbone_data_out.adr': dbus_adr,
121 'o_wishbone_data_out.dat': dbus.dat_w,
122 'o_wishbone_data_out.sel': dbus.sel,
123 'o_wishbone_data_out.cyc': dbus.cyc,
124 'o_wishbone_data_out.stb': dbus.stb,
125 'o_wishbone_data_out.we': dbus.we,
126 'i_wishbone_data_in.dat': dbus.dat_r,
127 'i_wishbone_data_in.ack': dbus.ack,
128 'i_wishbone_data_in.stall': dbus.stall,
129 # external interrupt request
130 'i_ext_irq': self.irq,
131 }
132 core = Instance("external_core_top", **kwargs)
133 m.submodules['core_top'] = core
134
135 return m
136
137
138 def create_ilang(dut, ports, test_name):
139 vl = rtlil.convert(dut, name=test_name, ports=ports)
140 with open("%s.il" % test_name, "w") as f:
141 f.write(vl)
142
143 def create_verilog(dut, ports, test_name):
144 vl = verilog.convert(dut, name=test_name, ports=ports)
145 with open("%s.v" % test_name, "w") as f:
146 f.write(vl)
147
148
149 if __name__ == "__main__":
150 core = ExternalCore(name="core")
151 create_ilang(core, [
152 core.ibus.cyc, core.ibus.stb, core.ibus.ack,
153 core.ibus.dat_r, core.ibus.dat_w, core.ibus.adr,
154 core.ibus.we, core.ibus.sel, core.ibus.stall,
155 core.dbus.cyc, core.dbus.stb, core.dbus.ack,
156 core.dbus.dat_r, core.dbus.dat_w, core.dbus.adr,
157 core.dbus.we, core.dbus.sel,
158 core.irq, core.alt_reset, core.terminated_o,
159 core.msr, core.nia, core.nia_req,
160 core.ldst_addr, core.ldst_req,
161 core.dmi.addr_i, core.dmi.req_i, core.dmi.we_i,
162 core.dmi.din, core.dmi.dout, core.dmi.ack_o,
163 ], "core_0")
164