hdl.{ast,cd,dsl,xfrm}: reject inappropriately used comb domain.

Fixes #125.
This commit is contained in:
whitequark 2019-07-08 10:26:49 +00:00
parent 345a26b04b
commit a7fbff94d8
8 changed files with 45 additions and 0 deletions

View file

@ -693,6 +693,8 @@ class ClockSignal(Value):
super().__init__(src_loc_at=src_loc_at)
if not isinstance(domain, str):
raise TypeError("Clock domain name must be a string, not '{!r}'".format(domain))
if domain == "comb":
raise ValueError("Domain '{}' does not have a clock".format(domain))
self.domain = domain
def shape(self):
@ -727,6 +729,8 @@ class ResetSignal(Value):
super().__init__(src_loc_at=src_loc_at)
if not isinstance(domain, str):
raise TypeError("Clock domain name must be a string, not '{!r}'".format(domain))
if domain == "comb":
raise ValueError("Domain '{}' does not have a reset".format(domain))
self.domain = domain
self.allow_reset_less = allow_reset_less

View file

@ -50,6 +50,8 @@ class ClockDomain:
raise ValueError("Clock domain name must be specified explicitly")
if name.startswith("cd_"):
name = name[3:]
if name == "comb":
raise ValueError("Domain '{}' may not be clocked".format(name))
self.name = name
self.clk = Signal(name=self._name_for(name, "clk"), src_loc_at=1)

View file

@ -261,6 +261,8 @@ class Module(_ModuleBuilderRoot, Elaboratable):
@contextmanager
def FSM(self, reset=None, domain="sync", name="fsm"):
self._check_context("FSM", context=None)
if domain == "comb":
raise ValueError("FSM may not be driven by the '{}' domain".format(domain))
fsm_data = self._set_ctrl("FSM", {
"name": name,
"signal": Signal(name="{}_state".format(name), src_loc_at=2),

View file

@ -326,6 +326,11 @@ class DomainRenamer(FragmentTransformer, ValueTransformer, StatementTransformer)
def __init__(self, domain_map):
if isinstance(domain_map, str):
domain_map = {"sync": domain_map}
for src, dst in domain_map.items():
if src == "comb":
raise ValueError("Domain '{}' may not be renamed".format(src))
if dst == "comb":
raise ValueError("Domain '{}' may not be renamed to '{}'".format(src, dst))
self.domain_map = OrderedDict(domain_map)
def on_ClockSignal(self, value):

View file

@ -515,6 +515,11 @@ class ClockSignalTestCase(FHDLTestCase):
s1 = ClockSignal()
self.assertEqual(repr(s1), "(clk sync)")
def test_wrong_name_comb(self):
with self.assertRaises(ValueError,
msg="Domain 'comb' does not have a clock"):
ClockSignal("comb")
class ResetSignalTestCase(FHDLTestCase):
def test_domain(self):
@ -534,6 +539,11 @@ class ResetSignalTestCase(FHDLTestCase):
s1 = ResetSignal()
self.assertEqual(repr(s1), "(rst sync)")
def test_wrong_name_comb(self):
with self.assertRaises(ValueError,
msg="Domain 'comb' does not have a reset"):
ResetSignal("comb")
class MockUserValue(UserValue):
def __init__(self, lowered):

View file

@ -55,3 +55,8 @@ class ClockDomainTestCase(FHDLTestCase):
sync.rename("pix")
self.assertEqual(sync.name, "pix")
self.assertEqual(sync.clk.name, "pix_clk")
def test_wrong_name_comb(self):
with self.assertRaises(ValueError,
msg="Domain 'comb' may not be clocked"):
comb = ClockDomain()

View file

@ -458,6 +458,13 @@ class DSLTestCase(FHDLTestCase):
()
""")
def test_FSM_wrong_domain(self):
m = Module()
with self.assertRaises(ValueError,
msg="FSM may not be driven by the 'comb' domain"):
with m.FSM(domain="comb"):
pass
def test_FSM_wrong_redefined(self):
m = Module()
with m.FSM():

View file

@ -88,6 +88,16 @@ class DomainRenamerTestCase(FHDLTestCase):
"pix": cd_pix,
})
def test_rename_wrong_to_comb(self):
with self.assertRaises(ValueError,
msg="Domain 'sync' may not be renamed to 'comb'"):
DomainRenamer("comb")
def test_rename_wrong_from_comb(self):
with self.assertRaises(ValueError,
msg="Domain 'comb' may not be renamed"):
DomainRenamer({"comb": "sync"})
class DomainLowererTestCase(FHDLTestCase):
def setUp(self):