From 7659f4bdf55f544280ea938739310f5446888531 Mon Sep 17 00:00:00 2001 From: Daniel Benusovich Date: Mon, 11 Mar 2019 19:51:25 -0700 Subject: [PATCH] Add RegisterFile class for usage in the TLB. --- TLB/src/RegisterFile.py | 59 ++++++++++++++++ TLB/test/test_register_file.py | 122 +++++++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 TLB/src/RegisterFile.py create mode 100644 TLB/test/test_register_file.py diff --git a/TLB/src/RegisterFile.py b/TLB/src/RegisterFile.py new file mode 100644 index 00000000..5fd691c8 --- /dev/null +++ b/TLB/src/RegisterFile.py @@ -0,0 +1,59 @@ +from nmigen import Array, Module, Signal +from nmigen.lib.coding import Decoder + +class RegisterFile(): + """ Register File + + The purpose of this module is to represent a bank of registers. + + Usage: + To Write: Set the address line to the desired register in the file, set + write_enable HIGH, and wait one cycle + To Read: Set the address line to the desired register in the file, set + write_enable LOW, and wait one cycle. + """ + + def __init__(self, data_size, file_size): + """ Arguments: + * data_size: (bit count) The number of bits in one register + * cam_size: (entry count) the number of registers in this file + """ + + # Internal + self.register_array = Array(Signal(data_size) for x in range(file_size)) + + # Input + self.enable = Signal(1) + self.write_enable = Signal(1) + self.address = Signal(max=file_size) + self.data_i = Signal(data_size) + + # Output + self.valid = Signal(1) + self.data_o = Signal(data_size) + + def elaborate(self, platform=None): + m = Module() + + with m.If(self.enable): + # Write Logic + with m.If(self.write_enable): + m.d.sync += [ + self.valid.eq(0), + self.data_o.eq(0), + self.register_array[self.address].eq(self.data_i) + ] + # Read Logic + with m.Else(): + m.d.sync += [ + self.valid.eq(1), + self.data_o.eq(self.register_array[self.address]) + ] + # Invalidate results when not enabled + with m.Else(): + m.d.sync += [ + self.valid.eq(0), + self.data_o.eq(0) + ] + + return m \ No newline at end of file diff --git a/TLB/test/test_register_file.py b/TLB/test/test_register_file.py new file mode 100644 index 00000000..ee8b172d --- /dev/null +++ b/TLB/test/test_register_file.py @@ -0,0 +1,122 @@ +import sys +sys.path.append("../src") +sys.path.append("../../TestUtil") + +from nmigen.compat.sim import run_simulation + +from RegisterFile import RegisterFile + +from test_helper import assert_eq, assert_ne, assert_op + +def setRegisterFile(dut, e, we, a, di): + yield dut.enable.eq(e) + yield dut.write_enable.eq(we) + yield dut.address.eq(a) + yield dut.data_i.eq(di) + yield + +# Checks the address output of the Cam +# Arguments: +# dut: The Cam being tested +# v (Valid): If the output is valid or not +# op (Operation): (0 => ==), (1 => !=) +def check_valid(dut, v, op): + out_v = yield dut.valid + assert_op("Valid", out_v, v, op) + +# Checks the address output of the Cam +# Arguments: +# dut: The Cam being tested +# do (Data Out): The current output data +# op (Operation): (0 => ==), (1 => !=) +def check_data(dut, do, op): + out_do = yield dut.data_o + assert_op("Data Out", out_do, do, op) + +# Checks the address output of the Cam +# Arguments: +# dut: The Cam being tested +# v (Valid): If the output is valid or not +# do (Data Out): The current output data +# v_op (Operation): Operation for the valid assertion (0 => ==), (1 => !=) +# do_op (Operation): Operation for the data assertion (0 => ==), (1 => !=) +def check_all(dut, v, do, v_op, do_op): + yield from check_valid(dut, v, v_op) + yield from check_data(dut, do, do_op) + +def testbench(dut): + # Test write 0 + enable = 1 + write_enable = 1 + address = 0 + data = 1 + valid = 0 + yield from setRegisterFile(dut, enable, write_enable, address, data) + yield + yield from check_all(dut, valid, 0, 0, 0) + + # Test read 0 + enable = 1 + write_enable = 0 + address = 0 + data = 1 + valid = 1 + yield from setRegisterFile(dut, enable, write_enable, address, data) + yield + yield from check_all(dut, valid, data, 0, 0) + + # Test write 3 + enable = 1 + write_enable = 1 + address = 3 + data = 5 + valid = 0 + yield from setRegisterFile(dut, enable, write_enable, address, data) + yield + yield from check_all(dut, valid, 0, 0, 0) + + # Test read 3 + enable = 1 + write_enable = 0 + address = 3 + data = 5 + valid = 1 + yield from setRegisterFile(dut, enable, write_enable, address, data) + yield + yield from check_all(dut, valid, data, 0, 0) + + # Test read 0 + enable = 1 + write_enable = 0 + address = 0 + data = 1 + valid = 1 + yield from setRegisterFile(dut, enable, write_enable, address, data) + yield + yield from check_all(dut, valid, data, 0, 0) + + # Test overwrite 0 + enable = 1 + write_enable = 1 + address = 0 + data = 6 + valid = 0 + yield from setRegisterFile(dut, enable, write_enable, address, data) + yield + yield from check_all(dut, valid, 0, 0, 0) + + # Test read 0 + enable = 1 + write_enable = 0 + address = 0 + data = 6 + valid = 1 + yield from setRegisterFile(dut, enable, write_enable, address, data) + yield + yield from check_all(dut, valid, data, 0, 0) + + +if __name__ == "__main__": + dut = RegisterFile(4, 4) + run_simulation(dut, testbench(dut), vcd_name="Waveforms/test_register_file.vcd") + print("RegisterFile Unit Test Success") \ No newline at end of file -- 2.30.2