aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel I. Kryukov <pavel.igorevich.kryukov@gmail.com>2022-05-17 20:13:53 +0300
committerGitHub <noreply@github.com>2022-05-17 10:13:53 -0700
commitf9272e8d496a8259f29b952797f595eb9e81078d (patch)
tree53c656baa3ac737bf6e75898567eb7cf033db891
parent301686e5b6b93d24ad85200f00ec60197ada86b6 (diff)
downloadriscv-opcodes-f9272e8d496a8259f29b952797f595eb9e81078d.zip
riscv-opcodes-f9272e8d496a8259f29b952797f595eb9e81078d.tar.gz
riscv-opcodes-f9272e8d496a8259f29b952797f595eb9e81078d.tar.bz2
Test error inputs handling, fix few bugs (#119)
* Test error inputs handling * Add mask tests * Apply code review fix
-rw-r--r--.github/workflows/tests.yml28
-rwxr-xr-xparse.py33
-rw-r--r--test.py44
3 files changed, 90 insertions, 15 deletions
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 0000000..9357293
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,28 @@
+name: Unit tests
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up Python 3.8
+ uses: actions/setup-python@v2
+ with:
+ python-version: 3.8
+ - name: Install PyYAML
+ run: |
+ pip3 install -r requirements.txt
+ pip3 install coverage
+ - name: Test error outputs
+ run: coverage run -m unittest -b
+ - name: Generate coverage
+ run: coverage xml
+ - name: Upload coverage
+ uses: codecov/codecov-action@v2
+
diff --git a/parse.py b/parse.py
index 83c1d72..243a8bb 100755
--- a/parse.py
+++ b/parse.py
@@ -13,6 +13,9 @@ import sys
pp = pprint.PrettyPrinter(indent=2)
logging.basicConfig(level=logging.INFO, format='%(levelname)s:: %(message)s')
+def parse_constant(string):
+ return int(string, 0)
+
def process_enc_line(line, ext):
'''
This function processes each line of the encoding files (rv*). As part of
@@ -61,14 +64,23 @@ def process_enc_line(line, ext):
temp_instr = ['-'] * 32
entries = [
x[0] for x in re.findall(
- r'((\d)+\.\.(\d)+\=((0b\d+)|(0x\d+)|(\d)+))*',
+ r'((\d)+\.\.(\d)+\=((0b\d+)|(0x[0-9a-fA-F]+)|(\d)+))*',
remaining) if x[0] != ''
]
for temp_entry in entries:
entry = temp_entry.split('=')[0]
- f1, f2 = entry.split('..')
- for ind in range(int(f1), int(f2)):
+ s2, s1 = entry.split('..')
+ msb = int(s2)
+ lsb = int(s1)
+
+ # check msb < lsb
+ if msb < lsb:
+ logging.error(
+ f'{line.split(" ")[0]:<10} has position {msb} less than position {lsb} in it\'s encoding'
+ )
+ raise SystemExit(1)
+ for ind in range(lsb, msb):
# overlapping bits
if temp_instr[ind] == 'X':
logging.error(
@@ -77,20 +89,11 @@ def process_enc_line(line, ext):
raise SystemExit(1)
temp_instr[ind] = 'X'
- # check x < y
- if int(f1) < int(f2):
- logging.error(
- f'{line.split(" ")[0]:<10} has position {f1} less than position {f2} in it\'s encoding'
- )
- raise SystemExit(1)
-
# illegal value assigned as per bit width
- entry_value = temp_entry.split('=')[1]
- temp_base = 16 if 'x' in entry_value else 2 if 'b' in entry_value else 10
- if len(str(int(entry_value,
- temp_base))[2:]) > (int(f1) - int(f2)):
+ entry_value = parse_constant(temp_entry.split('=')[1])
+ if entry_value >= (1 << (msb - lsb + 1)):
logging.error(
- f'{line.split(" ")[0]:<10} has an illegal value {entry_value} assigned as per the bit width {f1 - f2}'
+ f'{line.split(" ")[0]:<10} has an illegal value {entry_value} assigned as per the bit width {msb - lsb}'
)
raise SystemExit(1)
diff --git a/test.py b/test.py
new file mode 100644
index 0000000..89c014d
--- /dev/null
+++ b/test.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python3
+
+from parse import *
+import logging
+import unittest
+
+class ConstantParseTest(unittest.TestCase):
+ def test_constant(self):
+ self.assertEqual(parse_constant('10'), 10)
+ self.assertEqual(parse_constant('0xa'), 10)
+ self.assertEqual(parse_constant('0xA'), 10)
+ self.assertEqual(parse_constant('0b1010'), 10)
+
+class EncodingLineTest(unittest.TestCase):
+ def setUp(self):
+ logger = logging.getLogger()
+ logger.disabled = True
+
+ def assertError(self, string):
+ self.assertRaises(SystemExit, process_enc_line, string, 'rv_i')
+
+ def test_lui(self):
+ name, data = process_enc_line('lui rd imm20 6..2=0x0D 1..0=3', 'rv_i')
+ self.assertEqual(name, 'lui')
+ self.assertEqual(data['extension'], ['rv_i'])
+ self.assertEqual(data['match'], '0x37')
+ self.assertEqual(data['mask'], '0x7f')
+
+ def test_overlapping(self):
+ self.assertError('jol rd jimm20 6..2=0x00 3..0=7')
+
+ def test_invalid_order(self):
+ self.assertError('jol 2..6=0x1b')
+
+ def test_illegal_value(self):
+ self.assertError('jol rd jimm20 2..0=10')
+ self.assertError('jol rd jimm20 2..0=0xB')
+
+ @unittest.skip('not implemented')
+ def test_overlapping_field(self):
+ self.assertError('jol rd rs1 jimm20 6..2=0x1b 1..0=3')
+
+ def test_illegal_field(self):
+ self.assertError('jol rd jimm128 2..0=10')