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_data_in
= Signal(32)
60 self
.rw_data_out
= Signal(32)
62 self
.load_store_address
= Signal(32)
63 self
.load_store_address_low_2
= Signal(2)
64 self
.load_store_misaligned
= Signal()
65 self
.loaded_value
= Signal(32)
67 self
.comb
+= self
.load_store_address
.eq(self
.dc_immediate
+ self
.rs1
)
68 self
.comb
+= self
.load_store_address_low_2
.eq(
69 self
.dc_immediate
[:2] + self
.rs1
[:2])
71 lsa
= self
.get_ls_misaligned(self
.load_store_misaligned
, self
.dc_funct3
,
72 self
.load_store_address_low_2
)
76 b3
= Mux(self
.load_store_address_low_2
[1],
77 Mux(self
.load_store_address_low_2
[0], self
.rs2
[0:8],
79 Mux(self
.load_store_address_low_2
[0], self
.rs2
[16:24],
81 b2
= Mux(self
.load_store_address_low_2
[1], self
.rs2
[0:8],
83 b1
= Mux(self
.load_store_address_low_2
[0], self
.rs2
[0:8],
87 self
.comb
+= self
.rw_data_in
.eq(Cat(b0
, b1
, b2
, b3
))
90 unmasked_loaded_value
= Signal(32)
92 b0
= Mux(self
.load_store_address_low_2
[1],
93 Mux(self
.load_store_address_low_2
[0], self
.rw_data_out
[24:32],
94 self
.rw_data_out
[16:24]),
95 Mux(self
.load_store_address_low_2
[0], self
.rw_data_out
[15:8],
96 self
.rw_data_out
[0:8]))
97 b1
= Mux(self
.load_store_address_low_2
[1], self
.rw_data_out
[24:31],
98 self
.rw_data_out
[8:16])
99 b23
= self
.rw_data_out
[16:32]
101 self
.comb
+= unmasked_loaded_value
.eq(Cat(b0
, b1
, b23
))
105 b0
= unmasked_loaded_value
[0:8]
106 b1
= Mux(self
.dc_funct3
[0:2] == 0,
107 Replicate(~self
.dc_funct3
[2] & unmasked_loaded_value
[7], 8),
108 unmasked_loaded_value
[8:16])
109 b2
= Mux(self
.dc_funct3
[1] == 0,
110 Replicate(~self
.dc_funct3
[2] &
111 Mux(self
.dc_funct3
[0], unmasked_loaded_value
[15],
112 unmasked_loaded_value
[7]),
114 unmasked_loaded_value
[16:32])
116 self
.comb
+= self
.loaded_value
.eq(Cat(b0
, b1
, b2
))
119 if __name__
== "__main__":
120 example
= CPULoadStoreCalc()
121 print(verilog
.convert(example
,
123 example
.dc_immediate
,
129 example
.load_store_address
,
130 example
.load_store_address_low_2
,
131 example
.load_store_misaligned
,
132 example
.loaded_value
,