New specification for width and signedness

This commit is contained in:
Sebastien Bourdeauducq 2012-11-29 21:22:38 +01:00
parent 6eebfce44a
commit 50ed73c937
40 changed files with 228 additions and 454 deletions

View File

@ -4,8 +4,8 @@ from migen.fhdl import verilog
dx = 5
dy = 5
x = Signal(BV(bits_for(dx-1)))
y = Signal(BV(bits_for(dy-1)))
x = Signal(bits_for(dx-1))
y = Signal(bits_for(dy-1))
out = Signal()
my_2d_array = Array(Array(Signal() for a in range(dx)) for b in range(dy))

View File

@ -7,36 +7,36 @@ class LM32:
Instance.ClockPort("clk_i"),
Instance.ResetPort("rst_i"),
Instance.Input("interrupt", BV(32)),
Instance.Input("ext_break", BV(1)),
Instance.Input("interrupt", 32),
Instance.Input("ext_break", 1),
Instance.Output("I_ADR_O", BV(32)),
Instance.Output("I_DAT_O", BV(32)),
Instance.Output("I_SEL_O", BV(4)),
Instance.Output("I_CYC_O", BV(1)),
Instance.Output("I_STB_O", BV(1)),
Instance.Output("I_WE_O", BV(1)),
Instance.Output("I_CTI_O", BV(3)),
Instance.Output("I_LOCK_O", BV(1)),
Instance.Output("I_BTE_O", BV(1)),
Instance.Input("I_DAT_I", BV(32)),
Instance.Input("I_ACK_I", BV(1)),
Instance.Input("I_ERR_I", BV(1)),
Instance.Input("I_RTY_I", BV(1)),
Instance.Output("I_ADR_O", 32),
Instance.Output("I_DAT_O", 32),
Instance.Output("I_SEL_O", 4),
Instance.Output("I_CYC_O", 1),
Instance.Output("I_STB_O", 1),
Instance.Output("I_WE_O", 1),
Instance.Output("I_CTI_O", 3),
Instance.Output("I_LOCK_O", 1),
Instance.Output("I_BTE_O", 1),
Instance.Input("I_DAT_I", 32),
Instance.Input("I_ACK_I", 1),
Instance.Input("I_ERR_I", 1),
Instance.Input("I_RTY_I", 1),
Instance.Output("D_ADR_O", BV(32)),
Instance.Output("D_DAT_O", BV(32)),
Instance.Output("D_SEL_O", BV(4)),
Instance.Output("D_CYC_O", BV(1)),
Instance.Output("D_STB_O", BV(1)),
Instance.Output("D_WE_O", BV(1)),
Instance.Output("D_CTI_O", BV(3)),
Instance.Output("D_LOCK_O", BV(1)),
Instance.Output("D_BTE_O", BV(1)),
Instance.Input("D_DAT_I", BV(32)),
Instance.Input("D_ACK_I", BV(1)),
Instance.Input("D_ERR_I", BV(1)),
Instance.Input("D_RTY_I", BV(1)),
Instance.Output("D_ADR_O", 32),
Instance.Output("D_DAT_O", 32),
Instance.Output("D_SEL_O", 4),
Instance.Output("D_CYC_O", 1),
Instance.Output("D_STB_O", 1),
Instance.Output("D_WE_O", 1),
Instance.Output("D_CTI_O", 3),
Instance.Output("D_LOCK_O", 1),
Instance.Output("D_BTE_O", 1),
Instance.Input("D_DAT_I", 32),
Instance.Input("D_ACK_I", 1),
Instance.Input("D_ERR_I", 1),
Instance.Input("D_RTY_I", 1),
name="lm32")

View File

@ -7,7 +7,7 @@ def gen_list(n):
return s
def gen_2list(n):
s = [Signal(BV(2)) for i in range(n)]
s = [Signal(2) for i in range(n)]
return s
class Foo:

View File

@ -10,8 +10,8 @@ oreg = description.RegisterField("o", noutputs, atomic_write=True)
ireg = description.RegisterField("i", ninputs, READ_ONLY, WRITE_ONLY)
# input path
gpio_in = Signal(BV(ninputs))
gpio_in_s = Signal(BV(ninputs)) # synchronizer
gpio_in = Signal(ninputs)
gpio_in_s = Signal(ninputs) # synchronizer
insync = [gpio_in_s.eq(gpio_in), ireg.field.w.eq(gpio_in_s)]
inf = Fragment(sync=insync)

View File

@ -2,11 +2,11 @@ from migen.fhdl.structure import *
from migen.corelogic.record import *
L = [
("x", BV(10), 8),
("y", BV(10), 8),
("x", 10, 8),
("y", 10, 8),
("level2", [
("a", BV(5), 32),
("b", BV(5), 16)
("a", 5, 32),
("b", 5, 16)
])
]

View File

@ -1,54 +0,0 @@
import sys
import matplotlib.pyplot as plt
import networkx as nx
from migen.flow.network import *
from migen.actorlib.ala import *
from migen.actorlib.sim import *
from migen.sim.generic import Simulator
from migen.sim.icarus import Runner
class NumberGen(SimActor):
def __init__(self):
self.bv_r = BV(16)
def number_gen():
for i in range(10):
yield Token("result", {"r": i})
super().__init__(number_gen(),
("result", Source, [("r", self.bv_r)]))
def draw(g):
if len(sys.argv) > 1 and sys.argv[1] == "draw":
nx.draw_spectral(g)
plt.show()
def main():
# Create graph
g = DataFlowGraph()
gen1 = ComposableNode(g, NumberGen())
gen2 = ComposableNode(g, NumberGen())
ps = gen1 + gen2
result = ps*gen1 + ps*gen2
g.add_connection(result, ActorNode(Dumper([("r", BV(32))])))
gen1.actor.name = "gen1"
gen2.actor.name = "gen2"
result.name = "result"
# Elaborate
print("is_abstract before elaboration: " + str(g.is_abstract()))
draw(g)
g.elaborate()
print("is_abstract after elaboration : " + str(g.is_abstract()))
draw(g)
# Simulate
c = CompositeActor(g)
fragment = c.get_fragment()
sim = Simulator(fragment, Runner())
sim.run(100)
main()

View File

@ -70,9 +70,9 @@ def asmi_sim(efragment, hub, end_simulation):
def test_wb_reader():
print("*** Testing Wishbone reader")
adrgen = ActorNode(SimActor(adrgen_gen(), ("address", Source, [("a", BV(30))])))
adrgen = ActorNode(SimActor(adrgen_gen(), ("address", Source, [("a", 30)])))
reader = ActorNode(dma_wishbone.Reader())
dumper = ActorNode(SimActor(dumper_gen(), ("data", Sink, [("d", BV(32))])))
dumper = ActorNode(SimActor(dumper_gen(), ("data", Sink, [("d", 32)])))
g = DataFlowGraph()
g.add_connection(adrgen, reader)
g.add_connection(reader, dumper)
@ -83,7 +83,7 @@ def test_wb_reader():
def test_wb_writer():
print("*** Testing Wishbone writer")
trgen = ActorNode(SimActor(trgen_gen(), ("address_data", Source, [("a", BV(30)), ("d", BV(32))])))
trgen = ActorNode(SimActor(trgen_gen(), ("address_data", Source, [("a", 30), ("d", 32)])))
writer = ActorNode(dma_wishbone.Writer())
g = DataFlowGraph()
g.add_connection(trgen, writer)
@ -99,9 +99,9 @@ def test_asmi_reader(nslots):
port = hub.get_port(nslots)
hub.finalize()
adrgen = ActorNode(SimActor(adrgen_gen(), ("address", Source, [("a", BV(32))])))
adrgen = ActorNode(SimActor(adrgen_gen(), ("address", Source, [("a", 32)])))
reader = ActorNode(dma_asmi.Reader(port))
dumper = ActorNode(SimActor(dumper_gen(), ("data", Sink, [("d", BV(32))])))
dumper = ActorNode(SimActor(dumper_gen(), ("data", Sink, [("d", 32)])))
g = DataFlowGraph()
g.add_connection(adrgen, reader)
g.add_connection(reader, dumper)

View File

@ -1,63 +0,0 @@
from migen.flow.network import *
from migen.flow import plumbing
from migen.actorlib.ala import *
from migen.actorlib.sim import *
from migen.sim.generic import Simulator
from migen.sim.icarus import Runner
# Pushes a "1" token and then becomes transparent.
class Init(Actor):
def __init__(self, nbits):
super().__init__(
("in", Sink, [("d", BV(nbits))]),
("out", Source, [("d", BV(nbits))]))
def get_fragment(self):
done = Signal()
comb = [
self.busy.eq(~done),
If(done,
self.endpoints["in"].ack.eq(self.endpoints["out"].ack),
self.endpoints["out"].stb.eq(self.endpoints["in"].stb),
self.endpoints["out"].token.d.eq(self.endpoints["in"].token.d)
).Else(
self.endpoints["in"].ack.eq(0),
self.endpoints["out"].stb.eq(1),
self.endpoints["out"].token.d.eq(1)
)
]
sync = [
If(self.endpoints["out"].ack, done.eq(1))
]
return Fragment(comb, sync)
def main():
nbits = 32
# See:
# http://www.csse.monash.edu.au/~damian/Idioms/Topics/12.1.DataFlow/html/text.html
g = DataFlowGraph()
adder = ActorNode(Add(BV(nbits)))
bufadd = ActorNode(plumbing.Buffer) # TODO FIXME: deadlocks without this buffer
init1 = ActorNode(Init(nbits))
buf1 = ActorNode(plumbing.Buffer)
init2 = ActorNode(Init(nbits))
buf2 = ActorNode(plumbing.Buffer)
g.add_connection(adder, bufadd)
g.add_connection(bufadd, init1)
g.add_connection(init1, buf1)
g.add_connection(buf1, adder, sink_subr="a")
g.add_connection(buf1, init2)
g.add_connection(init2, buf2)
g.add_connection(buf2, adder, sink_subr="b")
g.add_connection(bufadd, ActorNode(Dumper([("r", BV(nbits))])))
c = CompositeActor(g)
fragment = c.get_fragment()
sim = Simulator(fragment, Runner())
sim.run(100)
main()

View File

@ -17,9 +17,9 @@ def sink_gen():
print(t.value["value"])
def main():
source = ActorNode(SimActor(source_gen(), ("source", Source, [("value", BV(32))])))
source = ActorNode(SimActor(source_gen(), ("source", Source, [("value", 32)])))
loop = ActorNode(misc.IntSequence(32))
sink = ActorNode(SimActor(sink_gen(), ("sink", Sink, [("value", BV(32))])))
sink = ActorNode(SimActor(sink_gen(), ("sink", Sink, [("value", 32)])))
g = DataFlowGraph()
g.add_connection(source, loop)
g.add_connection(loop, sink)

View File

@ -23,9 +23,9 @@ def sink_gen():
print(t.value["value"])
def main():
base_layout = [("value", BV(32))]
base_layout = [("value", 32)]
packed_layout = structuring.pack_layout(base_layout, pack_factor)
rawbits_layout = [("value", BV(32*pack_factor))]
rawbits_layout = [("value", 32*pack_factor)]
source = ActorNode(SimActor(source_gen(), ("source", Source, base_layout)))
sink = ActorNode(SimActor(sink_gen(), ("sink", Sink, base_layout)))

View File

@ -5,7 +5,7 @@ from migen.sim.generic import Simulator
from migen.sim.icarus import Runner
from migen.fhdl import verilog
layout = [("r", BV(32))]
layout = [("r", 32)]
def number_gen():
for i in range(10):

View File

@ -9,7 +9,7 @@ from migen.sim.generic import Simulator
from migen.sim.icarus import Runner
from migen.fhdl import verilog
layout = [("r", BV(32))]
layout = [("r", 32)]
def gen():
ds = Register(32)

View File

@ -9,7 +9,7 @@ from migen.sim.icarus import Runner
# and prints its current value in simulation.
class Counter:
def __init__(self):
self.count = Signal(BV(4))
self.count = Signal(4)
# This function will be called at every cycle.
def do_simulation(self, s):

View File

@ -12,7 +12,7 @@ class Counter:
def __init__(self):
self.ce = Signal()
# Demonstrate negative numbers and signals larger than 32 bits.
self.count = Signal(BV(37, True), reset=-5)
self.count = Signal((37, True), reset=-5)
def do_simulation(self, s):
# Only assert CE every second cycle.

View File

@ -17,8 +17,8 @@ def sink_gen():
print("Received: " + str(t.value["value"]))
def main():
source = ActorNode(SimActor(source_gen(), ("source", Source, [("value", BV(32))])))
sink = ActorNode(SimActor(sink_gen(), ("sink", Sink, [("value", BV(32))])))
source = ActorNode(SimActor(source_gen(), ("source", Source, [("value", 32)])))
sink = ActorNode(SimActor(sink_gen(), ("sink", Sink, [("value", 32)])))
g = DataFlowGraph()
g.add_connection(source, sink)
comp = CompositeActor(g)

View File

@ -17,21 +17,20 @@ class FIR:
def __init__(self, coef, wsize=16):
self.coef = coef
self.wsize = wsize
self.i = Signal(BV(self.wsize, True))
self.o = Signal(BV(self.wsize, True))
self.i = Signal((self.wsize, True))
self.o = Signal((self.wsize, True))
def get_fragment(self):
muls = []
sync = []
src = self.i
for c in self.coef:
sreg = Signal(BV(self.wsize, True))
sreg = Signal((self.wsize, True))
sync.append(sreg.eq(src))
src = sreg
c_fp = int(c*2**(self.wsize - 1))
c_e = Constant(c_fp, BV(bits_for(c_fp), True))
muls.append(c_e*sreg)
sum_full = Signal(BV(2*self.wsize-1, True))
muls.append(c_fp*sreg)
sum_full = Signal((2*self.wsize-1, True))
sync.append(sum_full.eq(optree("+", muls)))
comb = [self.o.eq(sum_full[self.wsize-1:])]
return Fragment(comb, sync)

View File

@ -1,143 +0,0 @@
from migen.fhdl.structure import *
from migen.fhdl.structure import _Operator
from migen.flow.actor import *
from migen.flow.network import *
from migen.corelogic.record import *
from migen.corelogic import divider
class _SimpleBinary(CombinatorialActor):
def __init__(self, bv_op, bv_r=None):
self.bv_op = bv_op
if bv_r is None:
bv_r = self.__class__.get_result_bv(bv_op)
self.bv_r = bv_r
super().__init__(
("operands", Sink, [("a", bv_op), ("b", bv_op)]),
("result", Source, [("r", bv_r)]))
def get_process_fragment(self):
return Fragment([
self.token("result").r.eq(_Operator(self.op,
[self.token("operands").a, self.token("operands").b]))
])
class Add(_SimpleBinary):
op = "+"
def get_result_bv(bv):
return BV(bv.width+1, bv.signed)
class Sub(_SimpleBinary):
op = "-"
def get_result_bv(bv):
return BV(bv.width+1, bv.signed)
class Mul(_SimpleBinary):
op = "*"
def get_result_bv(bv):
return BV(2*bv.width, bv.signed)
class And(_SimpleBinary):
op = "&"
def get_result_bv(bv):
return bv
class Xor(_SimpleBinary):
op = "^"
def get_result_bv(bv):
return bv
class Or(_SimpleBinary):
op = "|"
def get_result_bv(bv):
return bv
class LT(_SimpleBinary):
op = "<"
def get_result_bv(bv):
return BV(1)
class LE(_SimpleBinary):
op = "<="
def get_result_bv(bv):
return BV(1)
class EQ(_SimpleBinary):
op = "=="
def get_result_bv(bv):
return BV(1)
class NE(_SimpleBinary):
op = "!="
def get_result_bv(bv):
return BV(1)
class DivMod(SequentialActor):
def __init__(self, width):
self.div = divider.Divider(width)
super().__init__(width,
("operands", Sink, [("dividend", self.div.dividend_i), ("divisor", self.div.divisor_i)]),
("result", Source, [("quotient", self.div.quotient_o), ("remainder", self.div.remainder_o)]))
def get_process_fragment(self):
return self.div.get_fragment() + Fragment([self.div.start_i.eq(self.trigger)])
def _create(a, b, actor_class):
assert id(a.dfg) == id(b.dfg)
dfg = a.dfg
bva = a.get_dict()["bv_r"]
bvb = b.get_dict()["bv_r"]
bv_op = BV(max(bva.width, bvb.width), bva.signed and bvb.signed)
bv_r = actor_class.get_result_bv(bv_op)
new_actor = ComposableNode(dfg, actor_class, {"bv_op": bv_op, "bv_r": bv_r})
dfg.add_connection(a, new_actor, "result", "operands", sink_subr=["a"])
dfg.add_connection(b, new_actor, "result", "operands", sink_subr=["b"])
return new_actor
class ComposableNode(ActorNode):
def __init__(self, dfg, actor_class, parameters=dict()):
self.dfg = dfg
super().__init__(actor_class, parameters)
def __hash__(self):
return id(self)
def __add__(self, other):
return _create(self, other, Add)
def __radd__(self, other):
return _create(other, self, Add)
def __sub__(self, other):
return _create(self, other, Sub)
def __rsub__(self, other):
return _create(other, self, Sub)
def __mul__(self, other):
return _create(self, other, Mul)
def __rmul__(self, other):
return _create(other, self, Mul)
def __and__(self, other):
return _create(self, other, And)
def __rand__(self, other):
return _create(other, self, And)
def __xor__(self, other):
return _create(self, other, Xor)
def __rxor__(self, other):
return _create(other, self, Xor)
def __or__(self, other):
return _create(self, other, Or)
def __ror__(self, other):
return _create(other, self, Or)
def __lt__(self, other):
return _create(self, other, LT)
def __le__(self, other):
return _create(self, other, LE)
def __eq__(self, other):
return _create(self, other, EQ)
def __ne__(self, other):
return _create(self, other, NE)
def __gt__(self, other):
return _create(other, self, LT)
def __ge__(self, other):
return _create(other, self, LE)

View File

@ -7,13 +7,13 @@ class SequentialReader(Actor):
self.port = port
assert(len(self.port.slots) == 1)
super().__init__(
("address", Sink, [("a", BV(self.port.hub.aw))]),
("data", Source, [("d", BV(self.port.hub.dw))]))
("address", Sink, [("a", self.port.hub.aw)]),
("data", Source, [("d", self.port.hub.dw)]))
def get_fragment(self):
sample = Signal()
data_reg_loaded = Signal()
data_reg = Signal(BV(self.port.hub.dw))
data_reg = Signal(self.port.hub.dw)
accept_new = Signal()
@ -49,8 +49,8 @@ class OOOReader(Actor):
self.port = port
assert(len(self.port.slots) > 1)
super().__init__(
("address", Sink, [("a", BV(self.port.hub.aw))]),
("data", Source, [("d", BV(self.port.hub.dw))]))
("address", Sink, [("a", self.port.hub.aw)]),
("data", Source, [("d", self.port.hub.dw)]))
def get_fragment(self):
tag_width = len(self.port.tag_call)

View File

@ -6,14 +6,14 @@ class Reader(Actor):
def __init__(self):
self.bus = wishbone.Interface()
super().__init__(
("address", Sink, [("a", BV(30))]),
("data", Source, [("d", BV(32))]))
("address", Sink, [("a", 30)]),
("data", Source, [("d", 32)]))
def get_fragment(self):
bus_stb = Signal()
data_reg_loaded = Signal()
data_reg = Signal(BV(32))
data_reg = Signal(32)
comb = [
self.busy.eq(data_reg_loaded),
@ -42,7 +42,7 @@ class Writer(Actor):
def __init__(self):
self.bus = wishbone.Interface()
super().__init__(
("address_data", Sink, [("a", BV(30)), ("d", BV(32))]))
("address_data", Sink, [("a", 30), ("d", 32)]))
def get_fragment(self):
comb = [

View File

@ -10,23 +10,23 @@ class IntSequence(Actor):
self.offsetbits = offsetbits
self.step = step
parameters_layout = [("maximum", BV(self.nbits))]
parameters_layout = [("maximum", self.nbits)]
if self.offsetbits:
parameters_layout.append(("offset", BV(self.offsetbits)))
parameters_layout.append(("offset", self.offsetbits))
super().__init__(
("parameters", Sink, parameters_layout),
("source", Source, [("value", BV(max(self.nbits, self.offsetbits)))]))
("source", Source, [("value", max(self.nbits, self.offsetbits))]))
def get_fragment(self):
load = Signal()
ce = Signal()
last = Signal()
maximum = Signal(BV(self.nbits))
maximum = Signal(self.nbits)
if self.offsetbits:
offset = Signal(BV(self.offsetbits))
counter = Signal(BV(self.nbits))
offset = Signal(self.offsetbits)
counter = Signal(self.nbits)
if self.step > 1:
comb = [last.eq(counter + self.step >= maximum)]

View File

@ -3,7 +3,7 @@ from migen.flow.actor import *
def _rawbits_layout(l):
if isinstance(l, int):
return [("rawbits", BV(l))]
return [("rawbits", l)]
else:
return l
@ -34,7 +34,7 @@ class Unpack(Actor):
def get_fragment(self):
muxbits = bits_for(self.n-1)
mux = Signal(BV(muxbits))
mux = Signal(muxbits)
last = Signal()
comb = [
last.eq(mux == (self.n-1)),
@ -65,7 +65,7 @@ class Pack(Actor):
def get_fragment(self):
demuxbits = bits_for(self.n-1)
demux = Signal(BV(demuxbits))
demux = Signal(demuxbits)
load_part = Signal()
strobe_all = Signal()

View File

@ -10,8 +10,8 @@ class RegisterRaw:
self.name = name
self.size = size
self.re = Signal()
self.r = Signal(BV(self.size))
self.w = Signal(BV(self.size))
self.r = Signal(self.size)
self.w = Signal(self.size)
(READ_ONLY, WRITE_ONLY, READ_WRITE) = range(3)
@ -21,15 +21,15 @@ class Field:
self.size = size
self.access_bus = access_bus
self.access_dev = access_dev
self.storage = Signal(BV(self.size), reset=reset)
self.storage = Signal(self.size, reset=reset)
self.atomic_write = atomic_write
if self.access_bus == READ_ONLY and self.access_dev == WRITE_ONLY:
self.w = Signal(BV(self.size))
self.w = Signal(self.size)
else:
if self.access_dev == READ_ONLY or self.access_dev == READ_WRITE:
self.r = Signal(BV(self.size))
self.r = Signal(self.size)
if self.access_dev == WRITE_ONLY or self.access_dev == READ_WRITE:
self.w = Signal(BV(self.size))
self.w = Signal(self.size)
self.we = Signal()
class RegisterFields:
@ -51,7 +51,7 @@ class FieldAlias:
self.access_bus = f.access_bus
self.access_dev = f.access_dev
if mode == ALIAS_ATOMIC_HOLD:
self.storage = Signal(BV(end-start), name="atomic_hold")
self.storage = Signal(end-start, name="atomic_hold")
self.commit_to = f.storage[start:end]
else:
self.storage = f.storage[start:end]

View File

@ -10,17 +10,17 @@ class FinalizeError(Exception):
class Slot:
def __init__(self, aw, time):
self.state = Signal(BV(2))
self.state = Signal(2)
self.we = Signal()
self.adr = Signal(BV(aw))
self.adr = Signal(aw)
self.time = time
if self.time:
self._counter = Signal(BV(bits_for(time)))
self._counter = Signal(bits_for(time))
self.mature = Signal()
self.allocate = Signal()
self.allocate_we = Signal()
self.allocate_adr = Signal(BV(aw))
self.allocate_adr = Signal(aw)
self.process = Signal()
self.call = Signal()
@ -55,7 +55,7 @@ class Port:
self.finalized = False
# request issuance
self.adr = Signal(BV(self.hub.aw))
self.adr = Signal(self.hub.aw)
self.we = Signal()
self.stb = Signal()
# tag_issue is created by finalize()
@ -64,9 +64,9 @@ class Port:
# request completion
self.call = Signal()
# tag_call is created by finalize()
self.dat_r = Signal(BV(self.hub.dw))
self.dat_w = Signal(BV(self.hub.dw))
self.dat_wm = Signal(BV(self.hub.dw//8))
self.dat_r = Signal(self.hub.dw)
self.dat_w = Signal(self.hub.dw)
self.dat_wm = Signal(self.hub.dw//8)
def finalize(self, tagbits, base):
if self.finalized:
@ -76,8 +76,8 @@ class Port:
self.base = base
nslots = len(self.slots)
if nslots > 1:
self.tag_issue = Signal(BV(bits_for(nslots-1)))
self.tag_call = Signal(BV(tagbits))
self.tag_issue = Signal(bits_for(nslots-1))
self.tag_call = Signal(tagbits)
def get_call_expression(self, slotn=0):
if not self.finalized:
@ -127,9 +127,9 @@ class Hub:
self.call = Signal()
# tag_call is created by finalize()
self.dat_r = Signal(BV(self.dw))
self.dat_w = Signal(BV(self.dw))
self.dat_wm = Signal(BV(self.dw//8))
self.dat_r = Signal(self.dw)
self.dat_w = Signal(self.dw)
self.dat_wm = Signal(self.dw//8)
def get_port(self, nslots=1):
if self.finalized:
@ -148,7 +148,7 @@ class Hub:
for port in self.ports:
port.finalize(tagbits, base)
base += len(port.slots)
self.tag_call = Signal(BV(tagbits))
self.tag_call = Signal(tagbits)
def get_slots(self):
if not self.finalized:

View File

@ -25,7 +25,7 @@ class SimpleInterface:
busname = modules[len(modules)-1]
for signal in self.desc.desc:
signame = signal[1]
setattr(self, signame, Signal(BV(signal[2]), busname + "_" + signame))
setattr(self, signame, Signal(signal[2], busname + "_" + signame))
def simple_interconnect_stmts(desc, master, slaves):
s2m = desc.get_names(S_TO_M)

View File

@ -74,8 +74,8 @@ class Decoder:
sync = []
ns = len(self.slaves)
slave_sel = Signal(BV(ns))
slave_sel_r = Signal(BV(ns))
slave_sel = Signal(ns)
slave_sel_r = Signal(ns)
# decode slave addresses
comb += [slave_sel[i].eq(fun(self.master.adr))

View File

@ -38,7 +38,7 @@ class WB2ASMI:
write_from_asmi = Signal()
write_to_asmi = Signal()
adr_offset_r = Signal(BV(offsetbits))
adr_offset_r = Signal(offsetbits)
comb += [
data_port.adr.eq(adr_line),
If(write_from_asmi,
@ -62,7 +62,7 @@ class WB2ASMI:
tag_mem = Memory(tagbits+1, 2**linebits)
tag_port = tag_mem.get_port(write_capable=True)
tag_layout = [("tag", BV(tagbits)), ("dirty", BV(1))]
tag_layout = [("tag", tagbits), ("dirty", 1)]
tag_do = Record(tag_layout)
tag_di = Record(tag_layout)
comb += [

View File

@ -4,8 +4,8 @@ class ReorderSlot:
def __init__(self, tag_width, data_width):
self.wait_data = Signal()
self.has_data = Signal()
self.tag = Signal(BV(tag_width))
self.data = Signal(BV(data_width))
self.tag = Signal(tag_width)
self.data = Signal(data_width)
class ReorderBuffer:
def __init__(self, tag_width, data_width, depth):
@ -14,21 +14,21 @@ class ReorderBuffer:
# issue
self.can_issue = Signal()
self.issue = Signal()
self.tag_issue = Signal(BV(tag_width))
self.tag_issue = Signal(tag_width)
# call
self.call = Signal()
self.tag_call = Signal(BV(tag_width))
self.data_call = Signal(BV(data_width))
self.tag_call = Signal(tag_width)
self.data_call = Signal(data_width)
# readback
self.can_read = Signal()
self.read = Signal()
self.data_read = Signal(BV(data_width))
self.data_read = Signal(data_width)
self._empty_count = Signal(BV(bits_for(self.depth)), reset=self.depth)
self._produce = Signal(BV(bits_for(self.depth-1)))
self._consume = Signal(BV(bits_for(self.depth-1)))
self._empty_count = Signal(max=self.depth+1, reset=self.depth)
self._produce = Signal(max=self.depth)
self._consume = Signal(max=self.depth)
self._slots = Array(ReorderSlot(tag_width, data_width)
for n in range(self.depth))

View File

@ -5,19 +5,19 @@ class Divider:
self.w = w
self.start_i = Signal()
self.dividend_i = Signal(BV(w))
self.divisor_i = Signal(BV(w))
self.dividend_i = Signal(w)
self.divisor_i = Signal(w)
self.ready_o = Signal()
self.quotient_o = Signal(BV(w))
self.remainder_o = Signal(BV(w))
self.quotient_o = Signal(w)
self.remainder_o = Signal(w)
def get_fragment(self):
w = self.w
qr = Signal(BV(2*w))
counter = Signal(BV(bits_for(w)))
divisor_r = Signal(BV(w))
diff = Signal(BV(w+1))
qr = Signal(2*w)
counter = Signal(bits_for(w))
divisor_r = Signal(w)
diff = Signal(w+1)
comb = [
self.quotient_o.eq(qr[:w]),

View File

@ -4,9 +4,8 @@ class FSM:
def __init__(self, *states, delayed_enters=[]):
nstates = len(states) + sum([d[2] for d in delayed_enters])
self._state_bv = BV(bits_for(nstates-1))
self._state = Signal(self._state_bv)
self._next_state = Signal(self._state_bv)
self._state = Signal(max=nstates)
self._next_state = Signal(max=nstates)
for n, state in enumerate(states):
setattr(self, state, n)
self.actions = [[] for i in range(len(states))]

View File

@ -54,7 +54,7 @@ def chooser(signal, shift, output, n=None, reverse=False):
def timeline(trigger, events):
lastevent = max([e[0] for e in events])
counter = Signal(BV(bits_for(lastevent)))
counter = Signal(bits_for(lastevent))
counterlogic = If(counter != 0,
counter.eq(counter + 1)

View File

@ -1,5 +1,5 @@
from migen.fhdl.structure import *
from migen.fhdl.tools import value_bv
from migen.fhdl.tools import value_bits_sign
class Record:
def __init__(self, layout, name=""):
@ -11,7 +11,7 @@ class Record:
prefix = ""
for f in layout:
if isinstance(f, tuple):
if isinstance(f[1], BV):
if isinstance(f[1], (int, tuple)):
setattr(self, f[0], Signal(f[1], prefix + f[0]))
elif isinstance(f[1], Signal) or isinstance(f[1], Record):
setattr(self, f[0], f[1])
@ -24,7 +24,7 @@ class Record:
else:
self.field_order.append((f[0], 1))
else:
setattr(self, f, Signal(BV(1), prefix + f))
setattr(self, f, Signal(1, prefix + f))
self.field_order.append((f, 1))
def layout(self):
@ -32,7 +32,7 @@ class Record:
for key, alignment in self.field_order:
e = self.__dict__[key]
if isinstance(e, Signal):
l.append((key, e.bv, alignment))
l.append((key, (e.nbits, e.signed), alignment))
elif isinstance(e, Record):
l.append((key, e.layout(), alignment))
return l
@ -88,7 +88,7 @@ class Record:
else:
raise TypeError
for x in added:
offset += value_bv(x).width
offset += value_bits_sign(x)[0]
l += added
if return_offset:
return (l, offset)
@ -97,7 +97,7 @@ class Record:
def to_signal(self, assignment_list, sig_out, align=False):
flattened, length = self.flatten(align, return_offset=True)
raw = Signal(BV(length))
raw = Signal(length)
if sig_out:
assignment_list.append(raw.eq(Cat(*flattened)))
else:

View File

@ -6,8 +6,8 @@ class RoundRobin:
def __init__(self, n, switch_policy=SP_WITHDRAW):
self.n = n
self.bn = bits_for(self.n-1)
self.request = Signal(BV(self.n))
self.grant = Signal(BV(self.bn))
self.request = Signal(self.n)
self.grant = Signal(self.bn)
self.switch_policy = switch_policy
if self.switch_policy == SP_CE:
self.ce = Signal()

View File

@ -1,5 +1,6 @@
import inspect
import re
import builtins
from collections import defaultdict
from migen.fhdl import tracer
@ -24,22 +25,6 @@ def bits_for(n, require_sign_bit=False):
r += 1
return r
class BV:
def __init__(self, width=1, signed=False):
self.width = width
self.signed = signed
def __repr__(self):
r = str(self.width) + "'"
if self.signed:
r += "s"
r += "d"
return r
def __eq__(self, other):
return self.width == other.width and self.signed == other.signed
class HUID:
__next_uid = 0
def __init__(self):
@ -66,13 +51,13 @@ class Value(HUID):
def __rmul__(self, other):
return _Operator("*", [other, self])
def __lshift__(self, other):
return _Operator("<<", [self, other])
return _Operator("<<<", [self, other])
def __rlshift__(self, other):
return _Operator("<<", [other, self])
return _Operator("<<<", [other, self])
def __rshift__(self, other):
return _Operator(">>", [self, other])
return _Operator(">>>", [self, other])
def __rrshift__(self, other):
return _Operator(">>", [other, self])
return _Operator(">>>", [other, self])
def __and__(self, other):
return _Operator("&", [self, other])
def __rand__(self, other):
@ -145,17 +130,34 @@ class Replicate(Value):
self.n = n
class Signal(Value):
def __init__(self, bv=BV(), name=None, variable=False, reset=0, name_override=None):
def __init__(self, bits_sign=None, name=None, variable=False, reset=0, name_override=None, min=None, max=None):
super().__init__()
assert(isinstance(bv, BV))
self.bv = bv
# determine number of bits and signedness
if bits_sign is None:
if min is None:
min = 0
if max is None:
max = 2
max -= 1 # make both bounds inclusive
assert(min < max)
self.signed = min < 0 or max < 0
self.nbits = builtins.max(bits_for(min, self.signed), bits_for(max, self.signed))
else:
assert(min is None and max is None)
if isinstance(bits_sign, tuple):
self.nbits, self.signed = bits_sign
else:
self.nbits, self.signed = bits_sign, False
assert(isinstance(self.nbits, int))
self.variable = variable
self.reset = reset
self.name_override = name_override
self.backtrace = tracer.trace_back(name)
def __len__(self):
return self.bv.width
def __len__(self): # TODO: remove (use tools.value_bits_sign instead)
return self.nbits
def __repr__(self):
return "<Signal " + (self.backtrace[-1][0] or "anonymous") + " at " + hex(id(self)) + ">"
@ -238,9 +240,9 @@ class Instance(HUID):
self.items = items
class _IO:
def __init__(self, name, expr=BV(1)):
def __init__(self, name, expr=1):
self.name = name
if isinstance(expr, BV):
if isinstance(expr, (int, tuple)):
self.expr = Signal(expr, name)
else:
self.expr = expr
@ -300,14 +302,14 @@ class Memory(HUID):
clock_domain="sys"):
if we_granularity >= self.width:
we_granularity = 0
adr = Signal(BV(bits_for(self.depth-1)))
dat_r = Signal(BV(self.width))
adr = Signal(max=self.depth)
dat_r = Signal(self.width)
if write_capable:
if we_granularity:
we = Signal(BV(self.width//we_granularity))
we = Signal(self.width//we_granularity)
else:
we = Signal()
dat_w = Signal(BV(self.width))
dat_w = Signal(self.width)
else:
we = None
dat_w = None

View File

@ -104,43 +104,77 @@ def insert_reset(rst, sl):
resetcode = [t.eq(t.reset) for t in sorted(targets, key=lambda x: x.huid)]
return If(rst, *resetcode).Else(*sl)
def value_bv(v):
def value_bits_sign(v):
if isinstance(v, bool):
return BV(1, False)
return 1, False
elif isinstance(v, int):
return BV(bits_for(v), v < 0)
return bits_for(v), v < 0
elif isinstance(v, Signal):
return v.bv
return v.nbits, v.signed
elif isinstance(v, _Operator):
obv = list(map(value_bv, v.operands))
obs = list(map(value_bits_sign, v.operands))
if v.op == "+" or v.op == "-":
return BV(max(obv[0].width, obv[1].width) + 1,
obv[0].signed and obv[1].signed)
elif v.op == "*":
signed = obv[0].signed and obv[1].signed
if signed:
return BV(obv[0].width + obv[1].width - 1, signed)
if not obs[0][1] and not obs[1][1]:
# both operands unsigned
return max(obs[0][0], obs[1][0]) + 1, False
elif obs[0][1] and obs[1][1]:
# both operands signed
return max(obs[0][0], obs[1][0]) + 1, True
elif not obs[0][1] and obs[1][1]:
# first operand unsigned (add sign bit), second operand signed
return max(obs[0][0] + 1, obs[1][0]) + 1, True
else:
return BV(obv[0].width + obv[1].width, signed)
elif v.op == "<<" or v.op == ">>":
return obv[0].bv
# first signed, second operand unsigned (add sign bit)
return max(obs[0][0], obs[1][0] + 1) + 1, True
elif v.op == "*":
if not obs[0][1] and not obs[1][1]:
# both operands unsigned
return obs[0][0] + obs[1][0]
elif obs[0][1] and obs[1][1]:
# both operands signed
return obs[0][0] + obs[1][0] - 1
else:
# one operand signed, the other unsigned (add sign bit)
return obs[0][0] + obs[1][0] + 1 - 1
elif v.op == "<<<":
if obs[1][1]:
extra = 2**(obs[1][0] - 1) - 1
else:
extra = 2**obs[1][0] - 1
return obs[0][0] + extra, obs[0][1]
elif v.op == ">>>":
if obs[1][1]:
extra = 2**(obs[1][0] - 1)
else:
extra = 0
return obs[0][0] + extra, obs[0][1]
elif v.op == "&" or v.op == "^" or v.op == "|":
return BV(max(obv[0].width, obv[1].width),
obv[0].signed and obv[1].signed)
if not obs[0][1] and not obs[1][1]:
# both operands unsigned
return max(obs[0][0], obs[1][0]), False
elif obs[0][1] and obs[1][1]:
# both operands signed
return max(obs[0][0], obs[1][0]), True
elif not obs[0][1] and obs[1][1]:
# first operand unsigned (add sign bit), second operand signed
return max(obs[0][0] + 1, obs[1][0]), True
else:
# first signed, second operand unsigned (add sign bit)
return max(obs[0][0], obs[1][0] + 1), True
elif v.op == "<" or v.op == "<=" or v.op == "==" or v.op == "!=" \
or v.op == ">" or v.op == ">=":
return BV(1)
return 1, False
else:
raise TypeError
elif isinstance(v, _Slice):
return BV(v.stop - v.start, value_bv(v.value).signed)
return v.stop - v.start, value_bits_sign(v.value)[1]
elif isinstance(v, Cat):
return BV(sum(value_bv(sv).width for sv in v.l))
return sum(value_bits_sign(sv)[0] for sv in v.l), False
elif isinstance(v, Replicate):
return BV(value_bv(v.v).width*v.n)
return (value_bits_sign(v.v)[0])*v.n, False
elif isinstance(v, _ArrayProxy):
bvc = map(value_bv, v.choices)
return BV(max(bv.width for bv in bvc), any(bv.signed for bv in bvc))
bsc = map(value_bits_sign, v.choices)
return max(bs[0] for bs in bsc), any(bs[1] for bs in bsc)
else:
raise TypeError
@ -160,7 +194,7 @@ class _ArrayLowerer(NodeTransformer):
return super().visit_Assign(node)
def visit_ArrayProxy(self, node):
array_muxed = Signal(value_bv(node))
array_muxed = Signal(value_bits_sign(node))
cases = dict((n, _Assign(array_muxed, self.visit(choice)))
for n, choice in enumerate(node.choices))
self.comb.append(Case(self.visit(node.key), cases).makedefault())

View File

@ -8,7 +8,7 @@ from migen.fhdl.namer import Namespace, build_namespace
from migen.fhdl import verilog_mem_behavioral
def _printsig(ns, s):
if s.bv.signed:
if s.signed:
n = "signed "
else:
n = ""

View File

@ -112,7 +112,7 @@ class SequentialActor(BinaryActor):
def get_binary_control_fragment(self, stb_i, ack_o, stb_o, ack_i):
ready = Signal()
timer = Signal(BV(bits_for(self.delay)))
timer = Signal(bits_for(self.delay))
comb = [ready.eq(timer == 0)]
sync = [
If(self.trigger,
@ -143,7 +143,7 @@ class PipelinedActor(BinaryActor):
super().__init__(*endpoint_descriptions, **misc)
def get_binary_control_fragment(self, stb_i, ack_o, stb_o, ack_i):
valid = Signal(BV(self.latency))
valid = Signal(self.latency)
if self.latency > 1:
sync = [If(self.pipe_ce, valid.eq(Cat(stb_i, valid[:self.latency-1])))]
else:

View File

@ -23,8 +23,8 @@ class EndpointReporter:
def get_fragment(self):
stb = Signal()
ack = Signal()
ack_count = Signal(BV(self.nbits))
nack_count = Signal(BV(self.nbits))
ack_count = Signal(self.nbits)
nack_count = Signal(self.nbits)
comb = [
self._cur_stb.w.eq(stb),
self._cur_ack.w.eq(ack)

View File

@ -51,7 +51,7 @@ class Splitter(Actor):
sources = [self.endpoints[e] for e in self.sources()]
sink = self.endpoints[self.sinks()[0]]
already_acked = Signal(BV(len(sources)))
already_acked = Signal(len(sources))
sync = [
If(sink.stb,
already_acked.eq(already_acked | Cat(*[s.ack for s in sources])),

View File

@ -26,7 +26,7 @@ class LowerAbstractLoad(fhdl.NodeTransformer):
class ImplRegister:
def __init__(self, name, nbits):
self.name = name
self.storage = Signal(BV(nbits), name=self.name)
self.storage = Signal(nbits, name=self.name)
self.source_encoding = {}
self.id_to_source = {}
self.finalized = False
@ -40,7 +40,7 @@ class ImplRegister:
def finalize(self):
if self.finalized:
raise FinalizeError
self.sel = Signal(BV(bits_for(len(self.source_encoding) + 1)), name="pl_regsel_"+self.name)
self.sel = Signal(max=len(self.source_encoding)+2, name="pl_regsel_"+self.name)
self.finalized = True
def get_fragment(self):

View File

@ -122,7 +122,7 @@ class Simulator:
signed = False
nbits = item.width
else:
signed = item.bv.signed
signed = item.signed
nbits = len(item)
value = reply.value & (2**nbits - 1)
if signed and (value & 2**(nbits - 1)):