From 95d8b69c68a17cf3fbcfb6d9f4752c9a90e9da69 Mon Sep 17 00:00:00 2001 From: s-ol Date: Thu, 28 May 2020 14:42:14 +0200 Subject: tests, cleanup, verify.py --- riscv.py | 229 ++++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 192 insertions(+), 37 deletions(-) (limited to 'riscv.py') diff --git a/riscv.py b/riscv.py index c0d5a15..245d60d 100644 --- a/riscv.py +++ b/riscv.py @@ -1,44 +1,199 @@ +def u(num, bits): + if num < 0: + raise ValueError("negative value not allowed: {}".format(num)) + + if num.bit_length() > bits: + raise ValueError("value too large for u{} field: {} ({} bits)", + bits, num, num.bit_length()) + + return (num, bits) + +def i(num, bits): + if num < 0: + num = (1 << bits) + num + + return u(num, bits) + +def bit_concat(*parts): + val, size = 0, 0 + for (pval, psize) in parts: + val = val | pval << size + size += psize + return (val, size) + +def bit_slice(bits, top, bottom): + (val, size) = bits + + if top < bottom: + raise ValueError("cant slice reverse range") + elif bottom < 0: + raise ValueError("negative slice index") + elif top >= size: + raise ValueError("cant slice [{}:{}] from {} bit value".format(top, bottom, size)) + + width = top - bottom + 1 + val = (val >> bottom) & ((1 << width) - 1) + return (val, width) + +def byteify(word): + (val, size) = word + if size != 32: + raise ValueError("Expected 32-bit word") + + b0 = bit_slice(word, 7, 0) + b1 = bit_slice(word, 15, 8) + b2 = bit_slice(word, 23, 16) + b3 = bit_slice(word, 31, 24) + return [b0[:1], b1[:1], b2[:1], b3[:1]] + def format_r(op, rd, r1, r2, funct3, funct7): - # opcode[7] rd[5] funct3[3] rs1[5] rs2[5] funct7[7] - b0 = (rd & 0x1) << 7 | op - b1 = (r1 & 0x1) << 7 | funct3 << 4 | rd >> 1 - b2 = (r2 & 0xf) << 4 | r1 >> 1 - b3 = funct7 << 1 | r2 >> 4 - return [(b0,), (b1,), (b2,), (b3,)] + # HH funct7 rs2 rs1 funct3 rd opcode LL + return byteify(bit_concat( + u(op, 7), + u(rd, 5), + u(funct3, 3), + u(r1, 5), + u(r2, 5), + u(funct7, 7), + )) def format_i(op, rd, r1, imm12, funct3): - # opcode[7] rd[5] funct3[3] rs1[5] imm[12] - b0 = (rd & 0x1) << 7 | op - b1 = (r1 & 0x1) << 7 | funct3 << 4 | rd >> 1 - b2 = (imm12 & 0xf) << 4 | r1 >> 1 - b3 = imm12 >> 4 - return [(b0,), (b1,), (b2,), (b3,)] + # HH imm[11:0] rs1 funct3 rd opcode LL + return byteify(bit_concat( + u(op, 7), + u(rd, 5), + u(funct3, 3), + u(r1, 5), + i(imm12, 12), + )) def format_s(op, r1, r2, imm12, funct3): - # opcode[7] rd[5] funct3[3] rs1[5] rs2[5] funct7[7] - b0 = (imm12 & 0x1) << 7 | op - b1 = (r1 & 0x1) << 7 | funct3 << 4 | (imm12 & 0x1f) >> 1 - b2 = (r2 & 0xf) << 4 | r1 >> 1 - b3 = (imm12 & 0xf0) | r2 >> 4 - return [(b0,), (b1,), (b2,), (b3,)] + # HH imm[11:5] rs2 rs1 funct3 imm[4:0] opcode LL + imm = i(imm12, 12) + imm_lo = bit_slice(imm, 4, 0) + imm_hi = bit_slice(imm, 11, 5) + return byteify(bit_concat( + u(op, 7), + imm_lo, + u(funct3, 3), + u(r1, 5), + u(r2, 5), + imm_hi + )) + + # imm12 = i(imm12, 12) + # r1 = i(r1, 5, neg=False) + # r2 = i(r2, 5, neg=False) + # + # b0 = (imm12 & 0x1) << 7 | op + # b1 = (r1 & 0x1) << 7 | funct3 << 4 | (imm12 & 0x1f) >> 1 + # b2 = (r2 & 0xf) << 4 | r1 >> 1 + # b3 = (imm12 & 0xf0) | r2 >> 4 + # return [(b0,), (b1,), (b2,), (b3,)] def format_u(op, rd, imm20): - # opcode[7] rd[5] imm31:12[20] - b0 = (rd & 0x1) << 7 | op - b1 = (imm20 & 0xf) << 4 | rd >> 1 - b2 = (imm20 >> 4) & 0xff - b3 = imm20 >> 12 - return [(b0,), (b1,), (b2,), (b3,)] - -def format_j(op, rd, imm): - # opcode[7] rd[5] imm19:12[8] imm11[1] imm10:1[10] imm20[1] - imm12 = (imm >> 11) & 0xff - imm11 = (imm >> 12) & 0x1 - imm1 = imm & 0x3ff - imm20 = imm >> 19 - - b0 = (rd & 0x1) << 7 | op # rd[1] op[7:0] - b1 = (imm12 & 0xf) << 4 | rd >> 1 # imm[15:12] rd[5:2] - b2 = (imm1 << 5) & 0xe0 | imm11 << 4 | (imm12 >> 4) # imm[3:1] imm[11] imm[19:16] - b3 = imm20 << 7 | imm1 >> 3 - return [(b0,), (b1,), (b2,), (b3,)] + # HH imm[31:12] rd opcode LL + return byteify(bit_concat( + u(op, 7), + u(rd, 5), + i(imm20, 20) + )) + +def format_j(op, rd, imm20): + # HH imm[20] imm[10:1] imm[11] imm[19:12] rd opcode LL + imm = i(imm20, 20) + imm_lo = bit_slice(imm, 9, 0) + imm_10 = bit_slice(imm, 10, 10) + imm_hi = bit_slice(imm, 18, 11) + imm_19 = bit_slice(imm, 19, 19) + return byteify(bit_concat( + u(op, 7), + u(rd, 5), + imm_hi, + imm_10, + imm_lo, + imm_19 + )) + +import unittest +class TestHelpers(unittest.TestCase): + def test_bit_concat(self): + self.assertEqual( + bit_concat((0b10, 2), (0b00, 2)), + (0b0010, 4) + ) + self.assertEqual( + bit_concat((0b1, 1), (0b0110, 4), (0b110, 3)), + (0b11001101, 8) + ) + + def test_bit_slice(self): + self.assertEqual( + bit_slice((0x7f, 8), 7, 4), + (0x7, 4) + ) + self.assertEqual( + bit_slice((0b100, 3), 2, 2), + (0b1, 1) + ) + with self.assertRaises(ValueError): + bit_slice((0xf, 4), 4, 0) + with self.assertRaises(ValueError): + bit_slice((0xf, 4), 2, 3) + with self.assertRaises(ValueError): + bit_slice((0xf, 4), 3, -1) + self.assertEqual( + bit_slice((0x12345678, 32), 7, 0), + (0x78, 8) + ) + self.assertEqual( + bit_slice((0x12345678, 32), 15, 8), + (0x56, 8) + ) + self.assertEqual( + bit_slice((0x12345678, 32), 23, 16), + (0x34, 8) + ) + + def test_byteify(self): + self.assertEqual( + byteify((0x12345678, 32)), + [(0x78,), (0x56,), (0x34,), (0x12,)] + ) + +class TestFormats(unittest.TestCase): + def test_format_u(self): + self.assertEqual( + format_u(0x37, 0x5, 0x10010), + [(183,), (2,), (1,), (16,)] + ) + + def test_format_i(self): + self.assertEqual( + format_i(0x13, 5, 0, 72, 0x0), + [(147,), (2,), (128,), (4,)] + ) + self.assertEqual( + format_i(0x13, 9, 2, 72, 0x3), + [(147,), (52,), (129,), (4,)] + ) + + def test_format_s(self): + self.assertEqual( + format_s(0x23, 3, 4, 0, 0x2), + [(35,), (160,), (65,), (0,)] + ) + self.assertEqual( + format_s(0x23, 2, 0, -4, 0x2), + [(35,), (46,), (1,), (254,)] + ) + + def test_format_j(self): + self.assertEqual( + format_j(0x6f, 0, -26), + [(111,), (240,), (223,), (252,)] + ) + self.assertEqual( + format_j(0x6f, 9, 0), + [(239,), (4,), (0,), (0,)] + ) -- cgit v1.2.3