Skip to content

Commit 13108c6

Browse files
committed
update clone_wire so that name is required when part of the same block
1 parent b46213a commit 13108c6

File tree

2 files changed

+56
-39
lines changed

2 files changed

+56
-39
lines changed

pyrtl/transform.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@
1919
structures (through Block.logic, block.Wirevector_set, etc).
2020
"""
2121
import functools
22+
from pyrtl.pyrtlexceptions import PyrtlError
2223

2324
from .core import set_working_block, LogicNet, working_block
24-
from .wire import Const, Input, Output, WireVector, Register, next_tempvar_name
25+
from .wire import Const, Input, Output, WireVector, Register
2526

2627

2728
def net_transform(transform_func, block=None, **kwargs):
@@ -240,16 +241,21 @@ def clone_wire(old_wire, name=None):
240241
""" Makes a copy of any existing wire.
241242
242243
:param old_wire: The wire to clone
243-
:param name: A name for the new wire
244+
:param name: A name for the new wire (required if the old wire
245+
and newly cloned wire are part of the same block)
244246
245-
Naming the newly cloned wire the same as another existing wire in the same
246-
block will cause the other wire to be given a new internally created name. This
247-
function is mainly intended to be used when the two wires are from different blocks.
247+
This function is mainly intended to be used when the two wires are from different
248+
blocks. Making two wires with the same name in the same block is not allowed.
248249
"""
249-
name = old_wire.name if name is None else name
250-
if name in working_block().wirevector_by_name and (working_block() is old_wire._block):
251-
w = working_block().wirevector_by_name[name]
252-
w.name = next_tempvar_name()
250+
if name is None:
251+
if working_block() is old_wire._block:
252+
raise PyrtlError("Must provide a name for the newly cloned wire "
253+
"when cloning within the same block.")
254+
name = old_wire.name
255+
256+
if name in working_block().wirevector_by_name:
257+
raise PyrtlError("Cannot give a newly cloned wire the same name "
258+
"as an existing wire.")
253259

254260
if isinstance(old_wire, Const):
255261
return Const(old_wire.val, old_wire.bitwidth, name=name)

tests/test_transform.py

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ def insert_random_inversions(rate=0.5):
5151

5252
def randomly_replace(wire):
5353
if random.random() < rate:
54-
new_src, new_dst = transform.clone_wire(wire), transform.clone_wire(wire)
54+
new_src = transform.clone_wire(wire, pyrtl.wire.next_tempvar_name())
55+
new_dst = transform.clone_wire(wire, pyrtl.wire.next_tempvar_name())
5556
new_dst <<= ~new_src
5657
return new_src, new_dst
5758
return wire, wire
@@ -263,26 +264,47 @@ class TestCloning(unittest.TestCase):
263264
def setUp(self):
264265
pyrtl.reset_working_block()
265266

266-
def test_clone_wire_no_or_same_name_same_block(self):
267-
for clone_name in (None, 'a'):
268-
a = pyrtl.WireVector(1, 'a')
269-
self.assertEqual(a.name, 'a')
270-
self.assertEqual(pyrtl.working_block().wirevector_set, {a})
271-
self.assertIs(pyrtl.working_block().wirevector_by_name['a'], a)
267+
def test_same_type(self):
268+
for ix, cls in enumerate([pyrtl.WireVector, pyrtl.Register, pyrtl.Input, pyrtl.Output]):
269+
w1 = cls(4, 'w%d' % ix)
270+
w2 = pyrtl.clone_wire(w1, 'y%d' % ix)
271+
self.assertIsInstance(w2, cls)
272+
self.assertEqual(w1.bitwidth, w2.bitwidth)
272273

273-
w = pyrtl.clone_wire(a, name=clone_name)
274-
self.assertTrue(a.name.startswith("tmp"))
275-
self.assertEqual(w.name, 'a')
276-
self.assertIs(pyrtl.working_block().wirevector_by_name['a'], w)
277-
self.assertEqual(pyrtl.working_block().wirevector_set, {a, w})
274+
def test_clone_wire_no_name_same_block(self):
275+
a = pyrtl.WireVector(1, 'a')
276+
with self.assertRaises(pyrtl.PyrtlError) as error:
277+
pyrtl.clone_wire(a)
278+
self.assertEqual(
279+
str(error.exception),
280+
"Must provide a name for the newly cloned wire "
281+
"when cloning within the same block."
282+
)
283+
284+
def test_clone_wire_same_name_same_block(self):
285+
a = pyrtl.WireVector(1, 'a')
286+
with self.assertRaises(pyrtl.PyrtlError) as error:
287+
pyrtl.clone_wire(a, 'a')
288+
self.assertEqual(
289+
str(error.exception),
290+
"Cannot give a newly cloned wire the same name as an existing wire."
291+
)
292+
293+
def test_clone_wire_different_name_same_block(self):
294+
a = pyrtl.WireVector(1, 'a')
295+
self.assertEqual(a.name, 'a')
296+
self.assertEqual(pyrtl.working_block().wirevector_set, {a})
297+
self.assertIs(pyrtl.working_block().wirevector_by_name['a'], a)
278298

279-
w.name = 'w'
280-
self.assertEqual(w.name, 'w')
281-
self.assertIs(pyrtl.working_block().wirevector_by_name['w'], w)
299+
w = pyrtl.clone_wire(a, name='w')
300+
self.assertEqual(w.name, 'w')
301+
self.assertEqual(a.name, 'a')
302+
self.assertIs(pyrtl.working_block().wirevector_by_name['w'], w)
303+
self.assertIs(pyrtl.working_block().wirevector_by_name['a'], a)
304+
self.assertEqual(pyrtl.working_block().wirevector_set, {a, w})
282305

283-
pyrtl.working_block().remove_wirevector(a)
284-
self.assertEqual(pyrtl.working_block().wirevector_set, {w})
285-
pyrtl.reset_working_block()
306+
pyrtl.working_block().remove_wirevector(a)
307+
self.assertEqual(pyrtl.working_block().wirevector_set, {w})
286308

287309
def test_clone_wire_no_or_same_name_different_block(self):
288310
for clone_name in (None, 'a'):
@@ -300,18 +322,7 @@ def test_clone_wire_no_or_same_name_different_block(self):
300322
self.assertEqual(b.wirevector_set, {w})
301323
pyrtl.reset_working_block()
302324

303-
def test_clone_wire_with_different_name_same_block(self):
304-
a = pyrtl.WireVector(1, 'a')
305-
w = pyrtl.clone_wire(a, 'w')
306-
self.assertEqual(a.name, 'a')
307-
self.assertEqual(w.name, 'w')
308-
self.assertIs(pyrtl.working_block().wirevector_by_name['a'], a)
309-
self.assertEqual(pyrtl.working_block().wirevector_set, {a, w})
310-
311-
pyrtl.working_block().remove_wirevector(a)
312-
self.assertEqual(pyrtl.working_block().wirevector_set, {w})
313-
314-
def test_clone_wire_with_different_name_different_block(self):
325+
def test_clone_wire_different_name_different_block(self):
315326
a = pyrtl.WireVector(1, 'a')
316327
b = pyrtl.Block()
317328
with set_working_block(b):

0 commit comments

Comments
 (0)