class SimDumper(SimActor):
def __init__(self):
self.data = Sink([("d", 32)])
- SimActor.__init__(self, dumper_gen())
+ SimActor.__init__(self, dumper_gen())
def trgen_gen():
for i in range(10):
def __init__(self):
source = SimSource()
sink = SimSink()
-
+
# A tortuous way of passing integer tokens.
packer = structuring.Pack(base_layout, pack_factor)
to_raw = structuring.Cast(packed_layout, rawbits_layout)
from_raw = structuring.Cast(rawbits_layout, packed_layout)
unpacker = structuring.Unpack(pack_factor, base_layout)
-
+
self.g = DataFlowGraph()
self.g.add_connection(source, packer)
self.g.add_connection(packer, to_raw)
if __name__ == "__main__":
tb = TB()
run_simulation(tb, ncycles=1000)
-
+
g = nx.MultiDiGraph()
for u, v, edge in tb.g.edges_iter():
g.add_edge(u, v, **edge)
g = DataFlowGraph()
d = Dumper(layout)
g.add_connection(ng, d)
-
+
c = CompositeActor(g)
run_simulation(c, ncycles=20)
print("Simulating native Python:")
ng_native = SimNumberGen()
run_ng_sim(ng_native)
-
+
print("Simulating Pytholite:")
ng_pytholite = make_ng_pytholite()
run_ng_sim(ng_pytholite)
-
+
print("Converting Pytholite to Verilog:")
ng_pytholite = make_ng_pytholite()
print(verilog.convert(ng_pytholite))
g = DataFlowGraph()
d = Dumper(layout)
g.add_connection(ng, d)
-
+
self.submodules.slave = wishbone.Target(SlaveModel())
self.submodules.intercon = wishbone.InterconnectPointToPoint(ng.wb, self.slave.bus)
self.submodules.ca = CompositeActor(g)
def main():
print("Simulating native Python:")
ng_native = UnifiedIOSimulation(gen())
- add_interfaces(ng_native)
+ add_interfaces(ng_native)
run_ng_sim(ng_native)
-
+
print("Simulating Pytholite:")
ng_pytholite = Pytholite(gen)
add_interfaces(ng_pytholite)
run_ng_sim(ng_pytholite)
-
+
print("Converting Pytholite to Verilog:")
ng_pytholite = Pytholite(gen)
add_interfaces(ng_pytholite)
t = TWrite(4*bank+x, 0x1000*bank + 0x100*x)
yield t
print("{0}: Wrote in {1} cycle(s)".format(n, t.latency))
-
+
for x in range(4):
t = TRead(4*bank+x)
yield t
r = 0x1000*bank + 0x100*address
#print("read from bank {0} address {1} -> {2:x}".format(bank, address, r))
return r
-
+
def write(self, bank, address, data, we):
print("write to bank {0} address {1:x} data {2:x}".format(bank, address, data))
assert(data == 0x1000*bank + 0x100*address)
# At each cycle, increase the value of the count signal.
# We do it with convertible/synthesizable FHDL code.
self.sync += self.count.eq(self.count + 1)
-
+
# This function will be called at every cycle.
def do_simulation(self, selfp):
# Simply read the count signal and print it.
# The output is:
- # Count: 0
+ # Count: 0
# Count: 1
# Count: 2
# ...
self.count = Signal((37, True), reset=-5)
self.sync += If(self.ce, self.count.eq(self.count + 1))
-
+
def do_simulation(self, selfp):
# Only assert CE every second cycle.
# => each counter value is held for two cycles.
selfp.ce = 1
print("Cycle: " + str(selfp.simulator.cycle_counter) + " Count: " + \
str(selfp.count))
-
+
# Output is:
# Cycle: 0 Count: -5
# Cycle: 1 Count: -5
self.wsize = wsize
self.i = Signal((self.wsize, True))
self.o = Signal((self.wsize, True))
-
+
###
muls = []
self.frequency = frequency
self.inputs = []
self.outputs = []
-
+
def do_simulation(self, selfp):
f = 2**(self.fir.wsize - 1)
v = 0.1*cos(2*pi*self.frequency*selfp.simulator.cycle_counter)
if __name__ == "__main__":
# Compute filter coefficients with SciPy.
coef = signal.remez(30, [0, 0.1, 0.2, 0.4, 0.45, 0.5], [0, 1, 0])
-
+
# Simulate for different frequencies and concatenate
# the results.
in_signals = []
run_simulation(tb, ncycles=200)
in_signals += tb.inputs
out_signals += tb.outputs
-
+
# Plot data from the input and output waveforms.
plt.plot(in_signals)
plt.plot(out_signals)
plt.show()
-
+
# Print the Verilog source for the filter.
fir = FIR(coef)
print(verilog.convert(fir, ios={fir.i, fir.o}))
# Initialize the beginning of the memory with integers
# from 0 to 19.
self.specials.mem = Memory(16, 2**12, init=list(range(20)))
-
+
def do_simulation(self, selfp):
# Read the memory. Use the cycle counter as address.
value = selfp.mem[selfp.simulator.cycle_counter]
if isinstance(c, Pins):
return "set_location_assignment PIN_" + c.identifiers[0]
elif isinstance(c, IOStandard):
- return "set_instance_assignment -name IO_STANDARD " + "\"" + c.name + "\""
+ return "set_instance_assignment -name IO_STANDARD " + "\"" + c.name + "\""
elif isinstance(c, Misc):
return c.misc
if not isinstance(fragment, _Fragment):
fragment = fragment.get_fragment()
self.finalize(fragment)
-
+
v_src, named_sc, named_pc = self.get_verilog(fragment)
v_file = build_name + ".v"
tools.write_to_file(v_file, v_src)
_build_files(self.device, sources, self.verilog_include_paths, named_sc, named_pc, build_name)
if run:
_run_quartus(build_name, quartus_path)
-
+
os.chdir("..")
def add_period_constraint(self, clk, period):
class ConstraintError(Exception):
pass
-
+
class Pins:
def __init__(self, *identifiers):
self.identifiers = []
if resource[0] == name and (number is None or resource[1] == number):
return resource
raise ConstraintError("Resource not found: " + name + ":" + str(number))
-
+
def _resource_type(resource):
t = None
for element in resource[2:]:
def add_extension(self, io):
self.available.extend(io)
-
+
def request(self, name, number=None):
resource = _lookup(self.available, name, number)
- rt = _resource_type(resource)
+ rt = _resource_type(resource)
if isinstance(rt, int):
obj = Signal(rt, name_override=resource[0])
else:
if resource[0] == name and (number is None or resource[1] == number):
return obj
raise ConstraintError("Resource not found: " + name + ":" + str(number))
-
+
def add_platform_command(self, command, **signals):
self.platform_commands.append((command, signals))
-
+
def get_io_signals(self):
r = set()
for resource, obj in self.matched:
else:
r.update(obj.flatten())
return r
-
+
def get_sig_constraints(self):
r = []
for resource, obj in self.matched:
def get_verilog(self, fragment, **kwargs):
return self._get_source(fragment, lambda f: verilog.convert(f, self.constraint_manager.get_io_signals(),
return_ns=True, create_clock_domains=False, **kwargs))
-
+
def get_edif(self, fragment, cell_library, vendor, device, **kwargs):
return self._get_source(fragment, lambda f: edif.convert(f, self.constraint_manager.get_io_signals(),
cell_library, vendor, device, return_ns=True, **kwargs))
("key", 0, Pins("J15"), IOStandard("3.3-V LVTTL")),
("key", 1, Pins("E1"), IOStandard("3.3-V LVTTL")),
-
+
("sw", 0, Pins("M1"), IOStandard("3.3-V LVTTL")),
- ("sw", 1, Pins("T9"), IOStandard("3.3-V LVTTL")),
+ ("sw", 1, Pins("T9"), IOStandard("3.3-V LVTTL")),
("sw", 2, Pins("B9"), IOStandard("3.3-V LVTTL")),
("sw", 3, Pins("M15"), IOStandard("3.3-V LVTTL")),
Subsignal("tx", Pins("D3"), IOStandard("3.3-V LVTTL")),
Subsignal("rx", Pins("C3"), IOStandard("3.3-V LVTTL"))
),
-
+
("sdram_clock", 0, Pins("R4"), IOStandard("3.3-V LVTTL")),
("sdram", 0,
Subsignal("a", Pins("P2 N5 N6 M8 P8 T7 N8 T6 R1 P1 N2 N1 L4")),
Subsignal("dm", Pins("R6","T5")),
IOStandard("3.3-V LVTTL")
),
-
+
("epcs", 0,
Subsignal("data0", Pins("H2")),
Subsignal("dclk", Pins("H1")),
Subsignal("asd0", Pins("C1")),
IOStandard("3.3-V LVTTL")
),
-
+
("i2c", 0,
Subsignal("sclk", Pins("F2")),
Subsignal("sdat", Pins("F1")),
Subsignal("int", Pins("M2")),
IOStandard("3.3-V LVTTL")
),
-
+
("adc", 0,
Subsignal("cs_n", Pins("A10")),
Subsignal("saddr", Pins("B10")),
Subsignal("sdat", Pins("A9")),
IOStandard("3.3-V LVTTL")
),
-
+
("gpio_0", 0,
Pins("D3 C3 A2 A3 B3 B4 A4 B5 A5 D5 B6 A6 B7 D6 A7 C6",
"C8 E6 E7 D8 E8 F8 F9 E9 C9 D9 E11 E10 C11 B11 A12 D11",
("user_led", 5, Pins("G19"), IOStandard("LVCMOS25")),
("user_led", 6, Pins("E18"), IOStandard("LVCMOS25")),
("user_led", 7, Pins("F16"), IOStandard("LVCMOS25")),
-
+
("cpu_reset", 0, Pins("AB7"), IOStandard("LVCMOS15")),
-
+
("user_btn_c", 0, Pins("G12"), IOStandard("LVCMOS25")),
("user_btn_n", 0, Pins("AA12"), IOStandard("LVCMOS15")),
("user_btn_s", 0, Pins("AB12"), IOStandard("LVCMOS15")),
("user_btn_w", 0, Pins("AC6"), IOStandard("LVCMOS15")),
("user_btn_e", 0, Pins("AG5"), IOStandard("LVCMOS15")),
-
+
("user_dip_btn", 0, Pins("Y29"), IOStandard("LVCMOS25")),
("user_dip_btn", 1, Pins("W29"), IOStandard("LVCMOS25")),
("user_dip_btn", 2, Pins("AA28"), IOStandard("LVCMOS25")),
("user_dip_btn", 3, Pins("Y28"), IOStandard("LVCMOS25")),
-
+
("clk200", 0,
Subsignal("p", Pins("AD12"), IOStandard("LVDS")),
Subsignal("n", Pins("AD11"), IOStandard("LVDS"))
),
-
+
("clk156", 0,
Subsignal("p", Pins("K28"), IOStandard("LVDS_25")),
Subsignal("n", Pins("K29"), IOStandard("LVDS_25"))
),
-
+
("i2c", 0,
Subsignal("scl", Pins("K21")),
Subsignal("sda", Pins("L21")),
IOStandard("LVCMOS25")),
-
+
("serial", 0,
Subsignal("cts", Pins("L27")),
Subsignal("rts", Pins("K23")),
Subsignal("clk", Pins("AB23")),
Subsignal("dat", Pins("AC20 AA23 AA22 AC21")),
IOStandard("LVCMOS25")),
-
+
("lcd", 0,
Subsignal("db", Pins("AA13 AA10 AA11 Y10")),
Subsignal("e", Pins("AB10")),
Subsignal("rs", Pins("Y11")),
Subsignal("rw", Pins("AB13")),
IOStandard("LVCMOS15")),
-
+
("rotary", 0,
Subsignal("a", Pins("Y26")),
Subsignal("b", Pins("Y25")),
Subsignal("push", Pins("AA26")),
IOStandard("LVCMOS25")),
-
+
("hdmi", 0,
Subsignal("d", Pins("B23 A23 E23 D23 F25 E25 E24 D24 F26 E26 G23 G24 J19 H19 L17 L18 K19 K20")),
Subsignal("de", Pins("H17")),
if isinstance(self, XilinxISEPlatform):
self.add_platform_command("CONFIG DCI_CASCADE = \"33 32 34\";")
else:
- self.add_platform_command("set_property DCI_CASCADE {{32 34}} [get_iobanks 33]")
+ self.add_platform_command("set_property DCI_CASCADE {{32 34}} [get_iobanks 33]")
return RealPlatform(*args, **kwargs)
("user_btn", 0, Pins("AB4"), IOStandard("LVCMOS33")),
("user_btn", 1, Pins("AA4"), IOStandard("LVCMOS33")),
("user_btn", 2, Pins("AB5"), IOStandard("LVCMOS33")),
-
+
("clk50", 0, Pins("AB11"), IOStandard("LVCMOS33")),
# When executing softcore code in-place from the flash, we want
Subsignal("ce_n", Pins("M21")),
IOStandard("LVCMOS33"), Misc("SLEW=FAST"), Drive(8)
),
-
+
("serial", 0,
Subsignal("tx", Pins("L17"), IOStandard("LVCMOS33"), Misc("SLEW=SLOW")),
Subsignal("rx", Pins("K18"), IOStandard("LVCMOS33"), Misc("PULLUP"))
),
-
+
("ddram_clock", 0,
Subsignal("p", Pins("M3")),
Subsignal("n", Pins("L4")),
IOStandard("SSTL2_I")
- ),
+ ),
("ddram", 0,
Subsignal("a", Pins("B1 B2 H8 J7 E4 D5 K7 F5 G6 C1 C3 D1 D2")),
Subsignal("ba", Pins("A2 E6")),
Subsignal("ce_n", Pins("M21")),
IOStandard("LVCMOS33"), Misc("SLEW=FAST"), Drive(8)
),
-
+
("serial", 0,
Subsignal("tx", Pins("L17"), IOStandard("LVCMOS33"), Misc("SLEW=SLOW")),
Subsignal("rx", Pins("K18"), IOStandard("LVCMOS33"), Misc("PULLUP"))
),
-
+
("ddram_clock", 0,
Subsignal("p", Pins("M3")),
Subsignal("n", Pins("L4")),
IOStandard("SSTL2_I")
- ),
+ ),
("ddram", 0,
Subsignal("a", Pins("B1 B2 H8 J7 E4 D5 K7 F5 G6 C1 C3 D1 D2")),
Subsignal("ba", Pins("A2 E6")),
("user_led", 5, Pins("V1")),
("user_led", 6, Pins("U2")),
("user_led", 7, Pins("U1")),
-
+
("clk100", 0,
Subsignal("p", Pins("B14"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")),
Subsignal("n", Pins("A14"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE"))
),
-
+
("gpio", 0, Pins("R8")),
-
- ("gpmc", 0,
+
+ ("gpmc", 0,
Subsignal("clk", Pins("R26")),
Subsignal("a", Pins("N17 N18 L23 L24 N19 N20 N21 N22 P17 P19")),
Subsignal("d", Pins("N23 N24 R18 R19 P21 P22 R20 R21 P24 P26 R23 R24 T22 T23 U23 R25")),
("gpmc_dmareq_n", 1, Pins("T26"), IOStandard("LVCMOS33")), # nCS3
("gpmc_dmareq_n", 2, Pins("V24"), IOStandard("LVCMOS33")), # nCS4
("gpmc_dmareq_n", 3, Pins("V26"), IOStandard("LVCMOS33")), # nCS5
-
+
# FMC150
("fmc150_ctrl", 0,
Subsignal("spi_sclk", Pins("AE5")),
Subsignal("spi_data", Pins("AF5")),
-
+
Subsignal("adc_sdo", Pins("U13")),
Subsignal("adc_en_n", Pins("AA15")),
Subsignal("adc_reset", Pins("V13")),
-
+
Subsignal("cdce_sdo", Pins("AA8")),
Subsignal("cdce_en_n", Pins("Y9")),
Subsignal("cdce_reset_n", Pins("AB7")),
Subsignal("cdce_pd_n", Pins("AC6")),
Subsignal("cdce_pll_status", Pins("W7")),
Subsignal("cdce_ref_en", Pins("W8")),
-
+
Subsignal("dac_sdo", Pins("W9")),
Subsignal("dac_en_n", Pins("W10")),
-
+
Subsignal("mon_sdo", Pins("AC5")),
Subsignal("mon_en_n", Pins("AD6")),
Subsignal("mon_reset_n", Pins("AF6")),
Subsignal("mon_int_n", Pins("AD5")),
-
+
Subsignal("pg_c2m", Pins("AA23"), IOStandard("LVCMOS33"))
),
("ti_dac", 0, # DAC3283
Subsignal("adc_clk_n", Pins("AF15"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")),
Subsignal("clk_to_fpga", Pins("W24"), IOStandard("LVCMOS25"))
),
-
+
("fmc150_ext_trigger", 0, Pins("U26")),
-
+
# Vermeer radar testbed
# Switch controller
("pca9555", 0,
Subsignal("r_w_n", Pins("AF20")),
Subsignal("be_n", Pins("AF14 AF18")),
Subsignal("oe_n", Pins("AF21")),
- Subsignal("addr", Pins("AE23 AE22 AG18 AG12 AG15 AG23 AF19 AE12 AG16 AF13 AG20 AF23",
+ Subsignal("addr", Pins("AE23 AE22 AG18 AG12 AG15 AG23 AF19 AE12 AG16 AF13 AG20 AF23",
"AH17 AH15 L20 J22 H22 L15 L16 K22 K21 K16 J15")),
Subsignal("addr_gp", Pins("L21 G22 K23 K14 L14 J12")),
Subsignal("data", Pins("AF15 AE16 AE21 AD20 AF16 AE17 AE19 AD19 AG22 AH22 AH12 AG13",
"G16 F16 J12 J13 L14 L16 M15 M16 "
"L13 K13 P16 N16 R15 P15 N13 N14")),
- ("adc", 0,
+ ("adc", 0,
Subsignal("sync", Pins("D10")),
Subsignal("d", Pins("A4 B3 A3 D9 C10 A9 C9 D8 "
"C8 B8 A8 B15")),
pass
def language_by_filename(name):
- extension = name.rsplit(".")[-1]
+ extension = name.rsplit(".")[-1]
if extension in ["v", "vh", "vo"]:
return "verilog"
if extension in ["vhd", "vhdl", "vho"]:
incflags += " -I" + path
for filename, language in sources:
ys_contents += "read_{}{} {}\n".format(language, incflags, filename)
-
+
if device[:2] == "xc":
archcode = device[2:4]
else:
"7v": "virtex7",
"7z": "zynq7000"
}[archcode]
-
+
ys_contents += """hierarchy -check -top top
proc; memory; opt; fsm; opt
synth_xilinx -arch {arch} -top top -edif {build_name}.edif""".format(arch=arch, build_name=build_name)
-
+
ys_name = build_name + ".ys"
tools.write_to_file(ys_name, ys_contents)
r = subprocess.call(["yosys", ys_name])
if isinstance(c, Pins):
return "set_property LOC " + c.identifiers[0]
elif isinstance(c, IOStandard):
- return "set_property IOSTANDARD " + c.name
+ return "set_property IOSTANDARD " + c.name
elif isinstance(c, Drive):
return "set_property DRIVE " + str(c.strength)
elif isinstance(c, Misc):
fmt_r = resname[0] + ":" + str(resname[1])
if resname[2] is not None:
fmt_r += "." + resname[2]
- r = " ## %s\n" %fmt_r
+ r = " ## %s\n" %fmt_r
for c in fmt_c:
r += c + " [get_ports " + signame + "]\n"
return r
tools.write_to_file(build_name + ".xdc", _build_xdc(named_sc, named_pc))
if run:
_run_vivado(build_name, vivado_path, source)
-
+
os.chdir("..")
def add_period_constraint(self, clk, period):
self.address = Sink([("a", lasmim.aw)])
self.data = Source([("d", lasmim.dw)])
self.busy = Signal()
-
+
###
if fifo_depth is None:
fifo_depth = lasmim.req_queue_size + lasmim.read_latency + 2
-
+
# request issuance
request_enable = Signal()
request_issued = Signal()
self.address = Sink([("a", 30)])
self.data = Source([("d", 32)])
self.busy = Signal()
-
+
###
-
+
bus_stb = Signal()
data_reg_loaded = Signal()
data_reg = Signal(32)
-
+
self.comb += [
self.busy.eq(data_reg_loaded),
self.bus.we.eq(0),
parameters_layout = [("maximum", nbits)]
if offsetbits:
parameters_layout.append(("offset", offsetbits))
-
+
self.parameters = Sink(parameters_layout)
self.source = Source([("value", max(nbits, offsetbits))])
self.busy = Signal()
-
+
###
-
+
load = Signal()
ce = Signal()
last = Signal()
-
+
maximum = Signal(nbits)
if offsetbits:
offset = Signal(offsetbits)
counter = Signal(nbits)
-
+
if step > 1:
self.comb += last.eq(counter + step >= maximum)
else:
self.comb += self.source.payload.value.eq(counter + offset)
else:
self.comb += self.source.payload.value.eq(counter)
-
+
fsm = FSM()
self.submodules += fsm
fsm.act("IDLE",
def __init__(self, generator):
self.busy = Signal()
self.submodules.token_exchanger = TokenExchanger(generator, self)
-
+
def do_simulation(self, selfp):
selfp.busy = self.token_exchanger.busy
do_simulation.passive = True
def __init__(self, layout, mode):
self.source = Source(_convert_layout(layout))
self.busy = Signal()
-
+
self.comb += self.busy.eq(self.source.stb)
if mode == MODE_EXTERNAL:
self._r_wc = CSRStorage(bits_for(depth), write_from_dev=True, atomic_write=True)
self._r_ra = CSRStorage(bits_for(depth-1))
self._r_rd = CSRStatus(dw)
-
+
###
-
+
mem = Memory(dw, depth)
self.specials += mem
wp = mem.get_port(write_capable=True)
rp = mem.get_port()
self.specials += wp, rp
-
+
self.comb += [
self.busy.eq(0),
),
self._r_wa.dat_w.eq(self._r_wa.storage + 1),
self._r_wc.dat_w.eq(self._r_wc.storage - 1),
-
+
wp.adr.eq(self._r_wa.storage),
wp.dat_w.eq(self.sink.payload.raw_bits()),
-
+
rp.adr.eq(self._r_ra.storage),
self._r_rd.status.eq(rp.dat_r)
]
bus_aw = flen(bus_accessor.address.payload.a)
bus_dw = flen(bus_accessor.data.payload.d)
_DMAController.__init__(self, bus_accessor, bus_aw, bus_dw, *args, **kwargs)
-
+
g = DataFlowGraph()
g.add_pipeline(self.generator,
misc.IntSequence(bus_aw, bus_aw),
bus_aw = flen(bus_accessor.address_data.payload.a)
bus_dw = flen(bus_accessor.address_data.payload.d)
_DMAController.__init__(self, bus_accessor, bus_aw, bus_dw, *args, **kwargs)
-
+
g = DataFlowGraph()
adr_buffer = AbstractActor(plumbing.Buffer)
int_sequence = misc.IntSequence(bus_aw, bus_aw)
if bus is None:
bus = csr.Interface()
self.bus = bus
-
+
###
if not description:
return
-
+
# Turn description into simple CSRs and claim ownership of compound CSR modules
simple_csrs = []
for c in description:
# Decode selection
sel = Signal()
self.comb += sel.eq(self.bus.adr[9:] == address)
-
+
# Bus writes
for i, c in enumerate(simple_csrs):
self.comb += [
self.bus.we & \
(self.bus.adr[:nbits] == i))
]
-
+
# Bus reads
brcases = dict((i, self.bus.dat_r.eq(c.w)) for i, c in enumerate(simple_csrs))
self.sync += [
class EventManager(Module, AutoCSR):
def __init__(self):
self.irq = Signal()
-
+
def do_finalize(self):
sources_u = [v for k, v in xdir(self, True) if isinstance(v, _EventSource)]
sources = sorted(sources_u, key=lambda x: x.huid)
If(self.pending.re & self.pending.r[i], source.clear.eq(1)),
self.pending.w[i].eq(source.pending)
]
-
+
irqs = [self.pending.w[i] & self.enable.storage[i] for i in range(n)]
self.comb += self.irq.eq(optree("|", irqs))
self.transaction = None
self.read_data_ready = False
self.done = False
-
+
def do_simulation(self, selfp):
if not self.done:
if self.transaction is not None:
read_only = mem.bus_read_only
else:
read_only = False
-
+
###
port = mem.get_port(write_capable=not read_only)
self.specials += mem, port
-
+
sel = Signal()
sel_r = Signal()
self.sync += sel_r.eq(sel)
port.we.eq(sel & self.bus.we),
port.dat_w.eq(self.bus.dat_w)
]
-
+
if self._page is None:
self.comb += port.adr.eq(self.bus.adr[word_bits:word_bits+flen(port.adr)])
else:
def phase_cmd_description(a, ba):
return [
- ("address", a, DIR_M_TO_S),
+ ("address", a, DIR_M_TO_S),
("bank", ba, DIR_M_TO_S),
("cas_n", 1, DIR_M_TO_S),
("cs_n", 1, DIR_M_TO_S),
p.cs_n.reset = 1
p.ras_n.reset = 1
p.we_n.reset = 1
-
+
# Returns pairs (DFI-mandated signal name, Migen signal object)
def get_standard_names(self, m2s=True, s2m=True):
r = []
m_ca, m_ba, m_rca = self._split_master_addresses(self._controller_bits,
self._bank_bits, self._rca_bits, self._cba_shift)
-
+
for nc, controller in enumerate(self._controllers):
if self._controller_bits:
controller_selected = [ca == nc for ca in m_ca]
self.transaction_start = 0
self.transaction = None
self.transaction_end = None
-
+
def do_simulation(self, selfp):
selfp.bus.dat_w = 0
selfp.bus.dat_we = 0
def read(self, bank, address):
return 0
-
+
def write(self, bank, address, data, we):
pass
selected_transaction = self.req_fifos[nb].contents.pop(0)
else:
bank.dat_ack = 0
-
+
rd_transaction = None
wr_transaction = None
if selected_bank_n >= 0:
self.sel = sel
self.busname = busname
self.latency = 0
-
+
def __str__(self):
return "<" + self.__class__.__name__ + " adr:" + hex(self.address) + " dat:" + hex(self.data) + ">"
class Arbiter(Module):
def __init__(self, masters, target):
self.submodules.rr = roundrobin.RoundRobin(len(masters))
-
+
# mux master->slave signals
for name, size, direction in _layout:
if direction == DIR_M_TO_S:
choices = Array(getattr(m, name) for m in masters)
self.comb += getattr(target, name).eq(choices[self.rr.grant])
-
+
# connect slave->master signals
for name, size, direction in _layout:
if direction == DIR_S_TO_M:
self.comb += dest.eq(source & (self.rr.grant == i))
else:
self.comb += dest.eq(source)
-
+
# connect bus requests to round-robin selector
reqs = [m.cyc for m in masters]
self.comb += self.rr.request.eq(Cat(*reqs))
ns = len(slaves)
slave_sel = Signal(ns)
slave_sel_r = Signal(ns)
-
+
# decode slave addresses
self.comb += [slave_sel[i].eq(fun(master.adr))
for i, (fun, bus) in enumerate(slaves)]
self.sync += slave_sel_r.eq(slave_sel)
else:
self.comb += slave_sel_r.eq(slave_sel)
-
+
# connect master->slaves signals except cyc
for slave in slaves:
for name, size, direction in _layout:
if direction == DIR_M_TO_S and name != "cyc":
self.comb += getattr(slave[1], name).eq(getattr(master, name))
-
+
# combine cyc with slave selection signals
self.comb += [slave[1].cyc.eq(master.cyc & slave_sel[i])
for i, slave in enumerate(slaves)]
-
+
# generate master ack (resp. err) by ORing all slave acks (resp. errs)
self.comb += [
master.ack.eq(optree("|", [slave[1].ack for slave in slaves])),
master.err.eq(optree("|", [slave[1].err for slave in slaves]))
]
-
+
# mux (1-hot) slave data return
masked = [Replicate(slave_sel_r[i], flen(master.dat_r)) & slaves[i][1].dat_r for i in range(ns)]
self.comb += master.dat_r.eq(optree("|", masked))
self.ratio = dw_i//dw_o
###
-
+
rst = Signal()
# generate internal write and read ack
write_ack.eq(ack & self.wishbone_o.we),
read_ack.eq(ack & ~self.wishbone_o.we)
]
-
+
# accesses counter logic
cnt = Signal(max=self.ratio)
self.sync += If(rst, cnt.eq(0)).Elif(ack, cnt.eq(cnt + 1))
-
+
# read data path
dat_r = Signal(dw_i)
self.sync += If(ack, dat_r.eq(Cat(self.wishbone_o.dat_r, dat_r[:dw_i-dw_o])))
-
+
# write data path
dat_w = Signal(dw_i)
self.comb += dat_w.eq(self.wishbone_i.dat_w)
-
+
# errors generation
err = Signal()
self.sync += If(ack, err.eq(self.wishbone_o.err))
-
+
# direct connection of wishbone_i --> wishbone_o signals
for name, size, direction in self.wishbone_i.layout:
if direction == DIR_M_TO_S and name not in ["adr", "dat_w"]:
self.comb += getattr(self.wishbone_o, name).eq(getattr(self.wishbone_i, name))
-
+
# adaptation of adr & dat signals
self.comb += [
self.wishbone_o.adr[0:flen(cnt)].eq(cnt),
self.wishbone_o.adr[flen(cnt):].eq(self.wishbone_i.adr)
]
-
+
self.comb += chooser(dat_w, cnt, self.wishbone_o.dat_w, reverse=True)
-
+
# fsm
fsm = FSM(reset_state="IDLE")
self.submodules += fsm
-
+
fsm.act("IDLE",
If(write_ack, NextState("WRITE_ADAPT")),
If(read_ack, NextState("READ_ADAPT"))
)
-
+
fsm.act("WRITE_ADAPT",
If(write_ack & (cnt == self.ratio-1),
NextState("IDLE"),
self.wishbone_i.ack.eq(1),
)
)
-
+
master_i_dat_r = Signal(dw_i)
self.comb += master_i_dat_r.eq(Cat(self.wishbone_o.dat_r, dat_r[:dw_i-dw_o]))
def __init__(self, bus, handler=print):
self.bus = bus
self.handler = handler
-
+
def do_simulation(self, selfp):
if selfp.bus.ack:
assert(selfp.bus.cyc and selfp.bus.stb)
self.bus = bus
self.transaction_start = 0
self.transaction = None
-
+
def do_simulation(self, selfp):
if self.transaction is None or selfp.bus.ack:
if self.transaction is not None:
class TargetModel:
def read(self, address):
return 0
-
+
def write(self, address, data, sel):
pass
-
+
def can_ack(self, bus):
return True
bus = Interface()
self.bus = bus
self.model = model
-
+
def do_simulation(self, selfp):
bus = selfp.bus
if not bus.ack:
read_only = self.mem.bus_read_only
else:
read_only = False
-
+
###
-
+
# memory
port = self.mem.get_port(write_capable=not read_only, we_granularity=8)
self.specials += self.mem, port
if bus_csr is None:
bus_csr = csr.Interface()
self.csr = bus_csr
-
+
###
self.sync += [
wordbits = log2_int(max(data_width//lasmim.dw, 1))
adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits)
word = Signal(wordbits) if wordbits else None
-
+
# Data memory
data_mem = Memory(lasmim.dw*2**wordbits, 2**linebits)
data_port = data_mem.get_port(write_capable=True, we_granularity=8)
self.specials += data_mem, data_port
-
+
write_from_lasmi = Signal()
write_to_lasmi = Signal()
if adr_offset is None:
displacer(self.wishbone.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True)
)
),
- If(write_to_lasmi,
+ If(write_to_lasmi,
chooser(data_port.dat_r, word, lasmim.dat_w),
lasmim.dat_we.eq(2**(lasmim.dw//8)-1)
),
chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True)
]
-
+
# Tag memory
tag_layout = [("tag", tagbits), ("dirty", 1)]
tag_mem = Memory(layout_len(tag_layout), 2**linebits)
tag_do.raw_bits().eq(tag_port.dat_r),
tag_port.dat_w.eq(tag_di.raw_bits())
]
-
+
self.comb += [
tag_port.adr.eq(adr_line),
tag_di.tag.eq(adr_tag)
if word is not None:
self.comb += lasmim.adr.eq(Cat(word, adr_line, tag_do.tag))
else:
- self.comb += lasmim.adr.eq(Cat(adr_line, tag_do.tag))
-
+ self.comb += lasmim.adr.eq(Cat(adr_line, tag_do.tag))
+
# Lasmim word computation, word_clr and word_inc will be simplified
# at synthesis when wordbits=0
word_clr = Signal()
assert(lasmim.write_latency >= 1 and lasmim.read_latency >= 1)
fsm = FSM(reset_state="IDLE")
self.submodules += fsm
-
+
fsm.delayed_enter("EVICT_DATAD", "EVICT_DATA", lasmim.write_latency-1)
fsm.delayed_enter("REFILL_DATAD", "REFILL_DATA", lasmim.read_latency-1)
)
)
)
-
+
fsm.act("EVICT_REQUEST",
lasmim.stb.eq(1),
lasmim.we.eq(1),
NextState("EVICT_REQUEST")
)
)
-
+
fsm.act("REFILL_WRTAG",
# Write the tag first to set the LASMI address
tag_port.we.eq(1),
object.__setattr__(self, "_ic_control_name", control_name)
object.__setattr__(self, "_ic_clock_domains", clock_domains)
-
+
if clock_domains is None:
ctl = Signal(name=control_name)
assert(not hasattr(decorated, control_name))
class InsertCE(InsertControl):
def __init__(self, *args, **kwargs):
InsertControl.__init__(self, "ce", *args, **kwargs)
-
+
def transform_fragment_insert(self, f, to_insert):
for ce, cdn in to_insert:
f.sync[cdn] = [If(ce, *f.sync[cdn])]
_Property = namedtuple("_Property", "name value")
_Instance = namedtuple("_Instance", "name cell properties")
_NetBranch = namedtuple("_NetBranch", "portname instancename")
-
+
def _write_cells(cells):
r = ""
for cell in cells:
(property PART (string "{1}") (owner "{2}"))
)
)""".format(design_name, part, vendor)
-
+
return r
def _generate_cells(f):
def _generate_instances(f,ns):
instances = []
for special in f.specials:
- if isinstance(special, Instance):
+ if isinstance(special, Instance):
props = []
for prop in special.items:
if isinstance(prop, Instance.Input):
def __setattr__(self, name, value):
self._fm._submodules += [(name, e) for e in _flat_list(value)]
setattr(self._fm, name, value)
-
+
def __iadd__(self, other):
self._fm._submodules += [(None, e) for e in _flat_list(other)]
return self
def _display_tree(filename, tree):
from migen.util.treeviz import RenderNode
-
+
def _to_render_node(name, node):
children = [_to_render_node(k, v) for k, v in node.children.items()]
if node.use_name:
r.add((c_prefix, ) + c_name)
else:
r |= c_names
-
+
if node.signal_count > sum(c.signal_count for c in node.children.values()):
node.use_name = True
r.add((node_name, ))
return r
-
+
def _name_signal(tree, signal):
elements = []
treepos = tree
else:
if _debug:
print("namer: using basic strategy (group {0})".format(group_n))
-
+
# ...then add number suffixes by HUID
inv_pnd = _invert_pnd(pnd)
huid_suffixed = False
self.counts = {}
self.sigs = {}
self.pnd = pnd
-
+
def get_name(self, sig):
if sig.name_override is not None:
sig_name = sig.name_override
for port in orig.ports:
port_granularity = port.we_granularity if port.we_granularity else orig.width
newport = _MemoryPort(adr=port.adr,
-
+
dat_r=port.dat_r[i*global_granularity:(i+1)*global_granularity] if port.dat_r is not None else None,
we=port.we[i*global_granularity//port_granularity] if port.we is not None else None,
dat_w=port.dat_w[i*global_granularity:(i+1)*global_granularity] if port.dat_w is not None else None,
expr = Signal()
self.expr = expr
class Input(_IO):
- pass
+ pass
class Output(_IO):
pass
class InOut(_IO):
"p": Instance.Parameter
}[item_type]
self.items.append(item_class(item_name, v))
-
+
def get_io(self, name):
for item in self.items:
if isinstance(item, Instance._IO) and item.name == name:
raise TypeError
r += ")"
r += "\n) "
- r += ns.get_name(instance)
+ r += ns.get_name(instance)
if parameters: r += " "
r += "(\n"
firstp = True
self.ports = []
self.init = init
self.name_override = get_obj_var_name(name, "mem")
-
+
def get_port(self, write_capable=False, async_read=False,
has_re=False, we_granularity=0, mode=WRITE_FIRST,
clock_domain="sys"):
else:
return verilog_printexpr(ns, e)[0]
adrbits = bits_for(memory.depth-1)
-
+
r += "reg [" + str(memory.width-1) + ":0] " \
+ gn(memory) \
+ "[0:" + str(memory.depth-1) + "];\n"
r += "\tif (" + gn(port.re) + ")\n"
r += "\t" + rd.replace("\n\t", "\n\t\t")
r += "end\n\n"
-
+
for port in memory.ports:
if port.async_read:
r += "assign " + gn(port.dat_r) + " = " + gn(memory) + "[" + gn(port.adr) + "];\n"
else:
r += "assign " + gn(port.dat_r) + " = " + gn(data_regs[id(port)]) + ";\n"
r += "\n"
-
+
if memory.init is not None:
r += "initial begin\n"
for i, c in enumerate(memory.init):
r += "\t" + gn(memory) + "[" + str(i) + "] <= " + str(memory.width) + "'d" + str(c) + ";\n"
r += "end\n\n"
-
+
return r
class SynthesisDirective(Special):
def __init__(self):
self.huid = HUID.__next_uid
HUID.__next_uid += 1
-
+
def __hash__(self):
return self.huid
return _Operator("|", [self, other])
def __ror__(self, other):
return _Operator("|", [other, self])
-
+
def __lt__(self, other):
return _Operator("<", [self, other])
def __le__(self, other):
return _Operator(">", [self, other])
def __ge__(self, other):
return _Operator(">=", [self, other])
-
-
+
+
def __getitem__(self, key):
from migen.fhdl.bitcontainer import flen
return _Slice(self, start, stop)
else:
raise TypeError
-
+
def eq(self, r):
"""Assignment
synchronous context.
"""
return _Assign(self, r)
-
+
def __hash__(self):
return HUID.__hash__(self)
from migen.fhdl.bitcontainer import bits_for
Value.__init__(self)
-
+
# determine number of bits and signedness
if bits_sign is None:
if min is None:
self.nbits, self.signed = bits_sign, False
if not isinstance(self.nbits, int) or self.nbits <= 0:
raise ValueError("Signal width must be a strictly positive integer")
-
+
self.variable = variable # deprecated
self.reset = reset
self.name_override = name_override
def __init__(self, cd="sys"):
Value.__init__(self)
self.cd = cd
-
+
class ResetSignal(Value):
"""Reset signal for a given clock domain
self.cond = cond
self.t = list(t)
self.f = []
-
+
def Else(self, *f):
"""Add an `else` conditional block
"""
_insert_else(self, list(f))
return self
-
+
def Elif(self, cond, *t):
"""Add an `else if` conditional block
def __init__(self, test, cases):
self.test = test
self.cases = cases
-
+
def makedefault(self, key=None):
"""Mark a key as the default case
def __init__(self, choices, key):
self.choices = choices
self.key = key
-
+
def __getattr__(self, attr):
return _ArrayProxy([getattr(choice, attr) for choice in self.choices],
self.key)
-
+
def __getitem__(self, key):
return _ArrayProxy([choice.__getitem__(key) for choice in self.choices],
self.key)
if specials is None: specials = set()
if clock_domains is None: clock_domains = _ClockDomainList()
if sim is None: sim = []
-
+
self.comb = comb
self.sync = sync
self.specials = specials
self.clock_domains = _ClockDomainList(clock_domains)
self.sim = sim
-
+
def __add__(self, other):
newsync = defaultdict(list)
for k, v in self.sync.items():
class _SignalLister(NodeVisitor):
def __init__(self):
self.output_list = set()
-
+
def visit_Signal(self, node):
self.output_list.add(node)
def __init__(self):
self.output_list = set()
self.target_context = False
-
+
def visit_Signal(self, node):
if self.target_context:
self.output_list.add(node)
-
+
def visit_Assign(self, node):
self.target_context = True
self.visit(node.l)
def visit_ArrayProxy(self, node):
for choice in node.choices:
self.visit(choice)
-
+
def list_signals(node):
lister = _SignalLister()
lister.visit(node)
r = _Assign(lhs, rhs)
if self.extra_stmts:
r = [r] + self.extra_stmts
-
+
self.target_context, self.extra_stmts = old_target_context, old_extra_stmts
return r
varname = remove_underscore(varname)
l.insert(0, (varname, name_to_idx[varname]))
name_to_idx[varname] += 1
-
+
try:
obj = frame.f_locals["self"]
except KeyError:
obj = None
if hasattr(obj, "__del__"):
obj = None
-
+
if obj is None:
if varname is not None:
coname = frame.f_code.co_name
objs.append(obj)
classname = remove_underscore(classname)
l.insert(0, (classname, idx))
-
+
varname = None
frame = frame.f_back
return l
r += "reg " + _printsig(ns, dummy_s) + ";\n"
r += "initial " + ns.get_name(dummy_s) + " <= 1'd0;\n"
r += syn_on
-
+
groups = group_by_targets(f.comb)
-
+
for n, g in enumerate(groups):
if len(g[1]) == 1 and isinstance(g[1][0], _Assign):
r += "assign " + _printnode(ns, _AT_BLOCKING, 0, g[1][0])
r += "\n" + syn_off
r += "reg " + _printsig(ns, dummy_d) + ";\n"
r += syn_on
-
+
r += "always @(*) begin\n"
if display_run:
r += "\t$display(\"Running comb block #" + str(n) + "\");\n"
ios |= {cd.clk, cd.rst}
else:
raise KeyError("Unresolved clock domain: '"+cd_name+"'")
-
+
f = lower_complex_slices(f)
insert_resets(f)
f = lower_basics(f)
self.visit_ArrayProxy(node)
elif node is not None:
self.visit_unknown(node)
-
+
def visit_constant(self, node):
pass
-
+
def visit_Signal(self, node):
pass
def visit_ResetSignal(self, node):
pass
-
+
def visit_Operator(self, node):
for o in node.operands:
self.visit(o)
-
+
def visit_Slice(self, node):
self.visit(node.value)
-
+
def visit_Cat(self, node):
for e in node.l:
self.visit(e)
-
+
def visit_Replicate(self, node):
self.visit(node.v)
-
+
def visit_Assign(self, node):
self.visit(node.l)
self.visit(node.r)
-
+
def visit_If(self, node):
self.visit(node.cond)
self.visit(node.t)
self.visit(node.f)
-
+
def visit_Case(self, node):
self.visit(node.test)
for v, statements in node.cases.items():
self.visit(statements)
-
+
def visit_Fragment(self, node):
self.visit(node.comb)
self.visit(node.sync)
-
+
def visit_statements(self, node):
for statement in node:
self.visit(statement)
-
+
def visit_clock_domains(self, node):
for clockname, statements in node.items():
self.visit(statements)
-
+
def visit_ArrayProxy(self, node):
for choice in node.choices:
self.visit(choice)
self.visit(node.key)
-
+
def visit_unknown(self, node):
pass
return self.visit_unknown(node)
else:
return None
-
+
def visit_constant(self, node):
return node
-
+
def visit_Signal(self, node):
return node
-
+
def visit_ClockSignal(self, node):
return node
def visit_Operator(self, node):
return _Operator(node.op, [self.visit(o) for o in node.operands])
-
+
def visit_Slice(self, node):
return _Slice(self.visit(node.value), node.start, node.stop)
-
+
def visit_Cat(self, node):
return Cat(*[self.visit(e) for e in node.l])
-
+
def visit_Replicate(self, node):
return Replicate(self.visit(node.v), node.n)
-
+
def visit_Assign(self, node):
return _Assign(self.visit(node.l), self.visit(node.r))
-
+
def visit_If(self, node):
r = If(self.visit(node.cond))
r.t = self.visit(node.t)
r.f = self.visit(node.f)
return r
-
+
def visit_Case(self, node):
cases = dict((v, self.visit(statements)) for v, statements in node.cases.items())
r = Case(self.visit(node.test), cases)
return r
-
+
def visit_Fragment(self, node):
r = copy(node)
r.comb = self.visit(node.comb)
r.sync = self.visit(node.sync)
return r
-
+
# NOTE: this will always return a list, even if node is a tuple
def visit_statements(self, node):
return [self.visit(statement) for statement in node]
-
+
def visit_clock_domains(self, node):
return dict((clockname, self.visit(statements)) for clockname, statements in node.items())
-
+
def visit_ArrayProxy(self, node):
return _ArrayProxy([self.visit(choice) for choice in node.choices],
self.visit(node.key))
-
+
def visit_unknown(self, node):
return node
class EndpointSimHook(Module):
def __init__(self, endpoint):
self.endpoint = endpoint
-
+
def on_ack(self):
pass
-
+
def on_nack(self):
pass
-
+
def on_inactive(self):
pass
-
+
def do_simulation(self, selfp):
if selfp.endpoint.stb:
if selfp.endpoint.ack:
h = create(u, ep, v)
ep_to_hook[ep] = h
setattr(self.submodules, "hook"+str(hookn), h)
-
+
def hooks_iter(self):
for v1 in self.nodepair_to_ep.values():
for v2 in v1.values():
def __init__(self, endpoint, nbits):
self.reset = Signal()
self.freeze = Signal()
-
+
self._ack_count = CSRStatus(nbits)
self._nack_count = CSRStatus(nbits)
self._cur_status = CSRStatus(2)
-
+
###
stb = Signal()
self._r_nbits = CSRStatus(8)
self._r_freeze = CSRStorage()
self._r_reset = CSR()
-
+
###
DFGHook.__init__(self, dfg,
from migen.flow.actor import *
from migen.flow import plumbing
-# Abstract actors mean that the actor class should be instantiated with the parameters
+# Abstract actors mean that the actor class should be instantiated with the parameters
# from the dictionary. They are needed to enable actor duplication or sharing during
# elaboration, and automatic parametrization of plumbing actors.
self.parameters = parameters
self.name = name
self.busy = Signal()
-
+
def create_instance(self):
return self.actor_class(**self.parameters)
-
+
def __repr__(self):
r = "<abstract " + self.actor_class.__name__
if self.name is not None:
MultiDiGraph.__init__(self)
self.elaborated = False
self.abstract_busy_signals = dict()
-
+
def add_connection(self, source_node, sink_node,
source_ep=None, sink_ep=None, # default: assume nodes have 1 source/sink and use that one
source_subr=None, sink_subr=None): # default: use whole record
def add_pipeline(self, *nodes):
for n1, n2 in zip(nodes, nodes[1:]):
self.add_connection(n1, n2)
-
+
def del_connections(self, source_node, sink_node, data_requirements):
edges_to_delete = []
edge_data = self.get_edge_data(source_node, sink_node)
edges_to_delete.append(key)
for key in edges_to_delete:
self.remove_edge(source_node, sink_node, key)
-
+
def replace_actor(self, old, new):
self.add_node(new)
for xold, v, data in self.out_edges(old, data=True):
for u, xold, data in self.in_edges(old, data=True):
self.add_edge(u, new, **data)
self.remove_node(old)
-
+
def instantiate(self, actor):
inst = actor.create_instance()
self.abstract_busy_signals[id(inst)] = actor.busy
else:
d[el_dst] = [el_src]
return d
-
+
# List sources that feed more than one sink.
def _list_divergences(self):
d = self._source_to_sinks()
or any(d["source_subr"] is not None or d["sink_subr"] is not None
for u, v, d in self.edges_iter(data=True)) \
or bool(self._list_divergences())
-
+
def _eliminate_subrecords_and_divergences(self):
# Insert combinators.
for (dst_node, dst_endpoint), sources in self._sink_to_sources().items():
"source{0}".format(n), dst_endpoint)
# connect source -> splitter_sink
self.add_connection(src_node, splitter, src_endpoint, "sink")
-
+
def _infer_plumbing_layout(self):
while True:
ap = [a for a in self if isinstance(a, AbstractActor) and a.actor_class in plumbing.actors]
layout = other_ep.payload.layout
a.parameters["layout"] = layout
self.instantiate(a)
-
+
def _instantiate_actors(self):
# 1. instantiate all abstract non-plumbing actors
for actor in list(self):
d["source"] = get_single_ep(u, Source)[0]
if d["sink"] is None:
d["sink"] = get_single_ep(v, Sink)[0]
-
+
# Elaboration turns an abstract DFG into a physical one.
# Pass 1: eliminate subrecords and divergences
# by inserting Combinator/Splitter actors
if self.elaborated:
return
self.elaborated = True
-
+
self._eliminate_subrecords_and_divergences()
if optimizer is not None:
optimizer(self)
def __init__(self, endpoint):
EndpointSimHook.__init__(self, endpoint)
self.reset()
-
+
def reset(self):
self.inactive = 0
self.ack = 0
self.nack = 0
-
+
# Total number of cycles per token (inverse token rate)
def cpt(self):
return (self.inactive + self.nack + self.ack)/self.ack
-
+
# Inactivity cycles per token (slack)
def ipt(self):
return self.inactive/self.ack
-
+
# NAK cycles per token (backpressure)
def npt(self):
return self.nack/self.ack
-
+
def report_str(self):
if self.ack:
return "C/T={:.2f}\nI/T={:.2f}\nN/T={:.2f}".format(self.cpt(), self.ipt(), self.npt())
else:
return "N/A"
-
+
def on_ack(self):
self.ack += 1
-
+
def on_nack(self):
self.nack += 1
-
+
def on_inactive(self):
self.inactive += 1
self.busy = Signal()
###
-
+
self.comb += [
self.busy.eq(0),
self.source.stb.eq(optree("&", [sink.stb for sink in sinks]))
setattr(self, "source"+str(n), s)
sources.append(s)
self.busy = Signal()
-
+
###
self.comb += [source.payload.eq(self.sink.payload) for source in sources]
sinks.append(sink)
self.busy = Signal()
self.sel = Signal(max=n)
-
+
###
cases = {}
sources.append(source)
self.busy = Signal()
self.sel = Signal(max=n)
-
+
###
cases = {}
self.regs = [Signal((w, signed)) for i in range(n)]
###
-
+
src = self.i
for reg in self.regs:
sd = getattr(self.sync, self.odomain)
sync_i = getattr(self.sync, idomain)
sync_o = getattr(self.sync, odomain)
-
+
sync_i += If(self.i, toggle_i.eq(~toggle_i))
self.specials += MultiReg(toggle_i, toggle_o, odomain)
sync_o += toggle_o_r.eq(toggle_o)
def __init__(self, real, imag):
self.real = real
self.imag = imag
-
+
def __neg__(self):
return Complex(-self.real, -self.imag)
-
+
def __add__(self, other):
if isinstance(other, Complex):
return Complex(self.real + other.real, self.imag + other.imag)
else:
return Complex(self.real*other, self.imag*other)
__rmul__ = __mul__
-
+
def __lshift__(self, other):
return Complex(self.real << other, self.imag << other)
def __rshift__(self, other):
def __repr__(self):
return repr(self.real) + " + " + repr(self.imag) + "j"
-
+
def eq(self, r):
if isinstance(r, Complex):
return self.real.eq(r.real), self.imag.eq(r.imag)
self.ready_o = Signal()
self.quotient_o = Signal(w)
self.remainder_o = Signal(w)
-
+
###
-
+
qr = Signal(2*w)
counter = Signal(max=w+1)
divisor_r = Signal(w)
diff = Signal(w+1)
-
+
self.comb += [
self.quotient_o.eq(qr[:w]),
self.remainder_o.eq(qr[w:]),
"""
Data written to the input interface (`din`, `we`, `writable`) is
buffered and can be read at the output interface (`dout`, `re`,
- `readable`). The data entry written first to the input
+ `readable`). The data entry written first to the input
also appears first on the output.
Parameters
self.next_state_signal = next_state_signal
self.encoding = encoding
self.aliases = aliases
-
+
def visit_unknown(self, node):
if isinstance(node, NextState):
try:
caller = memory.Initiator(g, v)
callers.append(caller)
self.submodules += callers
-
+
self.dispatch_state = _WAIT_COMPLETE
self.dispatch_caller = 0
self.pending_transaction = None
-
+
def identify_transaction(self, t):
if isinstance(t, Token):
return 0
return self.busname_to_caller_id[t.busname]
else:
raise TypeError
-
+
def dispatch_g(self, caller_id):
while True:
if self.dispatch_state == _WAIT_COMPLETE and self.dispatch_caller == caller_id:
def timeline(trigger, events):
lastevent = max([e[0] for e in events])
counter = Signal(max=lastevent+1)
-
+
counterlogic = If(counter != 0,
counter.eq(counter + 1)
).Elif(trigger,
).Else(
counterlogic
)
-
+
def get_cond(e):
if e[0] == 0:
return trigger & (counter == 0)
yield from e.iter_flat()
else:
raise TypeError
-
+
def flatten(self):
return [signal for signal, direction in self.iter_flat()]
def raw_bits(self):
return Cat(*self.flatten())
-
+
def connect(self, *slaves):
r = []
for f in self.layout:
Special.__init__(self)
self.cd = cd
self.async_reset = async_reset
-
+
def iter_expressions(self):
yield self.cd, "clk", SPECIAL_INPUT
yield self.cd, "rst", SPECIAL_OUTPUT
self.can_issue = Signal()
self.issue = Signal()
self.tag_issue = Signal(tag_width)
-
+
# call
self.call = Signal()
self.tag_call = Signal(tag_width)
self.data_call = Signal(data_width)
-
+
# readback
self.can_read = Signal()
self.read = Signal()
self.data_read = Signal(data_width)
-
+
###
empty_count = Signal(max=depth+1, reset=depth)
slots[produce].wait_data.eq(1),
slots[produce].tag.eq(self.tag_issue)
)
-
+
# call
for n, slot in enumerate(slots):
self.sync += If(self.call & slot.wait_data & (self.tag_call == slot.tag),
slot.has_data.eq(1),
slot.data.eq(self.data_call)
)
-
+
# readback
self.comb += [
self.can_read.eq(slots[consume].has_data),
slots[consume].has_data.eq(0)
)
]
-
+
# do not touch empty count when issuing and reading at the same time
self.sync += If(self.issue & self.can_issue & self.read & self.can_read,
empty_count.eq(empty_count)
self.switch_policy = switch_policy
if self.switch_policy == SP_CE:
self.ce = Signal()
-
+
###
if n > 1:
self.symdict = symdict
self.registers = registers
self.ec = ExprCompiler(self.symdict)
-
+
def visit_top(self, node, args, kwargs):
if isinstance(node, ast.Module) \
and len(node.body) == 1 \
return states
else:
raise NotImplementedError
-
+
# blocks and statements
def visit_block(self, statements):
sa = StateAssembler()
else:
raise NotImplementedError
statement = None
-
+
def visit_assign(self, sa, node, statements):
if isinstance(node.value, ast.Call):
is_special = False
sa.assemble([r], [r])
else:
raise NotImplementedError
-
+
def visit_assign_special(self, sa, node, statements):
value = node.value
assert(isinstance(value, ast.Call))
callee = self.symdict[value.func.id]
else:
raise NotImplementedError
-
+
if callee == transel.Register:
if len(value.args) != 1:
raise TypeError("Register() takes exactly 1 argument")
raise NotImplementedError
else:
return self.visit_io_pattern(sa, node.targets, callee, value.args, value.keywords, statements)
-
+
def visit_io_pattern(self, sa, targets, model, args, keywords, statements):
# first statement is <modelname> = <model>(<args>)
if len(targets) != 1 or not isinstance(targets[0], ast.Name):
modelname = targets[0].id
if modelname in self.symdict:
raise NotImplementedError("I/O model name is not free")
-
+
# second statement must be yield <modelname>
try:
ystatement = next(statements)
or ystatement.value.value.id != modelname:
print(ast.dump(ystatement))
raise NotImplementedError("Unrecognized I/O pattern")
-
+
# following optional statements are assignments to registers
# with <modelname> used in expressions.
from_model = []
else:
raise NotImplementedError
from_model.append((tregs, fstatement.value))
-
+
states, exit_states = gen_io(self, modelname, model, args, keywords, from_model)
sa.assemble(states, exit_states)
return fstatement
-
+
def visit_if(self, sa, node):
test = self.ec.visit_expr(node.test)
states_t, exit_states_t = self.visit_block(node.body)
states_f, exit_states_f = self.visit_block(node.orelse)
exit_states = exit_states_t + exit_states_f
-
+
test_state_stmt = If(test, id_next_state(states_t[0]))
test_state = [test_state_stmt]
if states_f:
test_state_stmt.Else(id_next_state(states_f[0]))
else:
exit_states.append(test_state)
-
+
sa.assemble([test_state] + states_t + states_f,
exit_states)
-
+
def visit_while(self, sa, node):
test = self.ec.visit_expr(node.test)
states_b, exit_states_b = self.visit_block(node.body)
test_state = [If(test, id_next_state(states_b[0]))]
for exit_state in exit_states_b:
exit_state.insert(0, id_next_state(test_state))
-
+
sa.assemble([test_state] + states_b, [test_state])
-
+
def visit_for(self, sa, node):
if not isinstance(node.target, ast.Name):
raise NotImplementedError
states += states_b
del self.symdict[target]
sa.assemble(states, last_exit_states)
-
+
def visit_iterator(self, node):
return eval_ast(node, self.symdict)
tree = ast.parse(inspect.getsource(self.func))
symdict = self.func.__globals__.copy()
registers = []
-
+
states = _Compiler(self, symdict, registers).visit_top(tree, self.args, self.kwargs)
-
+
for register in registers:
if register.source_encoding:
register.finalize()
self.submodules += register
-
+
fsm = implement_fsm(states)
self.submodules += TransformModule(LowerAbstractLoad().visit, fsm)
class ExprCompiler:
def __init__(self, symdict):
self.symdict = symdict
-
+
def visit_expr(self, node):
# Attempt compile-time evaluation first
try:
return self.visit_expr_subscript(node)
else:
raise NotImplementedError
-
+
def visit_expr_call(self, node):
if isinstance(node.func, ast.Name):
callee = self.symdict[node.func.id]
return _Slice(val, low, up)
else:
raise NotImplementedError
-
+
def visit_expr_binop(self, node):
left = self.visit_expr(node.left)
right = self.visit_expr(node.right)
return left & right
else:
raise NotImplementedError
-
+
def visit_expr_compare(self, node):
test = self.visit_expr(node.left)
r = None
r = r & comparison
test = comparator
return r
-
+
def visit_expr_name(self, node):
if node.id == "True":
return 1
if isinstance(r, ImplRegister):
r = r.storage
return r
-
+
def visit_expr_num(self, node):
return node.n
-
+
def visit_expr_attribute(self, node):
raise NotImplementedError
-
+
def visit_expr_subscript(self, node):
raise NotImplementedError
ExprCompiler.__init__(self, symdict)
self.modelname = modelname
self.ep = ep
-
+
def visit_expr_subscript(self, node):
# check that we are subscripting <modelname>.value
if not isinstance(node.value, ast.Attribute) \
or not isinstance(node.value.value, ast.Name) \
or node.value.value.id != self.modelname:
raise NotImplementedError
-
+
if not isinstance(node.slice, ast.Index):
raise NotImplementedError
field = eval_ast(node.slice.value, self.symdict)
signal = getattr(self.ep.payload, field)
-
+
return signal
def _gen_df_io(compiler, modelname, to_model, from_model):
state = [compiler.ioo.busy.eq(0)]
else:
state = []
-
+
if isinstance(values, ast.Name) and values.id == "None":
# token pull from sink
if not isinstance(ep, Sink):
ExprCompiler.__init__(self, symdict)
self.modelname = modelname
self.data_signal = data_signal
-
+
def visit_expr_attribute(self, node):
# recognize <modelname>.data as the bus read signal, raise exception otherwise
if not isinstance(node.value, ast.Name) \
bus.stb.eq(1),
bus.adr.eq(compiler.ec.visit_expr(to_model["address"])),
]
-
+
if model == TWrite:
if from_model:
raise TypeError("Attempted to read from write transaction")
name, default = param
else:
name, default = param, None
-
+
# build the set of argument names at the same time
argnames.add(name)
-
+
if value is None:
if default is None:
raise TypeError("No default value for parameter " + name)
def __init__(self, target, source):
self.target = target
self.source = source
-
+
def lower(self):
if not self.target.finalized:
raise FinalizeError
self.storage = Signal(bits_sign, name=self.name)
self.source_encoding = {}
self.id_to_source = {}
-
+
def load(self, source):
if id(source) not in self.source_encoding:
self.source_encoding[id(source)] = len(self.source_encoding) + 1
self.id_to_source[id(source)] = source
return AbstractLoad(self, source)
-
+
def do_finalize(self):
self.sel = Signal(max=len(self.source_encoding)+1, name="pl_regsel_"+self.name)
# do nothing when sel == 0
else:
self._nbits, self._signed = bits_sign, False
self._val = 0
-
+
def _set_store(self, val):
if self._signed:
sbw = 2**(self._nbits - 1)
return self._val << other
def __rlshift__(self, other):
return other << self._val
-
+
def __rshift__(self, other):
if isinstance(other, Register):
return self._val >> other._val
def __init__(self):
self.states = []
self.exit_states = []
-
+
def assemble(self, n_states, n_exit_states):
self.states += n_states
for exit_state in self.exit_states:
exit_state.insert(0, id_next_state(n_states[0]))
self.exit_states = n_exit_states
-
+
def ret(self):
return self.states, self.exit_states
self.top_name = top_name
self.dut_type = dut_type
self.dut_name = dut_name
-
+
self._cd_name = cd_name
self._clk_period = clk_period
-
+
cd = ClockDomain(self._cd_name)
self.clock_domains = [cd]
self.ios = {cd.clk, cd.rst}
-
+
def get(self, sockaddr):
template1 = """`timescale 1ns / 1ps
self.top_level = top_level
self.ipc = Initiator(sockaddr)
self.sim_runner = sim_runner
-
+
c_top = self.top_level.get(sockaddr)
-
+
fragment = fragment + _Fragment(clock_domains=top_level.clock_domains)
c_fragment, self.namespace = verilog.convert(fragment,
ios=self.top_level.ios,
name=self.top_level.dut_type,
return_ns=True,
**vopts)
-
+
self.cycle_counter = -1
self.sim_runner = sim_runner
self.sim_functions = fragment.sim
self.active_sim_functions = set(f for f in fragment.sim if not hasattr(f, "passive") or not f.passive)
-
+
def run(self, ncycles=None):
counter = 0
if signed and (value & 2**(nbits - 1)):
value -= 2**nbits
return value
-
+
def wr(self, item, value, index=0):
name = self.top_level.top_name + "." \
+ self.top_level.dut_name + "." \
value += 2**nbits
assert(value >= 0 and value < 2**nbits)
self.ipc.send(MessageWrite(name, Int32(index), value))
-
+
def __del__(self):
if hasattr(self, "ipc"):
warnings.warn("call Simulator.close() to clean up "
self.dut_file = dut_file
self.vvp_file = vvp_file
self.keep_files = keep_files
-
+
def start(self, c_top, c_dut):
_str2file(self.top_file, c_top)
_str2file(self.dut_file, c_dut)
def __init__(self, *pvalues):
for parameter, value in zip(self.parameters, pvalues):
setattr(self, parameter[1], parameter[0](value))
-
+
def __str__(self):
p = []
for parameter in self.parameters:
class PacketTooLarge(Exception):
pass
-
+
class Initiator:
def __init__(self, sockaddr):
self.sockaddr = sockaddr
self._cleanup_file()
self.socket.bind(self.sockaddr)
self.socket.listen(1)
-
+
def _cleanup_file(self):
try:
os.remove(self.sockaddr)
except OSError:
pass
-
+
def accept(self):
self.conn, addr = self.socket.accept()
-
+
def send(self, message):
self.conn.send(_pack(message))
-
+
def recv(self):
maxlen = 2048
packet = self.conn.recv(maxlen)
return MemoryProxy(self.simulator, item)
else:
return Proxy(self.simulator, item)
-
+
def __getattr__(self, name):
return self.__process_get(getattr(self._simproxy_obj, name))
-
+
def __setattr__(self, name, value):
item = getattr(self._simproxy_obj, name)
assert(isinstance(item, Signal))