3 * Copyright 2018 Jacob Lifshay
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 from migen
.fhdl
import verilog
32 from migen
.fhdl
.structure
import _Operator
34 from riscvdefs
import *
37 class CPULoadStoreCalc(Module
):
41 def get_ls_misaligned(self
, ls
, funct3
, load_store_address_low_2
):
42 """ returns whether a load/store is misaligned
44 return Case(funct3
[:2],
45 { F3
.sb
: ls
.eq(Constant(0)),
46 F3
.sh
: ls
.eq(load_store_address_low_2
[0] != 0),
47 F3
.sw
: ls
.eq(load_store_address_low_2
[0:2] != Constant(0, 2)),
48 "default": ls
.eq(Constant(1))
53 self
.clk
= ClockSignal()
54 self
.reset
= ResetSignal()
55 self
.dc_immediate
= Signal(32)
56 self
.dc_funct3
= Signal(3)
59 self
.rw_address
= Signal(32)
60 self
.rw_data_in
= Signal(32)
61 self
.rw_data_out
= Signal(32)
63 self
.load_store_address
= Signal(32)
64 self
.load_store_address_low_2
= Signal(2)
65 self
.load_store_misaligned
= Signal()
66 self
.loaded_value
= Signal(32)
68 self
.comb
+= self
.load_store_address
.eq(self
.dc_immediate
+ self
.rs1
)
69 self
.comb
+= self
.load_store_address_low_2
.eq(
70 self
.dc_immediate
[:2] + self
.rs1
[:2])
72 lsa
= self
.get_ls_misaligned(self
.load_store_misaligned
, self
.dc_funct3
,
73 self
.load_store_address_low_2
)
76 # XXX rwaddr not 31:2 any more
77 self
.comb
+= self
.rw_address
.eq(self
.load_store_address
[2:])
80 b3
= Mux(self
.load_store_address_low_2
[1],
81 Mux(self
.load_store_address_low_2
[0], self
.rs2
[0:8],
83 Mux(self
.load_store_address_low_2
[0], self
.rs2
[16:24],
85 b2
= Mux(self
.load_store_address_low_2
[1], self
.rs2
[0:8],
87 b1
= Mux(self
.load_store_address_low_2
[0], self
.rs2
[0:8],
91 self
.comb
+= self
.rw_data_in
.eq(Cat(b0
, b1
, b2
, b3
))
94 unmasked_loaded_value
= Signal(32)
96 b0
= Mux(self
.load_store_address_low_2
[1],
97 Mux(self
.load_store_address_low_2
[0], self
.rw_data_out
[24:32],
98 self
.rw_data_out
[16:24]),
99 Mux(self
.load_store_address_low_2
[0], self
.rw_data_out
[15:8],
100 self
.rw_data_out
[0:8]))
101 b1
= Mux(self
.load_store_address_low_2
[1], self
.rw_data_out
[24:31],
102 self
.rw_data_out
[8:16])
103 b23
= self
.rw_data_out
[16:32]
105 self
.comb
+= unmasked_loaded_value
.eq(Cat(b0
, b1
, b23
))
109 b0
= unmasked_loaded_value
[0:8]
110 b1
= Mux(self
.dc_funct3
[0:2] == 0,
111 Replicate(~self
.dc_funct3
[2] & unmasked_loaded_value
[7], 8),
112 unmasked_loaded_value
[8:16])
113 b2
= Mux(self
.dc_funct3
[1] == 0,
114 Replicate(~self
.dc_funct3
[2] &
115 Mux(self
.dc_funct3
[0], unmasked_loaded_value
[15],
116 unmasked_loaded_value
[7]),
118 unmasked_loaded_value
[16:32])
120 self
.comb
+= self
.loaded_value
.eq(Cat(b0
, b1
, b2
))
123 if __name__
== "__main__":
124 example
= CPULoadStoreCalc()
125 print(verilog
.convert(example
,
127 example
.dc_immediate
,
134 example
.load_store_address
,
135 example
.load_store_address_low_2
,
136 example
.load_store_misaligned
,
137 example
.loaded_value
,