]>
Witch of Git - jade-rabbit/blob - core.py
3 from nmigen
.build
import Platform
4 from nmigen
.cli
import main
5 from nmigen
.hdl
.ast
import Statement
21 class JadeRabbitCore(Elaboratable
):
24 self
.halted
= Signal()
25 self
.addr
= Signal(16)
26 self
.d_in
= Signal(32)
27 self
.d_out
= Signal(32)
30 self
.inst
= Signal(32)
32 self
.reg_a
= Signal(range(8))
33 self
.reg_b
= Signal(range(8))
34 self
.reg_d
= Signal(range(8))
35 self
.offset
= Signal(16)
41 # Fetch - fetch data from memory
42 # Decode - read from registers
43 # Execute - do ALU work
44 # Memory (optional) - read/write memory if needed
46 self
.cycle
= Signal(range(5))
47 self
.regs
= Array(Signal(32, name
=f
"r{i}") for i
in range(8))
49 def decode(self
, m
: Module
, inst
: Statement
) -> None:
50 reg_a
, reg_b
= inst
[19:22], inst
[16:19]
53 self
.op
.eq(inst
[22:25]),
56 self
.reg_d
.eq(inst
[0:3]),
57 self
.offset
.eq(inst
[0:16]),
60 self
.a
.eq(self
.regs
[reg_a
]),
61 self
.b
.eq(self
.regs
[reg_b
]),
64 def end_inst(self
, m
: Module
, dest
: Statement
) -> None:
65 m
.d
.sync
+= self
.cycle
.eq(0)
66 m
.d
.sync
+= self
.pc
.eq(dest
)
68 def elaborate(self
, platform
: Platform
) -> Module
:
70 with m
.If(~self
.halted
):
71 m
.d
.sync
+= self
.cycle
.eq(self
.cycle
+ 1)
72 with m
.If(self
.cycle
== 0):
73 m
.d
.comb
+= self
.en
.eq(True)
74 m
.d
.comb
+= self
.rw
.eq(Rw
.READ
)
75 m
.d
.comb
+= self
.addr
.eq(self
.pc
)
76 with m
.Elif(self
.cycle
== 1):
77 self
.decode(m
, self
.d_in
)
79 with m
.Switch(self
.op
):
81 with m
.If(self
.cycle
== 2):
83 m
.d
.sync
+= self
.regs
[self
.reg_d
].eq(tmp
)
84 self
.end_inst(m
, self
.pc
+ 1)
86 with m
.If(self
.cycle
== 2):
87 tmp
= ~
(self
.a | self
.b
)
88 m
.d
.sync
+= self
.regs
[self
.reg_d
].eq(tmp
)
89 self
.end_inst(m
, self
.pc
+ 1)
91 with m
.If(self
.cycle
== 2):
92 m
.d
.comb
+= self
.en
.eq(True)
93 m
.d
.comb
+= self
.addr
.eq(self
.a
+ self
.offset
)
94 m
.d
.comb
+= self
.rw
.eq(Rw
.READ
)
95 with m
.If(self
.cycle
== 3):
96 m
.d
.sync
+= self
.regs
[self
.reg_b
].eq(self
.d_in
)
97 self
.end_inst(m
, self
.pc
+ 1)
99 with m
.If(self
.cycle
== 2):
100 m
.d
.comb
+= self
.addr
.eq(self
.a
+ self
.offset
)
101 m
.d
.comb
+= self
.en
.eq(True)
102 m
.d
.comb
+= self
.rw
.eq(Rw
.WRITE
)
103 m
.d
.comb
+= self
.d_out
.eq(self
.b
)
104 with m
.If(self
.cycle
== 3):
105 self
.end_inst(m
, self
.pc
+ 1)
107 with m
.If(self
.cycle
== 2):
108 dest
= self
.pc
+ 1 + self
.offset
109 dest
= Mux(self
.a
== self
.b
, dest
, self
.pc
+ 1)
110 self
.end_inst(m
, dest
)
111 with m
.Case(Op
.JALR
):
112 with m
.If(self
.cycle
== 2):
113 same_reg
= self
.reg_a
== self
.reg_b
114 dest
= Mux(same_reg
, self
.pc
+ 1, self
.a
)
115 m
.d
.sync
+= self
.regs
[self
.reg_b
].eq(self
.pc
+ 1)
116 self
.end_inst(m
, dest
)
117 with m
.Case(Op
.HALT
):
118 with m
.If(self
.cycle
== 2):
119 m
.d
.sync
+= self
.halted
.eq(True)
120 self
.end_inst(m
, self
.pc
+ 1)
121 with m
.Case(Op
.NOOP
):
122 with m
.If(self
.cycle
== 2):
123 self
.end_inst(m
, self
.pc
+ 1)
130 return [self
.addr
, self
.d_out
, self
.rw
, self
.en
, self
.halted
]
133 return self
.inputs() + self
.outputs()
136 class FakeRam(Elaboratable
):
137 def __init__(self
, data
):
138 self
.data
= list(data
)
139 self
.addr
= Signal(16)
140 self
.d_in
= Signal(32)
141 self
.d_out
= Signal(32)
144 self
.mem
= Memory(width
=32, depth
=2**8, init
=self
.data
)
146 def elaborate(self
, platform
: Platform
) -> Module
:
148 m
.submodules
.rdport
= rdport
= self
.mem
.read_port()
149 m
.submodules
.wrport
= wrport
= self
.mem
.write_port()
151 rdport
.addr
.eq(self
.addr
),
152 self
.d_out
.eq(rdport
.data
),
153 wrport
.addr
.eq(self
.addr
),
154 wrport
.data
.eq(self
.d_in
),
155 wrport
.en
.eq(self
.en
& (self
.rw
== Rw
.WRITE
)),
210 if __name__
== '__main__':
212 m
.submodules
.core
= core
= JadeRabbitCore()
213 m
.submodules
.ram
= ram
= FakeRam(int(x
) for x
in CODE
.strip().split())
215 ram
.addr
.eq(core
.addr
),
216 ram
.d_in
.eq(core
.d_out
),
217 core
.d_in
.eq(ram
.d_out
),
221 main(m
, ports
=core
.ports())