"""
-from nmigen.compat.sim import run_simulation
+from nmigen.compat.sim import run_simulation, Settle
from nmigen.cli import verilog, rtlil
from nmigen import Module, Signal, Mux, Elaboratable, Array, Cat
from nmutil.iocontrol import RecordObject
from nmutil.latch import SRLatch, latchregister
from soc.decoder.power_decoder2 import Data
from soc.decoder.power_enums import InternalOp
+from soc.regfile.regfile import ortreereduce
+from nmutil.util import treereduce
from soc.experiment.compldst import CompLDSTOpSubset
from soc.decoder.power_decoder2 import Data
# for testing purposes
from soc.experiment.testmem import TestMemory
-
class PortInterface(RecordObject):
"""PortInterface
self.ld = Data(regwid, "ld_data_o") # ok to be set by L0 Cache/Buf
self.st = Data(regwid, "st_data_i") # ok to be set by CompUnit
-# TODO:
+# TODO: elaborate function
class DualPortSplitter(Elaboratable):
once that is done each pair of ports may be wired directly
to the dual ports of L0CacheBuffer
+
+ The split is carried out so that, regardless of alignment or
+ mis-alignment, outgoing PortInterface[0] takes bit 4 == 0
+ of the address, whilst outgoing PortInterface[1] takes
+ bit 4 == 1.
+
+ PortInterface *may* need to be changed so that the length is
+ a binary number (accepting values 1-16).
"""
- pass
+ def __init__(self):
+ self.outp = []
+ self.outp[0] = PortInterface(name="outp_0")
+ self.outp[1] = PortInterface(name="outp_1")
+ self.inp = PortInterface(name="inp")
+
+ def elaborate(self, platform):
+ splitter = LDSTSplitter(64, 48, 4)
class DataMergerRecord(Record):
Record.__init__(self, Layout(layout), name=name)
-# TODO:
+ #FIXME: make resetless
+# TODO: formal verification
class DataMerger(Elaboratable):
"""DataMerger
- Merges data based on an address-match matrix.
- Identifies (picks) one (any) row, then uses that row,
+ Merges data based on an address-match matrix.
+ Identifies (picks) one (any) row, then uses that row,
based on matching address bits, to merge (OR) all data
rows into the output.
self.data_i = Array(ul)
self.data_o = DataMergerRecord()
- def elaborate(self, platform):
- m = Module()
- comb, sync = m.d.comb, m.d.sync
- #(1) pick a row
- m.submodules.pick = pick = PriorityEncoder(self.array_size)
- for j in range(self.array_size):
- with m.If(self.addr_match_i[j].bool()):
- pick.i.eq(pick.i||(1<<j))
- valid = ~pick.n
- idx = pick.o
- #(2) merge
- #not needed # self.data_o.eq(0)
- #TODO
+ def elaborate(self, platform):
+ m = Module()
+ comb = m.d.comb
+ #(1) pick a row
+ m.submodules.pick = pick = PriorityEncoder(self.array_size)
+ for j in range(self.array_size):
+ comb += pick.i[j].eq(self.addr_array_i[j].bool())
+ valid = ~pick.n
+ idx = pick.o
+ #(2) merge
+ with m.If(valid):
l = []
for j in range(self.array_size):
- select = self.addr_match_i[idx][j] & valid
- l.append(Mux(select, self.data_i[j], 0))
- self.data_o.eq(ortreereduce(l))
+ select = self.addr_array_i[idx][j]
+ r = DataMergerRecord()
+ with m.If(select):
+ comb += r.eq(self.data_i[j])
+ l.append(r)
+ comb += self.data_o.data.eq(ortreereduce(l,"data"))
+ comb += self.data_o.en.eq(ortreereduce(l,"en"))
+
+ return m
class LDSTPort(Elaboratable):
assert data == result, "data %x != %x" % (result, data)
assert data2 == result2, "data2 %x != %x" % (result2, data2)
+def data_merger_merge(dut):
+ print("data_merger")
+ #starting with all inputs zero
+ yield Settle()
+ en = yield dut.data_o.en
+ data = yield dut.data_o.data
+ assert en == 0, "en must be zero"
+ assert data == 0, "data must be zero"
+ yield
+
+ yield dut.addr_array_i[0].eq(0xFF)
+ for j in range(dut.array_size):
+ yield dut.data_i[j].en.eq(1 << j)
+ yield dut.data_i[j].data.eq(0xFF << (16*j))
+ yield Settle()
+
+ en = yield dut.data_o.en
+ data = yield dut.data_o.data
+ assert data == 0xff00ff00ff00ff00ff00ff00ff00ff
+ assert en == 0xff
+ yield
def test_l0_cache():
dut = TstL0CacheBuffer()
- vl = rtlil.convert(dut, ports=dut.ports())
- with open("test_basic_l0_cache.il", "w") as f:
- f.write(vl)
+ #vl = rtlil.convert(dut, ports=dut.ports())
+ #with open("test_basic_l0_cache.il", "w") as f:
+ # f.write(vl)
run_simulation(dut, l0_cache_ldst(dut),
vcd_name='test_l0_cache_basic.vcd')
+def test_data_merger():
+
+ dut = DataMerger(8)
+ #vl = rtlil.convert(dut, ports=dut.ports())
+ #with open("test_data_merger.il", "w") as f:
+ # f.write(vl)
+
+ run_simulation(dut, data_merger_merge(dut),
+ vcd_name='test_data_merger.vcd')
+
if __name__ == '__main__':
test_l0_cache()
+ test_data_merger()